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; } }