소스 검색

Merge branch 'next' of https://github.com/blackberry/GamePlay into next

Conflicts:
	gameplay/src/ScriptController.cpp
Darryl Gough 13 년 전
부모
커밋
356ab9e809

+ 45 - 40
gameplay-encoder/src/DAESceneEncoder.cpp

@@ -1611,7 +1611,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     }
     mesh = new Mesh();
     mesh->setId(geometryId.c_str());
-    
+
     std::vector<DAEPolygonInput*> polygonInputs;
 
     // Quickly just go through each triangles array and make sure they have the same number of inputs
@@ -1819,7 +1819,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                                 break;
                             case 'b':
                             case 'B':
-                                vertex.diffuse.z = (float)source.get(index + i); // blue
+                                vertex.diffuse.z = (float)source.get(index+ i ); // blue
                                 break;
                             case 'a':
                             case 'A':
@@ -1849,34 +1849,43 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                 break;
 
             case TEXCOORD0:
-                vertex.hasTexCoord = true;
-                if (polygonInputs[k]->accessor)
-                {
-                    // TODO: This assumes (s, t) are first
-                    unsigned int stride = (unsigned int)polygonInputs[k]->accessor->getStride();
-                    if (polyIndexInt < 0)
-                    {
-                        unsigned int i = (unsigned int)((int)polygonInputs[k]->accessor->getCount()) + polyIndexInt;
-                        vertex.texCoord.x = (float)source.get(i * stride);
-                        vertex.texCoord.y = (float)source.get(i * stride + 1);
-                    }
-                    else
-                    {
-                        vertex.texCoord.x = (float)source.get(polyIndex * stride);
-                        vertex.texCoord.y = (float)source.get(polyIndex * stride + 1);
-                    }
-                }
-                else
+            case TEXCOORD1:
+            case TEXCOORD2:
+            case TEXCOORD3:
+            case TEXCOORD4:
+            case TEXCOORD5:
+            case TEXCOORD6:
+            case TEXCOORD7:
                 {
-                    vertex.texCoord.x = (float)source.get(polyIndex * 2);
-                    vertex.texCoord.y = (float)source.get(polyIndex * 2 + 1);
+                    unsigned int index = polygonInputs[k]->type - TEXCOORD0;
+                    //for (unsigned int i = 0; i < uvSetCount; ++i)
+                    //{
+                        vertex.hasTexCoord[index] = true;
+                        if (polygonInputs[k]->accessor)
+                        {
+                            // TODO: This assumes (s, t) are first
+                            unsigned int stride = (unsigned int)polygonInputs[k]->accessor->getStride();
+                            if (polyIndexInt < 0)
+                            {
+                                unsigned int i = (unsigned int)((int)polygonInputs[k]->accessor->getCount()) + polyIndexInt;
+                                vertex.texCoord[index].x = (float)source.get(i * stride);
+                                vertex.texCoord[index].y = (float)source.get(i * stride + 1);
+                            }
+                            else
+                            {
+                                vertex.texCoord[index].x = (float)source.get(polyIndex * stride);
+                                vertex.texCoord[index].y = (float)source.get(polyIndex * stride + 1);
+                            }
+                        }
+                        else
+                        {
+                            vertex.texCoord[index].x = (float)source.get(polyIndex * 2);
+                            vertex.texCoord[index].y = (float)source.get(polyIndex * 2 + 1);
+                        }
+                    //}
                 }
                 break;
 
-            case TEXCOORD1:
-                // TODO
-                break;
-
             default:
                 break;
             }
@@ -1909,13 +1918,6 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
         // Add our new subset for the mesh.
         mesh->addMeshPart(subset);
     }
-    
-    bool hasNormals = mesh->vertices[0].hasNormal;
-    bool hasDiffuses = mesh->vertices[0].hasDiffuse;
-    bool hasTangents = mesh->vertices[0].hasTangent;
-    bool hasBinormals = mesh->vertices[0].hasBinormal;
-    bool hasTexCoords = mesh->vertices[0].hasTexCoord;
-    bool hasWeights = mesh->vertices[0].hasWeights;
 
     // The order that the vertex elements are add to the list matters.
     // It should be the same order as how the Vertex data is written.
@@ -1924,32 +1926,35 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     mesh->addVetexAttribute(POSITION, Vertex::POSITION_COUNT);
     
     // Normals
-    if (hasNormals)
+    if (mesh->vertices[0].hasNormal)
     {
         mesh->addVetexAttribute(NORMAL, Vertex::NORMAL_COUNT);
     }
     // Tangents
-    if (hasTangents)
+    if (mesh->vertices[0].hasTangent)
     {
         mesh->addVetexAttribute(TANGENT, Vertex::TANGENT_COUNT);
     }
     // Binormals
-    if (hasBinormals)
+    if (mesh->vertices[0].hasBinormal)
     {
         mesh->addVetexAttribute(BINORMAL, Vertex::BINORMAL_COUNT);
     }
     // Texture Coordinates
-    if (hasTexCoords)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        mesh->addVetexAttribute(TEXCOORD0, Vertex::TEXCOORD_COUNT);
+        if (mesh->vertices[0].hasTexCoord[i])
+        {
+            mesh->addVetexAttribute(TEXCOORD0 + i, Vertex::TEXCOORD_COUNT);
+        }
     }
     // Diffuse Color
-    if (hasDiffuses)
+    if (mesh->vertices[0].hasDiffuse)
     {
         mesh->addVetexAttribute(COLOR, Vertex::DIFFUSE_COUNT);
     }
     // Skinning BlendWeights BlendIndices
-    if (hasWeights)
+    if (mesh->vertices[0].hasWeights)
     {
         mesh->addVetexAttribute(BLENDWEIGHTS, Vertex::BLEND_WEIGHTS_COUNT);
         mesh->addVetexAttribute(BLENDINDICES, Vertex::BLEND_INDICES_COUNT);

+ 6 - 2
gameplay-encoder/src/EncoderArguments.cpp

@@ -185,7 +185,8 @@ void EncoderArguments::printUsage() const
         "\t\tGenerates a single heightmap image using meshes from the specified\n" \
         "\t\tnodes. Node id list should be in quotes with a space between each id.\n" \
         "\t\tFilename is the name of the image (PNG) to be saved.\n" \
-        "\t\tMultiple -h arguments can be supplied to generate more than one heightmap.\n");
+        "\t\tMultiple -h arguments can be supplied to generate more than one heightmap.\n" \
+        "\t\tFor 24-bit packed height data use -hp instead of -h.\n");
     fprintf(stderr,"\n");
     fprintf(stderr,"TTF file options:\n");
     fprintf(stderr,"  -s <size>\tSize of the font.\n");
@@ -315,13 +316,16 @@ void EncoderArguments::readOption(const std::vector<std::string>& options, size_
         break;
     case 'h':
         {
-            if (str.compare("-heightmap") == 0 || str.compare("-h") == 0)
+            bool isHighPrecision = str.compare("-hp") == 0;
+            if (str.compare("-heightmap") == 0 || str.compare("-h") == 0 || isHighPrecision)
             {
                 (*index)++;
                 if (*index < (options.size() + 1))
                 {
                     _heightmaps.resize(_heightmaps.size() + 1);
                     HeightmapOption& heightmap = _heightmaps.back();
+                    
+                    heightmap.isHighPrecision = isHighPrecision;
 
                     // Split node id list into tokens
                     unsigned int length = options[*index].size() + 1;

+ 1 - 0
gameplay-encoder/src/EncoderArguments.h

@@ -24,6 +24,7 @@ public:
     {
         std::vector<std::string> nodeIds;
         std::string filename;
+        bool isHighPrecision;
     };
 
     /**

+ 60 - 49
gameplay-encoder/src/FBXSceneEncoder.cpp

@@ -30,11 +30,14 @@ static float getFieldOfView(FbxCamera* fbxCamera);
  * Loads the texture coordinates from given mesh's polygon part into the vertex.
  * 
  * @param fbxMesh The mesh to get the polygon from.
- * @param polyIndex The index of the polygon.
- * @param posInPoly The position in the polygon.
+ * @param uvs The UV list to load tex coords from.
+ * @param uvSetIndex The UV set index of the uvs.
+ * @param polyIndex The index of the polygon in the mesh.
+ * @param posInPoly The position of the vertex in the polygon.
+ * @param meshVertexIndex The index of the vertex in the mesh.
  * @param vertex The vertex to copy the texture coordinates to.
  */
-static void loadTextureCoords(FbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex);
+static void loadTextureCoords(FbxMesh* fbxMesh, const FbxGeometryElementUV* uvs, int uvSetIndex, int polyIndex, int posInPoly, int meshVertexIndex, Vertex* vertex);
 
 /**
  * Loads the normal from the mesh and adds it to the given vertex.
@@ -851,6 +854,11 @@ Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
     std::vector<std::vector<Vector2> > weights;
     bool hasSkin = loadBlendWeights(fbxMesh, weights);
     
+    // Get list of uv sets for mesh
+    FbxStringList uvSetNameList;
+    fbxMesh->GetUVSetNames(uvSetNameList);
+    const int uvSetCount = uvSetNameList.GetCount();
+
     int vertexIndex = 0;
     FbxVector4* controlPoints = fbxMesh->GetControlPoints();
     const int polygonCount = fbxMesh->GetPolygonCount();
@@ -867,7 +875,15 @@ Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
             vertex.position.y = (float)position[1];
             vertex.position.z = (float)position[2];
 
-            loadTextureCoords(fbxMesh, polyIndex, posInPoly, &vertex);
+            // Load tex coords for all uv sets
+            for (int uvSetIndex = 0; uvSetIndex < uvSetCount; ++uvSetIndex)
+            {
+                const FbxGeometryElementUV* uvElement = fbxMesh->GetElementUV(uvSetNameList.GetStringAt(uvSetIndex));
+                if (uvElement)
+                    loadTextureCoords(fbxMesh, uvElement, uvSetIndex, polyIndex, posInPoly, vertexIndex, &vertex);
+            }
+
+            // Load other data
             loadNormal(fbxMesh, vertexIndex, controlPointIndex, &vertex);
             loadTangent(fbxMesh, vertexIndex, &vertex);
             loadBinormal(fbxMesh, vertexIndex, &vertex);
@@ -931,9 +947,12 @@ Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
         mesh->addVetexAttribute(BINORMAL, Vertex::BINORMAL_COUNT);
     }
     // Texture Coordinates
-    if (vertex.hasTexCoord)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        mesh->addVetexAttribute(TEXCOORD0, Vertex::TEXCOORD_COUNT);
+        if (vertex.hasTexCoord[i])
+        {
+            mesh->addVetexAttribute(TEXCOORD0 + i, Vertex::TEXCOORD_COUNT);
+        }
     }
     // Diffuse Color
     if (vertex.hasDiffuse)
@@ -1061,54 +1080,46 @@ float getFieldOfView(FbxCamera* fbxCamera)
     return (float)fieldOfViewY;
 }
 
-void loadTextureCoords(FbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex)
+void loadTextureCoords(FbxMesh* fbxMesh, const FbxGeometryElementUV* uvs, int uvSetIndex, int polyIndex, int posInPoly, int meshVertexIndex, Vertex* vertex)
 {
     assert(fbxMesh && polyIndex >=0 && posInPoly >= 0);
-    if (fbxMesh->GetElementUVCount() > 0)
+
+    const bool useIndex = uvs->GetReferenceMode() != FbxGeometryElement::eDirect;
+    const int indexCount = useIndex ? uvs->GetIndexArray().GetCount() : 0;
+    int uvIndex = -1;
+
+    switch (uvs->GetMappingMode())
     {
-        // Get only the first UV coordinates.
-        FbxGeometryElementUV* uv = fbxMesh->GetElementUV(0);
-        switch (uv->GetMappingMode())
+    case FbxGeometryElement::eByControlPoint:
         {
-        case FbxGeometryElement::eByControlPoint:
-            switch (uv->GetReferenceMode())
-            {
-            case FbxGeometryElement::eDirect:
-                vertex->hasTexCoord = true;
-                vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(polyIndex)[0];
-                vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(polyIndex)[1];
-                break;
-            case FbxGeometryElement::eIndexToDirect:
-                {
-                    int id = uv->GetIndexArray().GetAt(polyIndex);
-                    vertex->hasTexCoord = true;
-                    vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(id)[0];
-                    vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(id)[1];
-                }
-                break;
-            default:
-                break;
-            }
-            break;
-        case FbxGeometryElement::eByPolygonVertex:
-            {
-                int lTextureUVIndex = fbxMesh->GetTextureUVIndex(polyIndex, posInPoly);
-                switch (uv->GetReferenceMode())
-                {
-                case FbxGeometryElement::eDirect:
-                case FbxGeometryElement::eIndexToDirect:
-                    vertex->hasTexCoord = true;
-                    vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(lTextureUVIndex)[0];
-                    vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(lTextureUVIndex)[1];
-                    break;
-                default:
-                    break;
-                }
-            }
-            break;
-        default:
-            break;
+            // Get the index of the current vertex in control points array
+            int polyVertIndex = fbxMesh->GetPolygonVertex(polyIndex, posInPoly);
+
+            // The UV index depends on the reference mode
+            uvIndex = useIndex ? uvs->GetIndexArray().GetAt(polyVertIndex) : polyVertIndex;
         }
+        break;
+
+    case FbxGeometryElement::eByPolygonVertex:
+        if (meshVertexIndex < indexCount)
+        {
+            uvIndex = useIndex ? uvs->GetIndexArray().GetAt(meshVertexIndex) : meshVertexIndex;
+        }
+        break;
+
+    default:
+        // Only support eByPolygonVertex and eByControlPoint mappings
+        break;
+    }
+
+    vertex->hasTexCoord[uvSetIndex] = true;
+
+    // Store UV information in vertex
+    if (uvIndex != -1)
+    {
+        FbxVector2 uvValue = uvs->GetDirectArray().GetAt(uvIndex);
+        vertex->texCoord[uvSetIndex].x = (float)uvValue[0];
+        vertex->texCoord[uvSetIndex].y = (float)uvValue[1];
     }
 }
 

+ 1 - 1
gameplay-encoder/src/GPBFile.cpp

@@ -330,7 +330,7 @@ void GPBFile::adjust()
     const std::vector<EncoderArguments::HeightmapOption>& heightmaps = EncoderArguments::getInstance()->getHeightmapOptions();
     for (unsigned int i = 0, count = heightmaps.size(); i < count; ++i)
     {
-        Heightmap::generate(heightmaps[i].nodeIds, heightmaps[i].filename.c_str());
+        Heightmap::generate(heightmaps[i].nodeIds, heightmaps[i].filename.c_str(), heightmaps[i].isHighPrecision);
     }
 }
 

+ 18 - 8
gameplay-encoder/src/Heightmap.cpp

@@ -36,7 +36,7 @@ bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const Vect
 int intersect_triangle(const float orig[3], const float dir[3], const float vert0[3], const float vert1[3], const float vert2[3], float *t, float *u, float *v);
 bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const std::vector<Vertex>& vertices, const std::vector<MeshPart*>& parts, Vector3* point);
 
-void Heightmap::generate(const std::vector<std::string>& nodeIds, const char* filename)
+void Heightmap::generate(const std::vector<std::string>& nodeIds, const char* filename, bool highP)
 {
     printf("Generating heightmap: %s...\n", filename);
 
@@ -203,14 +203,24 @@ void Heightmap::generate(const std::vector<std::string>& nodeIds, const char* fi
             // Write height value normalized between 0-255 (between min and max height)
             float h = heights[y*width + x];
             float nh = (h - minHeight) / maxHeight;
-            int bits = (int)(nh * 16777215.0f); // 2^24-1
-
             int pos = x*3;
-            row[pos+2] = (png_byte)(bits & 0xff);
-            bits >>= 8;
-            row[pos+1] = (png_byte)(bits & 0xff);
-            bits >>= 8;
-            row[pos] = (png_byte)(bits & 0xff);
+            if (highP)
+            {
+                // high precision packed 24-bit (RGB)
+                int bits = (int)(nh * 16777215.0f); // 2^24-1
+                
+                row[pos+2] = (png_byte)(bits & 0xff);
+                bits >>= 8;
+                row[pos+1] = (png_byte)(bits & 0xff);
+                bits >>= 8;
+                row[pos] = (png_byte)(bits & 0xff);
+            }
+            else
+            {
+                // standard precision 8-bit (grayscale)
+                png_byte b = (png_byte)(nh * 255.0f);
+                row[pos] = row[pos+1] = row[pos+2] = b;
+            }
         }
         png_write_row(png_ptr, row);
     }

+ 2 - 1
gameplay-encoder/src/Heightmap.h

@@ -15,8 +15,9 @@ public:
      *
      * @param nodeIds List of node ids to include in the heightmap generation.
      * @param filename Output PNG file to write the heightmap image to.
+     * @param highP Use packed 24-bit (RGB) instead of standard 8-bit grayscale.
      */
-    static void generate(const std::vector<std::string>& nodeIds, const char* filename);
+    static void generate(const std::vector<std::string>& nodeIds, const char* filename, bool highP = false);
 
 
 };

+ 19 - 8
gameplay-encoder/src/Vertex.cpp

@@ -5,8 +5,10 @@ namespace gameplay
 {
 
 Vertex::Vertex(void)
-    : hasNormal(false), hasTangent(false), hasBinormal(false), hasTexCoord(false), hasDiffuse(false), hasWeights(false)
+    : hasNormal(false), hasTangent(false), hasBinormal(false), hasDiffuse(false), hasWeights(false)
 {
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+        hasTexCoord[i] = false;
 }
 
 Vertex::~Vertex(void)
@@ -22,8 +24,11 @@ unsigned int Vertex::byteSize() const
         count += TANGENT_COUNT;
     if (hasBinormal)
         count += BINORMAL_COUNT;
-    if (hasTexCoord)
-        count += TEXCOORD_COUNT;
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+    {
+        if (hasTexCoord[i])
+            count += TEXCOORD_COUNT;
+    }
     if (hasWeights)
         count += BLEND_WEIGHTS_COUNT + BLEND_INDICES_COUNT;
     if (hasDiffuse)
@@ -46,9 +51,12 @@ void Vertex::writeBinary(FILE* file) const
     {
         writeVectorBinary(binormal, file);
     }
-    if (hasTexCoord)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        writeVectorBinary(texCoord, file);
+        if (hasTexCoord[i])
+        {
+            writeVectorBinary(texCoord[i], file);
+        }
     }
     if (hasDiffuse)
     {
@@ -80,10 +88,13 @@ void Vertex::writeText(FILE* file) const
         write("// binormal\n", file);
         writeVectorText(binormal, file);
     }
-    if (hasTexCoord)
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
     {
-        write("// texCoord\n", file);
-        writeVectorText(texCoord, file);
+        if (hasTexCoord[i])
+        {
+            write("// texCoord\n", file);
+            writeVectorText(texCoord[i], file);
+        }
     }
     if (hasDiffuse)
     {

+ 21 - 12
gameplay-encoder/src/Vertex.h

@@ -6,6 +6,9 @@
 #include "Vector3.h"
 #include "Vector4.h"
 
+// Maximum number of supported UV sets
+#define MAX_UV_SETS 8
+
 namespace gameplay
 {
 
@@ -36,13 +39,13 @@ public:
     Vector3 normal;
     Vector3 tangent;
     Vector3 binormal;
-    Vector2 texCoord;
+    Vector2 texCoord[MAX_UV_SETS];
     Vector4 diffuse;
 
     Vector4 blendWeights;
     Vector4 blendIndices;
 
-    bool hasNormal, hasTangent, hasBinormal, hasTexCoord, hasDiffuse, hasWeights;
+    bool hasNormal, hasTangent, hasBinormal, hasTexCoord[MAX_UV_SETS], hasDiffuse, hasWeights;
 
     inline bool operator<(const Vertex& v) const
     {
@@ -54,23 +57,24 @@ public:
                 {
                     if (binormal == v.binormal)
                     {
-                        if (texCoord == v.texCoord)
+                        if (diffuse == v.diffuse)
                         {
-                            if (diffuse == v.diffuse)
+                            if (blendWeights == v.blendWeights)
                             {
-                                if (blendWeights == v.blendWeights)
+                                if (blendIndices == v.blendIndices)
                                 {
-                                    if (blendIndices == v.blendIndices)
+                                    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
                                     {
-                                        return false;
+                                        if (!(texCoord[i] == v.texCoord[i]))
+                                            return texCoord[i] < v.texCoord[i];
                                     }
-                                    return blendIndices < v.blendIndices;
+                                    return false;
                                 }
-                                return blendWeights < v.blendWeights;
+                                return blendIndices < v.blendIndices;
                             }
-                            return diffuse < v.diffuse;
+                            return blendWeights < v.blendWeights;
                         }
-                        return texCoord < v.texCoord;
+                        return diffuse < v.diffuse;
                     }
                     return binormal < v.binormal;
                 }
@@ -83,7 +87,12 @@ public:
 
     inline bool operator==(const Vertex& v) const
     {
-        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal && texCoord==v.texCoord &&
+        for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+        {
+            if (!(texCoord[i] == v.texCoord[i]))
+                return false;
+        }
+        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal &&
             diffuse==v.diffuse && blendWeights==v.blendWeights && blendIndices==v.blendIndices;
     }
 

+ 4 - 1
gameplay/res/shaders/colored-unlit.frag

@@ -6,6 +6,9 @@ precision highp float;
 #if defined(VERTEX_COLOR)
 varying vec3 v_color;						// Input Vertex color ( r g b )
 #endif
+#if defined(TEXTURE_LIGHTMAP)
+varying vec2 v_texCoord;
+#endif
 
 // Uniforms
 uniform vec4 u_diffuseColor;               	// Diffuse color
@@ -30,7 +33,7 @@ void main()
     #endif
 	#if defined(TEXTURE_LIGHTMAP)
 	vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord);
-	gl_FragColor.a *= lightColor.a;
+	gl_FragColor.rgb *= lightColor.rgb;
 	#endif
 	// Global color modulation
 	#if defined(MODULATE_COLOR)

+ 16 - 2
gameplay/res/shaders/colored-unlit.vert

@@ -1,14 +1,23 @@
 // Inputs
 attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
+#if defined(TEXTURE_LIGHTMAP)
+attribute vec2 a_texCoord;                                  // Texture Coordinate (for lightmapping)
+#endif
 #if defined(SKINNING)
 attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
 attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
 #endif
 #if defined(VERTEX_COLOR)
 attribute vec3 a_color;										// Vertex Color								(r, g, b)
-varying vec3 v_color;										// Output Vertex color						(r, g, b)
 #endif
 
+// Outputs
+#if defined(TEXTURE_LIGHTMAP)
+varying vec2 v_texCoord;                                    // Output Texture Coordinate
+#endif
+#if defined(VERTEX_COLOR)
+varying vec3 v_color;										// Output Vertex color						(r, g, b)
+#endif
 
 // Uniforms
 uniform mat4 u_worldViewProjectionMatrix;					// Matrix to transform a position to clip space.
@@ -32,8 +41,13 @@ void main()
     // Transform position to clip space.a
     gl_Position = u_worldViewProjectionMatrix *  position;
     
+    // Pass lightmap tex coord to fragment shader
+    #if defined(TEXTURE_LIGHTMAP)
+    v_texCoord0 = a_texCoord0;
+    #endif
+
      // Pass on vertex color to fragment shader
     #if defined(VERTEX_COLOR)
 	v_color = a_color;
     #endif
-}
+}

+ 11 - 4
gameplay/res/shaders/textured-unlit.frag

@@ -15,16 +15,23 @@ uniform float u_modulateAlpha;              // Modulation alpha
 #endif
 
 // Inputs
-varying vec2 v_texCoord;                	// Texture coordinate(u, v)
+varying vec2 v_texCoord0;                	// Texture coordinate(u, v)
+#if defined(TEXCOORD1)
+varying vec2 v_texCoord1;                   // Second tex coord for multi-texturing
+#endif
 
 // Fragment Program
 void main()
 {
     // Sample the texture for the color
-    gl_FragColor = texture2D(u_diffuseTexture, v_texCoord);
+    gl_FragColor = texture2D(u_diffuseTexture, v_texCoord0);
 	#if defined(TEXTURE_LIGHTMAP)
-	vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord);
-	gl_FragColor.a *= lightColor.a;
+    #if defined(TEXCOORD1)
+    vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord1);
+    #else
+    vec4 lightColor = texture2D(u_lightmapTexture, v_texCoord0);
+    #endif
+    gl_FragColor.rgb *= lightColor.rgb;
 	#endif
 	// Global color modulation
 	#if defined(MODULATE_COLOR)

+ 12 - 3
gameplay/res/shaders/textured-unlit.vert

@@ -1,6 +1,9 @@
 // Inputs
 attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
-attribute vec2 a_texCoord;									// Vertex Texture Coordinate				(u, v)
+attribute vec2 a_texCoord0;									// Vertex Texture Coordinate				(u, v)
+#if defined(TEXCOORD1)
+attribute vec2 a_texCoord1;                                 // Second tex coord for multi-texturing
+#endif
 #if defined(SKINNING)
 attribute vec4 a_blendWeights;								// Vertex blend weight, up to 4				(0, 1, 2, 3) 
 attribute vec4 a_blendIndices;								// Vertex blend index int u_matrixPalette	(0, 1, 2, 3)
@@ -19,7 +22,10 @@ uniform vec2 u_textureOffset;								// Texture offset
 #endif
 
 // Outputs
-varying vec2 v_texCoord;									// Texture Coordinate
+varying vec2 v_texCoord0;									// Texture Coordinate
+#if defined(TEXCOORD1)
+varying vec2 v_texCoord1;                                   // Second tex coord for multi-texturing
+#endif
 
 // Vertex attribute accessors
 #if defined(SKINNING)
@@ -38,7 +44,10 @@ void main()
     gl_Position = u_worldViewProjectionMatrix * position;
 
     // Texture transformation.
-    v_texCoord = a_texCoord;
+    v_texCoord0 = a_texCoord0;
+    #if defined(TEXCOORD1)
+    v_texCoord1 = a_texCoord1;
+    #endif
     #if defined(TEXTURE_REPEAT)
     v_texCoord *= u_textureRepeat;
     #endif

+ 0 - 1
gameplay/src/ScriptController.cpp

@@ -1025,4 +1025,3 @@ template<> std::string ScriptController::executeFunction<std::string>(const char
     SCRIPT_EXECUTE_FUNCTION_PARAM_LIST(std::string, luaL_checkstring);
 }
 
-}

+ 1 - 1
gameplay/src/ScriptController.h

@@ -839,4 +839,4 @@ template<> std::string ScriptController::executeFunction<std::string>(const char
 
 #include "ScriptController.inl"
 
-#endif
+#endif

+ 7 - 5
gameplay/src/VertexAttributeBinding.cpp

@@ -171,15 +171,17 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
             attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_BLENDINDICES_NAME);
             break;
         case VertexFormat::TEXCOORD0:
-            attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME);
-            // Try adding a "0" after the texcoord attrib name (flexible name for this case).
+            if ((attrib = effect->getVertexAttribute(VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME)) != -1)
+                break;
+
+            /*// Try adding a "0" after the texcoord attrib name (flexible name for this case).
             if (attrib == -1)
             {
                 name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME;
-                name += "0";
+                name += '0';
                 attrib = effect->getVertexAttribute(name.c_str());
             }
-            break; 
+            break;*/
         case VertexFormat::TEXCOORD1:
         case VertexFormat::TEXCOORD2:
         case VertexFormat::TEXCOORD3:
@@ -188,7 +190,7 @@ VertexAttributeBinding* VertexAttributeBinding::create(Mesh* mesh, const VertexF
         case VertexFormat::TEXCOORD6:
         case VertexFormat::TEXCOORD7:
             name = VERTEX_ATTRIBUTE_TEXCOORD_PREFIX_NAME;
-            name += (e.usage - VertexFormat::TEXCOORD0);
+            name += '0' + (e.usage - VertexFormat::TEXCOORD0);
             attrib = effect->getVertexAttribute(name.c_str());
             break;
         default:

+ 63 - 1
gameplay/src/lua/lua_ScriptController.cpp

@@ -16,7 +16,11 @@ void luaRegister_ScriptController()
         {"loadUrl", lua_ScriptController_loadUrl},
         {NULL, NULL}
     };
-    const luaL_Reg* lua_statics = NULL;
+    const luaL_Reg lua_statics[] = 
+    {
+        {"print", lua_ScriptController_static_print},
+        {NULL, NULL}
+    };
     std::vector<std::string> scopePath;
 
     ScriptUtil::registerClass("ScriptController", lua_members, NULL, NULL, lua_statics, scopePath);
@@ -132,4 +136,62 @@ int lua_ScriptController_loadUrl(lua_State* state)
     return 0;
 }
 
+int lua_ScriptController_static_print(lua_State* state)
+{
+    // Get the number of parameters.
+    int paramCount = lua_gettop(state);
+
+    // Attempt to match the parameters to a valid binding.
+    switch (paramCount)
+    {
+        case 1:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(1, false);
+
+                ScriptController::print(param1);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_ScriptController_static_print - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        case 2:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(1, false);
+
+                // Get parameter 2 off the stack.
+                const char* param2 = ScriptUtil::getString(2, false);
+
+                ScriptController::print(param1, param2);
+                
+                return 0;
+            }
+            else
+            {
+                lua_pushstring(state, "lua_ScriptController_static_print - Failed to match the given parameters to a valid function signature.");
+                lua_error(state);
+            }
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 1 or 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 }

+ 1 - 0
gameplay/src/lua/lua_ScriptController.h

@@ -7,6 +7,7 @@ namespace gameplay
 // Lua bindings for ScriptController.
 int lua_ScriptController_loadScript(lua_State* state);
 int lua_ScriptController_loadUrl(lua_State* state);
+int lua_ScriptController_static_print(lua_State* state);
 
 void luaRegister_ScriptController();