TerrainQuad.getHeight occasionally 0 (ray collision result exists, but wrong)?

Hi.

I’m having this problem since I started my terrain height following scrollable camera project… TerrainQuad.getHeight relatively often return zero. First I thought the ray collision didn’t happen or I provided wrong coordinates or whatever, but the collision works in all cases… only the result seems to be faulty. I pinned the TerrainQuad.java with a few sysouts to see what’s going on.

[java]TerrainQuad.java

protected float getHeight(float x, float z, Vector2f xz)

{

System.out.println(“tprotected TerrainQuad.getHeight(” + x + ", " + z + ", " + xz + “)”);



if (num > 0)

{

System.out.println(“t” + num + " ray collision(s): height = "

  • cr.getClosestCollision().getContactPoint().y);

    return cr.getClosestCollision().getContactPoint().y;

    }

    System.out.println(“tno ray collision -> height = 0”);

    return 0;[/java]

    Here’s the snippet of the log:

    public TerrainQuad.getHeight((1.5, 99.0))

    protected TerrainQuad.getHeight(258.0, 355.5, (1.5, 99.0))

    1 ray collision(s): height = 44.62378

    public TerrainQuad.getHeight((0.99999994, 99.0))

    protected TerrainQuad.getHeight(257.5, 355.5, (0.99999994, 99.0))

    1 ray collision(s): height = 44.552868

    public TerrainQuad.getHeight((0.49999988, 99.0))

    protected TerrainQuad.getHeight(257.0, 355.5, (0.49999988, 99.0))

    1 ray collision(s): height = 44.413696

    public TerrainQuad.getHeight((-1.7881393E-7, 99.0))

    protected TerrainQuad.getHeight(256.5, 355.5, (-1.7881393E-7, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-0.50000024, 99.0))

    protected TerrainQuad.getHeight(256.0, 355.5, (-0.50000024, 99.0))

    1 ray collision(s): height = 44.11102

    public TerrainQuad.getHeight((-1.0000002, 99.0))

    protected TerrainQuad.getHeight(255.5, 355.5, (-1.0000002, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-1.5000002, 99.0))

    protected TerrainQuad.getHeight(255.0, 355.5, (-1.5000002, 99.0))

    1 ray collision(s): height = 43.822563

    public TerrainQuad.getHeight((-2.0000002, 99.0))

    protected TerrainQuad.getHeight(254.5, 355.5, (-2.0000002, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-2.5000002, 99.0))

    protected TerrainQuad.getHeight(254.0, 355.5, (-2.5000002, 99.0))

    1 ray collision(s): height = 43.568146

    public TerrainQuad.getHeight((-3.0000002, 99.0))

    protected TerrainQuad.getHeight(253.5, 355.5, (-3.0000002, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-3.5000002, 99.0))

    protected TerrainQuad.getHeight(253.0, 355.5, (-3.5000002, 99.0))

    1 ray collision(s): height = 43.318188

    public TerrainQuad.getHeight((-4.0000005, 99.0))

    protected TerrainQuad.getHeight(252.5, 355.5, (-4.0000005, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-4.5000005, 99.0))

    protected TerrainQuad.getHeight(252.0, 355.5, (-4.5000005, 99.0))

    1 ray collision(s): height = 43.10566

    public TerrainQuad.getHeight((-5.0000005, 99.0))

    protected TerrainQuad.getHeight(251.5, 355.5, (-5.0000005, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-5.5000005, 99.0))

    protected TerrainQuad.getHeight(251.0, 355.5, (-5.5000005, 99.0))

    1 ray collision(s): height = 42.958344

    public TerrainQuad.getHeight((-6.0000005, 99.0))

    protected TerrainQuad.getHeight(250.5, 355.5, (-6.0000005, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-6.5000005, 99.0))

    protected TerrainQuad.getHeight(250.0, 355.5, (-6.5000005, 99.0))

    1 ray collision(s): height = 42.848095

    public TerrainQuad.getHeight((-7.0000005, 99.0))

    protected TerrainQuad.getHeight(249.5, 355.5, (-7.0000005, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-7.5000005, 99.0))

    protected TerrainQuad.getHeight(249.0, 355.5, (-7.5000005, 99.0))

    1 ray collision(s): height = 42.74283

    public TerrainQuad.getHeight((-8.000001, 99.0))

    protected TerrainQuad.getHeight(248.5, 355.5, (-8.000001, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-8.500001, 99.0))

    protected TerrainQuad.getHeight(248.0, 355.5, (-8.500001, 99.0))

    1 ray collision(s): height = 42.64039

    public TerrainQuad.getHeight((-9.000001, 99.0))

    protected TerrainQuad.getHeight(247.5, 355.5, (-9.000001, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-9.500001, 99.0))

    protected TerrainQuad.getHeight(247.0, 355.5, (-9.500001, 99.0))

    1 ray collision(s): height = 42.507835

    public TerrainQuad.getHeight((-10.000001, 99.0))

    protected TerrainQuad.getHeight(246.5, 355.5, (-10.000001, 99.0))

    1 ray collision(s): height = 0.0

    public TerrainQuad.getHeight((-10.500001, 99.0))

    protected TerrainQuad.getHeight(246.0, 355.5, (-10.500001, 99.0))

    1 ray collision(s): height = 42.312305

    public TerrainQuad.getHeight((-11.003126, 99.0))

    protected TerrainQuad.getHeight(245.49687, 355.5, (-11.003126, 99.0))

    1 ray collision(s): height = 42.196392

    public TerrainQuad.getHeight((-11.503126, 99.0))

    protected TerrainQuad.getHeight(244.99687, 355.5, (-11.503126, 99.0))

    1 ray collision(s): height = 42.06878

    public TerrainQuad.getHeight((-12.003126, 99.0))

    protected TerrainQuad.getHeight(244.49687, 355.5, (-12.003126, 99.0))

    1 ray collision(s): height = 41.94112

    public TerrainQuad.getHeight((-12.503126, 99.0))

    protected TerrainQuad.getHeight(243.99687, 355.5, (-12.503126, 99.0))

    1 ray collision(s): height = 41.805573


    As you can see, there are spots the collision detection simply seems to fail. It’s not always alternating in such a beautiful way. Sometimes the “holes” are huge too. I tried with and without my TerrainLodControl but results don’t seem to change. Is this a known problem? Might I be doing something wrong again? I’m not familiar with the way ray collision works, but I guess it shouldn’t be possible to fail except there is indeed no collision? Here’s the code that request the height.

    [java]ScrollCamera.java

    public void update(float tpf)

    {

    if (!this.enabled)

    return;

    if (this.isPressed(ScrollCamera.SCROLL_UP))

    {

    this.moveCamera(1f, false, tpf);

    }

    if (this.isPressed(ScrollCamera.SCROLL_DOWN))

    {

    this.moveCamera(-1f, false, tpf);

    }

    if (this.isPressed(ScrollCamera.SCROLL_LEFT))

    {

    this.moveCamera(1f, true, tpf);

    }

    if (this.isPressed(ScrollCamera.SCROLL_RIGHT))

    {

    this.moveCamera(-1f, true, tpf);

    }

    if (this.updateTransform)

    {

    this.updateTransform = false;

    this.updateTransformDontCallDirectly();

    }

    }

    protected void updateTransformDontCallDirectly()

    {

    if (!this.enabled)

    return;

    Vector3f lookAt = new Vector3f(this.location.x, 0, this.location.y);

    if (Client.getInstance().getMap() != null)

    {

    lookAt.y = Client.getInstance().getMap().getHeight(this.location); // <==================================

    }

    Vector3f loc = new Vector3f(0, this.height, this.distance);

    Quaternion rot = new Quaternion().fromAngleAxis(this.rotation, Vector3f.UNIT_Y);

    loc = rot.mult(loc).addLocal(lookAt);

    Camera cam = Client.getInstance().getCamera();

    cam.setLocation(loc);

    cam.lookAt(lookAt, Vector3f.UNIT_Y);

    }[/java]

    [java]Map.java

    public float getHeight(Vector2f xz)

    {

    if (this.terrain == null)

    {

    return 0;

    }

    return this.terrain.getHeight(xz); // <=======================================================

    }[/java]

Okay - my current workaround is as follows:

[java]Map.java

public float getHeight(Vector2f xz)

{

if (this.terrain == null)

{

return 0;

}

float height = this.terrain.getHeight(xz);

int attempts = 0;

while (height == 0)

{

// TODO fix Map.getHeight()

// BUG(?) WORKAROUND

// re-attempt height check by moving the coords towards center a

// few millimeters

attempts++;

Logger.getLogger("").log(Level.WARNING, “Map.getHeight() re-attempt #” + attempts);

xz.x += FastMath.nextRandomFloat() * xz.x > 0 ? -.01f : .01f;

xz.y += FastMath.nextRandomFloat() * xz.y > 0 ? -.01f : .01f;

height = this.terrain.getHeight(xz);

}

return height;

}[/java]

Attempts never exceeded 1 so far! Still, this workaround sucks. Ideas?



I just tested simply repeating getHeight without displacing the coords a little. Doesn’t work, creates an infinite loop as expected. Anyway, I was curious.

See http://hub.jmonkeyengine.org/groups/contribution-depot-jme3/forum/topic/terrainquad-getheight-wrong-interpolation/

I’ve read this post way before but I’m not sure if it has to do with the problem. The only thing I can imagine is that the interpolation result (which is still calculated) is sometimes so wrongly low, that the ray doesn’t start above the terrain and therefore results in a height of 0. But as I said, I doubt it. I don’t think they ray collision would even exist in that case.