Sfoglia il codice sorgente

Animated model loading merged into Loader class

Tankernn 8 anni fa
parent
commit
b9ef0b66dc

+ 15 - 0
src/main/java/eu/tankernn/gameEngine/animation/animatedModel/Joint.java

@@ -6,6 +6,7 @@ import java.util.List;
 import org.lwjgl.util.vector.Matrix4f;
 
 import eu.tankernn.gameEngine.animation.animation.Animator;
+import eu.tankernn.gameEngine.loader.colladaLoader.JointData;
 
 /**
  * 
@@ -65,6 +66,20 @@ public class Joint {
 		for (Joint j : joint.children)
 			this.children.add(new Joint(j));
 	}
+	
+	/**
+	 * Constructs the joint-hierarchy skeleton from the data extracted from the
+	 * collada file.
+	 * 
+	 * @param data
+	 *            - the joints data from the collada file for the head joint.
+	 * @return The created joint, with all its descendants added.
+	 */
+	public Joint(JointData data) {
+		this(data.index, data.nameId, data.bindLocalTransform);
+		for (JointData child : data.children)
+			this.addChild(new Joint(child));
+	}
 
 	/**
 	 * Adds a child joint to this joint. Used during the creation of the joint

+ 0 - 73
src/main/java/eu/tankernn/gameEngine/animation/loaders/AnimatedModelLoader.java

@@ -1,73 +0,0 @@
-package eu.tankernn.gameEngine.animation.loaders;
-
-import eu.tankernn.gameEngine.animation.animatedModel.AnimatedModel;
-import eu.tankernn.gameEngine.animation.animatedModel.Joint;
-import eu.tankernn.gameEngine.loader.colladaLoader.AnimatedModelData;
-import eu.tankernn.gameEngine.loader.colladaLoader.ColladaLoader;
-import eu.tankernn.gameEngine.loader.colladaLoader.JointData;
-import eu.tankernn.gameEngine.loader.colladaLoader.JointsData;
-import eu.tankernn.gameEngine.loader.colladaLoader.MeshData;
-import eu.tankernn.gameEngine.loader.textures.ModelTexture;
-import eu.tankernn.gameEngine.renderEngine.Vao;
-import eu.tankernn.gameEngine.util.InternalFile;
-
-public class AnimatedModelLoader {
-	
-	public static final int MAX_WEIGHTS = 3;
-
-	/**
-	 * Creates an AnimatedEntity from the data in an entity file. It loads up
-	 * the collada model data, stores the extracted data in a VAO, sets up the
-	 * joint heirarchy, and loads up the entity's texture.
-	 * 
-	 * @param entityFile
-	 *            - the file containing the data for the entity.
-	 * @return The animated entity (no animation applied though)
-	 */
-	public static AnimatedModel loadEntity(InternalFile modelFile, ModelTexture texture) {
-		AnimatedModelData entityData = ColladaLoader.loadColladaModel(modelFile, MAX_WEIGHTS);
-		Vao model = createVao(entityData.getMeshData());
-		JointsData skeletonData = entityData.getJointsData();
-		Joint headJoint = createJoints(skeletonData.headJoint);
-		return new AnimatedModel(model, texture, headJoint, skeletonData.jointCount);
-	}
-
-	/**
-	 * Constructs the joint-hierarchy skeleton from the data extracted from the
-	 * collada file.
-	 * 
-	 * @param data
-	 *            - the joints data from the collada file for the head joint.
-	 * @return The created joint, with all its descendants added.
-	 */
-	private static Joint createJoints(JointData data) {
-		Joint joint = new Joint(data.index, data.nameId, data.bindLocalTransform);
-		for (JointData child : data.children) {
-			joint.addChild(createJoints(child));
-		}
-		return joint;
-	}
-
-	/**
-	 * Stores the mesh data in a VAO.
-	 * 
-	 * @param data
-	 *            - all the data about the mesh that needs to be stored in the
-	 *            VAO.
-	 * @return The VAO containing all the mesh data for the model.
-	 */
-	private static Vao createVao(MeshData data) {
-		Vao vao = Vao.create();
-		vao.bind();
-		vao.createIndexBuffer(data.getIndices());
-		vao.createAttribute(0, data.getVertices(), 3);
-		vao.createAttribute(1, data.getTextureCoords(), 2);
-		vao.createAttribute(2, data.getNormals(), 3);
-		vao.createAttribute(3, data.getTangents(), 3);
-		vao.createIntAttribute(4, data.getJointIds(), 3);
-		vao.createAttribute(5, data.getVertexWeights(), 3);
-		vao.unbind();
-		return vao;
-	}
-
-}

+ 90 - 49
src/main/java/eu/tankernn/gameEngine/loader/Loader.java

@@ -13,8 +13,12 @@ import org.json.JSONArray;
 import org.json.JSONObject;
 
 import eu.tankernn.gameEngine.animation.animatedModel.AnimatedModel;
-import eu.tankernn.gameEngine.animation.loaders.AnimatedModelLoader;
+import eu.tankernn.gameEngine.animation.animatedModel.Joint;
 import eu.tankernn.gameEngine.animation.loaders.AnimationLoader;
+import eu.tankernn.gameEngine.loader.colladaLoader.AnimatedModelData;
+import eu.tankernn.gameEngine.loader.colladaLoader.ColladaLoader;
+import eu.tankernn.gameEngine.loader.colladaLoader.JointsData;
+import eu.tankernn.gameEngine.loader.colladaLoader.MeshData;
 import eu.tankernn.gameEngine.loader.models.AABB;
 import eu.tankernn.gameEngine.loader.models.TexturedModel;
 import eu.tankernn.gameEngine.loader.obj.ModelData;
@@ -30,16 +34,19 @@ import eu.tankernn.gameEngine.util.InternalFile;
  * @author Frans
  */
 public class Loader {
+	public static final int MAX_WEIGHTS = 3;
+
 	private List<Vao> vaos = new ArrayList<>();
 	private List<Texture> textures = new ArrayList<>();
 	private Map<Integer, TexturedModel> models = new HashMap<>();
-	private List<AABB> boundingBoxes = new ArrayList<>();
-	
+	private Map<Integer, AABB> boundingBoxes = new HashMap<>();
+
 	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, int[] indices) {
-		return loadToVAO(vertices, textureCoords, normals, null, indices);
+		return loadToVAO(vertices, textureCoords, normals, null, null, null, indices);
 	}
-	
-	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, float[] tangents, int[] indices) {
+
+	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, float[] tangents, int[] jointIds,
+			float[] weights, int[] indices) {
 		Vao model = Vao.create();
 		model.bind();
 		model.createIndexBuffer(indices);
@@ -48,11 +55,15 @@ public class Loader {
 		model.createAttribute(2, normals, 3);
 		if (tangents != null)
 			model.createAttribute(3, tangents, 3);
+		if (jointIds != null)
+			model.createIntAttribute(4, jointIds, 3);
+		if (weights != null)
+			model.createAttribute(5, weights, 3);
 		model.unbind();
 		vaos.add(model);
 		return model;
 	}
-	
+
 	public Vao loadToVAO(float[] positions, float[] textureCoords) {
 		Vao vao = Vao.create();
 		vao.bind();
@@ -61,7 +72,7 @@ public class Loader {
 		vao.unbind();
 		return vao;
 	}
-	
+
 	public Vao loadToVAO(float[] positions, int dimensions) {
 		Vao vao = Vao.create(positions.length / 2);
 		vao.bind();
@@ -69,16 +80,23 @@ public class Loader {
 		vao.unbind();
 		return vao;
 	}
-	
+
 	public Vao loadToVAO(ModelData data) {
-		return (Vao) loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(), data.getIndices());
+		return (Vao) loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(), null,
+				null, data.getIndices());
+	}
+
+	public Vao loadToVAO(MeshData data) {
+		return loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(),
+				data.getJointIds(), data.getVertexWeights(), data.getIndices());
 	}
-	
+
 	/**
 	 * Loads a texture to the GPU.
 	 * 
-	 * @param filename The path, relative to the root of the jar file, of the
-	 *        file to load.
+	 * @param filename
+	 *            The path, relative to the root of the jar file, of the file to
+	 *            load.
 	 * @return The texture ID
 	 * @throws FileNotFoundException
 	 */
@@ -87,28 +105,30 @@ public class Loader {
 		textures.add(texture);
 		return texture;
 	}
-	
+
 	public Texture loadTexture(String filename) throws FileNotFoundException {
 		return loadTexture(new InternalFile(filename));
 	}
-	
+
 	/**
 	 * Creates a new cube map from the images specified. File 0: Right face File
 	 * 1: Left face File 2: Top face File 3: Bottom face File 4: Back face File
 	 * 5: Front face
 	 * 
-	 * @param textureFiles Filenames of images that make up the cube map
+	 * @param textureFiles
+	 *            Filenames of images that make up the cube map
 	 * @return The ID of the new cube map
 	 */
-	
+
 	public Texture loadCubeMap(InternalFile[] textureFiles) {
 		Texture cubeMap = Texture.newCubeMap(textureFiles, 500);
 		textures.add(cubeMap);
 		return cubeMap;
 	}
-	
-	private static final int[] CUBE_INDICES = {0, 1, 3, 1, 2, 3, 1, 5, 2, 2, 5, 6, 4, 7, 5, 5, 7, 6, 0, 3, 4, 4, 3, 7, 7, 3, 6, 6, 3, 2, 4, 5, 0, 0, 5, 1};
-	
+
+	private static final int[] CUBE_INDICES = { 0, 1, 3, 1, 2, 3, 1, 5, 2, 2, 5, 6, 4, 7, 5, 5, 7, 6, 0, 3, 4, 4, 3, 7,
+			7, 3, 6, 6, 3, 2, 4, 5, 0, 0, 5, 1 };
+
 	public Vao generateCube(float size) {
 		Vao vao = Vao.create();
 		vao.bind();
@@ -118,38 +138,56 @@ public class Loader {
 		vaos.add(vao);
 		return vao;
 	}
-	
+
 	private static float[] getCubeVertexPositions(float size) {
-		return new float[] {-size, size, size, size, size, size, size, -size, size, -size, -size, size, -size, size, -size, size, size, -size, size, -size, -size, -size, -size, -size};
+		return new float[] { -size, size, size, size, size, size, size, -size, size, -size, -size, size, -size, size,
+				-size, size, size, -size, size, -size, -size, -size, -size, -size };
 	}
-	
+
 	public void cleanUp() {
-		for (Texture tex: textures)
+		for (Texture tex : textures)
 			tex.delete();
-		for (Vao model: vaos)
+		for (Vao model : vaos)
 			model.delete();
 	}
-	
+
 	public Vao loadOBJ(InternalFile objFile) {
 		ModelData data = ObjLoader.loadOBJ(objFile);
-		boundingBoxes.add(new AABB(data));
-		return this.loadToVAO(data);
+		Vao vao = this.loadToVAO(data);
+		boundingBoxes.put(vao.id, new AABB(data));
+		return vao;
 	}
-	
+	/**
+	 * Creates an AnimatedEntity from the data in an entity file. It loads up
+	 * the collada model data, stores the extracted data in a VAO, sets up the
+	 * joint heirarchy, and loads up the entity's texture.
+	 * 
+	 * @param entityFile
+	 *            - the file containing the data for the entity.
+	 * @return The animated entity (no animation applied though)
+	 */
+	public AnimatedModel loadDAE(InternalFile modelFile, ModelTexture texture) {
+		AnimatedModelData entityData = ColladaLoader.loadColladaModel(modelFile, MAX_WEIGHTS);
+		Vao model = loadToVAO(entityData.getMeshData());
+		JointsData skeletonData = entityData.getJointsData();
+		Joint headJoint = new Joint(skeletonData.headJoint);
+		return new AnimatedModel(model, texture, headJoint, skeletonData.jointCount);
+	}
+
 	public void readModelSpecification(InternalFile file) throws IOException {
 		Map<InternalFile, Vao> cachedRawModels = new HashMap<InternalFile, Vao>();
 		Map<InternalFile, Texture> cachedTextures = new HashMap<InternalFile, Texture>();
 		JSONObject spec;
-		
+
 		JSONArray jsonArr = new JSONArray(file.readFile());
-		
+
 		for (int j = 0; j < jsonArr.length(); j++) {
 			spec = jsonArr.getJSONObject(j);
-			
+
 			int id;
 			Vao model;
 			ModelTexture modelTexture;
-			
+
 			id = spec.getInt("id");
 			InternalFile modelFile;
 			try {
@@ -157,9 +195,10 @@ public class Loader {
 			} catch (FileNotFoundException e) {
 				modelFile = new InternalFile("models/" + optFilename(spec, "model", ".dae"));
 			}
-			
-			String[] textureFiles = {optFilename(spec, "texture", ".png"), optFilename(spec, "specular", "S.png"), optFilename(spec, "normal", "N.png")};
-			
+
+			String[] textureFiles = { optFilename(spec, "texture", ".png"), optFilename(spec, "specular", "S.png"),
+					optFilename(spec, "normal", "N.png") };
+
 			Texture[] textures = Arrays.stream(textureFiles).map(fileName -> {
 				try {
 					InternalFile f = new InternalFile("textures/" + fileName);
@@ -176,19 +215,19 @@ public class Loader {
 					return null;
 				}
 			}).toArray(size -> new Texture[size]);
-			
+
 			modelTexture = new ModelTexture(textures[0]);
 			if (textures[1] != null)
 				modelTexture.setNormalMap(textures[2]);
 			if (textures[2] != null)
 				modelTexture.setSpecularMap(textures[1]);
-			
+
 			modelTexture.setShineDamper(optFloat(spec, "shinedamper", 10.0f));
 			modelTexture.setReflectivity(optFloat(spec, "reflectivity", 0f));
 			modelTexture.setRefractivity(optFloat(spec, "refractivity", 0f));
-			
+
 			modelTexture.setHasTransparency(spec.optBoolean("transparency"));
-			
+
 			if (cachedRawModels.containsKey(modelFile)) {
 				model = cachedRawModels.get(modelFile);
 				models.put(id, new TexturedModel(model, modelTexture));
@@ -200,11 +239,13 @@ public class Loader {
 					models.put(id, new TexturedModel(model, modelTexture));
 					break;
 				case "dae":
-					AnimatedModel animatedModel = AnimatedModelLoader.loadEntity(modelFile, modelTexture);
+					AnimatedModel animatedModel = loadDAE(modelFile, modelTexture);
 					JSONObject animations = spec.getJSONObject("animations");
-					for (Object key: animations.names().toList()) {
+					for (Object key : animations.names().toList()) {
 						String name = (String) key;
-						//TODO Create a file format to specify animation frame ranges, then glue all animations together in Blender before exporting
+						// TODO Create a file format to specify animation frame
+						// ranges, then glue all animations together in Blender
+						// before exporting
 						animatedModel.registerAnimation(name, AnimationLoader.loadAnimation(modelFile));
 					}
 					models.put(id, animatedModel);
@@ -215,15 +256,15 @@ public class Loader {
 			}
 		}
 	}
-	
+
 	private float optFloat(JSONObject spec, String key, float defaultValue) {
 		return BigDecimal.valueOf(spec.optDouble(key, (double) defaultValue)).floatValue();
 	}
-	
+
 	private String optFilename(JSONObject spec, String key, String extension) {
 		return spec.has(key) ? spec.getString(key) : spec.get("name") + extension;
 	}
-	
+
 	public TexturedModel getModel(int id) {
 		TexturedModel model = models.get(id);
 		if (model instanceof AnimatedModel)
@@ -231,8 +272,8 @@ public class Loader {
 		else
 			return model;
 	}
-	
-	public AABB getBoundingBox(int id) {
-		return boundingBoxes.get(id);
+
+	public AABB getBoundingBox(int vaoId) {
+		return boundingBoxes.get(vaoId);
 	}
 }