OBJLoader.java revision a6b44658eb1c55295f132a36233a11aa2bd8f9cf
159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.scene.plugins; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.*; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.Material; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.MaterialList; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector2f; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.queue.RenderQueue.Bucket; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh.Mode; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.*; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.mesh.IndexBuffer; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.mesh.IndexIntBuffer; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.mesh.IndexShortBuffer; 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.IntMap; 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.File; 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.InputStream; 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.FloatBuffer; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.IntBuffer; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.ShortBuffer; 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Map.Entry; 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.*; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level; 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger; 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Reads OBJ format models. 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic final class OBJLoader implements AssetLoader { 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final Logger logger = Logger.getLogger(OBJLoader.class.getName()); 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected final ArrayList<Vector3f> verts = new ArrayList<Vector3f>(); 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected final ArrayList<Vector2f> texCoords = new ArrayList<Vector2f>(); 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected final ArrayList<Vector3f> norms = new ArrayList<Vector3f>(); 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected final ArrayList<Face> faces = new ArrayList<Face>(); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected final HashMap<String, ArrayList<Face>> matFaces = new HashMap<String, ArrayList<Face>>(); 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected String currentMatName; 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected String currentObjectName; 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected final HashMap<Vertex, Integer> vertIndexMap = new HashMap<Vertex, Integer>(100); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected final IntMap<Vertex> indexVertMap = new IntMap<Vertex>(100); 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected int curIndex = 0; 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected int objectIndex = 0; 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected int geomIndex = 0; 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Scanner scan; 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected ModelKey key; 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected AssetManager assetManager; 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected MaterialList matList; 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected String objName; 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Node objNode; 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected static class Vertex { 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f v; 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector2f vt; 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vn; 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int index; 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean equals(Object obj) { 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (obj == null) { 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (getClass() != obj.getClass()) { 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta final Vertex other = (Vertex) obj; 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.v != other.v && (this.v == null || !this.v.equals(other.v))) { 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.vt != other.vt && (this.vt == null || !this.vt.equals(other.vt))) { 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.vn != other.vn && (this.vn == null || !this.vn.equals(other.vn))) { 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int hashCode() { 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int hash = 5; 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hash = 53 * hash + (this.v != null ? this.v.hashCode() : 0); 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hash = 53 * hash + (this.vt != null ? this.vt.hashCode() : 0); 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hash = 53 * hash + (this.vn != null ? this.vn.hashCode() : 0); 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return hash; 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected static class Face { 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex[] verticies; 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected class ObjectGroup { 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta final String objectName; 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public ObjectGroup(String objectName){ 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.objectName = objectName; 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Spatial createGeometry(){ 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Node groupNode = new Node(objectName); 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (matFaces.size() > 0){ 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// for (Entry<String, ArrayList<Face>> entry : matFaces.entrySet()){ 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// ArrayList<Face> materialFaces = entry.getValue(); 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (materialFaces.size() > 0){ 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// Geometry geom = createGeometry(materialFaces, entry.getKey()); 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// objNode.attachChild(geom); 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// }else if (faces.size() > 0){ 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// // generate final geometry 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// Geometry geom = createGeometry(faces, null); 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// objNode.attachChild(geom); 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return groupNode; 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void reset(){ 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verts.clear(); 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta texCoords.clear(); 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta norms.clear(); 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta faces.clear(); 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta matFaces.clear(); 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertIndexMap.clear(); 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexVertMap.clear(); 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentMatName = null; 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta matList = null; 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curIndex = 0; 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomIndex = 0; 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scan = null; 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void findVertexIndex(Vertex vert){ 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Integer index = vertIndexMap.get(vert); 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (index != null){ 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vert.index = index.intValue(); 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vert.index = curIndex++; 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertIndexMap.put(vert, vert.index); 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexVertMap.put(vert.index, vert); 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Face[] quadToTriangle(Face f){ 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert f.verticies.length == 4; 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Face[] t = new Face[]{ new Face(), new Face() }; 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[0].verticies = new Vertex[3]; 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[1].verticies = new Vertex[3]; 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex v0 = f.verticies[0]; 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex v1 = f.verticies[1]; 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex v2 = f.verticies[2]; 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex v3 = f.verticies[3]; 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // find the pair of verticies that is closest to each over 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // v0 and v2 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // OR 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // v1 and v3 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float d1 = v0.v.distanceSquared(v2.v); 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float d2 = v1.v.distanceSquared(v3.v); 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (d1 < d2){ 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // put an edge in v0, v2 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[0].verticies[0] = v0; 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[0].verticies[1] = v1; 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[0].verticies[2] = v3; 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[1].verticies[0] = v1; 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[1].verticies[1] = v2; 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[1].verticies[2] = v3; 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // put an edge in v1, v3 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[0].verticies[0] = v0; 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[0].verticies[1] = v1; 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[0].verticies[2] = v2; 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[1].verticies[0] = v0; 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[1].verticies[1] = v2; 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t[1].verticies[2] = v3; 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return t; 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ArrayList<Vertex> vertList = new ArrayList<Vertex>(); 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void readFace(){ 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Face f = new Face(); 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertList.clear(); 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String line = scan.nextLine().trim(); 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String[] verticies = line.split("\\s"); 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (String vertex : verticies){ 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int v = 0; 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int vt = 0; 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int vn = 0; 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String[] split = vertex.split("/"); 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (split.length == 1){ 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = Integer.parseInt(split[0].trim()); 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (split.length == 2){ 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = Integer.parseInt(split[0].trim()); 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vt = Integer.parseInt(split[1].trim()); 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (split.length == 3 && !split[1].equals("")){ 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = Integer.parseInt(split[0].trim()); 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vt = Integer.parseInt(split[1].trim()); 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vn = Integer.parseInt(split[2].trim()); 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (split.length == 3){ 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = Integer.parseInt(split[0].trim()); 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vn = Integer.parseInt(split[2].trim()); 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex vx = new Vertex(); 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vx.v = verts.get(v - 1); 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vt > 0) 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vx.vt = texCoords.get(vt - 1); 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vn > 0) 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vx.vn = norms.get(vn - 1); 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertList.add(vx); 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vertList.size() > 4 || vertList.size() <= 2) 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.warning("Edge or polygon detected in OBJ. Ignored."); 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta f.verticies = new Vertex[vertList.size()]; 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < vertList.size(); i++){ 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta f.verticies[i] = vertList.get(i); 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (matList != null && matFaces.containsKey(currentMatName)){ 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta matFaces.get(currentMatName).add(f); 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta faces.add(f); // faces that belong to the default material 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Vector3f readVector3(){ 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f v = new Vector3f(); 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.set(Float.parseFloat(scan.next()), 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Float.parseFloat(scan.next()), 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Float.parseFloat(scan.next())); 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return v; 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Vector2f readVector2(){ 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector2f v = new Vector2f(); 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String line = scan.nextLine().trim(); 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String[] split = line.split("\\s"); 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.setX( Float.parseFloat(split[0].trim()) ); 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v.setY( Float.parseFloat(split[1].trim()) ); 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// v.setX(scan.nextFloat()); 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (scan.hasNextFloat()){ 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// v.setY(scan.nextFloat()); 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (scan.hasNextFloat()){ 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// scan.nextFloat(); // ignore 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return v; 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void loadMtlLib(String name) throws IOException{ 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!name.toLowerCase().endsWith(".mtl")) 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException("Expected .mtl file! Got: " + name); 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: Cut off any relative/absolute paths 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta name = new File(name).getName(); 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AssetKey mtlKey = new AssetKey(key.getFolder() + name); 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta matList = (MaterialList) assetManager.loadAsset(mtlKey); 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (AssetNotFoundException ex){ 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "Cannot locate {0} for model {1}", new Object[]{name, key}); 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (matList != null){ 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create face lists for every material 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (String matName : matList.keySet()){ 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta matFaces.put(matName, new ArrayList<Face>()); 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean nextStatement(){ 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scan.skip(".*\r{0,1}\n"); 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (NoSuchElementException ex){ 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // EOF 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean readLine() throws IOException{ 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!scan.hasNext()){ 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String cmd = scan.next(); 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (cmd.startsWith("#")){ 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // skip entire comment until next line 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return nextStatement(); 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (cmd.equals("v")){ 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // vertex position 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verts.add(readVector3()); 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (cmd.equals("vn")){ 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // vertex normal 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta norms.add(readVector3()); 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (cmd.equals("vt")){ 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // texture coordinate 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta texCoords.add(readVector2()); 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (cmd.equals("f")){ 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // face, can be triangle, quad, or polygon (unsupported) 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta readFace(); 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (cmd.equals("usemtl")){ 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // use material from MTL lib for the following faces 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentMatName = scan.next(); 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// if (!matList.containsKey(currentMatName)) 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// throw new IOException("Cannot locate material " + currentMatName + " in MTL file!"); 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (cmd.equals("mtllib")){ 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // specify MTL lib to use for this OBJ file 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String mtllib = scan.nextLine().trim(); 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta loadMtlLib(mtllib); 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (cmd.equals("s") || cmd.equals("g")){ 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return nextStatement(); 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // skip entire command until next line 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "Unknown statement in OBJ! {0}", cmd); 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return nextStatement(); 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Geometry createGeometry(ArrayList<Face> faceList, String matName) throws IOException{ 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (faceList.isEmpty()) 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException("No geometry data to generate mesh"); 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Create mesh from the faces 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Mesh mesh = constructMesh(faceList); 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Geometry geom = new Geometry(objName + "-geom-" + (geomIndex++), mesh); 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Material material = null; 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (matName != null && matList != null){ 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Get material from material list 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = matList.get(matName); 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material == null){ 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create default material 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md"); 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material.setFloat("Shininess", 64); 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geom.setMaterial(material); 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material.isTransparent()) 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geom.setQueueBucket(Bucket.Transparent); 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geom.setQueueBucket(Bucket.Opaque); 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material.getMaterialDef().getName().contains("Lighting") 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta && mesh.getFloatBuffer(Type.Normal) == null){ 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "OBJ mesh {0} doesn't contain normals! " 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + "It might not display correctly", geom.getName()); 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return geom; 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Mesh constructMesh(ArrayList<Face> faceList){ 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Mesh m = new Mesh(); 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.setMode(Mode.Triangles); 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean hasTexCoord = false; 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean hasNormals = false; 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ArrayList<Face> newFaces = new ArrayList<Face>(faceList.size()); 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < faceList.size(); i++){ 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Face f = faceList.get(i); 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Vertex v : f.verticies){ 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta findVertexIndex(v); 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!hasTexCoord && v.vt != null) 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hasTexCoord = true; 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!hasNormals && v.vn != null) 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta hasNormals = true; 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (f.verticies.length == 4){ 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Face[] t = quadToTriangle(f); 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta newFaces.add(t[0]); 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta newFaces.add(t[1]); 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta newFaces.add(f); 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FloatBuffer posBuf = BufferUtils.createFloatBuffer(vertIndexMap.size() * 3); 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FloatBuffer normBuf = null; 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FloatBuffer tcBuf = null; 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (hasNormals){ 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normBuf = BufferUtils.createFloatBuffer(vertIndexMap.size() * 3); 457a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta m.setBuffer(VertexBuffer.Type.Normal, 3, normBuf); 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (hasTexCoord){ 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tcBuf = BufferUtils.createFloatBuffer(vertIndexMap.size() * 2); 461a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta m.setBuffer(VertexBuffer.Type.TexCoord, 2, tcBuf); 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta IndexBuffer indexBuf = null; 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (vertIndexMap.size() >= 65536){ 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // too many verticies: use intbuffer instead of shortbuffer 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta IntBuffer ib = BufferUtils.createIntBuffer(newFaces.size() * 3); 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.setBuffer(VertexBuffer.Type.Index, 3, ib); 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBuf = new IndexIntBuffer(ib); 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ShortBuffer sb = BufferUtils.createShortBuffer(newFaces.size() * 3); 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.setBuffer(VertexBuffer.Type.Index, 3, sb); 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBuf = new IndexShortBuffer(sb); 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int numFaces = newFaces.size(); 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < numFaces; i++){ 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Face f = newFaces.get(i); 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (f.verticies.length != 3) 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta continue; 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex v0 = f.verticies[0]; 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex v1 = f.verticies[1]; 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vertex v2 = f.verticies[2]; 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta posBuf.position(v0.index * 3); 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta posBuf.put(v0.v.x).put(v0.v.y).put(v0.v.z); 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta posBuf.position(v1.index * 3); 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta posBuf.put(v1.v.x).put(v1.v.y).put(v1.v.z); 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta posBuf.position(v2.index * 3); 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta posBuf.put(v2.v.x).put(v2.v.y).put(v2.v.z); 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (normBuf != null){ 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (v0.vn != null){ 49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normBuf.position(v0.index * 3); 49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normBuf.put(v0.vn.x).put(v0.vn.y).put(v0.vn.z); 49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normBuf.position(v1.index * 3); 49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normBuf.put(v1.vn.x).put(v1.vn.y).put(v1.vn.z); 49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normBuf.position(v2.index * 3); 50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normBuf.put(v2.vn.x).put(v2.vn.y).put(v2.vn.z); 50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (tcBuf != null){ 50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (v0.vt != null){ 50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tcBuf.position(v0.index * 2); 50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tcBuf.put(v0.vt.x).put(v0.vt.y); 50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tcBuf.position(v1.index * 2); 50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tcBuf.put(v1.vt.x).put(v1.vt.y); 51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tcBuf.position(v2.index * 2); 51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tcBuf.put(v2.vt.x).put(v2.vt.y); 51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int index = i * 3; // current face * 3 = current index 51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBuf.put(index, v0.index); 51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBuf.put(index+1, v1.index); 51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBuf.put(index+2, v2.index); 51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.setBuffer(VertexBuffer.Type.Position, 3, posBuf); 522a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta // index buffer and others were set on creation 52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.setStatic(); 52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.updateBound(); 52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta m.updateCounts(); 52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //m.setInterleaved(); 52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // clear data generated face statements 53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // to prepare for next mesh 53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertIndexMap.clear(); 53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexVertMap.clear(); 53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curIndex = 0; 53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return m; 53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @SuppressWarnings("empty-statement") 53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Object load(AssetInfo info) throws IOException{ 54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta reset(); 54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta key = (ModelKey) info.getKey(); 54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assetManager = info.getManager(); 54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objName = key.getName(); 54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String folderName = key.getFolder(); 54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String ext = key.getExtension(); 54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objName = objName.substring(0, objName.length() - ext.length() - 1); 54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (folderName != null && folderName.length() > 0){ 55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objName = objName.substring(folderName.length()); 55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objNode = new Node(objName + "-objnode"); 55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!(info.getKey() instanceof ModelKey)) 55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("Model assets must be loaded using a ModelKey"); 55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputStream in = null; 55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta in = info.openStream(); 56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scan = new Scanner(in); 56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scan.useLocale(Locale.US); 56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (readLine()); 56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } finally { 56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (in != null){ 56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta in.close(); 56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (matFaces.size() > 0){ 57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Entry<String, ArrayList<Face>> entry : matFaces.entrySet()){ 57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ArrayList<Face> materialFaces = entry.getValue(); 57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (materialFaces.size() > 0){ 57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Geometry geom = createGeometry(materialFaces, entry.getKey()); 57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objNode.attachChild(geom); 57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (faces.size() > 0){ 58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // generate final geometry 58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Geometry geom = createGeometry(faces, null); 58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objNode.attachChild(geom); 58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (objNode.getQuantity() == 1) 58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // only 1 geometry, so no need to send node 58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return objNode.getChild(0); 58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else 59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return objNode; 59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 594