Renderer/src/main/java/electrosphere/collision/CollisionBodyCreation.java
2023-11-05 12:28:19 -05:00

162 lines
5.5 KiB
Java

package electrosphere.collision;
import java.nio.IntBuffer;
import org.joml.Vector3d;
import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIFace;
import org.lwjgl.assimp.AIMesh;
import org.lwjgl.assimp.AIScene;
import org.lwjgl.assimp.AIVector3D;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DBox;
import org.ode4j.ode.DCylinder;
import org.ode4j.ode.DSphere;
import org.ode4j.ode.DTriMesh;
import electrosphere.entity.types.terrain.TerrainChunkData;
/**
* Utilities for creating types of rigid bodies
*/
public class CollisionBodyCreation {
//The width of a plane rigid body
//It's really a box under the hood
static final double PLANE_WIDTH = 0.3;
/**
* Creates a plane DBody. Dimensions x and z control the length and width of the plane;
* @param dimensions The dimensions of the plane
* @return The DBody
*/
public static DBody createPlaneBody(CollisionEngine collisionEngine, Vector3d dimensions){
DBox geom = collisionEngine.createCubeGeom(new Vector3d(dimensions.x,PLANE_WIDTH,dimensions.z));
return collisionEngine.createDBody(geom);
}
/**
* Creates a cube DBody. Dimensions controlled by the dimensions vector.
* @param collisionEngine The collision engine to create the body inside of
* @param dimensions The dimensions of the cube
* @return The DBody
*/
public static DBody createCubeBody(CollisionEngine collisionEngine, Vector3d dimensions){
DBox geom = collisionEngine.createCubeGeom(new Vector3d(dimensions));
return collisionEngine.createDBody(geom);
}
/**
* Creates a cylinder DBody. Dimensions controlled by the dimensions vector.
* @param collisionEngine The collision engine to create the body inside of
* @param dimensions The dimensions of the cube
* @return The DBody
*/
public static DBody createCylinderBody(CollisionEngine collisionEngine, double radius, double length){
DCylinder geom = collisionEngine.createCylinderGeom(radius,length);
return collisionEngine.createDBody(geom);
}
/**
* Creates a sphere body in the collision engine
* @param collisionEngine The collision engine
* @param radius The radius of the sphere
* @return The DBody
*/
public static DBody createSphereBody(CollisionEngine collisionEngine, double radius){
DSphere geom = collisionEngine.createSphereGeom(radius);
return collisionEngine.createDBody(geom);
}
/**
* Creates an ode DBody from a terrain chunk data object
* @param data The terrain data
* @return The DBody
*/
public static DBody generateBodyFromTerrainData(CollisionEngine collisionEngine, TerrainChunkData data){
DBody body = null;
//create data
int numberTriangles = data.getFaceElements().size() / 3;
int numberVertices = data.getVertices().size() / 3;
float[] vertices = new float[numberVertices * 3];
int vertexInserterPos = 0;
int[] indices = new int[numberTriangles * 3];
int indexInserterPos = 0;
for(float vertexValue : data.getVertices()){
vertices[vertexInserterPos] = vertexValue;
vertexInserterPos++;
}
for(int element : data.getFaceElements()){
indices[indexInserterPos] = element;
indexInserterPos++;
}
//create trimesh
if(vertices.length > 0){
DTriMesh triMesh = collisionEngine.createTrimeshGeom(vertices,indices);
body = collisionEngine.createDBody(triMesh);
}
return body;
}
/**
* Generates a body from an AIScene
* @param scene The AIScene to generate a rigid body off of
* @return A rigid body based on the AIScene
*/
public static DBody generateRigidBodyFromAIScene(CollisionEngine collisionEngine, AIScene scene){
DBody body = collisionEngine.createDBody(null);
PointerBuffer meshesBuffer = scene.mMeshes();
while(meshesBuffer.hasRemaining()){
float[] verts;
int numVertices;
int[] indices;
int numTriangles;
AIMesh aiMesh = AIMesh.create(meshesBuffer.get());
//allocate array for vertices
numVertices = aiMesh.mNumVertices();
verts = new float[numVertices * 3];
//read vertices
AIVector3D.Buffer vertexBuffer = aiMesh.mVertices();
int vertPos = 0;
while(vertexBuffer.hasRemaining()){
AIVector3D vector = vertexBuffer.get();
verts[vertPos+0] = vector.x();
verts[vertPos+1] = vector.y();
verts[vertPos+2] = vector.z();
vertPos = vertPos + 3;
}
numTriangles = aiMesh.mNumFaces();
indices = new int[numTriangles * 3];
int indicesPos = 0;
//read faces
AIFace.Buffer faceBuffer = aiMesh.mFaces();
while(faceBuffer.hasRemaining()){
AIFace currentFace = faceBuffer.get();
IntBuffer indexBuffer = currentFace.mIndices();
while(indexBuffer.hasRemaining()){
int index = indexBuffer.get();
indices[indicesPos] = index;
indicesPos++;
}
}
DTriMesh meshGeom = collisionEngine.createTrimeshGeom(verts, indices);
meshGeom.setBody(body);
}
return body;
}
}