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 Bartapackage com.jme3.scene.plugins.blender.meshes; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartaimport java.nio.ByteBuffer; 35a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartaimport java.util.ArrayList; 36a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartaimport java.util.HashMap; 37a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartaimport java.util.LinkedList; 38a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartaimport java.util.List; 39a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartaimport java.util.Map; 40a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartaimport java.util.Map.Entry; 41a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.BlenderKey.FeaturesToLoad; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.Material; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector2f; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.renderer.queue.RenderQueue.Bucket; 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Geometry; 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Mesh; 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer; 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Format; 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Usage; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.AbstractBlenderHelper; 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.BlenderContext; 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.DynamicArray; 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.Pointer; 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.Structure; 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.materials.MaterialContext; 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.materials.MaterialHelper; 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.objects.Properties; 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.textures.TextureHelper; 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator; 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture; 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A class that is used in mesh calculations. 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Marcin Roguski (Kaelthas) 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class MeshHelper extends AbstractBlenderHelper { 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This constructor parses the given blender version and stores the result. Some functionalities may differ in different blender 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * versions. 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderVersion 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the version read from the blend file 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param fixUpAxis 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a variable that indicates if the Y asxis is the UP axis or not 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public MeshHelper(String blenderVersion, boolean fixUpAxis) { 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super(blenderVersion,fixUpAxis); 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method reads converts the given structure into mesh. The given structure needs to be filled with the appropriate data. 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param structure 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the structure we read the mesh from 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the mesh feature 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws BlenderFileException 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @SuppressWarnings("unchecked") 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public List<Geometry> toMesh(Structure structure, BlenderContext blenderContext) throws BlenderFileException { 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Geometry> geometries = (List<Geometry>) blenderContext.getLoadedFeature(structure.getOldMemoryAddress(), 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta LoadedFeatureDataType.LOADED_FEATURE); 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (geometries != null) { 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Geometry> copiedGeometries = new ArrayList<Geometry>(geometries.size()); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Geometry geometry : geometries) { 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta copiedGeometries.add(geometry.clone()); 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return copiedGeometries; 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // helpers 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class); 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // reading mesh data 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String name = structure.getName(); 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta MeshContext meshContext = new MeshContext(); 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // reading vertices 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f[] vertices = this.getVertices(structure, blenderContext); 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int verticesAmount = vertices.length; 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // vertices Colors 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<byte[]> verticesColors = this.getVerticesColors(structure, blenderContext); 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // reading faces 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // the following map sorts faces by material number (because in jme Mesh can have only one material) 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Map<Integer, List<Integer>> meshesMap = new HashMap<Integer, List<Integer>>(); 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pMFace = (Pointer) structure.getFieldValue("mface"); 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> mFaces = null; 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pMFace.isNotNull()) { 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mFaces = pMFace.fetchData(blenderContext.getInputStream()); 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mFaces == null || mFaces.size() == 0) { 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return new ArrayList<Geometry>(0); 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else{ 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mFaces = new ArrayList<Structure>(0); 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pMTFace = (Pointer) structure.getFieldValue("mtface"); 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Vector2f> uvCoordinates = null; 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> mtFaces = null; 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pMTFace.isNotNull()) { 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mtFaces = pMTFace.fetchData(blenderContext.getInputStream()); 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int facesAmount = ((Number) structure.getFieldValue("totface")).intValue(); 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mtFaces.size() != facesAmount) { 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new BlenderFileException("The amount of faces uv coordinates is not equal to faces amount!"); 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordinates = new ArrayList<Vector2f>(); 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // normalMap merges normals of faces that will be rendered smooth 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Map<Vector3f, Vector3f> normalMap = new HashMap<Vector3f, Vector3f>(verticesAmount); 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Vector3f> normalList = new ArrayList<Vector3f>(); 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Vector3f> vertexList = new ArrayList<Vector3f>(); 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // indicates if the material with the specified number should have a texture attached 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Map<Integer, Texture> materialNumberToTexture = new HashMap<Integer, Texture>(); 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // this map's key is the vertex index from 'vertices 'table and the value are indices from 'vertexList' 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // positions (it simply tells which vertex is referenced where in the result list) 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Map<Integer, List<Integer>> vertexReferenceMap = new HashMap<Integer, List<Integer>>(verticesAmount); 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int vertexColorIndex = 0; 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < mFaces.size(); ++i) { 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Structure mFace = mFaces.get(i); 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean smooth = (((Number) mFace.getFieldValue("flag")).byteValue() & 0x01) != 0x00; 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta DynamicArray<Number> uvs = null; 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean materialWithoutTextures = false; 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pImage = null; 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mtFaces != null) { 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Structure mtFace = mtFaces.get(i); 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pImage = (Pointer) mtFace.getFieldValue("tpage"); 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialWithoutTextures = pImage.isNull(); 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // uvs always must be added wheater we have texture or not 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvs = (DynamicArray<Number>) mtFace.getFieldValue("uv"); 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordinates.add(new Vector2f(uvs.get(0, 0).floatValue(), uvs.get(0, 1).floatValue())); 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordinates.add(new Vector2f(uvs.get(1, 0).floatValue(), uvs.get(1, 1).floatValue())); 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordinates.add(new Vector2f(uvs.get(2, 0).floatValue(), uvs.get(2, 1).floatValue())); 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int matNr = ((Number) mFace.getFieldValue("mat_nr")).intValue(); 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Integer materialNumber = Integer.valueOf(materialWithoutTextures ? -1 * matNr - 1 : matNr); 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Integer> indexList = meshesMap.get(materialNumber); 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (indexList == null) { 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexList = new ArrayList<Integer>(); 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta meshesMap.put(materialNumber, indexList); 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // attaching image to texture (face can have UV's and image whlie its material may have no texture attached) 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pImage != null && pImage.isNotNull() && !materialNumberToTexture.containsKey(materialNumber)) { 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Texture texture = textureHelper.getTextureFromImage(pImage.fetchData(blenderContext.getInputStream()).get(0), 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blenderContext); 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (texture != null) { 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialNumberToTexture.put(materialNumber, texture); 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int v1 = ((Number) mFace.getFieldValue("v1")).intValue(); 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int v2 = ((Number) mFace.getFieldValue("v2")).intValue(); 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int v3 = ((Number) mFace.getFieldValue("v3")).intValue(); 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int v4 = ((Number) mFace.getFieldValue("v4")).intValue(); 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f n = FastMath.computeNormal(vertices[v1], vertices[v2], vertices[v3]); 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.addNormal(n, normalMap, smooth, vertices[v1], vertices[v2], vertices[v3]); 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalList.add(normalMap.get(vertices[v1])); 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalList.add(normalMap.get(vertices[v2])); 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalList.add(normalMap.get(vertices[v3])); 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.appendVertexReference(v1, vertexList.size(), vertexReferenceMap); 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexList.add(vertexList.size()); 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexList.add(vertices[v1]); 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.appendVertexReference(v2, vertexList.size(), vertexReferenceMap); 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexList.add(vertexList.size()); 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexList.add(vertices[v2]); 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.appendVertexReference(v3, vertexList.size(), vertexReferenceMap); 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexList.add(vertexList.size()); 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexList.add(vertices[v3]); 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (v4 > 0) { 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (uvs != null) { 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordinates.add(new Vector2f(uvs.get(0, 0).floatValue(), uvs.get(0, 1).floatValue())); 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordinates.add(new Vector2f(uvs.get(2, 0).floatValue(), uvs.get(2, 1).floatValue())); 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordinates.add(new Vector2f(uvs.get(3, 0).floatValue(), uvs.get(3, 1).floatValue())); 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.appendVertexReference(v1, vertexList.size(), vertexReferenceMap); 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexList.add(vertexList.size()); 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexList.add(vertices[v1]); 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.appendVertexReference(v3, vertexList.size(), vertexReferenceMap); 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexList.add(vertexList.size()); 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexList.add(vertices[v3]); 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.appendVertexReference(v4, vertexList.size(), vertexReferenceMap); 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexList.add(vertexList.size()); 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexList.add(vertices[v4]); 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.addNormal(n, normalMap, smooth, vertices[v4]); 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalList.add(normalMap.get(vertices[v1])); 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalList.add(normalMap.get(vertices[v3])); 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalList.add(normalMap.get(vertices[v4])); 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (verticesColors != null) { 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesColors.add(vertexColorIndex + 3, verticesColors.get(vertexColorIndex)); 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesColors.add(vertexColorIndex + 4, verticesColors.get(vertexColorIndex + 2)); 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexColorIndex += 6; 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (verticesColors != null) { 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesColors.remove(vertexColorIndex + 3); 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexColorIndex += 3; 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta meshContext.setVertexList(vertexList); 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta meshContext.setVertexReferenceMap(vertexReferenceMap); 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f[] normals = normalList.toArray(new Vector3f[normalList.size()]); 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // reading vertices groups (from the parent) 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Structure parent = blenderContext.peekParent(); 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Structure defbase = (Structure) parent.getFieldValue("defbase"); 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> defs = defbase.evaluateListBase(blenderContext); 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String[] verticesGroups = new String[defs.size()]; 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int defIndex = 0; 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Structure def : defs) { 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesGroups[defIndex++] = def.getFieldValue("name").toString(); 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // reading materials 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class); 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Material[] materials = null; 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Material[] nonTexturedMaterials = null; 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if ((blenderContext.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.MATERIALS) != 0) { 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materials = materialHelper.getMaterials(structure, blenderContext); 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nonTexturedMaterials = materials == null ? null : new Material[materials.length];// fill it when needed 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // creating the result meshes 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geometries = new ArrayList<Geometry>(meshesMap.size()); 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer verticesBuffer = new VertexBuffer(Type.Position); 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesBuffer.setupData(Usage.Stream, 3, Format.Float, 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BufferUtils.createFloatBuffer(vertexList.toArray(new Vector3f[vertexList.size()]))); 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // initial vertex position (used with animation) 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer verticesBind = new VertexBuffer(Type.BindPosePosition); 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesBind.setupData(Usage.CpuOnly, 3, Format.Float, BufferUtils.clone(verticesBuffer.getData())); 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer normalsBuffer = new VertexBuffer(Type.Normal); 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalsBuffer.setupData(Usage.Stream, 3, Format.Float, BufferUtils.createFloatBuffer(normals)); 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // initial normals position (used with animation) 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer normalsBind = new VertexBuffer(Type.BindPoseNormal); 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalsBind.setupData(Usage.CpuOnly, 3, Format.Float, BufferUtils.clone(normalsBuffer.getData())); 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer uvCoordsBuffer = null; 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (uvCoordinates != null) { 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordsBuffer = new VertexBuffer(Type.TexCoord); 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BufferUtils.createFloatBuffer(uvCoordinates.toArray(new Vector2f[uvCoordinates.size()]))); 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //reading custom properties 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Properties properties = this.loadProperties(structure, blenderContext); 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // generating meshes 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //FloatBuffer verticesColorsBuffer = this.createFloatBuffer(verticesColors); 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ByteBuffer verticesColorsBuffer = createByteBuffer(verticesColors); 307a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta verticesAmount = vertexList.size(); 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Entry<Integer, List<Integer>> meshEntry : meshesMap.entrySet()) { 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Mesh mesh = new Mesh(); 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // creating vertices indices for this mesh 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Integer> indexList = meshEntry.getValue(); 313a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta if(verticesAmount <= Short.MAX_VALUE) { 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta short[] indices = new short[indexList.size()]; 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < indexList.size(); ++i) { 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indices[i] = indexList.get(i).shortValue(); 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBuffer(Type.Index, 1, indices); 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int[] indices = new int[indexList.size()]; 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < indexList.size(); ++i) { 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indices[i] = indexList.get(i).intValue(); 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBuffer(Type.Index, 1, indices); 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBuffer(verticesBuffer); 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBuffer(verticesBind); 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // setting vertices colors 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (verticesColorsBuffer != null) { 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBuffer(Type.Color, 4, verticesColorsBuffer); 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.getBuffer(Type.Color).setNormalized(true); 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // setting faces' normals 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBuffer(normalsBuffer); 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBuffer(normalsBind); 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // creating the result 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Geometry geometry = new Geometry(name + (geometries.size() + 1), mesh); 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (materials != null) { 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int materialNumber = meshEntry.getKey().intValue(); 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Material material; 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (materialNumber >= 0) { 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = materials[materialNumber]; 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (materialNumberToTexture.containsKey(Integer.valueOf(materialNumber))) { 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material.getMaterialDef().getAssetName().contains("Lighting")) { 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!materialHelper.hasTexture(material, MaterialHelper.TEXTURE_TYPE_DIFFUSE)) { 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = material.clone(); 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material.setTexture(MaterialHelper.TEXTURE_TYPE_DIFFUSE, 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialNumberToTexture.get(Integer.valueOf(materialNumber))); 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!materialHelper.hasTexture(material, MaterialHelper.TEXTURE_TYPE_COLOR)) { 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = material.clone(); 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material.setTexture(MaterialHelper.TEXTURE_TYPE_COLOR, 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialNumberToTexture.get(Integer.valueOf(materialNumber))); 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialNumber = -1 * (materialNumber + 1); 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (nonTexturedMaterials[materialNumber] == null) { 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nonTexturedMaterials[materialNumber] = materialHelper.getNonTexturedMaterial(materials[materialNumber], 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TextureHelper.TEX_IMAGE); 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = nonTexturedMaterials[materialNumber]; 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geometry.setMaterial(material); 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material.isTransparent()) { 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geometry.setQueueBucket(Bucket.Transparent); 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geometry.setMaterial(blenderContext.getDefaultMaterial()); 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (properties != null && properties.getValue() != null) { 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geometry.setUserData("properties", properties); 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geometries.add(geometry); 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //applying uvCoordinates for all the meshes 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (uvCoordsBuffer != null) { 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Geometry geom : geometries) { 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geom.getMesh().setBuffer(uvCoordsBuffer); 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Map<Material, List<Geometry>> materialMap = new HashMap<Material, List<Geometry>>(); 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Geometry geom : geometries) { 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Material material = geom.getMaterial(); 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Geometry> geomsWithCommonMaterial = materialMap.get(material); 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (geomsWithCommonMaterial == null) { 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomsWithCommonMaterial = new ArrayList<Geometry>(); 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialMap.put(material, geomsWithCommonMaterial); 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomsWithCommonMaterial.add(geom); 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Entry<Material, List<Geometry>> entry : materialMap.entrySet()) { 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta MaterialContext materialContext = blenderContext.getMaterialContext(entry.getKey()); 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (materialContext != null && materialContext.getTexturesCount() > 0) { 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta VertexBuffer coords = UVCoordinatesGenerator.generateUVCoordinates(materialContext.getUvCoordinatesType(), 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialContext.getProjectionType(), materialContext.getTextureDimension(), 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialContext.getProjection(0), entry.getValue()); 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //setting the coordinates inside the mesh context 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Geometry geometry : entry.getValue()) { 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta meshContext.addUVCoordinates(geometry, coords); 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // if there are multiple materials used, extract the shared 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // vertex data 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (geometries.size() > 1){ 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // extract from itself 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Geometry geom : geometries){ 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geom.getMesh().extractVertexData(geom.getMesh()); 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blenderContext.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, geometries); 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blenderContext.setMeshContext(structure.getOldMemoryAddress(), meshContext); 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return geometries; 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method adds a normal to a normals' map. This map is used to merge normals of a vertor that should be rendered smooth. 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param normalToAdd 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a normal to be added 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param normalMap 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * merges normals of faces that will be rendered smooth; the key is the vertex and the value - its normal vector 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param smooth 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the variable that indicates wheather to merge normals (creating the smooth mesh) or not 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param vertices 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a list of vertices read from the blender file 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addNormal(Vector3f normalToAdd, Map<Vector3f, Vector3f> normalMap, boolean smooth, Vector3f... vertices) { 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Vector3f v : vertices) { 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f n = normalMap.get(v); 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!smooth || n == null) { 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta normalMap.put(v, normalToAdd.clone()); 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta n.addLocal(normalToAdd).normalizeLocal(); 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method fills the vertex reference map. The vertices are loaded once and referenced many times in the model. This map is created 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * to tell where the basic vertices are referenced in the result vertex lists. The key of the map is the basic vertex index, and its key 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * - the reference indices list. 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param basicVertexIndex 45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the index of the vertex from its basic table 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param resultIndex 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the index of the vertex in its result vertex list 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param vertexReferenceMap 46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the reference map 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void appendVertexReference(int basicVertexIndex, int resultIndex, Map<Integer, List<Integer>> vertexReferenceMap) { 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Integer> referenceList = vertexReferenceMap.get(Integer.valueOf(basicVertexIndex)); 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (referenceList == null) { 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta referenceList = new ArrayList<Integer>(); 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertexReferenceMap.put(Integer.valueOf(basicVertexIndex), referenceList); 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta referenceList.add(Integer.valueOf(resultIndex)); 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns the vertices colors. Each vertex is stored in byte[4] array. 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param meshStructure 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the structure containing the mesh data 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderContext 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the blender context 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return a list of vertices colors, each color belongs to a single vertex 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws BlenderFileException 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this exception is thrown when the blend file structure is somehow invalid or corrupted 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public List<byte[]> getVerticesColors(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException { 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pMCol = (Pointer) meshStructure.getFieldValue("mcol"); 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<byte[]> verticesColors = null; 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> mCol = null; 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pMCol.isNotNull()) { 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesColors = new LinkedList<byte[]>(); 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mCol = pMCol.fetchData(blenderContext.getInputStream()); 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Structure color : mCol) { 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte r = ((Number)color.getFieldValue("r")).byteValue(); 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte g = ((Number)color.getFieldValue("g")).byteValue(); 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte b = ((Number)color.getFieldValue("b")).byteValue(); 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte a = ((Number)color.getFieldValue("a")).byteValue(); 49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta verticesColors.add(new byte[]{b, g, r, a}); 49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return verticesColors; 49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns the vertices. 50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param meshStructure 50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the structure containing the mesh data 50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderContext 50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the blender context 50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return a list of vertices colors, each color belongs to a single vertex 50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws BlenderFileException 51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this exception is thrown when the blend file structure is somehow invalid or corrupted 51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @SuppressWarnings("unchecked") 51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Vector3f[] getVertices(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException { 51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int verticesAmount = ((Number) meshStructure.getFieldValue("totvert")).intValue(); 51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f[] vertices = new Vector3f[verticesAmount]; 51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (verticesAmount == 0) { 51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return vertices; 51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pMVert = (Pointer) meshStructure.getFieldValue("mvert"); 52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> mVerts = pMVert.fetchData(blenderContext.getInputStream()); 52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(this.fixUpAxis) { 52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < verticesAmount; ++i) { 52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta DynamicArray<Number> coordinates = (DynamicArray<Number>) mVerts.get(i).getFieldValue("co"); 52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertices[i] = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(2).floatValue(), -coordinates.get(1).floatValue()); 52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < verticesAmount; ++i) { 52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta DynamicArray<Number> coordinates = (DynamicArray<Number>) mVerts.get(i).getFieldValue("co"); 53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vertices[i] = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(1).floatValue(), coordinates.get(2).floatValue()); 53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return vertices; 53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean shouldBeLoaded(Structure structure, BlenderContext blenderContext) { 53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 541