Terrain Pick

Hi, I'm trying to pick a terrain page using the mouse. I want to get hold of the Vector in the terrain that has been picked. My code looks like this:


Ray ray = new Ray(cam.getLocation(), cam.getDirection());
       results = new TrianglePickResults();
       results.setCheckDistance(true);
       terrain.findPick(ray, results);



I get results but the Vector is not what I would expect. I use this code to get the picked Vector:

results.getPickData(0).getTargetMesh().getLocalTranslation();



I've noticed on other posts a getParentGeom() method, but that method doesn't seem to be in JME anymore! How can I get hold terrain Vectors that have been picked by the mouse?

Thanks.

Your TerrainPage Node creates a bunch of smaller TerrainPages and eventually TerrainBlock TriMeshes when it is created, what your current method is returning is the Translation of the Triangle Batch of the TerrainBlock that the ray goes through, I believe.  Do you really just want the translation of this mesh or do you actually want the displacement vector of the point of intersection the ray has with the terrain?  Because it would seem to me that you would readily have available the translation information. 



The intersection point (if that's what your looking for) is found as follows:




         ArrayList<Integer> tris = results.getPickData(0).getTargetTris();
                        Vector3f loc;
         if(tris.size() > 0){
            Vector3f[] verts = new Vector3f[3];
            ((TriangleBatch)results.getPickData(0).getTargetMesh()).getTriangle(tris.get(0).intValue(), verts);
            Vector3f[] vert = new Vector3f[3];
            Triangle t = new Triangle(vert[0], vert[1], vert[2]);
            loc = new Vector3f();
            ray.intersectWhere(t, loc);
         }



And that will put the point of intersection into the Vector3f loc.

I've tried this code but I don't have a TriangleBatch class. It doesn't seem to exist in JME! All I want to do is get the point of terrain that the mouse is over, but it looks like whats being returned is the terrains bounding box or something. Surely there is a simple way of picking the terrain?

I've figured it out now  :wink: Here is the code that works should anyone else be wanting to do a similar thing.



public void onMove(int xDelta, int yDelta, int newX, int newY) {
       Vector2f screenPos = new Vector2f(newX, newY);
       Vector3f startPoint = DisplaySystem.getDisplaySystem().getWorldCoordinates(screenPos, 0);
       Vector3f endPoint = DisplaySystem.getDisplaySystem().getWorldCoordinates(screenPos, 1);
       Ray ray = new Ray(startPoint, endPoint.subtract(startPoint));
      
       results = new TrianglePickResults();
       results.setCheckDistance(true);
       terrain.findPick(ray, results);
      
       Vector3f loc = new Vector3f();
       Vector3f[] vertex = new Vector3f[3];
       boolean foundMeshHit = false;
       if(results.getNumber() > 0) {
      TriMesh mesh = (TriMesh) results.getPickData(0).getTargetMesh();
      
      for(int j=0; j<mesh.getTriangleCount(); j++) {
          mesh.getTriangle(j, vertex);
          foundMeshHit = (ray.intersectWhere(
             vertex[0].addLocal(mesh.getWorldTranslation()),
             vertex[1].addLocal(mesh.getWorldTranslation()),
             vertex[2].addLocal(mesh.getWorldTranslation()), loc));
         
          if(foundMeshHit) {
         //translate your object to loc
          }
      }
       }
}


I've always wondered why something so widely used as terrain picking isn't implemented in jME itself.  Why does everyone who needs this feature need to either reinvent the wheel or use posted solutions?  After some searching here you'll find a few different implementations - which of these should the average person use?



I guess my comment/question is: "Why isn't this in jME as a simple function?"



I could understand the argument that there are people who use it for other purposes, but this comes up so often that I'm just confused.



ArrayList<Integer> tris = results.getPickData(0).getTargetTris();
Vector3f loc;
if(tris.size() > 0){
Vector3f[] verts = new Vector3f[3];
((TriangleBatch)results.getPickData(0).getTargetMesh()).getTriangle(tris.get(0).intValue(), verts);
...


TriMesh maybe? I wasn't able to work this out, but the one wolfgang posted worked with my code.  Thanks, it saved me some time trying to figure it out. 

Cheers  :D

Hello Good People!



I’m new to jme, found this thread while looking for something related and couldn’t resist asking any longer…

Namely, I would like my NPCs to do a bit of pathfinding, therefore I would like to feed them with some knowledge of terrain. Since I’m using a TerrainQuad generated from heightmap, I need a way to extract some pieces of info. After beating around the bush for a while I thought of raytesting. Is that a way to go? If so, does it make for a way good enough?



Bests,

Tomek

Yes, to get the actual height/location of a spot on the terrain, best use picking. For general pathfinding etc. theres lots of solutions out there, the most used is the A* (A-star) algorithm.

1 Like

There is also a fast method to get the elevation of the terrain at a specific point: terrain.getHeight(x,z). This is useful for resting an object on top of the terrain.



woa this thread is 2 years old :stuck_out_tongue:

1 Like

Thanks you guys very much. I overlooked something utterly obvious it seems, but lesson learnt is all that counts :slight_smile: