Collision ray seems to miss TerrainQuad

Hi,



In some instances a collision with a simple scene seems to miss the TerrainQuad. If the collisions is performed a mere pixel in any direction of this miss, the CollisionResults contains the TerrainQuad. I have attached a test class which reproduces the bug.



The test loads a TerrainQuad from file. This has to be placed in the working directory and can be downloaded from http://www.tygron.nl/download/terrain.bin



A System.out.println displays the amount of entries in the CollisionResults based on the camera’s location and direction. The default setup should have the camera pointing at the terrain at a location and direction that misses the terrain. Try moving the camera to see that it changes if minor changes are made to both direction and location.



[java]

package test;



import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

import com.jme3.app.SimpleApplication;

import com.jme3.asset.AssetInfo;

import com.jme3.collision.CollisionResults;

import com.jme3.export.JmeImporter;

import com.jme3.export.binary.BinaryImporter;

import com.jme3.light.DirectionalLight;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Ray;

import com.jme3.math.Vector3f;

import com.jme3.terrain.geomipmap.TerrainQuad;



public class TestCollisionBug extends SimpleApplication {



public static void main(String… strings) {

new TestCollisionBug().start();

}



private final Vector3f origin = new Vector3f(-277.81775f, 130.0f, 436.53714f);

private final Vector3f direction = new Vector3f(-0.23736148f, -0.64039016f, -0.73045194f);;

private TerrainQuad terrain;

private final CollisionResults results = new CollisionResults();

private Ray ray;



private void loadTerrainFromFile() {

AssetInfo info = new AssetInfo(assetManager, null) {



@Override

public InputStream openStream() {

File file = new File(“terrain.bin”);

try {

return new FileInputStream(file);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

return null;

}

};



JmeImporter importer = new BinaryImporter();

try {

terrain = (TerrainQuad) importer.load(info);

} catch (IOException e) {

e.printStackTrace();

}

}



/*

  • (non-Javadoc)
  • @see com.jme3.app.SimpleApplication#simpleInitApp()

    */

    @Override

    public void simpleInitApp() {



    loadTerrainFromFile();



    rootNode.attachChild(terrain);



    viewPort.getCamera().setLocation(origin);

    viewPort.getCamera().lookAtDirection(direction, Vector3f.UNIT_Y);



    DirectionalLight dl = new DirectionalLight();

    dl.setColor(ColorRGBA.White);

    dl.setDirection(new Vector3f(0, -1, -1));

    rootNode.addLight(dl);



    ray = new Ray(viewPort.getCamera().getLocation(), viewPort.getCamera().getDirection());

    }



    @Override

    public void simpleUpdate(float tpf) {

    ray.setOrigin(viewPort.getCamera().getLocation());

    ray.setDirection(viewPort.getCamera().getDirection());



    results.clear();

    rootNode.collideWith(ray, results);



    System.out.println("Collision result amount: " + results.size());

    }

    }

    [/java]
2 Likes

I this alpha-4? It had a bug where the result would be null if the ray way cast perfectly perpendicular to the terrain.

I just updated to the most recent svn version (I believe it’s 8121). The collision is also not perpendicular to the terrain. How can I check whether the collision might be perpendicular to the triangle it’s hitting?

It should only matter if its perpendicular to the terrain geometry object, the mesh data should be of no concern. Without an actual collision report its hard to tell the collision normal :wink: I guess its @Sploreg having to check out your test case then.

I’ve dug into the picking algorithm. It detects collision with the TerrainPath all the way down until it checks for collision with the Patch’s bounding volume. It checks whether the volume is notEntirelyClipped, which returns false.

I will run your test today and see. The issue with it being perpendicular was fixed a long time ago, so it might be a particular edge case that is being missed.

ok I tracked down the issue.

The problem arises when the terrain is flat, then its bounding box has zero volume and doesn’t intersect. So I am adding in a check to see if the yExtent of the bounding box is zero, and if it is, pad it a bit so it will have a volume.

So far with my testing here it is now intersecting everywhere with your sample file.



Thanks for finding this JWar, and especially thank you for providing a test case and data! It makes debugging much easier.



I should have this committed in the morning after a little more testing.

3 Likes

Thanks for reacting so quickly. We’re looking forward to the fix!

it’s committed now, giv’er a try

I just updated and the bug still seems to be there. When I run the test case it also still returns 0 collisions in its default state.

damn. I even tested it a lot too. But today it is failing for me as well.

I just committed a fix for it again, let me know if it is working for you.

Don’t know if this helps, but I can report that I get no height value when I send a ray straight down in the initial position [0,0] on a terraingrid, while getheightmapheight returns correct value for that pos. Is the problem that a ray is being sent exactly between two triangles?

normen said:
I this alpha-4? It had a bug where the result would be null if the ray way cast perfectly perpendicular to the terrain.

Perpendicular picking is returning a collision, so this might be something in TerrainGrid you are seeing.

@normen : As far as my amateur math-skills go a ray is not perpendicular to the terrain if it is cast between the triangles that build up the terrain, it’s perpendicular if the terrain is flat and the ray is cast straight down. I doubt a terrain built up with fractals is flat, although theoretically it can happen, but this would also assume that @sploreg did not fix the bounding box issue for some very specific situation.

I set every value on the terrain to the same value, still I can return the height with a ray without problems.

@sploreg : ok, i’ll try to look into it, although it’s not a problem at all after the interpolation fix.

I just tested with perfectly flat terrain and it collides fine with a perpendicular ray. I have not yet tried this with TerrainGrid however, so there could be a separate issue with that.

I’ve tested perpendicular ray with terraingrid, works fine, just not in position [0,0]

sorry, I meant I tested perpendicular at [0,0] and it was fine with TerrainQuad

It seems to be working now. I’ll give you an update on how the experience is after the team has worked with it for a week, ok?