question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RayCaster: Allow object tests to be more easily extended.

See original GitHub issue

Right now the only way to tell the RayCaster to include an object or not is with setting layers, and it is limited to checking any one of the RayCaster’s layers is included in the objects layers.

Because this check exists outside the object in a separate function, in order to override this behavior, you need to needlessly override the RayCaster’s intersectObject and intersectObjects functions, instead of just the outside intersectObject function.

Possible Solutions:

  1. Move the outside intersectObject function into the RayCaster object so that only it needs to be extended. (Maybe also include a second function for just the if ( object.layers.test( raycaster.layers ) ) { part.)
  2. Add some sort of specifiable test mode to the Layers object to allow for all, exact, and none alternative comparison modes to take advantage of the bit masking.
  3. Allow passing in a custom test object/function into intersectObject and intersectObjects.

Example Current Override It requires a lot of duplicate code to get the desired result.

import {
    RayCaster as ThreeRayCaster
} from 'three'

function ascSort(a, b) {
    return (a.distance - b.distance)
}

export default class extends ThreeRayCaster {
    constructor (origin, direction, near, far) {
        super(origin, direction, near, far)

        this._testMode = 'all'
    }

    get testMode () { return this._testMode }
    set testMode (value) { this._testMode = value }

    _intersectObject (object, intersects, recursive) {
        if (this._test(object)) {
            object.raycast(this, intersects)
        }

        if (recursive === true) {
            const children = object.children

            for (let i = 0, l = children.length; i < l; ++i) {
                this._intersectObject(children[i], intersects, true)
            }
        }
    }

    _test (object) {
        switch (this.testMode) {
            case 'any':
                return object.layers.test(this.layers)
            case 'none':
                return !object.layers.test(this.layers)
            case 'exact':
                return (object.layers.mask === this.layers.mask)
            case 'all':
            default:
                return ((object.layers.mask & this.layers.mask) === this.layers.mask)
        }
    }

    intersectObject (object, recursive, optionalTarget) {
        const intersects = optionalTarget || []

        this._intersectObject(object, intersects, recursive)

        intersects.sort(ascSort)

        return intersects
    },

    intersectObjects (objects, recursive, optionalTarget) {
        const intersects = optionalTarget || []

        for (let i = 0, l = objects.length; i < l; i ++) {
            this._intersectObject(objects[i], intersects, recursive)
        }

        intersects.sort(ascSort)

        return intersects
    }
}

Potential Override If More Extendable

import {
    RayCaster as ThreeRayCaster
} from 'three'

export default class extends ThreeRayCaster {
    constructor (origin, direction, near, far) {
        super(origin, direction, near, far)

        this._testMode = 'all'
    }

    get testMode () { return this._testMode }
    set testMode (value) { this._testMode = value }

    _test (object) {
        switch (this.testMode) {
            case 'any':
                return object.layers.test(this.layers)
            case 'none':
                return !object.layers.test(this.layers)
            case 'exact':
                return (object.layers.mask === this.layers.mask)
            case 'all':
            default:
                return ((object.layers.mask & this.layers.mask) === this.layers.mask)
        }
    }
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
Mugen87commented, Feb 23, 2021

Okay, understood. But since your requirements are quite application specific, there is not yet a compelling reason for changing/enhancing the API. We can reconsider this issue if more user are going to ask for similar features.

0reactions
BlakeHancockcommented, Feb 23, 2021

I guess in the contexts of games, I was planning on having a normal sight RayCaster, an infrared RayCaster, an X-Ray RayCaster and using layers to denote which objects are penetrable by each. For the infrared one for an example, depth is a consideration, so if it passes through too many objects, it would stop.

Again I can certainly create a wrapper class or function that handles this logic and uses the default ray tracer, it just seemed convenient to do it like my example.

I’m admittedly pretty new to 3d stuff, so I don’t know the best practices very well.

I simply thought it was too bad I couldn’t extend this part of the RayTracer due to it existing outside the exported object.

Read more comments on GitHub >

github_iconTop Results From Across the Web

raycaster - A-Frame
Raycasting is the method of extending a line from an origin towards a direction, and checking whether that line intersects with other entities....
Read more >
Detecting Objects with Raycasts in Unity3D - YouTube
`Boxcast` projects a box along the ray and allow you to test if a box may move ... To learn more about using...
Read more >
Raycasting - It's mighty useful - One Wheel Studio
What is Raycasting? Raycasting is a lightweight and performant way to reach out into a scene and see what objects are in a...
Read more >
Raycasts in Unity, made easy - Game Dev Beginner
Learn how to use Raycasts in Unity the right way, with layers, triggers and multiple objects, in this complete, step by step guide....
Read more >
Raycasting IV: Directional Sprites, Doors, And More
This can allow to extend the code of the previous tutorials with these new ... A raycaster cannot render such objects in true...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found