/* * Copyright 2016 Nathan Howard * * This file is part of OpenGrave * * OpenGrave is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenGrave is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenGrave. If not, see <http://www.gnu.org/licenses/>. */ package com.opengrave.og.models; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.opengrave.og.MainThread; import com.opengrave.og.engine.Location; import com.opengrave.og.util.Matrix4f; import com.opengrave.og.util.Vector3f; public class DAEFile { public Location location = new Location(); public Vector3f rotation = new Vector3f(); public Vector3f scale = new Vector3f(); public Document document; public ArrayList<DAEAnimatedMesh> meshAnim = new ArrayList<DAEAnimatedMesh>(); public ArrayList<DAEMesh> meshStatic = new ArrayList<DAEMesh>(); public ArrayList<DAEMeshInstance> meshStaticInstance = new ArrayList<DAEMeshInstance>(); private ArrayList<DAEController> controls = new ArrayList<DAEController>(); public ArrayList<DAEAnimation> animations = new ArrayList<DAEAnimation>(); public ArrayList<DAEAnimClip> animationClips = new ArrayList<DAEAnimClip>(); public void parseData(String fileName) throws ParserConfigurationException, SAXException, IOException { File file = new File(MainThread.cache, fileName); if (!file.exists()) { System.out.println("Error loading DAE file " + fileName + " : File not found"); return; } InputStream is = new FileInputStream(file); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; builder = dbf.newDocumentBuilder(); document = builder.parse(is); // Get all Materials // ArrayList<String> textureNames = new ArrayList<String>(); /* * NodeList nodes = document.getElementsByTagName("material"); for * (int i = 0; i < nodes.getLength(); i++) { DAEMaterial material = * new DAEMaterial(this, (Element) nodes.item(i)); * materials.add(material); if (material.textureName != null) { if * (!textureNames.contains(material.textureName)) { * textureNames.add(material.textureName); } material.textureIndex = * textureNames .indexOf(material.textureName); } } */ // Bake materials into a texture pile // TextureAtlas texture = (TextureAtlas) Resources // .loadTextures(textureNames); // Hide it in each Material, for access sake // for (DAEMaterial mat : materials) { // mat.texture = texture; // } // Get all Static Meshes. NodeList nodes = document.getElementsByTagName("geometry"); for (int i = 0; i < nodes.getLength(); i++) { DAEMesh object = new DAEMesh(this, nodes.item(i)); meshStatic.add(object); } /* * NodeList nodes = document.getElementsByTagName("triangles"); * * for (int i = 0; i < nodes.getLength(); i++) { DAEStaticMesh * object = new DAEStaticMesh(this, nodes.item(i)); * meshStatic.add(object); } */ // System.out.println("Meshes Found : " + meshStatic.size()); // Get all Scene nodes. These magically include bone/joint info too! nodes = document.getElementsByTagName("visual_scene"); DAESceneNode topLevel = new DAESceneNode(); // topLevel.total.scale(new Vector3f(0.03f, 0.03f, 0.03f)); for (int i = 0; i < nodes.getLength(); i++) { Node cNode = nodes.item(i); DAESceneNode.make(this, topLevel, (Element) cNode); } for (DAEController controller : controls) { controller.prepare(topLevel); } // System.out.println("Skeletal Controllers found : " // + controls.size()); // Get all Animations nodes = document.getElementsByTagName("animation"); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); DAEAnimation anim = new DAEAnimation(node); animations.add(anim); } nodes = document.getElementsByTagName("animation_clip"); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); DAEAnimClip anim = new DAEAnimClip(this, node); animationClips.add(anim); } // Create Animated Models using info we've garnered // This will be the perfect time to bake any of the info in // TODO Bake in BSM from skin instead of giving it to Anim Mesh // Every Vertex should be vertex = Matrix4f.transform(BSM, vertex, // null); for (DAEController controller : controls) { for (DAESkin skin : controller.skinList) { if (skin.staticModelName != null) { DAEMesh sMesh = getMesh(skin.staticModelName); DAESceneNode skeleton = controller.skeleton; // System.out.println("Mesh : " + skin.staticModelName // + " Skele : " + controller.skeleton.nodeName); if (sMesh == null || skeleton == null || animationClips.size() == 0) { continue; } DAEAnimatedMesh daeam = new DAEAnimatedMesh(this, sMesh, skeleton, animationClips, controller.animName); daeam.matrix = skin.bindShapeMatrix; meshAnim.add(daeam); } } } // System.out // .println("Animated, Skeletal Meshes : " + meshAnim.size()); } /* * public void update(float delta) { for (DAEMesh object : meshStatic) { * object.location = location; object.rotation = rotation; object.scale = * scale; object.update(delta); } for (DAEAnimatedMesh object : meshAnim) { * object.location = location; object.rotation = rotation; object.scale = * scale; object.update(delta); } } */ /* * public void renderForPicking() { for (DAEMesh object : meshStatic) { * object.renderForPicking(); } for (DAEAnimatedMesh object : meshAnim) { * object.renderForPicking(); } } */ /* * public void render() { for (DAEMesh object : meshStatic) { * object.render(); } for (DAEAnimatedMesh object : meshAnim) { * object.render(); } } */ public DAEMesh getMesh(String id) { for (DAEMesh object : meshStatic) { if (object == null || object.getName() == null) { continue; } if (object.getName().equalsIgnoreCase(id)) { return object; } } System.out.println("Failed to find static mesh : " + id); for (DAEMesh object : meshStatic) { System.out.println(object.getName()); } return null; } public DAEAnimatedMesh getAnimMesh(String id) { for (DAEAnimatedMesh object : meshAnim) { if (object == null || object.getName() == null) { continue; } if (object.getName().equalsIgnoreCase(id)) { return object; } } System.out.println("Failed to get animated mesh : " + id); return null; } public void addController(String animName, String skeleNode, String controllerName, Matrix4f total) { DAEController controller = new DAEController(this, skeleNode, controllerName, animName); // controller.bindShapeMatrix = total; controls.add(controller); } public static Matrix4f readMatrix(String textContent) { ArrayList<Matrix4f> matrixList = floatsToMatrix(getFloats(textContent)); if (matrixList.size() == 0) { System.out.println("No Matrices returned"); return new Matrix4f(); } return matrixList.get(0); } public static ArrayList<String> getStrings(Node node) { return getStrings(node.getTextContent()); } public static ArrayList<String> getStrings(String string) { ArrayList<String> strings = new ArrayList<String>(); for (String s : string.split("\\s+")) { if (s.length() == 0) { continue; } strings.add(s); } return strings; } public static ArrayList<Float> getFloats(String string) { ArrayList<Float> floats = new ArrayList<Float>(); for (String s : getStrings(string)) { floats.add(Float.parseFloat(s)); } return floats; } public static ArrayList<Float> getFloats(Node node) { return getFloats(node.getTextContent()); } public static ArrayList<Integer> getIntegers(Node node) { ArrayList<Integer> ints = new ArrayList<Integer>(); for (String s : getStrings(node)) { ints.add(Integer.parseInt(s)); } return ints; } public static ArrayList<Matrix4f> floatsToMatrix(ArrayList<Float> floats) { // TODO Check the order of Matrix filling. ArrayList<Matrix4f> matrixList = new ArrayList<Matrix4f>(); for (int index = 0; index < floats.size(); index += 16) { Matrix4f matrix = new Matrix4f(); // Pretty sure this option is correct. boolean swap = true; if (swap) { for (int i = 0; i < 16; i++) { matrix.put(i, floats.get(index + i)); } } else { // Swapped axis, no longer used. /* * matrix.m00 = floats.get(index + 0); * matrix.m01 = floats.get(index + 1); * matrix.m02 = floats.get(index + 2); * matrix.m03 = floats.get(index + 3); * matrix.m10 = floats.get(index + 4); * matrix.m11 = floats.get(index + 5); * matrix.m12 = floats.get(index + 6); * matrix.m13 = floats.get(index + 7); * matrix.m20 = floats.get(index + 8); * matrix.m21 = floats.get(index + 9); * matrix.m22 = floats.get(index + 10); * matrix.m23 = floats.get(index + 11); * matrix.m30 = floats.get(index + 12); * matrix.m31 = floats.get(index + 13); * matrix.m32 = floats.get(index + 14); * matrix.m33 = floats.get(index + 15); */ } matrixList.add(matrix); } return matrixList; } public void addMeshInstance(DAEMeshInstance minst) { meshStaticInstance.add(minst); } public DAEMeshInstance getMeshInstance(String modelName) { for (DAEMeshInstance minst : meshStaticInstance) { // System.out.println(minst.getName()); if (minst.getName().equalsIgnoreCase(modelName)) { return minst; } } return null; } public ArrayList<String> getMeshInstNames() { ArrayList<String> meshNames = new ArrayList<String>(); for (DAEMeshInstance minst : meshStaticInstance) { meshNames.add(minst.getName()); } return meshNames; } public ArrayList<String> getAnimMeshNames() { ArrayList<String> meshNames = new ArrayList<String>(); for (DAEAnimatedMesh mesh : meshAnim) { meshNames.add(mesh.getName()); } return meshNames; } public ArrayList<String> getAnimationNames() { ArrayList<String> animNames = new ArrayList<String>(); for (DAEAnimClip a : this.animationClips) { animNames.add(a.id); } return animNames; } }