I've coded the steep method too… of course I'm sharing it with you.
public boolean hillTooSteep(Vector3f origin, Vector3f goal) {
Vector3f intersection = new Vector3f();
Ray ray = new Ray(origin, goal)
PickResults results = new TrianglePickResults();
// Use the ray to find all the models on the player's island which are hit by the ray.
results.clear();
terrainNode.findPick(ray, results);
// Find the target model in the results.
boolean found = false;
boolean hit = false;
for(int i = 0; i < results.getNumber() && found == false; i++)
{
TriMesh model = (TriMesh)results.getPickData(i).getTargetMesh().getParentGeom();
if(model.getName().equalsIgnoreCase(terrainNode.getName()))
{
found = true;
// Find the intersection where the ray hits the target's boundingBox in world
// coordinate system.
Vector3f[] vertices = new Vector3f[3];
for(int j = 0; j < model.getTriangleCount() && hit == false; j++)
{
model.getTriangle(j, vertices);
hit = ray.intersectWhere(
vertices[0].addLocal(model.getWorldTranslation()),
vertices[1].addLocal(model.getWorldTranslation()),
vertices[2].addLocal(model.getWorldTranslation()), intersection);
}
}
}
// If the target cannot be found or the ray does not hit the target, return false.
if(found == false || hit == false)
{
return false;
}
return Distance.distance(characterNode.getLocalTranslation(), intersection) <= MAX_STEEP
}
as i promised, this is the updated version specifically working with model terrains.
/**
* Find the intersection of the ray passed in and the given island's nearest model from the origin
* of the ray. The returned value is either in the island's local coordinate system or the world
* coordinate system determined by the localCoordinateSystem boolean value passed in. If there is
* no intersection found, return null.
* @param ray The ray defines the direction of searching.
* @param island The island that is searching from.
* @param localCoordinateSystem The boolean value indicates if the returned value should be in the
* island's local coordinate system or the world coordinate system.
* @return A Vector3f which defines the intersection point.
*/
public static Vector3f findIntersection(Ray ray, Island island, boolean localCoordinateSystem) {
Vector3f intersection = new Vector3f();
PickResults results = new TrianglePickResults();
results.setCheckDistance(true);
// Find all the models on the island which are hit by the ray.
island.getModelNode().findPick(ray, results);
// Find the intersection where the ray hits the nearest model in world coordinate system.
if(results.getNumber() > 0)
{
boolean hit = false;
TriMesh model = (TriMesh)results.getPickData(0).getTargetMesh().getParentGeom();
ArrayList triangles = results.getPickData(0).getTargetTris();
Vector3f[] vertices = new Vector3f[3];
// If there are triangles hit, get the nearest triangle and find the intersection.
if(triangles.size() > 0)
{
model.getTriangle(((Integer)triangles.get(0)).intValue(), vertices);
hit = ray.intersectWhere(
vertices[0].multLocal(model.getWorldScale()).addLocal(model.getWorldTranslation()),
vertices[1].multLocal(model.getWorldScale()).addLocal(model.getWorldTranslation()),
vertices[2].multLocal(model.getWorldScale()).addLocal(model.getWorldTranslation()), intersection);
}
// Return the intersection in different coordinate system based on the given boolean value.
if(hit && localCoordinateSystem)
{
return intersection.subtractLocal(model.getWorldTranslation());
}
else if(hit && !localCoordinateSystem)
{
return intersection;
}
}
// If there is no intersection found, return null.
return null;
}
i made a bug in the collision detection method. im sry if it caused u any problems.
heres the corrected one.
/**
* Find the intersection of the ray passed in and the given island's nearest model from the origin
* of the ray. The returned value is either in the island's local coordinate system or the world
* coordinate system determined by the localCoordinateSystem boolean value passed in. If there is
* no intersection found, return null.
* @param ray The ray defines the direction of searching.
* @param island The island that is searching from.
* @param localCoordinateSystem The boolean value indicates if the returned value should be in the
* island's local coordinate system or the world coordinate system.
* @return A Vector3f which defines the intersection point.
*/
public static Vector3f findIntersection(Ray ray, Island island, boolean localCoordinateSystem) {
Vector3f intersection = new Vector3f();
TrianglePickResults results = new TrianglePickResults();
results.setCheckDistance(true);
// Find all the models on the island which are hit by the ray.
island.getModelNode().findPick(ray, results);
// Find the intersection where the ray hits the nearest model in world coordinate system.
if(results.getNumber() > 0)
{
boolean hit = false;
TriMesh model = (TriMesh)results.getPickData(0).getTargetMesh().getParentGeom();
ArrayList triangles = results.getPickData(0).getTargetTris();
Vector3f[] vertices = new Vector3f[3];
// If there are triangles hit, get the nearest triangle and find the intersection.
if(triangles.size() > 0)
{
model.getTriangle(((Integer)triangles.get(0)).intValue(), vertices);
hit = ray.intersectWhere(
vertices[0].multLocal(model.getWorldScale()).addLocal(model.getWorldTranslation()),
vertices[1].multLocal(model.getWorldScale()).addLocal(model.getWorldTranslation()),
vertices[2].multLocal(model.getWorldScale()).addLocal(model.getWorldTranslation()), intersection);
}
// Return the intersection in different coordinate system based on the given boolean value.
if(hit && localCoordinateSystem)
{
island.worldToLocal(intersection, intersection);
return intersection;
}
else if(hit && !localCoordinateSystem)
{
return intersection;
}
}
// If there is no intersection found, return null.
return null;
}
public void walking(){
this.loc.addLocal(this.player.getLocalRotation().getRotationColumn(2).multLocal(0.49f));
this.player.setLocalTranslation(this.loc);
Thank you very much for all the methods, I'm going to examine them as soon as I get my source code readable again (I had to decompile it because I accidentally deleted the sources).
I've tested the methods (finally) and it seems that they don't get any pick results (It returns an empty array). This throws an arrayoutofbounds. Can anyone tell me how to fix this?
PS method's I'm using included below:
public void setTerrain(Terrain terrain) {
terrainNode = terrain;
this.getLocalTranslation().y = getCollisionPoint(this.getLocalTranslation());
}
public float getCollisionPoint(Vector3f goal) {
Vector3f intersection = new Vector3f();
gravityRay = new Ray(goal, tempVector.set(goal.x, goal.y -1f, goal.z));
// Use the ray to find all the models on the player's island which are hit by the ray.
gravityResults.clear();
terrainNode.findPick(gravityRay, gravityResults);
// Find the target model in the results.
boolean found = false;
boolean hit = false;
//for(int i = 0; i < gravityResults.getNumber() && found == false; i++)
//{
TriMesh model = (TriMesh)gravityResults.getPickData(0).getTargetMesh().getParentGeom();
/*if(model.getName().equalsIgnoreCase(terrainNode.getName()))
{*/
found = true;
// Find the intersection where the ray hits the target's boundingBox in world
// coordinate system.
Vector3f[] vertices = new Vector3f[3];
for(int j = 0; j < model.getTriangleCount() && hit == false; j++)
{
model.getTriangle(j, vertices);
hit = gravityRay.intersectWhere(
vertices[0].addLocal(model.getWorldTranslation()),
vertices[1].addLocal(model.getWorldTranslation()),
vertices[2].addLocal(model.getWorldTranslation()), intersection);
}
//}
//}
// If the target cannot be found or the ray does not hit the target, return null.
if(found == false || hit == false)
return 0;
// Return the intersection.
return intersection.y;
}