Ray collision detection returns seemingly incorrect Vector3f Y value
Background:
I am working on placing forests and cities on maps that I randomly generate. In order to tell where to spawn the tree / building models, I use a 2D coordinate (x,z) and have a ray try to collide with my terrain object to determine the correct y value.
My code (in my Main class that extends SimpleApplication)
public Vector3f coordinateOf(int x, int y)
{
CollisionResults results = new CollisionResults();
Ray ray = new Ray(new Vector3f(x, 1_000_000, y), new Vector3f(0, -1, 0));
geography.collideWith(ray, results);
float height = -1;
if(results.size() > 0)
{
height = results.getClosestCollision().getContactPoint().y;
return new Vector3f(x, height, y);
}
return null;
}
geography is a Node with only one child, which is my terrain object.
As expected, the method returns a vector every time I pass an (x,z) value within the bounds of my terrain. However, every once in a while it will return what seems to be an invalid y value, placing the object below the terrian. (Almost always or always at y = 0.0f)
Here is the code calling Main. coordinateOf(int x, int y) :
Main.buildMap() //to place trees
...
for(int i = 0; i < forestNum; i++)
{
Vector3f treeLoc = null;
while(treeLoc == null || (Runner.allowWater() && treeLoc.y < baseHeight))
{
int x = gen.nextInt(MAP_SIZE) - (int) (.5f * MAP_SIZE);
int z = gen.nextInt(MAP_SIZE) - (int) (.5f * MAP_SIZE);
treeLoc = coordinateOf(x, z);
}
trees.add(new Tree(assetManager, rootNode, bulletAppState, treeLoc, 1, false));
}
…
Main.placeVillages() //Sets the center of a village, where I place a castle
…
while(loc == null || loc.y < baseHeight)
{
final int RANGE = 100;
int x = baseX + RandomNumber.randomInt(-RANGE, RANGE);
int z = baseZ + RandomNumber.randomInt(-RANGE, RANGE);
loc = coordinateOf(x, z);
}
…
and Village.getValidSpawn() //get placement for buildings, player, and NPCs,
{
Vector3f loc = null;
float d = FastMath.sqrt(2);
boolean valid = false;
while(loc == null || !valid)
{
int x = (int) (center.x + RandomNumber.randomInt((int) (-villageRadius / d), (int) (villageRadius / d)));
int z = (int) (center.z + RandomNumber.randomInt((int) (-villageRadius / d), (int) (villageRadius / d)));
loc = main.coordinateOf(x, z);
valid = true;
if(loc != null)
{
if(Runner.allowWater() && loc.y < main.waterHeight())
{
valid = false;
}
for(ArrayList<Building> buildingArray : buildings)
{
for(Building b : buildingArray)
{
float distance = b.loc().distance(loc);
if(distance < b.repel)
{
valid = false;
}
}
}
}
}
return loc;
}
The vast majority of trees (probably around 99%) spawn properly. The majority of buildings and NPCs (and the player) also do, but with more frequent errors. Castle placement in Main.placeVillages() never has given incorrect results, but I also spawn few castles.
The code does not throw any Exceptions, and otherwise runs as expected.
FYI—I have a screenshot, but it won’t let me upload now. I’ll try again later.
I also am aware of the former errors in the Node.collideWith function, but since these were fixed in 2016, and since I downloaded the 3.1.0 stable version released in 2017, I do not think these apply to my code (but I may be wrong).
Does anyone has an idea as to how to fix this problem?
Thanks in advance!