Hi there, can we override how an object handles raycasts?
For context, I have a shader-deformed mesh and want to be able to approximately raycast against it. I have a low poly mesh representation for this but I don’t know how to make the raycasting system actually use it.
Right now it uses the actual mesh (or the mesh-bvh-processed mesh?) which is not close enough to the drawn deformed mesh.
To override how an object handles raycasts in Needle Engine, especially for a shader-deformed mesh, you can create a custom raycaster by extending the existing raycaster classes. Since you want to approximate raycasting against a low poly representation instead of the deformed mesh, follow these steps:
Extend the Raycaster class: Create a new class that extends the Raycaster or ObjectRaycaster. Override the performRaycast method to implement your custom logic.
Implement the custom raycasting logic: In your overridden method, check against your low poly representation instead of the original deformed mesh.
Use the new raycaster: Attach your new raycaster to the objects or cameras that should utilize it for raycasting.
Here’s a simplified approach in code:
import { Raycaster, Mesh, Object3D, Intersection } from "three";
import { RaycastOptions } from "././engine/engine_physics.js"; // Ensure correct path
class CustomRaycaster extends Raycaster {
performRaycast(opts: RaycastOptions | null = null): Intersection[] | null {
opts = opts || new RaycastOptions();
// Replace this with your logic to get the low poly mesh for raycasting
const lowPolyMesh = this.getLowPolyMesh(this.gameObject);
if (lowPolyMesh) {
return super.intersectObject(lowPolyMesh, false, opts.results); // Raycast against low poly
}
return null;
}
private getLowPolyMesh(object: Object3D): Mesh | null {
// Logic to return the low poly representation of the object
// This may depend on your object structure and how it's stored
return null; // Replace with actual logic
}
}
// Usage: Attach CustomRaycaster to your GameObject instead of the default Raycaster
const customRaycaster = new CustomRaycaster();
myGameObject.add(customRaycaster);
Make sure to replace the getLowPolyMesh method with your actual logic to fetch or create the low poly representation of the mesh. This will allow your raycasting to use the simpler geometry, closely matching the shader-deformed appearance.
If you need more specific guidance or encounter difficulties, please provide more context about your current implementation or structure.
1 replies left - Get a PRO license for more AI replies. thread_LwJCpn5qOE05mEdgDyvl872J Reply to this message to continue the conversation
Could you clarify what you mean by how an object handles raycasts?
Are you using a prebuilt component? Otherwise you can just configure your custom mesh to the NoRaycast layer in Unity and hide the mesh renderer on your low poly mesh (so it’s not rendered but raycast against in the scene when you do a physics raycast).
And yes all raycasts automatically use the BVH structures for performance reasons.
Splitting it into two objects would be doable, yes. Let me explain though what I have in mind:
In threejs you can override the Object3D.raycast function to change the object’s reaction to a raycast. This can be used to e.g. switch to simpler geometry dynamically or do something else entirely
I need the same kind of behaviour working in needle. I imagine e.g. an interface which can be implemented by components. Which if present always gets higher prio than whatever the default raycasting engine does.
In the meantime I managed to force usage of my raycasting method:
Thinking further about it, I guess it would suffice to opt out of the bvh-acceleration somehow.
Like IRaycastOptions.useAcceleratedRaycast on a per-object basis. Then it’d fall back to the default raycast implementation which can easily be overriden.
We’re still using the three.js methods - e.g. Raycaster.intersectObject in all pathes - so I think you can do just what you described by overriding/wrapping the intersectObject method which you can use to customize the object or return an empty result to skip objects completely for example.
I kept the hacky override (this["acceleratedRaycast"] = this.myraycast;) because it worked and I had to shift my focus elsewhere.
So I cannot really speak about if using Raycaster.intersectObject would have worked too in my case