OSDN Git Service

Cube mapping for textures support.
authorKaelthas_Spellsinger@o2.pl <Kaelthas_Spellsinger@o2.pl@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Sun, 21 Aug 2011 21:07:46 +0000 (21:07 +0000)
committerKaelthas_Spellsinger@o2.pl <Kaelthas_Spellsinger@o2.pl@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Sun, 21 Aug 2011 21:07:46 +0000 (21:07 +0000)
Providing proper texture mapping data to UVCoordinatesGenerator.

git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@8054 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

engine/src/blender/com/jme3/scene/plugins/blender/DataRepository.java
engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialContext.java
engine/src/blender/com/jme3/scene/plugins/blender/materials/MaterialHelper.java
engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java

index 68dc187..8a63e34 100644 (file)
@@ -48,6 +48,7 @@ import com.jme3.scene.plugins.blender.file.BlenderInputStream;
 import com.jme3.scene.plugins.blender.file.DnaBlockData;\r
 import com.jme3.scene.plugins.blender.file.FileBlockHeader;\r
 import com.jme3.scene.plugins.blender.file.Structure;\r
+import com.jme3.scene.plugins.blender.materials.MaterialContext;\r
 import com.jme3.scene.plugins.blender.modifiers.Modifier;\r
 \r
 /**\r
@@ -88,6 +89,8 @@ public class DataRepository {
     protected Map<Long, List<Modifier>> modifiers = new HashMap<Long, List<Modifier>>();\r
     /** A list of constraints for the specified object. */\r
     protected Map<Long, List<Constraint>> constraints = new HashMap<Long, List<Constraint>>();\r
+    /** A map of material contexts. */\r
+    protected Map<Material, MaterialContext> materialContexts = new HashMap<Material, MaterialContext>();\r
     /** A map og helpers that perform loading. */\r
     private Map<String, AbstractBlenderHelper> helpers = new HashMap<String, AbstractBlenderHelper>();\r
 \r
@@ -394,6 +397,29 @@ public class DataRepository {
     public List<Constraint> getConstraints(Long objectOMA) {\r
        return constraints.get(objectOMA);\r
     }\r
+    \r
+       /**\r
+        * This method sets the material context for the given material.\r
+        * If the context is already set it will be replaced.\r
+        * @param material\r
+        *        the material\r
+        * @param materialContext\r
+        *        the material's context\r
+        */\r
+       public void setMaterialContext(Material material, MaterialContext materialContext) {\r
+               this.materialContexts.put(material, materialContext);\r
+       }\r
+\r
+       /**\r
+        * This method returns the material context for the given material.\r
+        * If no context exists then <b>null</b> is returned.\r
+        * @param material\r
+        *        the material\r
+        * @return material's context\r
+        */\r
+       public MaterialContext getMaterialContext(Material material) {\r
+               return materialContexts.get(material);\r
+       }\r
 \r
     /**\r
      * This metod returns the default material.\r
index c8f41b5..9cc776f 100644 (file)
@@ -13,23 +13,25 @@ import com.jme3.scene.plugins.blender.file.Structure;
 import com.jme3.scene.plugins.blender.textures.TextureHelper;
 import com.jme3.texture.Texture.Type;
 
-/*package*/final class MaterialContext {
+public final class MaterialContext {
        private static final Logger LOGGER = Logger.getLogger(MaterialContext.class.getName());
        
-       public final String name;
-       public final List<Structure> mTexs;
-       public final List<Structure> textures;
-       public final int texturesCount;
-       public final Type textureType;
-       public final int textureCoordinatesType;
+       /*package*/ final String name;
+       /*package*/ final List<Structure> mTexs;
+       /*package*/ final List<Structure> textures;
+       /*package*/ final int texturesCount;
+       /*package*/ final Type textureType;
        
-       public final boolean shadeless;
-       public final boolean vertexColor;
-       public final boolean transparent;
-       public final boolean vtangent;
+       /*package*/ final boolean shadeless;
+       /*package*/ final boolean vertexColor;
+       /*package*/ final boolean transparent;
+       /*package*/ final boolean vtangent;
+       
+       /*package*/ int uvCoordinatesType = -1;
+       /*package*/ int projectionType;
        
        @SuppressWarnings("unchecked")
-       public MaterialContext(Structure structure, DataRepository dataRepository) throws BlenderFileException {
+       /*package*/ MaterialContext(Structure structure, DataRepository dataRepository) throws BlenderFileException {
                name = structure.getName();
                
                int mode = ((Number) structure.getFieldValue("mode")).intValue();
@@ -43,16 +45,16 @@ import com.jme3.texture.Texture.Type;
                DynamicArray<Pointer> mtexsArray = (DynamicArray<Pointer>) structure.getFieldValue("mtex");
                int separatedTextures = ((Number) structure.getFieldValue("septex")).intValue();
                Type firstTextureType = null;
-               int texco = -1;
                for (int i = 0; i < mtexsArray.getTotalSize(); ++i) {
                        Pointer p = mtexsArray.get(i);
                        if (p.isNotNull() && (separatedTextures & 1 << i) == 0) {
                                Structure mtex = p.fetchData(dataRepository.getInputStream()).get(0);
                                
                                //the first texture determines the texture coordinates type
-                               if(texco == -1) {
-                                       texco = ((Number) mtex.getFieldValue("texco")).intValue();
-                               } else if(texco != ((Number) mtex.getFieldValue("texco")).intValue()) {
+                               if(uvCoordinatesType == -1) {
+                                       uvCoordinatesType = ((Number) mtex.getFieldValue("texco")).intValue();
+                                       projectionType = ((Number) mtex.getFieldValue("mapping")).intValue();
+                               } else if(uvCoordinatesType != ((Number) mtex.getFieldValue("texco")).intValue()) {
                                        LOGGER.log(Level.WARNING, "The texture with index: {0} has different UV coordinates type than the first texture! This texture will NOT be loaded!", i+1);
                                        continue;
                                }
@@ -79,10 +81,39 @@ import com.jme3.texture.Texture.Type;
                }
                
                this.texturesCount = mTexs.size();
-               this.textureCoordinatesType = texco;
                this.textureType = firstTextureType;
        }
        
+       /**
+        * This method returns the current material's texture UV coordinates type.
+        * @return uv coordinates type
+        */
+       public int getUvCoordinatesType() {
+               return uvCoordinatesType;
+       }
+       
+       /**
+        * This method returns the proper projection type for the material's texture.
+        * This applies only to 2D textures.
+        * @return texture's projection type
+        */
+       public int getProjectionType() {
+               return projectionType;
+       }
+
+       /**
+        * This method returns current material's texture dimension.
+        * @return the material's texture dimension
+        */
+       public int getTextureDimension() {
+               return this.textureType == Type.TwoDimensional ? 2 : 3;
+       }
+       
+       /**
+        * This method determines the type of the texture.
+        * @param texType texture type (from blender)
+        * @return texture type (used by jme)
+        */
        private Type getType(int texType) {
                switch (texType) {
                        case TextureHelper.TEX_IMAGE:// (it is first because probably this will be most commonly used)
index 905f016..c3cd83f 100644 (file)
@@ -178,6 +178,16 @@ public class MaterialHelper extends AbstractBlenderHelper {
                this.faceCullMode = faceCullMode;\r
        }\r
 \r
+       /**\r
+        * This method converts the material structure to jme Material.\r
+        * @param structure\r
+        *        structure with material data\r
+        * @param dataRepository\r
+        *        the data repository\r
+        * @return jme material\r
+        * @throws BlenderFileException\r
+        *         an exception is throw when problems with blend file occur\r
+        */\r
        public Material toMaterial(Structure structure, DataRepository dataRepository) throws BlenderFileException {\r
                LOGGER.log(Level.INFO, "Loading material.");\r
                if (structure == null) {\r
@@ -216,7 +226,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
 \r
                                                // NOTE: Enable mipmaps FOR ALL TEXTURES EVER\r
                                                texture.setMinFilter(MinFilter.Trilinear);\r
-//TODO: textures merging\r
+\r
                                                if ((mapto & 0x01) != 0) {// Col\r
                                                        // Map to COLOR channel or DIFFUSE\r
                                                        // Set diffuse to white so it doesn't get multiplied by texture\r
@@ -228,7 +238,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
                                                        float colfac = ((Number) mtex.getFieldValue("colfac")).floatValue();\r
                                                        texture = textureHelper.blendTexture(new float[] {1, 1, 1}, texture, color, colfac, blendType, negateTexture, dataRepository);\r
                                                        texture.setWrap(WrapMode.Repeat);\r
-                                                       \r
+                                                       //TODO: textures merging\r
                                                        if (materialContext.shadeless) {\r
                                                                texturesMap.put(firstTextureType==Type.ThreeDimensional ? TEXTURE_TYPE_3D : TEXTURE_TYPE_COLOR, texture);\r
                                                        } else {\r
@@ -316,6 +326,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
                        result.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);\r
                }\r
                \r
+               dataRepository.setMaterialContext(result, materialContext);\r
                dataRepository.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, result);\r
                return result;\r
        }\r
index 8064b7c..40b2613 100644 (file)
@@ -63,6 +63,7 @@ import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 import com.jme3.scene.plugins.blender.file.DynamicArray;\r
 import com.jme3.scene.plugins.blender.file.Pointer;\r
 import com.jme3.scene.plugins.blender.file.Structure;\r
+import com.jme3.scene.plugins.blender.materials.MaterialContext;\r
 import com.jme3.scene.plugins.blender.materials.MaterialHelper;\r
 import com.jme3.scene.plugins.blender.objects.Properties;\r
 import com.jme3.scene.plugins.blender.textures.TextureHelper;\r
@@ -391,9 +392,24 @@ public class MeshHelper extends AbstractBlenderHelper {
                        for(Geometry geom : geometries) {\r
                                geom.getMesh().setBuffer(uvCoordsBuffer);\r
                        }\r
-               } else {//TODO: get the proper texture coordinates type\r
-                       UVCoordinatesGenerator.generateUVCoordinates(UVCoordinatesGenerator.TEXCO_ORCO, \r
-                                       com.jme3.texture.Texture.Type.ThreeDimensional, geometries);\r
+               } else {\r
+                       Map<Material, List<Geometry>> materialMap = new HashMap<Material, List<Geometry>>();\r
+                       for(Geometry geom : geometries) {\r
+                               Material material = geom.getMaterial();\r
+                               List<Geometry> geomsWithCommonMaterial = materialMap.get(material);\r
+                               if(geomsWithCommonMaterial==null) {\r
+                                       geomsWithCommonMaterial = new ArrayList<Geometry>();\r
+                                       materialMap.put(material, geomsWithCommonMaterial);\r
+                               }\r
+                               geomsWithCommonMaterial.add(geom);\r
+                               \r
+                       }\r
+                       for(Entry<Material, List<Geometry>> entry : materialMap.entrySet()) {\r
+                               MaterialContext materialContext = dataRepository.getMaterialContext(entry.getKey());\r
+                               UVCoordinatesGenerator.generateUVCoordinates(materialContext.getUvCoordinatesType(), \r
+                                               materialContext.getProjectionType(),\r
+                                               materialContext.getTextureDimension(), entry.getValue());\r
+                       }\r
                }\r
                \r
                dataRepository.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, geometries);\r
index e4fcf68..1447871 100644 (file)
@@ -38,6 +38,7 @@ import java.util.logging.Logger;
 import com.jme3.bounding.BoundingBox;
 import com.jme3.bounding.BoundingSphere;
 import com.jme3.bounding.BoundingVolume;
+import com.jme3.math.Triangle;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Geometry;
@@ -45,7 +46,6 @@ import com.jme3.scene.Mesh;
 import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.VertexBuffer.Format;
 import com.jme3.scene.VertexBuffer.Usage;
-import com.jme3.texture.Texture.Type;
 import com.jme3.util.BufferUtils;
 
 /**
@@ -55,6 +55,7 @@ import com.jme3.util.BufferUtils;
 public class UVCoordinatesGenerator {
        private static final Logger     LOGGER                                          = Logger.getLogger(UVCoordinatesGenerator.class.getName());
 
+       // texture UV coordinates types
        public static final int         TEXCO_ORCO                                      = 1;
        public static final int         TEXCO_REFL                                      = 2;
        public static final int         TEXCO_NORM                                      = 4;
@@ -70,49 +71,61 @@ public class UVCoordinatesGenerator {
        public static final int         TEXCO_TANGENT                           = 4096;
        // still stored in vertex->accum, 1 D
        public static final int         TEXCO_PARTICLE_OR_STRAND        = 8192;                                                                                                 // strand is used
-                                                                                                                                                                                                                                               // for normal
-                                                                                                                                                                                                                                               // materials,
-                                                                                                                                                                                                                                               // particle for halo
-                                                                                                                                                                                                                                               // materials
        public static final int         TEXCO_STRESS                            = 16384;
        public static final int         TEXCO_SPEED                                     = 32768;
 
+       // 2D texture mapping (projection)
+       public static final int         PROJECTION_FLAT                         = 0;
+       public static final int         PROJECTION_CUBE                         = 1;
+       public static final int         PROJECTION_TUBE                         = 2;
+       public static final int         PROJECTION_SPHERE                       = 3;
+
        /**
-        * This method generates UV coordinates for the given geometries.
+        * This method generates UV coordinates for the given mesh.
+        * IMPORTANT! This method assumes that all geometries represent one node.
+        * Each containing mesh with separate material.
+        * So all meshes have the same reference to vertex table which stores all their vertices.
         * @param texco
         *        texture coordinates type
-        * @param textureType
-        *        the type of the texture (only 2D and 3D)
+        * @param projection
+        *        the projection type for 2D textures
+        * @param textureDimension
+        *        the dimension of the texture (only 2D and 3D)
         * @param geometries
-        *        a list of geometries that will have coordinates applied
+        *        a list of geometries the UV coordinates will be applied to
         */
-       public static void generateUVCoordinates(int texco, Type textureType, List<Geometry> geometries) {
-               for (Geometry geometry : geometries) {
-                       UVCoordinatesGenerator.generateUVCoordinates(texco, textureType, geometry.getMesh());
+       public static void generateUVCoordinates(int texco, int projection, int textureDimension, List<Geometry> geometries) {
+               if (textureDimension != 2 && textureDimension != 3) {
+                       throw new IllegalStateException("Unsupported texture dimension: " + textureDimension);
                }
-       }
 
-       /**
-        * This method generates UV coordinates for the given mesh.
-        * @param texco
-        *        texture coordinates type
-        * @param textureType
-        *        the type of the texture (only 2D and 3D)
-        * @param mesh
-        *        a mesh that will have coordinates applied
-        */
-       public static void generateUVCoordinates(int texco, Type textureType, Mesh mesh) {
-               VertexBuffer result = null;
+               VertexBuffer result = new VertexBuffer(VertexBuffer.Type.TexCoord);
+               Mesh mesh = geometries.get(0).getMesh();
+               BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometries);
+
                switch (texco) {
                        case TEXCO_ORCO:
-                               if (textureType == Type.TwoDimensional) {
-
-                               } else if (textureType == Type.ThreeDimensional) {
-                                       BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(mesh);
-
-                                       result = new VertexBuffer(com.jme3.scene.VertexBuffer.Type.TexCoord);
-                                       FloatBuffer positions = mesh.getFloatBuffer(com.jme3.scene.VertexBuffer.Type.Position);
-                                       float[] uvCoordinates = BufferUtils.getFloatArray(positions);
+                               float[] uvCoordinates = null;
+                               if (textureDimension == 2) {
+                                       switch (projection) {
+                                               case PROJECTION_FLAT:
+                                                       uvCoordinates = UVCoordinatesGenerator.flatProjection(mesh, bb);
+                                                       break;
+                                               case PROJECTION_CUBE:
+                                                       uvCoordinates = UVCoordinatesGenerator.cubeProjection(mesh, bb);
+                                                       break;
+                                               case PROJECTION_TUBE:
+                                                       uvCoordinates = UVCoordinatesGenerator.tubeProjection(mesh, bb);
+                                                       break;
+                                               case PROJECTION_SPHERE:
+                                                       uvCoordinates = UVCoordinatesGenerator.sphereProjection(mesh, bb);
+                                                       break;
+                                               default:
+                                                       throw new IllegalStateException("Unknown projection type: " + projection);
+                                       }
+                               } else {
+                                       FloatBuffer positions = mesh.getFloatBuffer(VertexBuffer.Type.Position);
+                                       uvCoordinates = BufferUtils.getFloatArray(positions);
                                        Vector3f min = bb.getMin(null);
                                        float[] ext = new float[] { bb.getXExtent() * 2, bb.getYExtent() * 2, bb.getZExtent() * 2 };
 
@@ -122,10 +135,22 @@ public class UVCoordinatesGenerator {
                                                uvCoordinates[i + 1] = (uvCoordinates[i + 1] - min.y) / ext[1];
                                                uvCoordinates[i + 2] = (uvCoordinates[i + 2] - min.z) / ext[2];
                                        }
-
-                                       result.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(uvCoordinates));
+                                       result.setupData(Usage.Static, textureDimension, Format.Float, BufferUtils.createFloatBuffer(uvCoordinates));
+                               }
+                               result.setupData(Usage.Static, textureDimension, Format.Float, BufferUtils.createFloatBuffer(uvCoordinates));
+                               break;
+                       case TEXCO_UV:
+                               if (textureDimension == 2) {
+                                       FloatBuffer uvCoordinatesBuffer = BufferUtils.createFloatBuffer(mesh.getVertexCount() << 1);
+                                       Vector2f[] data = new Vector2f[] { new Vector2f(0, 1), new Vector2f(0, 0), new Vector2f(1, 0) };
+                                       for (int i = 0; i < mesh.getVertexCount(); ++i) {
+                                               Vector2f uv = data[i % 3];
+                                               uvCoordinatesBuffer.put(uv.x);
+                                               uvCoordinatesBuffer.put(uv.y);
+                                       }
+                                       result.setupData(Usage.Static, textureDimension, Format.Float, uvCoordinatesBuffer);
                                } else {
-                                       throw new IllegalStateException("Unsupported texture type: " + textureType);
+
                                }
                                break;
                        case TEXCO_GLOB:
@@ -134,8 +159,6 @@ public class UVCoordinatesGenerator {
                        case TEXCO_TANGENT:
 
                                break;
-                       case TEXCO_UV:
-                               break;
                        case TEXCO_STRESS:
 
                                break;
@@ -157,38 +180,110 @@ public class UVCoordinatesGenerator {
                                throw new IllegalStateException("Unknown texture coordinates value: " + texco);
                }
 
-               mesh.clearBuffer(VertexBuffer.Type.TexCoord);// in case there are coordinates already set
-               mesh.setBuffer(result);
+               // each mesh will have the same coordinates
+               for (Geometry geometry : geometries) {
+                       mesh = geometry.getMesh();
+                       mesh.clearBuffer(VertexBuffer.Type.TexCoord);// in case there are coordinates already set
+                       mesh.setBuffer(result);
+               }
        }
 
        /**
         * Flat projection for 2D textures.
         * @param mesh
         *        mesh that is to be projected
+        * @param bb
+        *        the bounding box for projecting
         * @return UV coordinates after the projection
         */
-       public Vector2f[] flatProjection(Mesh mesh) {
-               return null;// TODO: implement
+       private static float[] flatProjection(Mesh mesh, BoundingBox bb) {
+               if (bb == null) {
+                       bb = UVCoordinatesGenerator.getBoundingBox(mesh);
+               }
+               Vector3f min = bb.getMin(null);
+               float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f };
+               FloatBuffer positions = mesh.getFloatBuffer(com.jme3.scene.VertexBuffer.Type.Position);
+               float[] uvCoordinates = new float[positions.limit() / 3 * 2];
+               for (int i = 0, j = 0; i < positions.limit(); i += 3, j += 2) {
+                       uvCoordinates[j] = (positions.get(i) - min.x) / ext[0];
+                       uvCoordinates[j + 1] = (positions.get(i + 1) - min.y) / ext[1];
+                       // skip the Z-coordinate
+               }
+               return uvCoordinates;
        }
 
        /**
         * Cube projection for 2D textures.
         * @param mesh
         *        mesh that is to be projected
+        * @param bb
+        *        the bounding box for projecting
         * @return UV coordinates after the projection
         */
-       public Vector2f[] cubeProjection(Mesh mesh) {
-               return null;// TODO: implement
+       private static float[] cubeProjection(Mesh mesh, BoundingBox bb) {
+               Triangle triangle = new Triangle();
+               Vector3f x = new Vector3f(1, 0, 0);
+               Vector3f y = new Vector3f(0, 1, 0);
+               Vector3f z = new Vector3f(0, 0, 1);
+               Vector3f min = bb.getMin(null);
+               float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f, bb.getZExtent() * 2.0f };
+
+               float[] uvCoordinates = new float[mesh.getTriangleCount() * 6];// 6 == 3 * 2
+               float borderAngle = (float)Math.sqrt(2.0f)/2.0f;
+               for (int i = 0, pointIndex = 0; i < mesh.getTriangleCount(); ++i) {
+                       mesh.getTriangle(i, triangle);
+                       Vector3f n = triangle.getNormal();
+                       float dotNX = Math.abs(n.dot(x));
+                       float dorNY = Math.abs(n.dot(y));
+                       float dotNZ = Math.abs(n.dot(z));
+                       if (dotNX > borderAngle) {
+                               if (dotNZ < borderAngle) {// discard X-coordinate
+                                       uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
+                                       uvCoordinates[pointIndex++] = (triangle.get1().z - min.z) / ext[2];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().z - min.z) / ext[2];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().z - min.z) / ext[2];
+                               } else {// discard Z-coordinate
+                                       uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
+                               }
+                       } else {
+                               if (dorNY > borderAngle) {// discard Y-coordinate
+                                       uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get1().z - min.z) / ext[2];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().z - min.z) / ext[2];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().z - min.z) / ext[2];
+                               } else {// discard Z-coordinate
+                                       uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
+                                       uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
+                               }
+                       }
+                       triangle.setNormal(null);//clear the previous normal vector
+               }
+               return uvCoordinates;
        }
 
        /**
         * Tube projection for 2D textures.
         * @param mesh
         *        mesh that is to be projected
+        * @param bb
+        *        the bounding box for projecting
         * @return UV coordinates after the projection
         */
 
-       public Vector2f[] tubeProjection(Mesh mesh) {
+       private static float[] tubeProjection(Mesh mesh, BoundingBox bb) {
                return null;// TODO: implement
        }
 
@@ -196,9 +291,11 @@ public class UVCoordinatesGenerator {
         * Sphere projection for 2D textures.
         * @param mesh
         *        mesh that is to be projected
+        * @param bb
+        *        the bounding box for projecting
         * @return UV coordinates after the projection
         */
-       public Vector2f[] sphereProjection(Mesh mesh) {
+       private static float[] sphereProjection(Mesh mesh, BoundingBox bb) {
                return null;// TODO: implement
                // Vector2f[] uvTable = new Vector2f[vertexList.size()];
                // Ray ray = new Ray();