Here is one of my TriangleUtils class (since what you’ve done is really triangle stuff and not really collision stuff, stylistically speaking):
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Format;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.mesh.IndexBuffer;
import com.jme3.util.BufferUtils;
import java.nio.FloatBuffer;
/**
* Various utility methods for easily extracting different vertex
* attributes for triangle corners and then performing barycentric
* based interpolation to find the value for some intersection point.
*
* See also: https://en.wikipedia.org/wiki/Barycentric_coordinate_system
*
* @author Paul Speed
*/
public class TriangleUtils {
public static Vector4f getBarycentricInterpolation( Vector2f coord, Vector4f t0, Vector4f t1, Vector4f t2 ) {
Vector4f tv1 = t1.subtract(t0);
Vector4f tv2 = t2.subtract(t0);
Vector4f result = t0.add(tv1.mult(coord.x)).add(tv2.mult(coord.y));
return result;
}
public static Vector4f getBarycentricInterpolation( Vector2f coord, Mesh mesh, Type type, int index ) {
Vector4f t0 = new Vector4f();
Vector4f t1 = new Vector4f();
Vector4f t2 = new Vector4f();
getTriangle(mesh, type, index, t0, t1, t2);
return getBarycentricInterpolation(coord, t0, t1, t2);
}
public static Vector2f getBarycentricCoordinates( Vector3f point, Vector3f tri0, Vector3f tri1, Vector3f tri2 ) {
// Get the triangle edges and the vector to p
Vector3f v0 = tri1.subtract(tri0);
Vector3f v1 = tri2.subtract(tri0);
Vector3f v2 = point.subtract(tri0);
float dot00 = v0.dot(v0);
float dot01 = v0.dot(v1);
float dot02 = v0.dot(v2);
float dot11 = v1.dot(v1);
float dot12 = v1.dot(v2);
float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
return new Vector2f(u, v);
}
public static Vector2f getBarycentricCoordinates( Vector3f p, Mesh mesh, int index ) {
Vector3f tri0 = new Vector3f();
Vector3f tri1 = new Vector3f();
Vector3f tri2 = new Vector3f();
getTriangle(mesh, Type.Position, index, tri0, tri1, tri2);
return getBarycentricCoordinates(p, tri0, tri1, tri2);
}
public static void getTriangle( Mesh mesh, Type type, int index, Vector3f v1, Vector3f v2, Vector3f v3 ){
VertexBuffer vb = mesh.getBuffer(type);
IndexBuffer ib = mesh.getIndicesAsList();
if( vb != null && vb.getFormat() == Format.Float && vb.getNumComponents() == 3 ) {
FloatBuffer fpb = (FloatBuffer)vb.getData();
// aquire triangle's vertex indices
int vertIndex = index * 3;
int vert1 = ib.get(vertIndex);
int vert2 = ib.get(vertIndex+1);
int vert3 = ib.get(vertIndex+2);
BufferUtils.populateFromBuffer(v1, fpb, vert1);
BufferUtils.populateFromBuffer(v2, fpb, vert2);
BufferUtils.populateFromBuffer(v3, fpb, vert3);
} else {
throw new UnsupportedOperationException("Buffer not set for:" + type + " or "
+ " has incompatible format: Float * 3");
}
}
public static void getTriangle( Mesh mesh, Type type, int index, Vector4f v1, Vector4f v2, Vector4f v3 ){
VertexBuffer vb = mesh.getBuffer(type);
IndexBuffer ib = mesh.getIndicesAsList();
if( vb != null && vb.getFormat() == Format.Float && vb.getNumComponents() == 4 ) {
FloatBuffer fpb = (FloatBuffer)vb.getData();
// aquire triangle's vertex indices
int vertIndex = index * 3;
int vert1 = ib.get(vertIndex);
int vert2 = ib.get(vertIndex+1);
int vert3 = ib.get(vertIndex+2);
BufferUtils.populateFromBuffer(v1, fpb, vert1);
BufferUtils.populateFromBuffer(v2, fpb, vert2);
BufferUtils.populateFromBuffer(v3, fpb, vert3);
} else {
throw new UnsupportedOperationException("Buffer not set for:" + type + " or "
+ " has incompatible format: Float * 4");
}
}
}
Some day this will go into one of my public utility libraries with some additional methods. For example, it needs some more versions of the getBarycentricInterpolation() method to handle Vector3f, Vector2f, etc…
The general approach:
- find the barycentric coordinate for your point, for example using: getBarycentricCoordinates( Vector3f point, Vector3f tri0, Vector3f tri1, Vector3f tri2 ) passing the collision point in model space along with the triangle points.
- then use one of the getBarycentricInterpolation() to interpolate a value from some vertex attributes. For example, TexCoord (if I’d written the Vector2f version of those methods… which is mostly a cut+paste op)
These were designed to interpolate any vertex attribute because in my case I have several things I want interpolated.