Hi,
I have a planets with some agents (pursuers and evaders) going around.
I want to identify all the triangles in the mesh of the planet that are actually visible to the pursuers.
All the pursuers have a direction and a certain angle for the field of sight (center of it being the direction)
Hence I’m trying to understand what would be the best way to check if an object (so the triangle) is inside, even if partially, into the field of sight of an agent.
What I’ve tried so far is to cast 3 rays from the position of the pursuer to the vertices of each triangle, and if it is not colliding with planet, it checks if the rays are in the field of sight of the pursuer, if at least one was inside, then it would be visible.
But this does not seem to work properly, plus, if only one internal part of the triangle is visible it won’t work at all.
Screenshot
(the yellow part is the part visible, is clearly not working)
That’s what I have got so far
(The vertex from the graph are the triangles of the outer green mesh that you can see in the screenshot)
public void calculateSafeTriangles(){
for(Agent agent: agents){ //loop through all the agent
if(!(agent instanceof Pursuer)) //if it is not a pursuer just continue with the next agent
continue;
Pursuer current = (Pursuer) agent;
for(Vertex v: graph.getVertices()){ // Here vertex v refers to a vertex of the graph, not a vertex of the mesh, it stores a triangle of the mesh and its info.
v.setSafe(true); //v is set initially to true, meaning that the triangle is not visible from the pursuer
//Here it casts rays to the 3 vertices of the triangle
Ray ray1 = new Ray(current.getNodeAgent().getWorldTranslation(),v.getTriangle().get1().subtract(current.getNodeAgent().getWorldTranslation()).normalizeLocal());
Ray ray2 = new Ray(current.getNodeAgent().getWorldTranslation(),v.getTriangle().get2().subtract(current.getNodeAgent().getWorldTranslation()).normalizeLocal());
Ray ray3 = new Ray(current.getNodeAgent().getWorldTranslation(),v.getTriangle().get3().subtract(current.getNodeAgent().getWorldTranslation()).normalizeLocal());
//And it checks the collision with the planet
CollisionResults results1 = new CollisionResults();
planet.getPlanet().collideWith(ray1, results1);
CollisionResults results2= new CollisionResults();
planet.getPlanet().collideWith(ray2, results2);
CollisionResults results3 = new CollisionResults();
planet.getPlanet().collideWith(ray3, results3);
//if it does not collide with the planet, it means that could be visible
// and so checks if the ray is inside the field of sight of the pursuer
if(results1.size()==0){
if(checkInSight(current, v.getTriangle().get1())){
v.setUnsafe();
return;
}
} if(results2.size()==0){
if(checkInSight(current, v.getTriangle().get2())){
v.setUnsafe();
return;
}
} if(results3.size()==0){
if(checkInSight(current, v.getTriangle().get3())){
v.setUnsafe();
return;
}
}
}
}
}
protected boolean checkInSight(Pursuer pursuer, Vector3f point){
Vector3f cube2ToOrigin = point.add(pursuer.getNodeAgent().getWorldTranslation().mult(-1));
Vector3f direction = pursuer.getNodeAgent().getWorldRotation().getRotationColumn(2);
double angle = getAngle(direction, cube2ToOrigin);
if (angle > Math.toRadians(pursuer.getField_of_sight()/2)) {
return false;
}
return true;
}
protected double getAngle(Vector3f v1, Vector3f v2){
double dot = v1.dot(v2);
double lenghtprod = v1.length()*v2.length();
double result = dot / lenghtprod;
return Math.acos(result);
}
Any hint?