|
@@ -21,6 +21,8 @@ import org.lwjgl.opengl.GL20;
|
|
|
import org.lwjgl.opengl.GL30;
|
|
|
import org.lwjgl.opengl.GL33;
|
|
|
|
|
|
+import eu.tankernn.gameEngine.animation.animatedModel.AnimatedModel;
|
|
|
+import eu.tankernn.gameEngine.animation.loaders.AnimatedModelLoader;
|
|
|
import eu.tankernn.gameEngine.loader.models.AABB;
|
|
|
import eu.tankernn.gameEngine.loader.models.TexturedModel;
|
|
|
import eu.tankernn.gameEngine.loader.obj.ModelData;
|
|
@@ -34,7 +36,6 @@ import eu.tankernn.gameEngine.util.InternalFile;
|
|
|
* General purpose loader
|
|
|
*
|
|
|
* @author Frans
|
|
|
- *
|
|
|
*/
|
|
|
public class Loader {
|
|
|
private List<Integer> vaos = new ArrayList<Integer>();
|
|
@@ -43,7 +44,7 @@ public class Loader {
|
|
|
private List<Texture> textures = new ArrayList<Texture>();
|
|
|
private Map<Integer, TexturedModel> models = new HashMap<Integer, TexturedModel>();
|
|
|
private List<AABB> boundingBoxes = new ArrayList<>();
|
|
|
-
|
|
|
+
|
|
|
public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, int[] indices) {
|
|
|
Vao model = Vao.create();
|
|
|
model.bind();
|
|
@@ -55,9 +56,8 @@ public class Loader {
|
|
|
rawModels.add(model);
|
|
|
return model;
|
|
|
}
|
|
|
-
|
|
|
- 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[] indices) {
|
|
|
Vao model = Vao.create();
|
|
|
model.bind();
|
|
|
model.createIndexBuffer(indices);
|
|
@@ -69,7 +69,7 @@ public class Loader {
|
|
|
rawModels.add(model);
|
|
|
return model;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public int createEmptyVBO(int floatCount) {
|
|
|
int vboID = GL15.glGenBuffers();
|
|
|
vbos.add(vboID);
|
|
@@ -78,9 +78,8 @@ public class Loader {
|
|
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
|
|
return vboID;
|
|
|
}
|
|
|
-
|
|
|
- public void addInstacedAttribute(int vao, int vbo, int attribute, int dataSize, int instancedDataLength,
|
|
|
- int offset) {
|
|
|
+
|
|
|
+ public void addInstacedAttribute(int vao, int vbo, int attribute, int dataSize, int instancedDataLength, int offset) {
|
|
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
|
|
GL30.glBindVertexArray(vao);
|
|
|
GL20.glVertexAttribPointer(attribute, dataSize, GL11.GL_FLOAT, false, instancedDataLength * 4, offset * 4);
|
|
@@ -88,7 +87,7 @@ public class Loader {
|
|
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
|
|
GL30.glBindVertexArray(0);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public void updateVBO(int vboID, float[] data, FloatBuffer buffer) {
|
|
|
buffer.clear();
|
|
|
buffer.put(data);
|
|
@@ -98,7 +97,7 @@ public class Loader {
|
|
|
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, buffer);
|
|
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public int loadToVAO(float[] positions, float[] textureCoords) {
|
|
|
int vaoID = createVAO();
|
|
|
storeDataInAttributeList(0, 2, positions);
|
|
@@ -106,7 +105,7 @@ public class Loader {
|
|
|
unbindVAO();
|
|
|
return vaoID;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public Vao loadToVAO(float[] positions, int dimensions) {
|
|
|
Vao vao = Vao.create();
|
|
|
vao.bind();
|
|
@@ -114,18 +113,16 @@ 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(), 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
|
|
|
*/
|
|
@@ -138,26 +135,24 @@ public class Loader {
|
|
|
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();
|
|
@@ -167,31 +162,29 @@ public class Loader {
|
|
|
rawModels.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 (int vao : vaos)
|
|
|
+ for (int vao: vaos)
|
|
|
GL30.glDeleteVertexArrays(vao);
|
|
|
- for (int vbo : vbos)
|
|
|
+ for (int vbo: vbos)
|
|
|
GL15.glDeleteBuffers(vbo);
|
|
|
- for (Texture tex : textures)
|
|
|
+ for (Texture tex: textures)
|
|
|
tex.delete();
|
|
|
- for (Vao model : rawModels)
|
|
|
+ for (Vao model: rawModels)
|
|
|
model.delete();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private int createVAO() {
|
|
|
int vaoID = GL30.glGenVertexArrays();
|
|
|
vaos.add(vaoID);
|
|
|
GL30.glBindVertexArray(vaoID);
|
|
|
return vaoID;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float[] data) {
|
|
|
int vboID = GL15.glGenBuffers();
|
|
|
vbos.add(vboID);
|
|
@@ -201,55 +194,55 @@ public class Loader {
|
|
|
GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0);
|
|
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private void unbindVAO() {
|
|
|
GL30.glBindVertexArray(0);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private FloatBuffer storeDataInFloatBuffer(float[] data) {
|
|
|
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
|
|
|
buffer.put(data);
|
|
|
buffer.flip();
|
|
|
return buffer;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public Vao loadOBJ(InternalFile objFile) {
|
|
|
ModelData data = ObjLoader.loadOBJ(objFile);
|
|
|
boundingBoxes.add(new AABB(data));
|
|
|
return this.loadToVAO(data);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ public AnimatedModel loadDAE(InternalFile colladaFile) {
|
|
|
+ return AnimatedModelLoader.loadEntity(colladaFile, new ModelTexture(textures.get(0)));
|
|
|
+ }
|
|
|
+
|
|
|
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 objFile = new InternalFile(optFilename(spec, "model", ".obj"));
|
|
|
-
|
|
|
- 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")};
|
|
|
+
|
|
|
if (cachedRawModels.containsKey(objFile))
|
|
|
model = cachedRawModels.get(objFile);
|
|
|
else {
|
|
|
model = loadOBJ(objFile);
|
|
|
cachedRawModels.put(objFile, model);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
Texture[] textures = Arrays.stream(textureFiles).map(fileName -> {
|
|
|
try {
|
|
|
InternalFile f = new InternalFile(fileName);
|
|
@@ -266,31 +259,31 @@ 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"));
|
|
|
-
|
|
|
+
|
|
|
models.put(id, new TexturedModel(model, modelTexture));
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
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 int registerModel(int id, TexturedModel model) throws Exception {
|
|
|
if (models.containsKey(id)) {
|
|
|
throw new Exception("There is already a model registered for the key " + id + ".");
|
|
@@ -299,11 +292,11 @@ public class Loader {
|
|
|
return id;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public int registerModel(TexturedModel model) throws Exception {
|
|
|
if (models.containsValue(model)) {
|
|
|
Iterator<Entry<Integer, TexturedModel>> i = models.entrySet().iterator();
|
|
|
-
|
|
|
+
|
|
|
while (i.hasNext()) {
|
|
|
Entry<Integer, TexturedModel> e = i.next();
|
|
|
if (e.getValue().equals(model)) {
|
|
@@ -315,11 +308,11 @@ public class Loader {
|
|
|
} else
|
|
|
return registerModel(models.size(), model);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public TexturedModel getModel(int id) {
|
|
|
return models.get(id);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public AABB getBoundingBox(int id) {
|
|
|
return boundingBoxes.get(id);
|
|
|
}
|