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