RayCaster: Allow object tests to be more easily extended.
See original GitHub issueRight 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:
- 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.) - 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.
- 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:
- Created 3 years ago
- Comments:6
Top 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 >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
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.
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.