I’m trying to generate a terrain on top of random meshes for a player to walk on. I figured, I would then hide the terrain and the players camera would do a Raycast from above the terrain to always stay on top. This way I would only need to do one Raycast per frame instead of checking all objects and also get a smoother walking experience.
Here’s an image of my hoped result (sideview). The red planeGeometry gets wrapped closely on top of all geometry:
My first approach is the following:
- Position of Objects
- Create a Plane covering all objects with a relative amount of vertices (depending on the size)
- Go through each vertice and do a raycast between that point and the group of objects below
- Move the vertice down for the calculated distance (results in red line)
This works quite well. The only problem is doing the Raycasts, which seem to be a huge bottleneck. It takes about 5 seconds)
I am now wondering about more performant approaches. One idea I have is to use a MeshDepthMaterial on the objects, then render a height map from that and then apply that heightmap to the plane. (Although I don’t know yet if the depthmaterial is relative to the camera distance globally or per mesh)
Another idea would be to somehow quickly generate a lot of points on the surface of the models and then apply a triangulation algorithm on that set of points. Something like this: Triangulation
I hope my question is clear and would be very happy for some advice or other ideas.
Seems like you’re trying to generate a navmap ?
(1) If your environment is 3D and concave - ie. at any point it has more than one level on y-axis, like here (assuming it’s a side-view):
the navmap “shrink-wrapping” won’t work. The height-map / plane won’t be able to wrap inside these caves / ledges, so it will prevent players from going somewhere they’d logically should be able to go.
(2) Ignoring complexities like spatial indices and region generation algorithms, if all you’d like is a simple navigable map, try the following:
- Create a collision-detection BufferGeometry.
- Assuming the actual ground geometry is relatively simple (which it should ), just duplicate the
position buffer from it to the newly created collision geometry (if the environment is super big, you can also split it into smaller “3D tiles”, and create a separate buffer geometry for every tile.)
- Then iterate through all the objects player can collide with on the scene. For each object, use Box3 to calculate a bounding box, then push 4 vertices of that bounding box into the collision buffer (you can also use bounding spheres / capsules - the point is just to simplify the collisions and not duplicate entire mesh geometries into the navmesh.)
(3) Mind, navmaps are good mostly for static things, like terrain - generating and updating a navmap to include dynamic objects, on every frame, will likely lead to a worse performance than actually blindly iterating through all scene objects, and just raycasting each one.
(Also quite sure there’s got to be a ready solution for you somewhere on github - take a look at mugen87/yuka, gkjohnson/three-mesh-bvh, there’s also this collision example.)