Selaa lähdekoodia

Added support for specifying depth function via the "depthFunc" string in materials.
Added support for defining terrains in .scene files, both inline and through external references.
Added support for defining inline camera's in .scene files.
Added support for defining .scene files without a 'path' (GPB/bundle) file. New nodes can now be created in the .scene file if an ID is used that does not exist in the bundle. This changes scene loading behavior so that it is no longer an error when a node is found that does not exist in the bundle. Instead, a new empty node is created when this occurs.
Added support for setting a light color and light direction on scene. Used to store and bind directional light information for simple lit scenes that have at least one main directional light (i.e. the Sun).
Added material auto binding support for SCENE_AMBIENT_COLOR, SCENE_LIGHT_COLOR and SCENE_LIGHT_DIRECTION.
Updated Lua generator to only write generated files if they differ from existing files. This will reduce both build times and committing of unchanged script binding files.
Added static Scene::getScene(const char*) to query currently active scenes in a game.
Change to allow multiple translate, rotate and scale commands in a single node entity within .scene files. The commands are applied in the order that they are declared.
Added methods to PhysicsCollisionObject to allow conversion to subclass types (i.e. PhysicsRigidBody, PhysicsCharacter, etc) from script.

Steve Grenier 13 vuotta sitten
vanhempi
sitoutus
d5ec7218cb
77 muutettua tiedostoa jossa 3920 lisäystä ja 1306 poistoa
  1. 5 0
      gameplay-luagen/src/Base.h
  2. 6 4
      gameplay-luagen/src/ClassBinding.cpp
  3. 30 21
      gameplay-luagen/src/Generator.cpp
  4. 37 0
      gameplay-luagen/src/main.cpp
  5. 4 2
      gameplay/gameplay.vcxproj
  6. 12 6
      gameplay/gameplay.vcxproj.filters
  7. 84 0
      gameplay/res/shaders/terrain.frag
  8. 58 0
      gameplay/res/shaders/terrain.vert
  9. 1 2
      gameplay/src/Bundle.cpp
  10. 68 0
      gameplay/src/Camera.cpp
  11. 18 0
      gameplay/src/Camera.h
  12. 14 0
      gameplay/src/FileSystem.cpp
  13. 14 0
      gameplay/src/FileSystem.h
  14. 226 0
      gameplay/src/HeightField.cpp
  15. 142 0
      gameplay/src/HeightField.h
  16. 3 0
      gameplay/src/Node.cpp
  17. 30 0
      gameplay/src/PhysicsCollisionObject.cpp
  18. 49 0
      gameplay/src/PhysicsCollisionObject.h
  19. 9 2
      gameplay/src/PhysicsCollisionShape.cpp
  20. 4 4
      gameplay/src/PhysicsCollisionShape.h
  21. 2 38
      gameplay/src/PhysicsController.cpp
  22. 2 5
      gameplay/src/PhysicsController.h
  23. 31 18
      gameplay/src/PhysicsRigidBody.cpp
  24. 2 2
      gameplay/src/PhysicsRigidBody.h
  25. 62 0
      gameplay/src/RenderState.cpp
  26. 20 1
      gameplay/src/RenderState.h
  27. 49 7
      gameplay/src/Scene.cpp
  28. 74 4
      gameplay/src/Scene.h
  29. 80 19
      gameplay/src/SceneLoader.cpp
  30. 7 5
      gameplay/src/SceneLoader.h
  31. 67 228
      gameplay/src/Terrain.cpp
  32. 62 108
      gameplay/src/Terrain.h
  33. 40 4
      gameplay/src/TerrainPatch.cpp
  34. 6 0
      gameplay/src/TerrainPatch.h
  35. 1 0
      gameplay/src/gameplay.h
  36. 53 0
      gameplay/src/lua/lua_Camera.cpp
  37. 1 0
      gameplay/src/lua/lua_Camera.h
  38. 38 0
      gameplay/src/lua/lua_FileSystem.cpp
  39. 1 0
      gameplay/src/lua/lua_FileSystem.h
  40. 4 1
      gameplay/src/lua/lua_Global.cpp
  41. 632 0
      gameplay/src/lua/lua_HeightField.cpp
  42. 24 0
      gameplay/src/lua/lua_HeightField.h
  43. 1 0
      gameplay/src/lua/lua_Material.cpp
  44. 1 0
      gameplay/src/lua/lua_Pass.cpp
  45. 228 0
      gameplay/src/lua/lua_PhysicsCharacter.cpp
  46. 5 0
      gameplay/src/lua/lua_PhysicsCharacter.h
  47. 230 0
      gameplay/src/lua/lua_PhysicsCollisionObject.cpp
  48. 5 0
      gameplay/src/lua/lua_PhysicsCollisionObject.h
  49. 5 0
      gameplay/src/lua/lua_PhysicsCollisionObjectCollisionListener.cpp
  50. 5 0
      gameplay/src/lua/lua_PhysicsCollisionObjectCollisionPair.cpp
  51. 2 1
      gameplay/src/lua/lua_PhysicsCollisionShape.cpp
  52. 1 0
      gameplay/src/lua/lua_PhysicsCollisionShapeDefinition.cpp
  53. 1 0
      gameplay/src/lua/lua_PhysicsController.cpp
  54. 1 0
      gameplay/src/lua/lua_PhysicsControllerHitFilter.cpp
  55. 1 0
      gameplay/src/lua/lua_PhysicsControllerHitResult.cpp
  56. 1 0
      gameplay/src/lua/lua_PhysicsControllerListener.cpp
  57. 229 0
      gameplay/src/lua/lua_PhysicsGhostObject.cpp
  58. 5 0
      gameplay/src/lua/lua_PhysicsGhostObject.h
  59. 230 0
      gameplay/src/lua/lua_PhysicsRigidBody.cpp
  60. 5 0
      gameplay/src/lua/lua_PhysicsRigidBody.h
  61. 5 0
      gameplay/src/lua/lua_PhysicsRigidBodyParameters.cpp
  62. 228 0
      gameplay/src/lua/lua_PhysicsVehicle.cpp
  63. 5 0
      gameplay/src/lua/lua_PhysicsVehicle.h
  64. 228 0
      gameplay/src/lua/lua_PhysicsVehicleWheel.cpp
  65. 5 0
      gameplay/src/lua/lua_PhysicsVehicleWheel.h
  66. 1 0
      gameplay/src/lua/lua_RenderState.cpp
  67. 15 0
      gameplay/src/lua/lua_RenderStateAutoBinding.cpp
  68. 1 0
      gameplay/src/lua/lua_RenderStateStateBlock.cpp
  69. 273 1
      gameplay/src/lua/lua_Scene.cpp
  70. 5 0
      gameplay/src/lua/lua_Scene.h
  71. 1 0
      gameplay/src/lua/lua_Technique.cpp
  72. 121 264
      gameplay/src/lua/lua_Terrain.cpp
  73. 2 1
      gameplay/src/lua/lua_Terrain.h
  74. 0 535
      gameplay/src/lua/lua_TerrainHeightField.cpp
  75. 0 21
      gameplay/src/lua/lua_TerrainHeightField.h
  76. 1 1
      gameplay/src/lua/lua_all_bindings.cpp
  77. 1 1
      gameplay/src/lua/lua_all_bindings.h

+ 5 - 0
gameplay-luagen/src/Base.h

@@ -2,6 +2,7 @@
 #include <cassert>
 #include <fstream>
 #include <iostream>
+#include <sstream>
 #include <map>
 #include <set>
 #include <string>
@@ -42,6 +43,10 @@ using namespace std;
 
 extern void printError(const char* format, ...);
 
+extern void writeFile(const string& path, const string& text);
+
+extern std::vector<string> generatedFiles;
+
 // Current function macro.
 #ifdef WIN32
 #define __current__func__ __FUNCTION__

+ 6 - 4
gameplay-luagen/src/ClassBinding.cpp

@@ -88,7 +88,7 @@ void ClassBinding::write(string dir, const set<string>& includes, string* bindin
     // Write out the header.
     {
         string path = dir + string("lua_") + uniquename + string(".h");
-        ofstream o(path.c_str());
+        ostringstream o;
         if (!o)
         {
             GP_ERROR("Failed to open file '%s' for generating Lua bindings.", path.c_str());
@@ -122,13 +122,14 @@ void ClassBinding::write(string dir, const set<string>& includes, string* bindin
         if (bindingNS)
             o << "}\n\n";
         o << "#endif\n";
-        o.close();
+
+        writeFile(path, o.str());
     }
 
     // Write out the implementation.
     {
         string path = dir + string("lua_") + uniquename + string(".cpp");
-        ofstream o(path.c_str());
+        ostringstream o;
         if (!o)
         {
             GP_ERROR("Failed to open file '%s' for generating Lua bindings.", path.c_str());
@@ -288,7 +289,8 @@ void ClassBinding::write(string dir, const set<string>& includes, string* bindin
 
         if (bindingNS)
             o << "}\n";
-        o.close();
+
+        writeFile(path, o.str());
     }
 
     SAFE_DELETE(constructorUniqueName);

+ 30 - 21
gameplay-luagen/src/Generator.cpp

@@ -171,13 +171,6 @@ void Generator::run(string inDir, string outDir, string* bindingNS)
     vector<string> oldBindingsFiles;
     getFileList(outDir, oldBindingsFiles, isGeneratedBindingFile);
 
-    // Delete the old bindings.
-    for (unsigned int i = 0; i < oldBindingsFiles.size(); i++)
-    {
-        remove(oldBindingsFiles[i].c_str());
-    }
-
-
     // Get a list of the Doxygen XML files that specify a namespace.
     // Note: we must do this before adding the normal files so that
     // when we process the files sequentially, we process the namespaces
@@ -278,6 +271,16 @@ void Generator::run(string inDir, string outDir, string* bindingNS)
         GP_WARN("Detected the use of variable argument lists; this feature of C++ is not supported.");
     if (__printOperatorWarning)
         GP_WARN("Detected the use of operator overloading; this feature of C++ is not supported.");
+
+    // Delete files that are no longer needed and print warnings for them
+    for (unsigned int i = 0; i < oldBindingsFiles.size(); i++)
+    {
+        if (std::find(generatedFiles.begin(), generatedFiles.end(), oldBindingsFiles[i]) == generatedFiles.end())
+        {
+            GP_WARN("Deleting unused file: %s", oldBindingsFiles[i].c_str());
+            remove(oldBindingsFiles[i].c_str());
+        }
+    }
 }
 
 Generator::Generator()
@@ -1373,14 +1376,14 @@ void Generator::generateBindings(string* bindingNS)
         generatingGameplay = true;
 
     string luaAllHStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".h");
-    ofstream luaAllH(luaAllHStr.c_str());
+    ostringstream luaAllH;
     string includeGuard = string(LUA_ALL_BINDINGS_FILENAME) + string("_H_");
     transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
     luaAllH << "#ifndef " << includeGuard << "\n";
     luaAllH << "#define " << includeGuard << "\n\n";
     
     string luaAllCppStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".cpp");
-    ofstream luaAllCpp(luaAllCppStr.c_str());
+    ostringstream luaAllCpp;
     luaAllCpp << "#include \"Base.h\"\n";
     luaAllCpp << "#include \"" << string(LUA_ALL_BINDINGS_FILENAME) << ".h\"\n\n";
     if (bindingNS)
@@ -1428,7 +1431,7 @@ void Generator::generateBindings(string* bindingNS)
 
                 // Header.
                 string enumHStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".h");
-                ofstream enumH(enumHStr.c_str());
+                ostringstream enumH;
                 includeGuard = string("lua_") + getUniqueName(iter->first) + string("_H_");
                 transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
                 enumH << "#ifndef " << includeGuard << "\n";
@@ -1451,11 +1454,12 @@ void Generator::generateBindings(string* bindingNS)
                 }
 
                 enumH << "#endif\n";
-                enumH.close();
+
+                writeFile(enumHStr, enumH.str());
 
                 // Implementation.
                 string enumCppStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".cpp"); 
-                ofstream enumCpp(enumCppStr.c_str());
+                ostringstream enumCpp(enumCppStr.c_str());
                 enumCpp << "#include \"Base.h\"\n";
                 enumCpp << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n\n";
 
@@ -1537,7 +1541,8 @@ void Generator::generateBindings(string* bindingNS)
                 {
                     enumCpp << "}\n\n";
                 }
-                enumCpp.close();
+
+                writeFile(enumCppStr, enumCpp.str());
             }
         }
     }
@@ -1577,7 +1582,7 @@ void Generator::generateBindings(string* bindingNS)
         // Write out the header file.
         {
             string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".h");
-            ofstream global(path.c_str());
+            ostringstream global;
             includeGuard = string(LUA_GLOBAL_FILENAME) + string("_H_");
             transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
             global << "#ifndef " << includeGuard << "\n";
@@ -1624,13 +1629,14 @@ void Generator::generateBindings(string* bindingNS)
             if (bindingNS)
                 global << "}\n\n";
             global << "#endif\n";
-            global.close();
+
+            writeFile(path, global.str());
         }
 
         // Write out the implementation.
         {
             string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".cpp");
-            ofstream global(path.c_str());            
+            ostringstream global;
             global << "#include \"ScriptController.h\"\n";
             global << "#include \"" << LUA_GLOBAL_FILENAME << ".h\"\n";
             map<string, set<string> >::iterator iter = _includes.find(string(LUA_GLOBAL_FILENAME) + string(".h"));
@@ -1745,14 +1751,16 @@ void Generator::generateBindings(string* bindingNS)
 
             if (bindingNS)
                 global << "}\n";
-            global.close();
+
+            writeFile(path, global.str());
         }
     }
 
     luaAllCpp << "}\n\n";
     if (bindingNS)
         luaAllCpp << "}\n\n";
-    luaAllCpp.close();
+
+    writeFile(luaAllCppStr, luaAllCpp.str());
 
     if (bindingNS)
     {
@@ -1763,7 +1771,8 @@ void Generator::generateBindings(string* bindingNS)
     if (bindingNS)
         luaAllH<< "}\n\n";
     luaAllH << "#endif\n";
-    luaAllH.close();
+
+    writeFile(luaAllHStr, luaAllH.str());
 }
 
 void Generator::getAllDerived(set<string>& derived, string classname)
@@ -1895,7 +1904,7 @@ static bool getFileList(string directory, vector<string>& files, bool (*isWanted
 
             if (isWantedFile(filename))
             {
-                filename = string(directory) + string("/") + filename;
+                filename = string(directory) + filename;
                 files.push_back(filename);
             }
         }
@@ -1926,7 +1935,7 @@ static bool getFileList(string directory, vector<string>& files, bool (*isWanted
                 string filename = dp->d_name;
                 if (isWantedFile(filename))
                 {
-                    filename = string(directory) + string("/") + filename;
+                    filename = string(directory) + filename;
                     files.push_back(filename);
                 }
             }

+ 37 - 0
gameplay-luagen/src/main.cpp

@@ -3,6 +3,9 @@
 
 //TRACK_MEMORY();
 
+// Generated file list (extern from Base.h)
+std::vector<string> generatedFiles;
+
 void printError(const char* format, ...)
 {
     va_list argptr;
@@ -23,6 +26,40 @@ void printError(const char* format, ...)
     va_end(argptr);
 }
 
+void writeFile(const std::string& path, const std::string& text)
+{
+    generatedFiles.push_back(path);
+
+    // Read in content of path to compare before writing
+    bool changed = true;
+    ifstream in(path);
+    if (in.is_open())
+    {
+        changed = false;
+        istringstream textStream(text, istringstream::in);
+        string line1, line2;
+        while (in.good() && textStream.good())
+        {
+            getline(in, line1);
+            getline(textStream, line2);
+            if (line1 != line2 || in.good() != textStream.good())
+            {
+                // Files differ
+                changed = true;
+                break;
+            }
+        }
+        in.close();
+    }
+
+    if (changed)
+    {
+        ofstream o(path);
+        o << text;
+        o.close();
+    }
+}
+
 int main(int argc, char** argv)
 {
     // Ensure the user is calling the program correctly.

+ 4 - 2
gameplay/gameplay.vcxproj

@@ -89,6 +89,7 @@
     <ClCompile Include="src\gameplay-main-blackberry.cpp" />
     <ClCompile Include="src\gameplay-main-linux.cpp" />
     <ClCompile Include="src\gameplay-main-windows.cpp" />
+    <ClCompile Include="src\HeightField.cpp" />
     <ClCompile Include="src\Image.cpp" />
     <ClCompile Include="src\Joint.cpp" />
     <ClCompile Include="src\Joystick.cpp" />
@@ -155,6 +156,7 @@
     <ClCompile Include="src\lua\lua_Gesture.cpp" />
     <ClCompile Include="src\lua\lua_GestureGestureEvent.cpp" />
     <ClCompile Include="src\lua\lua_Global.cpp" />
+    <ClCompile Include="src\lua\lua_HeightField.cpp" />
     <ClCompile Include="src\lua\lua_Image.cpp" />
     <ClCompile Include="src\lua\lua_ImageFormat.cpp" />
     <ClCompile Include="src\lua\lua_Joint.cpp" />
@@ -238,7 +240,6 @@
     <ClCompile Include="src\lua\lua_Technique.cpp" />
     <ClCompile Include="src\lua\lua_Terrain.cpp" />
     <ClCompile Include="src\lua\lua_TerrainFlags.cpp" />
-    <ClCompile Include="src\lua\lua_TerrainHeightField.cpp" />
     <ClCompile Include="src\lua\lua_TextBox.cpp" />
     <ClCompile Include="src\lua\lua_Texture.cpp" />
     <ClCompile Include="src\lua\lua_TextureFilter.cpp" />
@@ -363,6 +364,7 @@
     <ClInclude Include="src\Gamepad.h" />
     <ClInclude Include="src\gameplay.h" />
     <ClInclude Include="src\Gesture.h" />
+    <ClInclude Include="src\HeightField.h" />
     <ClInclude Include="src\Image.h" />
     <ClInclude Include="src\Joint.h" />
     <ClInclude Include="src\Joystick.h" />
@@ -430,6 +432,7 @@
     <ClInclude Include="src\lua\lua_Gesture.h" />
     <ClInclude Include="src\lua\lua_GestureGestureEvent.h" />
     <ClInclude Include="src\lua\lua_Global.h" />
+    <ClInclude Include="src\lua\lua_HeightField.h" />
     <ClInclude Include="src\lua\lua_Image.h" />
     <ClInclude Include="src\lua\lua_ImageFormat.h" />
     <ClInclude Include="src\lua\lua_Joint.h" />
@@ -513,7 +516,6 @@
     <ClInclude Include="src\lua\lua_Technique.h" />
     <ClInclude Include="src\lua\lua_Terrain.h" />
     <ClInclude Include="src\lua\lua_TerrainFlags.h" />
-    <ClInclude Include="src\lua\lua_TerrainHeightField.h" />
     <ClInclude Include="src\lua\lua_TextBox.h" />
     <ClInclude Include="src\lua\lua_Texture.h" />
     <ClInclude Include="src\lua\lua_TextureFilter.h" />

+ 12 - 6
gameplay/gameplay.vcxproj.filters

@@ -828,15 +828,18 @@
     <ClCompile Include="src\lua\lua_TerrainFlags.cpp">
       <Filter>lua</Filter>
     </ClCompile>
-    <ClCompile Include="src\lua\lua_TerrainHeightField.cpp">
-      <Filter>lua</Filter>
-    </ClCompile>
     <ClCompile Include="src\lua\lua_Terrain.cpp">
       <Filter>lua</Filter>
     </ClCompile>
     <ClCompile Include="src\lua\lua_RenderStateDepthFunction.cpp">
       <Filter>lua</Filter>
     </ClCompile>
+    <ClCompile Include="src\HeightField.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\lua\lua_HeightField.cpp">
+      <Filter>lua</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -1652,15 +1655,18 @@
     <ClInclude Include="src\lua\lua_TerrainFlags.h">
       <Filter>lua</Filter>
     </ClInclude>
-    <ClInclude Include="src\lua\lua_TerrainHeightField.h">
-      <Filter>lua</Filter>
-    </ClInclude>
     <ClInclude Include="src\lua\lua_Terrain.h">
       <Filter>lua</Filter>
     </ClInclude>
     <ClInclude Include="src\lua\lua_RenderStateDepthFunction.h">
       <Filter>lua</Filter>
     </ClInclude>
+    <ClInclude Include="src\HeightField.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\lua\lua_HeightField.h">
+      <Filter>lua</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Game.inl">

+ 84 - 0
gameplay/res/shaders/terrain.frag

@@ -0,0 +1,84 @@
+#ifdef OPENGL_ES
+precision highp float;
+#endif
+
+// Inputs
+#if defined(NORMAL_MAP)
+vec3 v_normalVector;                            // Normal vector variable (from normal map)
+#else
+varying vec3 v_normalVector;					// Normal vector from vertex shader
+#endif
+varying vec2 v_texCoord0;
+
+// Uniforms
+uniform vec3 u_ambientColor;                    // Ambient color
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_lightDirection;					// Light direction
+
+#if defined(DEBUG_PATCHES)
+uniform int u_row;
+uniform int u_column;
+#endif
+
+#if (LAYER_COUNT > 0)
+uniform sampler2D u_samplers[SAMPLER_COUNT];
+uniform int u_textureIndex[LAYER_COUNT];
+uniform vec2 u_textureRepeat[LAYER_COUNT];
+#if (LAYER_COUNT > 1)
+uniform int u_blendIndex[LAYER_COUNT-1];
+uniform int u_blendChannel[LAYER_COUNT-1];
+#endif
+#if defined (NORMAL_MAP)
+uniform sampler2D u_normalMap;
+#endif
+#endif
+
+#include "lib/lighting.frag"
+#include "lib/lighting-directional.frag"
+
+#if (LAYER_COUNT > 1)
+void blendLayer(int index)
+{
+    vec2 uv = v_texCoord0 * u_textureRepeat[index];
+
+    // Sample full intensity diffuse color
+    vec3 diffuse = texture2D(u_samplers[u_textureIndex[index]], uv).rgb;
+    
+    // Sample blend map
+    vec4 blend = texture2D(u_samplers[u_blendIndex[index-1]], v_texCoord0).rgba;
+    float channels[4] = float[4](blend.r, blend.g, blend.b, blend.a);
+    float a = channels[u_blendChannel[index-1]];
+
+    _baseColor.rgb = _baseColor.rgb * (1.0 - a) + diffuse * a;
+}
+#endif
+
+// Fragment program
+void main()
+{
+#if (LAYER_COUNT > 0)
+    // Set base diffuse color
+    vec2 uvCoord = v_texCoord0 * u_textureRepeat[0];
+	_baseColor = texture2D(u_samplers[u_textureIndex[0]], uvCoord);
+#else
+    // If no layers are defined, simple use a white color
+    _baseColor = vec4(1,1,1,1);
+#endif
+
+#if (LAYER_COUNT > 1)
+    blendLayer(1);
+#endif
+
+#if defined(DEBUG_PATCHES)
+    // If patch debug drawing is enabled, tint patches alternate colors
+    float tint = mod(u_row + mod(u_column, 2), 2);
+    _baseColor.rgb = _baseColor.rgb * 0.75 + vec3(1-tint, tint, 0) * 0.25;
+#endif
+
+    // Light the pixel
+#if defined(NORMAL_MAP)
+    v_normalVector = normalize(texture2D(u_normalMap, v_texCoord0).xyz * 2.0f - 1.0f);
+#endif
+    gl_FragColor.a = _baseColor.a;
+    gl_FragColor.rgb = getLitPixel();
+}

+ 58 - 0
gameplay/res/shaders/terrain.vert

@@ -0,0 +1,58 @@
+// Inputs
+attribute vec4 a_position;									// Vertex Position							(x, y, z, w)
+#ifndef NORMAL_MAP
+attribute vec3 a_normal;									// Vertex Normal							(x, y, z)
+#endif
+attribute vec2 a_texCoord0;
+#if LAYER_COUNT > 1
+attribute vec2 a_texCoord1;
+#endif
+#if LAYER_COUNT > 2
+attribute vec2 a_texCoord2;
+#endif
+#if LAYER_COUNT > 3
+attribute vec2 a_texCoord3;
+#endif
+
+// Uniforms
+uniform mat4 u_worldViewProjectionMatrix;					// World view projection matrix
+uniform vec3 u_lightDirection;								// Direction of light
+
+// Outputs
+#ifndef NORMAL_MAP
+varying vec3 v_normalVector;								// Normal vector out
+#endif
+varying vec2 v_texCoord0;
+#if LAYER_COUNT > 1
+varying vec2 v_texCoord1;
+#endif
+#if LAYER_COUNT > 2
+varying vec2 v_texCoord2;
+#endif
+#if LAYER_COUNT > 3
+varying vec2 v_texCoord3;
+#endif
+
+// Vertex program
+void main()
+{
+    // Transform position to clip space.
+    gl_Position = u_worldViewProjectionMatrix * a_position;
+
+#ifndef NORMAL_MAP
+    // Pass normal to fragment shader
+    v_normalVector = a_normal;
+#endif
+
+    v_texCoord0 = a_texCoord0;
+
+#if LAYER_COUNT > 1
+    v_texCoord1 = a_texCoord1;
+#endif
+#if LAYER_COUNT > 2
+    v_texCoord2 = a_texCoord2;
+#endif
+#if LAYER_COUNT > 3
+    v_texCoord3 = a_texCoord3;
+#endif*/
+}

+ 1 - 2
gameplay/src/Bundle.cpp

@@ -378,8 +378,7 @@ Scene* Bundle::loadScene(const char* id)
         }
     }
 
-    Scene* scene = Scene::create();
-    scene->setId(getIdFromOffset());
+    Scene* scene = Scene::create(getIdFromOffset());
 
     // Read the number of children.
     unsigned int childrenCount;

+ 68 - 0
gameplay/src/Camera.cpp

@@ -46,6 +46,74 @@ Camera* Camera::createOrthographic(float zoomX, float zoomY, float aspectRatio,
     return new Camera(zoomX, zoomY, aspectRatio, nearPlane, farPlane);
 }
 
+Camera* Camera::create(Properties* properties)
+{
+    GP_ASSERT(properties);
+
+    // Read camera type
+    std::string typeStr;
+    if (properties->exists("type"))
+        typeStr = properties->getString("type");
+    Camera::Type type;
+    if (typeStr == "PERSPECTIVE")
+    {
+        type = Camera::PERSPECTIVE;
+    }
+    else if (typeStr == "ORTHOGRAPHIC")
+    {
+        type = Camera::ORTHOGRAPHIC;
+    }
+    else
+    {
+        GP_ERROR("Invalid 'type' parameter for camera definition.");
+        return NULL;
+    }
+
+    // Read common parameters
+    float aspectRatio, nearPlane, farPlane;
+    if (properties->exists("aspectRatio"))
+    {
+        aspectRatio = properties->getFloat("aspectRatio");
+    }
+    else
+    {
+        // Use default aspect ratio
+        aspectRatio = (float)Game::getInstance()->getWidth() / Game::getInstance()->getHeight();
+    }
+
+    if (properties->exists("nearPlane"))
+        nearPlane = properties->getFloat("nearPlane");
+    else
+        nearPlane = 0.2f; // use some reasonable default value
+
+    if (properties->exists("farPlane"))
+        farPlane = properties->getFloat("farPlane");
+    else
+        farPlane = 100; // use some reasonable default value
+
+    Camera* camera = NULL;
+
+    switch (type)
+    {
+    case Camera::PERSPECTIVE:
+        // If field of view is not specified, use a default of 60 degrees
+        camera = createPerspective(
+            properties->exists("fieldOfView") ? properties->getFloat("fieldOfView") : 60.0f,
+            aspectRatio, nearPlane, farPlane);
+        break;
+
+    case Camera::ORTHOGRAPHIC:
+        // If zoomX and zoomY are not specified, use screen width/height
+        camera = createOrthographic(
+            properties->exists("zoomX") ? properties->getFloat("zoomX") : Game::getInstance()->getWidth(),
+            properties->exists("zoomY") ? properties->getFloat("zoomY") : Game::getInstance()->getHeight(),
+            aspectRatio, nearPlane, farPlane);
+        break;
+    }
+
+    return camera;
+}
+
 Camera::Type Camera::getCameraType() const
 {
     return _type;

+ 18 - 0
gameplay/src/Camera.h

@@ -5,6 +5,7 @@
 #include "Transform.h"
 #include "Frustum.h"
 #include "Rectangle.h"
+#include "Properties.h"
 
 namespace gameplay
 {
@@ -37,6 +38,8 @@ public:
      * @param aspectRatio The aspect ratio of the camera (normally the width of the viewport divided by the height of the viewport).
      * @param nearPlane The near plane distance.
      * @param farPlane The far plane distance.
+     *
+     * @return The new Camera.
      */
     static Camera* createPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane);
 
@@ -48,9 +51,24 @@ public:
      * @param aspectRatio The aspect ratio of the orthographic projection.
      * @param nearPlane The near plane distance.
      * @param farPlane The far plane distance.
+     *
+     * @return The new Camera.
      */
     static Camera* createOrthographic(float zoomX, float zoomY, float aspectRatio, float nearPlane, float farPlane);
 
+    /**
+     * Creates a camera from a properties definition.
+     *
+     * The properties object must contain a "type" parameter, specifying either PERSPECTIVE or ORTHOGRAPHIC,
+     * as well as values for all required parameters in the Camera::createPerspective and Camera::createOrthographic
+     * methods.
+     *
+     * @param properties The properties definition of the Camera.
+     *
+     * @return The new Camera.
+     */
+    static Camera* create(Properties* properties);
+
     /**
      * Gets the type of camera.
      *

+ 14 - 0
gameplay/src/FileSystem.cpp

@@ -516,6 +516,20 @@ void FileSystem::createFileFromAsset(const char* path)
 #endif
 }
 
+std::string FileSystem::getExtension(const char* path)
+{
+    const char* str = strrchr(path, '.');
+    if (str == NULL)
+        return "";
+
+    std::string ext;
+    size_t len = strlen(str);
+    for (size_t i = 0; i < len; ++i)
+        ext += std::toupper(str[i]);
+
+    return ext;
+}
+
 //////////////////
 
 FileStream::FileStream(FILE* file)

+ 14 - 0
gameplay/src/FileSystem.h

@@ -181,6 +181,20 @@ public:
      */
     static void createFileFromAsset(const char* path);
 
+    /**
+     * Returns the extension of the given file path.
+     *
+     * The extension returned includes all character after and including the last '.'
+     * in the file path. The extension is returned as all uppercase.
+     *
+     * If the path does not contain an extension, an empty string is returned.
+     * 
+     * @param path File path.
+     *
+     * @return The file extension, all uppercase, including the '.'.
+     */
+    static std::string getExtension(const char* path);
+
 private:
 
     /**

+ 226 - 0
gameplay/src/HeightField.cpp

@@ -0,0 +1,226 @@
+#include "Base.h"
+#include "HeightField.h"
+#include "Image.h"
+#include "FileSystem.h"
+
+namespace gameplay
+{
+
+HeightField::HeightField(unsigned int columns, unsigned int rows)
+    : _array(NULL), _cols(columns), _rows(rows)
+{
+    _array = new float[columns * rows];
+}
+
+HeightField::~HeightField()
+{
+    SAFE_DELETE_ARRAY(_array);
+}
+
+HeightField* HeightField::create(unsigned int columns, unsigned int rows)
+{
+    return new HeightField(columns, rows);
+}
+
+/**
+ * @script{ignore}
+ */
+float normalizedHeightPacked(float r, float g, float b)
+{
+    // This formula is intended for 24-bit packed heightmap images (that are generated
+    // with gameplay-encoder. However, it is also compatible with normal grayscale 
+    // heightmap images, with an error of approximately 0.4%. This can be seen by
+    // setting r=g=b=x and comparing the grayscale height expression to the packed
+    // height expression: the error is 2^-8 + 2^-16 which is just under 0.4%.
+    return (256.0f*r + g + 0.00390625f*b) / 65536.0f;
+}
+
+HeightField* HeightField::createFromImage(const char* path, float minHeight, float maxHeight)
+{
+    return create(path, 0, 0, minHeight, maxHeight);
+}
+
+HeightField* HeightField::createFromRAW(const char* path, unsigned int width, unsigned int height, float minHeight, float maxHeight)
+{
+    return create(path, width, height, minHeight, maxHeight);
+}
+
+HeightField* HeightField::create(const char* path, unsigned int width, unsigned int height, float minHeight, float maxHeight)
+{
+    GP_ASSERT(path);
+    GP_ASSERT(maxHeight >= minHeight);
+
+    // Validate input parameters
+    size_t pathLength = strlen(path);
+    if (pathLength <= 4)
+    {
+        GP_WARN("Unrecognized file extension for heightfield image: %s.", path);
+        return NULL;
+    }
+
+    float heightScale = maxHeight - minHeight;
+
+    HeightField* heightfield = NULL;
+
+    // Load height data from image
+    const char* ext = path + (pathLength - 4);
+    if (ext[0] == '.' && toupper(ext[1]) == 'P' && toupper(ext[2]) == 'N' && toupper(ext[3]) == 'G')
+    {
+        // Normal image
+        Image* image = Image::create(path);
+        if (!image)
+            return NULL;
+
+        unsigned int pixelSize = 0;
+        switch (image->getFormat())
+        {
+            case Image::RGB:
+                pixelSize = 3;
+                break;
+            case Image::RGBA:
+                pixelSize = 4;
+                break;
+            default:
+                SAFE_RELEASE(image);
+                GP_WARN("Unsupported pixel format for heightfield image: %s.", path);
+                return NULL;
+        }
+
+        // Calculate the heights for each pixel.
+        heightfield = HeightField::create(image->getWidth(), image->getHeight());
+        float* heights = heightfield->getArray();
+        unsigned char* data = image->getData();
+        int idx;
+        for (int y = image->getHeight()-1, i = 0; y >= 0; --y)
+        {
+            for (unsigned int x = 0, w = image->getWidth(); x < w; ++x)
+            {
+                idx = (y*w + x) * pixelSize;
+                heights[i++] = minHeight + normalizedHeightPacked(data[idx], data[idx + 1], data[idx + 2]) * heightScale;
+            }
+        }
+
+        SAFE_RELEASE(image);
+    }
+    else if (ext[0] == '.' && toupper(ext[1]) == 'R' && toupper(ext[2]) == 'A' && toupper(ext[3]) == 'W')
+    {
+        // RAW image (headerless)
+        if (width < 2 || height < 2 || maxHeight < 0)
+        {
+            GP_WARN("Invalid 'width', 'height' or 'maxHeight' parameter for RAW heightfield image: %s.", path);
+            return NULL;
+        }
+
+        // Load raw bytes
+        int fileSize = 0;
+        unsigned char* bytes = (unsigned char*)FileSystem::readAll(path, &fileSize);
+        if (bytes == NULL)
+        {
+            GP_WARN("Falied to read bytes from RAW heightfield image: %s.", path);
+            return NULL;
+        }
+
+        // Determine if the RAW file is 8-bit or 16-bit based on file size.
+        int bits = (fileSize / (width * height)) * 8;
+        if (bits != 8 && bits != 16)
+        {
+            GP_WARN("Invalid RAW file - must be 8-bit or 16-bit, but found neither: %s.", path);
+            SAFE_DELETE_ARRAY(bytes);
+            return NULL;
+        }
+
+        heightfield = HeightField::create(width, height);
+        float* heights = heightfield->getArray();
+
+        // RAW files have an origin of bottom left, whereas our height array needs an origin of
+        // top left, so we need to flip the Y as we write height values out.
+        if (bits == 16)
+        {
+            // 16-bit (0-65535)
+            int idx;
+            for (int y = height-1, i = 0; y >= 0; --y)
+            {
+                for (unsigned int x = 0; x < width; ++x, ++i)
+                {
+                    idx = (y * width + x) << 1;
+                    heights[i] = minHeight + ((bytes[idx] | (int)bytes[idx+1] << 8) / 65535.0f) * heightScale;
+                }
+            }
+        }
+        else
+        {
+            // 8-bit (0-255)
+            for (int y = height-1, i = 0; y >= 0; --y)
+            {
+                for (unsigned int x = 0; x < width; ++x, ++i)
+                {
+                    heights[i] = minHeight + (bytes[y * width + x] / 255.0f) * heightScale;
+                }
+            }
+        }
+
+        SAFE_DELETE_ARRAY(bytes);
+    }
+    else
+    {
+        GP_WARN("Unsupported heightfield image format: %s.", path);
+    }
+
+    return heightfield;
+}
+
+float* HeightField::getArray() const
+{
+    return _array;
+}
+
+float HeightField::getHeight(float column, float row) const
+{
+    // Clamp to heightfield boundaries
+    column = column < 0 ? 0 : (column > (_cols-1) ? (_cols-1) : column);
+    row = row < 0 ? 0 : (row > (_rows-1) ? (_rows-1) : row);
+
+    unsigned int x1 = column;
+    unsigned int y1 = row;
+    unsigned int x2 = x1 + 1;
+    unsigned int y2 = y1 + 1;
+    float tmp;
+    float xFactor = modf(column, &tmp);
+    float yFactor = modf(row, &tmp);
+    float xFactorI = 1.0f - xFactor;
+    float yFactorI = 1.0f - yFactor;
+
+    if (x2 >= _cols && y2 >= _rows)
+    {
+        return _array[x1 + y1 * _cols];
+    }
+    else if (x2 >= _cols)
+    {
+        return _array[x1 + y1 * _cols] * yFactorI + _array[x1 + y2 * _cols] * yFactor;
+    }
+    else if (y2 >= _rows)
+    {
+        return _array[x1 + y1 * _cols] * xFactorI + _array[x2 + y1 * _cols] * xFactor;
+    }
+    else
+    {
+        float a = xFactorI * yFactorI;
+        float b = xFactorI * yFactor;
+        float c = xFactor * yFactor;
+        float d = xFactor * yFactorI;
+        return _array[x1 + y1 * _cols] * a + _array[x1 + y2 * _cols] * b +
+            _array[x2 + y2 * _cols] * c + _array[x2 + y1 * _cols] * d;
+    }
+}
+
+unsigned int HeightField::getColumnCount() const
+{
+    return _cols;
+}
+
+unsigned int HeightField::getRowCount() const
+{
+    return _rows;
+}
+
+}

+ 142 - 0
gameplay/src/HeightField.h

@@ -0,0 +1,142 @@
+#ifndef HEIGHTFIELD_H_
+#define HEIGHTFIELD_H_
+
+#include "Ref.h"
+
+namespace gameplay
+{
+
+    /**
+     * Defines a reference counted class that holds heightfeild data.
+     *
+     * Heightfields can be used to construct both Terrain objects as well as PhysicsCollisionShape
+     * heightfield defintions, which are used in heightfield rigid body creation. Heightfields can
+     * be populated manually, or loaded from images and RAW files.
+     */
+    class HeightField : public Ref
+    {
+    public:
+
+        /**
+         * Creates a new HeightField of the given dimensions, with uninitialized height data.
+         *
+         * @param rows Number of rows in the height field.
+         * @param columns Number of columns in the height field.
+         *
+         * @return The new HeightField.
+         */
+        static HeightField* create(unsigned int rows, unsigned int columns);
+
+        /**
+         * Creates a HeightField from the specified heightfield image.
+         *
+         * The specified image path must refer to a valid heightfield image. Supported images are
+         * the same as those supported by the Image class (i.e. PNG). 
+         *
+         * The minHeight and maxHeight parameters provides a mapping from heightfield pixel
+         * intensity to height values. The minHeight parameter is mapped to zero intensity
+         * pixel, while maxHeight maxHeight is mapped to full intensity pixels.
+         *
+         * @param path Path to a heightfield image.
+         * @param width Width of the image (required for headerless/RAW files, can be zero for other image formats).
+         * @param height Height of the image (required for headerless/RAW files, can be zero for other image formats).
+         * @param minHeight Minimum height value for a zero intensity pixel.
+         * @param maxHeight Maximum height value for a full intensity heightfield pixel (must be >= minHeight).
+         * 
+         * @return The new HeightField.
+         */
+        static HeightField* createFromImage(const char* path, float minHeight = 0, float maxHeight = 1);
+
+        /**
+         * Creates a HeightField from the specified RAW8 or RAW16 file.
+         *
+         * RAW files are header-less files containing intensity values, either in 8-bit (RAW8)
+         * or 16-bit (RAW16) format. RAW16 files must have little endian (PC) byte ordering. Since
+         * RAW files have no header, you must specify the dimensions of the data in the file.
+         * This method automatically determines (based on file size) whether the input file
+         * is RAW8 or RAW16.
+         *
+         * RAW files are commonly used in software that produces heightmap images. Using RAW16 is 
+         * preferred or any 8-bit heightfield source since it allows greater precision, resulting in
+         * smoother height transitions.
+         *
+         * The minHeight and maxHeight parameters provides a mapping from heightfield pixel
+         * intensity to height values. The minHeight parameter is mapped to zero intensity
+         * pixel, while maxHeight maxHeight is mapped to full intensity pixels.
+         *
+         * @param path Path to the RAW file.
+         * @param width Width of the RAW data.
+         * @param height Height of the RAW data.
+         * @param minHeight Minimum height value for a zero intensity pixel.
+         * @param maxHeight Maximum height value for a full intensity heightfield pixel (must be >= minHeight).
+         * 
+         * @return The new HeightField.
+         */
+        static HeightField* createFromRAW(const char* path, unsigned int width, unsigned int height, float minHeight = 0, float maxHeight = 1);
+
+        /**
+         * Returns a pointer to the underying height array.
+         *
+         * The array is packed in row major order, meaning that the data is aligned in rows,
+         * from top left to bottom right.
+         *
+         * @return The underlying height array.
+         */
+        float* getArray() const;
+
+        /**
+         * Returns the height at the specified row and column.
+         *
+         * The specified row and column are specified as floating point numbers so that values
+         * between points can be specified. In this case, a height value is calculated that is
+         * interpolated between neighboring height values. 
+         *
+         * If the specified point lies outside the heightfield, it is clamped to the boundary
+         * of the heightfield.
+         *
+         * @param column The column of the height value to query.
+         * @param row The row of the height value to query.
+         *
+         * @return The height value.
+         */
+        float getHeight(float column, float row) const;
+
+        /**
+         * Returns the number of rows in the heightfield.
+         *
+         * @return The number of rows.
+         */
+        unsigned int getRowCount() const;
+
+        /**
+         * Returns the number of columns in the heightfield.
+         * 
+         * @return The column count.
+         */
+        unsigned int getColumnCount() const;
+
+    private:
+
+        /**
+         * Hidden constructor.
+         */
+        HeightField(unsigned int columns, unsigned int rows);
+
+        /**
+         * Hidden destructor (use Ref::release()).
+         */
+        ~HeightField();
+
+        /**
+         * Internal method for creating a HeightField.
+         */
+        static HeightField* create(const char* path, unsigned int width, unsigned int height, float minHeight, float maxHeight);
+
+        float* _array;
+        unsigned int _rows;
+        unsigned int _cols;
+    };
+
+}
+
+#endif

+ 3 - 0
gameplay/src/Node.cpp

@@ -856,6 +856,9 @@ const BoundingSphere& Node::getBoundingSphere() const
         // Start with our local bounding sphere
         // TODO: Incorporate bounds from entities other than mesh (i.e. emitters, audiosource, etc)
         bool empty = true;
+        if (_terrain)
+        {
+        }
         if (_model && _model->getMesh())
         {
             _bounds.set(_model->getMesh()->getBoundingSphere());

+ 30 - 0
gameplay/src/PhysicsCollisionObject.cpp

@@ -4,6 +4,11 @@
 #include "Game.h"
 #include "Node.h"
 #include "ScriptController.h"
+#include "PhysicsRigidBody.h"
+#include "PhysicsCharacter.h"
+#include "PhysicsGhostObject.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 
 namespace gameplay
 {
@@ -165,6 +170,31 @@ bool PhysicsCollisionObject::collidesWith(PhysicsCollisionObject* object) const
     return callback.result;
 }
 
+PhysicsRigidBody* PhysicsCollisionObject::asRigidBody()
+{
+    return getType() == RIGID_BODY ? static_cast<PhysicsRigidBody*>(this) : NULL;
+}
+
+PhysicsCharacter* PhysicsCollisionObject::asCharacter()
+{
+    return getType() == CHARACTER ? static_cast<PhysicsCharacter*>(this) : NULL;
+}
+
+PhysicsGhostObject* PhysicsCollisionObject::asGhostObject()
+{
+    return getType() == GHOST_OBJECT ? static_cast<PhysicsGhostObject*>(this) : NULL;
+}
+
+PhysicsVehicle* PhysicsCollisionObject::asVehicle()
+{
+    return getType() == VEHICLE ? static_cast<PhysicsVehicle*>(this) : NULL;
+}
+
+PhysicsVehicleWheel* PhysicsCollisionObject::asVehicleWheel()
+{
+    return getType() == VEHICLE_WHEEL ? static_cast<PhysicsVehicleWheel*>(this) : NULL;
+}
+
 PhysicsCollisionObject::CollisionPair::CollisionPair(PhysicsCollisionObject* objectA, PhysicsCollisionObject* objectB)
     : objectA(objectA), objectB(objectB)
 {

+ 49 - 0
gameplay/src/PhysicsCollisionObject.h

@@ -8,6 +8,11 @@ namespace gameplay
 {
 
 class Node;
+class PhysicsRigidBody;
+class PhysicsCharacter;
+class PhysicsGhostObject;
+class PhysicsVehicle;
+class PhysicsVehicleWheel;
 
 /**
  * Base class for all gameplay physics objects that support collision events.
@@ -238,6 +243,50 @@ public:
      */
     bool collidesWith(PhysicsCollisionObject* object) const;
 
+    /**
+     * Returns this collision object as a physics rigid body.
+     *
+     * If this collision object is not of type RIGID_BODY, this method returns NULL.
+     *
+     * @return This collision object cast to a PhysicsRigidBody.
+     */
+    PhysicsRigidBody* asRigidBody();
+
+    /**
+     * Returns this collision object as a physics character.
+     *
+     * If this collision object is not of type CHARACTER, this method returns NULL.
+     *
+     * @return This collision object cast to a PhysicsCharacter.
+     */
+    PhysicsCharacter* asCharacter();
+
+    /**
+     * Returns this collision object as a physics ghost object.
+     *
+     * If this collision object is not of type GHOST_OBJECT, this method returns NULL.
+     *
+     * @return This collision object cast to a PhysicsGhostObject.
+     */
+    PhysicsGhostObject* asGhostObject();
+
+    /**
+     * Returns this collision object as a physics vehicle.
+     *
+     * If this collision object is not of type VEHICLE, this method returns NULL.
+     *
+     * @return This collision object cast to a PhysicsVehicle.
+     */
+    PhysicsVehicle* asVehicle();
+
+    /**
+     * Returns this collision object as a physics vehicle wheel.
+     *
+     * If this collision object is not of type VEHICLE_WHEEL, this method returns NULL.
+     *
+     * @return This collision object cast to a PhysicsVehicleWheel.
+     */
+    PhysicsVehicleWheel* asVehicleWheel();
 
 protected:
     /**

+ 9 - 2
gameplay/src/PhysicsCollisionShape.cpp

@@ -4,6 +4,7 @@
 #include "Image.h"
 #include "Properties.h"
 #include "FileSystem.h"
+#include "HeightField.h"
 
 namespace gameplay
 {
@@ -327,7 +328,13 @@ PhysicsCollisionShape::Definition PhysicsCollisionShape::Definition::create(Node
             }
             else
             {
-                Terrain::HeightField* heightfield = Terrain::HeightField::create(imagePath, (unsigned int)width, (unsigned int)height, minHeight, maxHeight);
+                std::string ext = FileSystem::getExtension(imagePath);
+                HeightField* heightfield = NULL;
+                if (ext == ".PNG")
+                    heightfield = HeightField::createFromImage(imagePath, minHeight, maxHeight);
+                else if (ext == ".RAW")
+                    heightfield = HeightField::createFromRAW(imagePath, (unsigned int)width, (unsigned int)height, minHeight, maxHeight);
+
                 if (heightfield)
                 {
                     shape = PhysicsCollisionShape::heightfield(heightfield);
@@ -415,7 +422,7 @@ PhysicsCollisionShape::Definition PhysicsCollisionShape::heightfield()
     return d;
 }
 
-PhysicsCollisionShape::Definition PhysicsCollisionShape::heightfield(Terrain::HeightField* heightfield)
+PhysicsCollisionShape::Definition PhysicsCollisionShape::heightfield(HeightField* heightfield)
 {
     GP_ASSERT(heightfield);
 

+ 4 - 4
gameplay/src/PhysicsCollisionShape.h

@@ -3,7 +3,7 @@
 
 #include "Vector3.h"
 #include "Mesh.h"
-#include "Terrain.h"
+#include "HeightField.h"
 
 namespace gameplay
 {
@@ -107,7 +107,7 @@ public:
             /** @script{ignore} */
             CapsuleData capsule;
             /** @script{ignore} */
-            Terrain::HeightField* heightfield;
+            HeightField* heightfield;
             /** @script{ignore} */
             Mesh* mesh;
         } data;
@@ -226,7 +226,7 @@ public:
      *
      * @return Definition of a heightfield shape.
      */
-    static PhysicsCollisionShape::Definition heightfield(Terrain::HeightField* heightfield);
+    static PhysicsCollisionShape::Definition heightfield(HeightField* heightfield);
 
     /**
      * Defines a mesh shape using the specified mesh.
@@ -245,7 +245,7 @@ private:
 
     struct HeightfieldData
     {
-        Terrain::HeightField* heightfield;
+        HeightField* heightfield;
         bool inverseIsDirty;
         Matrix inverse;
         float minHeight;

+ 2 - 38
gameplay/src/PhysicsController.cpp

@@ -5,6 +5,7 @@
 #include "Game.h"
 #include "MeshPart.h"
 #include "Bundle.h"
+#include "Terrain.h"
 
 #ifdef GAMEPLAY_MEM_LEAK_DETECTION
 #undef new
@@ -995,7 +996,7 @@ PhysicsCollisionShape* PhysicsController::createCapsule(float radius, float heig
     return shape;
 }
 
-PhysicsCollisionShape* PhysicsController::createHeightfield(Node* node, Terrain::HeightField* heightfield, Vector3* centerOfMassOffset)
+PhysicsCollisionShape* PhysicsController::createHeightfield(Node* node, HeightField* heightfield, Vector3* centerOfMassOffset)
 {
     GP_ASSERT(node);
     GP_ASSERT(heightfield);
@@ -1226,43 +1227,6 @@ void PhysicsController::destroyShape(PhysicsCollisionShape* shape)
     }
 }
 
-float PhysicsController::calculateHeight(float* data, unsigned int width, unsigned int height, float x, float y)
-{
-    GP_ASSERT(data);
-
-    unsigned int x1 = x;
-    unsigned int y1 = y;
-    unsigned int x2 = x1 + 1;
-    unsigned int y2 = y1 + 1;
-    float tmp;
-    float xFactor = modf(x, &tmp);
-    float yFactor = modf(y, &tmp);
-    float xFactorI = 1.0f - xFactor;
-    float yFactorI = 1.0f - yFactor;
-
-    if (x2 >= width && y2 >= height)
-    {
-        return data[x1 + y1 * width];
-    }
-    else if (x2 >= width)
-    {
-        return data[x1 + y1 * width] * yFactorI + data[x1 + y2 * width] * yFactor;
-    }
-    else if (y2 >= height)
-    {
-        return data[x1 + y1 * width] * xFactorI + data[x2 + y1 * width] * xFactor;
-    }
-    else
-    {
-        float a = xFactorI * yFactorI;
-        float b = xFactorI * yFactor;
-        float c = xFactor * yFactor;
-        float d = xFactor * yFactorI;
-        return data[x1 + y1 * width] * a + data[x1 + y2 * width] * b +
-            data[x2 + y2 * width] * c + data[x2 + y1 * width] * d;
-    }
-}
-
 void PhysicsController::addConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b, PhysicsConstraint* constraint)
 {
     GP_ASSERT(a);

+ 2 - 5
gameplay/src/PhysicsController.h

@@ -9,7 +9,7 @@
 #include "PhysicsSpringConstraint.h"
 #include "PhysicsCollisionObject.h"
 #include "MeshBatch.h"
-#include "Terrain.h"
+#include "HeightField.h"
 #include "ScriptTarget.h"
 
 namespace gameplay
@@ -431,7 +431,7 @@ private:
     PhysicsCollisionShape* createCapsule(float radius, float height, const Vector3& scale);
 
     // Creates a heightfield collision shape.
-    PhysicsCollisionShape* createHeightfield(Node* node, Terrain::HeightField* heightfield, Vector3* centerOfMassOffset);
+    PhysicsCollisionShape* createHeightfield(Node* node, HeightField* heightfield, Vector3* centerOfMassOffset);
 
     // Creates a triangle mesh collision shape.
     PhysicsCollisionShape* createMesh(Mesh* mesh, const Vector3& scale);
@@ -439,9 +439,6 @@ private:
     // Destroys a collision shape created through PhysicsController
     void destroyShape(PhysicsCollisionShape* shape);
 
-    // Helper function for calculating heights from heightmap (image) or heightfield data.
-    static float calculateHeight(float* data, unsigned int width, unsigned int height, float x, float y);
-
     // Legacy method for grayscale heightmaps: r + g + b, normalized.
     static float normalizedHeightGrayscale(float r, float g, float b);
 

+ 31 - 18
gameplay/src/PhysicsRigidBody.cpp

@@ -5,6 +5,7 @@
 #include "Image.h"
 #include "MeshPart.h"
 #include "Node.h"
+#include "Terrain.h"
 
 namespace gameplay
 {
@@ -278,9 +279,10 @@ void PhysicsRigidBody::setEnabled(bool enable)
         _body->setMotionState(_motionState);
 }
 
-float PhysicsRigidBody::getHeight(float x, float y) const
+float PhysicsRigidBody::getHeight(float x, float z) const
 {
     GP_ASSERT(_collisionShape);
+    GP_ASSERT(_node);
 
     // This function is only supported for heightfield rigid bodies.
     if (_collisionShape->getType() != PhysicsCollisionShape::SHAPE_HEIGHTFIELD)
@@ -290,33 +292,44 @@ float PhysicsRigidBody::getHeight(float x, float y) const
     }
 
     GP_ASSERT(_collisionShape->_shapeData.heightfieldData);
-    GP_ASSERT(_node);
 
-    // Calculate the correct x, y position relative to the heightfield data.
+    // Ensure inverse matrix is updated so we can transform from world back into local heightfield coordinates for indexing
     if (_collisionShape->_shapeData.heightfieldData->inverseIsDirty)
     {
-        _node->getWorldMatrix().invert(&_collisionShape->_shapeData.heightfieldData->inverse);
+        Matrix& inverse = _collisionShape->_shapeData.heightfieldData->inverse;
+        inverse.set(_node->getWorldMatrix());
+
+        // Apply heightfield local scaling
+        const btVector3& localScale = _collisionShape->getShape()->getLocalScaling();
+        if (localScale.x() != 1.0f || localScale.y() != 1.0f || localScale.z() != 1.0f)
+            inverse.scale(localScale.x(), localScale.y(), localScale.z());
+
+        inverse.invert();
         _collisionShape->_shapeData.heightfieldData->inverseIsDirty = false;
     }
 
-    float w = _collisionShape->_shapeData.heightfieldData->heightfield->getColumnCount();
-    float h = _collisionShape->_shapeData.heightfieldData->heightfield->getRowCount();
+    // Calculate the correct x, z position relative to the heightfield data.
+    float cols = _collisionShape->_shapeData.heightfieldData->heightfield->getColumnCount();
+    float rows = _collisionShape->_shapeData.heightfieldData->heightfield->getRowCount();
 
-    GP_ASSERT(w - 1);
-    GP_ASSERT(h - 1);
+    GP_ASSERT(cols > 0);
+    GP_ASSERT(rows > 0);
 
-    Vector3 v = _collisionShape->_shapeData.heightfieldData->inverse * Vector3(x, 0.0f, y);
-    x = (v.x + (0.5f * (w - 1))) * w / (w - 1);
-    y = (v.z + (0.5f * (h - 1))) * h / (h - 1);
+    Vector3 v = _collisionShape->_shapeData.heightfieldData->inverse * Vector3(x, 0.0f, z);
+    //x = (v.x + (0.5f * (cols - 1))) * cols / (cols - 1);
+    //z = (v.z + (0.5f * (rows - 1))) * rows / (rows - 1);
+    x = v.x + (cols - 1) * 0.5f;
+    z = v.z + (rows - 1) * 0.5f;
 
-    // Check that the x, y position is within the bounds.
-    if (x < 0.0f || x > w || y < 0.0f || y > h)
-    {
-        GP_ERROR("Attempting to get height at point '%f, %f', which is outside the range of the heightfield with width %d and height %d.", x, y, w, h);
-        return 0.0f;
-    }
+    // Get the un-scaled height value from the HeightField
+    float height = _collisionShape->_shapeData.heightfieldData->heightfield->getHeight(x, z);
+
+    // Apply scaling (both world and local)
+    Vector3 worldScale;
+    _node->getWorldMatrix().getScale(&worldScale);
+    height *= worldScale.y * _collisionShape->getShape()->getLocalScaling().y();
 
-    return PhysicsController::calculateHeight(_collisionShape->_shapeData.heightfieldData->heightfield->getArray(), w, h, x, y) * _collisionShape->getShape()->getLocalScaling().y();
+    return height;
 }
 
 void PhysicsRigidBody::addConstraint(PhysicsConstraint* constraint)

+ 2 - 2
gameplay/src/PhysicsRigidBody.h

@@ -336,10 +336,10 @@ public:
      * Gets the height at the given point (only for rigid bodies of type HEIGHTFIELD).
      * 
      * @param x The x position, in world space.
-     * @param y The y position, in world space.
+     * @param z The z position, in world space.
      * @return The height at the given point, or zero if this is not a heightfield rigid body.
      */
-    float getHeight(float x, float y) const;
+    float getHeight(float x, float z) const;
 
     /**
      * Gets whether the rigid body is a static rigid body or not.

+ 62 - 0
gameplay/src/RenderState.cpp

@@ -4,6 +4,7 @@
 #include "Pass.h"
 #include "Technique.h"
 #include "Node.h"
+#include "Scene.h"
 
 // Render state override bits
 #define RS_BLEND 1
@@ -117,6 +118,15 @@ const char* autoBindingToString(RenderState::AutoBinding autoBinding)
     case RenderState::MATRIX_PALETTE:
         return "MATRIX_PALETTE";
 
+    case RenderState::SCENE_AMBIENT_COLOR:
+        return "SCENE_AMBIENT_COLOR";
+
+    case RenderState::SCENE_LIGHT_COLOR:
+        return "SCENE_LIGHT_COLOR";
+
+    case RenderState::SCENE_LIGHT_DIRECTION:
+        return "SCENE_LIGHT_DIRECTION";
+
     default:
         return "";
     }
@@ -262,6 +272,24 @@ void RenderState::applyAutoBinding(const char* uniformName, const char* autoBind
             param->bindValue(skin, &MeshSkin::getMatrixPalette, &MeshSkin::getMatrixPaletteSize);
         }
     }
+    else if (strcmp(autoBinding, "SCENE_AMBIENT_COLOR") == 0)
+    {
+        Scene* scene = _nodeBinding->getScene();
+        if (scene)
+            param->bindValue(scene, &Scene::getAmbientColor);
+    }
+    else if (strcmp(autoBinding, "SCENE_LIGHT_COLOR") == 0)
+    {
+        Scene* scene = _nodeBinding->getScene();
+        if (scene)
+            param->bindValue(scene, &Scene::getLightColor);
+    }
+    else if (strcmp(autoBinding, "SCENE_LIGHT_DIRECTION") == 0)
+    {
+        Scene* scene = _nodeBinding->getScene();
+        if (scene)
+            param->bindValue(scene, &Scene::getLightDirection);
+    }
     else
     {
         GP_WARN("Unsupported auto binding type (%d).", autoBinding);
@@ -549,6 +577,36 @@ static RenderState::Blend parseBlend(const char* value)
     }
 }
 
+static RenderState::DepthFunction parseDepthFunc(const char* value)
+{
+    GP_ASSERT(value);
+
+    // Convert string to uppercase for comparison
+    std::string upper(value);
+    std::transform(upper.begin(), upper.end(), upper.begin(), (int(*)(int))toupper);
+    if (upper == "NEVER")
+        return RenderState::DEPTH_NEVER;
+    else if (upper == "LESS")
+        return RenderState::DEPTH_LESS;
+    else if (upper == "EQUAL")
+        return RenderState::DEPTH_EQUAL;
+    else if (upper == "LEQUAL")
+        return RenderState::DEPTH_LEQUAL;
+    else if (upper == "GREATER")
+        return RenderState::DEPTH_GREATER;
+    else if (upper == "NOTEQUAL")
+        return RenderState::DEPTH_NOTEQUAL;
+    else if (upper == "GEQUAL")
+        return RenderState::DEPTH_GEQUAL;
+    else if (upper == "ALWAYS")
+        return RenderState::DEPTH_ALWAYS;
+    else
+    {
+        GP_ERROR("Unsupported depth function value (%s). Will default to DEPTH_LESS if errors are treated as warnings)", value);
+        return RenderState::DEPTH_LESS;
+    }
+}
+
 void RenderState::StateBlock::setState(const char* name, const char* value)
 {
     GP_ASSERT(name);
@@ -577,6 +635,10 @@ void RenderState::StateBlock::setState(const char* name, const char* value)
     {
         setDepthWrite(parseBoolean(value));
     }
+    else if (strcmp(name, "depthFunc") == 0)
+    {
+        setDepthFunction(parseDepthFunc(value));
+    }
     else
     {
         GP_ERROR("Unsupported render state string '%s'.", name);

+ 20 - 1
gameplay/src/RenderState.h

@@ -84,7 +84,26 @@ public:
         /**
          * Binds the matrix palette of MeshSkin attached to a node's model.
          */
-        MATRIX_PALETTE
+        MATRIX_PALETTE,
+
+        /**
+         * Binds the current scene's ambient color (Vector3).
+         */
+        SCENE_AMBIENT_COLOR,
+
+        /**
+         * Binds the current scene's light color (Vector3).
+         *
+         * This is typically used for the main directional light in a scene, such as the Sun.
+         */
+        SCENE_LIGHT_COLOR,
+
+        /**
+         * Binds the current scene's light direction (Vector3).
+         *
+         * This is typically used for the main directional light in a scene, such as the Sun.
+         */
+        SCENE_LIGHT_DIRECTION
     };
 
     /**

+ 49 - 7
gameplay/src/Scene.cpp

@@ -8,8 +8,14 @@
 namespace gameplay
 {
 
-Scene::Scene() : _activeCamera(NULL), _firstNode(NULL), _lastNode(NULL), _nodeCount(0), _bindAudioListenerToCamera(true), _debugBatch(NULL)
+// Global list of active scenes
+static std::vector<Scene*> __sceneList;
+
+Scene::Scene(const char* id)
+    : _id(id ? id : ""), _activeCamera(NULL), _firstNode(NULL), _lastNode(NULL), _nodeCount(0), 
+    _lightColor(1,1,1), _lightDirection(0,-1,0), _bindAudioListenerToCamera(true), _debugBatch(NULL)
 {
+    __sceneList.push_back(this);
 }
 
 Scene::~Scene()
@@ -29,11 +35,16 @@ Scene::~Scene()
     // Remove all nodes from the scene
     removeAllNodes();
     SAFE_DELETE(_debugBatch);
+
+    // Remove the scene from global list
+    std::vector<Scene*>::iterator itr = std::find(__sceneList.begin(), __sceneList.end(), this);
+    if (itr != __sceneList.end())
+        __sceneList.erase(itr);
 }
 
-Scene* Scene::create()
+Scene* Scene::create(const char* id)
 {
-    return new Scene();
+    return new Scene(id);
 }
 
 Scene* Scene::load(const char* filePath)
@@ -41,6 +52,20 @@ Scene* Scene::load(const char* filePath)
     return SceneLoader::load(filePath);
 }
 
+Scene* Scene::getScene(const char* id)
+{
+    if (id == NULL)
+        return __sceneList.size() ? __sceneList[0] : NULL;
+
+    for (size_t i = 0, count = __sceneList.size(); i < count; ++i)
+    {
+        if (__sceneList[i]->_id == id)
+            return __sceneList[i];
+    }
+
+    return NULL;
+}
+
 const char* Scene::getId() const
 {
     return _id.c_str();
@@ -48,10 +73,7 @@ const char* Scene::getId() const
 
 void Scene::setId(const char* id)
 {
-    if (id)
-    {
-        _id = id;
-    }
+    _id = id ? id : "";
 }
 
 Node* Scene::findNode(const char* id, bool recursive, bool exactMatch) const
@@ -278,6 +300,26 @@ void Scene::setAmbientColor(float red, float green, float blue)
     _ambientColor.set(red, green, blue);
 }
 
+const Vector3& Scene::getLightColor() const
+{
+    return _lightColor;
+}
+
+void Scene::setLightColor(float red, float green, float blue)
+{
+    _lightColor.set(red, green, blue);
+}
+
+const Vector3& Scene::getLightDirection() const
+{
+    return _lightDirection;
+}
+
+void Scene::setLightDirection(const Vector3& direction)
+{
+    _lightDirection = direction;
+}
+
 static Material* createDebugMaterial()
 {
     // Vertex shader for drawing colored lines.

+ 74 - 4
gameplay/src/Scene.h

@@ -4,6 +4,7 @@
 #include "Node.h"
 #include "MeshBatch.h"
 #include "ScriptController.h"
+#include "Light.h"
 
 namespace gameplay
 {
@@ -27,10 +28,12 @@ public:
     /**
      * Creates a new empty scene.
      * 
+     * @param id ID of the new scene, or NULL to use an empty string for the ID (default).
+     *
      * @return The newly created empty scene.
      * @script{create}
      */
-    static Scene* create();
+    static Scene* create(const char* id = NULL);
 
     /**
      * Loads a scene from the given '.scene' file.
@@ -42,6 +45,17 @@ public:
      */
     static Scene* load(const char* filePath);
 
+    /**
+     * Gets a currently active scene.
+     *
+     * If id is an NULL, the first active scene is returned.
+     *
+     * @param id ID of the scene to retrieve, or NULL to retrieve the first active scene.
+     *
+     * @return The scene that matches the specified ID, or NULL if no matching scene could be found.
+     */
+    static Scene* getScene(const char* id = NULL);
+
     /**
      * Gets the identifier for the scene.
      *
@@ -147,9 +161,13 @@ public:
     void bindAudioListenerToCamera(bool bind);
 
     /**
-     * Returns the ambient color of the scene. Black is the default color.
+     * Returns the ambient color of the scene.
+     *
+     * The default ambient light color is black (0,0,0).
+     *
+     * This value can be bound to materials using the SCENE_LIGHT_AMBIENT_COLOR auto binding.
      * 
-     * @return The ambient color of the scene.
+     * @return The scene's ambient color.
      */
     const Vector3& getAmbientColor() const;
 
@@ -159,9 +177,59 @@ public:
      * @param red The red channel between 0.0 and 1.0.
      * @param green The green channel between 0.0 and 1.0.
      * @param blue The blue channel between 0.0 and 1.0.
+     *
+     * @see getAmbientColor()
      */
     void setAmbientColor(float red, float green, float blue);
 
+    /**
+     * Returns the light color of the scene.
+     *
+     * The default light color is white (1,1,1).
+     *
+     * This color is typically used to represent the color of the main directional light (i.e. the Sun) in a scene.
+     * The corresponding direction can be queried using Scene::getLightDirection().
+     *
+     * This value can be bound to materials using the SCENE_LIGHT_COLOR auto binding.
+     *
+     * @return The scene's light color.
+     */
+    const Vector3& getLightColor() const;
+
+    /**
+     * Sets the scene's light color.
+     *
+     * @param red The red channel between 0.0 and 1.0.
+     * @param green The green channel between 0.0 and 1.0.
+     * @param blue The blue channel between 0.0 and 1.0.
+     *
+     * @see getLightColor()
+     */
+    void setLightColor(float red, float green, float blue);
+
+    /**
+     * Returns the current light direction for the scene.
+     *
+     * The default value is (0,-1,0), which is a pointing directly down the Y-axis.
+     *
+     * This value is typically used to represent the the main directional lihgt (i.e. the Sun) in a scene.
+     * The corresponding light color can be queried using Scene::getLightColor().
+     *
+     * This value can be bound to materials using the SCENE_LIGHT_DIRECTION auto binding.
+     *
+     * @return The scene's light direction.
+     */
+    const Vector3& getLightDirection() const;
+
+    /**
+     * Sets the scene's light direction.
+     *
+     * @param direction The new light direction.
+     *
+     * @see getLightDirection()
+     */
+    void setLightDirection(const Vector3& direction);
+
     /**
      * Visits each node in the scene and calls the specified method pointer.
      *
@@ -222,7 +290,7 @@ private:
     /**
      * Constructor.
      */
-    Scene();
+    Scene(const char* id);
 
     /**
      * Hidden copy constructor.
@@ -262,6 +330,8 @@ private:
     Node* _lastNode;
     unsigned int _nodeCount;
     Vector3 _ambientColor;
+    Vector3 _lightColor;
+    Vector3 _lightDirection;
     bool _bindAudioListenerToCamera;
     MeshBatch* _debugBatch;
 };

+ 80 - 19
gameplay/src/SceneLoader.cpp

@@ -3,6 +3,7 @@
 #include "Game.h"
 #include "Bundle.h"
 #include "SceneLoader.h"
+#include "Terrain.h"
 
 namespace gameplay
 {
@@ -42,19 +43,31 @@ Scene* SceneLoader::loadInternal(const char* url)
     }
 
     // Get the path to the main GPB.
-    _gpbPath = sceneProperties->getString("path");
+    const char* path = sceneProperties->getString("path");
+    if (path)
+        _gpbPath = path;
 
     // Build the node URL/property and animation reference tables and load the referenced files/store the inline properties objects.
     buildReferenceTables(sceneProperties);
     loadReferencedFiles();
 
     // Load the main scene data from GPB and apply the global scene properties.
-    Scene* scene = loadMainSceneData(sceneProperties);
-    if (!scene)
+    Scene* scene = NULL;
+    if (!_gpbPath.empty())
     {
-        GP_ERROR("Failed to load main scene from bundle.");
-        SAFE_DELETE(properties);
-        return NULL;
+        // Load scene from bundle
+        scene = loadMainSceneData(sceneProperties);
+        if (!scene)
+        {
+            GP_ERROR("Failed to load main scene from bundle.");
+            SAFE_DELETE(properties);
+            return NULL;
+        }
+    }
+    else
+    {
+        // Create a new empty scene
+        scene = Scene::create(sceneProperties->getId());
     }
 
     // First apply the node url properties. Following that,
@@ -67,6 +80,8 @@ Scene* SceneLoader::loadInternal(const char* url)
         SceneNodeProperty::AUDIO | 
         SceneNodeProperty::MATERIAL | 
         SceneNodeProperty::PARTICLE |
+        SceneNodeProperty::TERRAIN |
+        SceneNodeProperty::CAMERA |
         SceneNodeProperty::ROTATE |
         SceneNodeProperty::SCALE |
         SceneNodeProperty::TRANSLATE);
@@ -83,6 +98,24 @@ Scene* SceneLoader::loadInternal(const char* url)
         }
     }
 
+    // Set active camera
+    const char* activeCamera = sceneProperties->getString("activeCamera");
+    if (activeCamera)
+    {
+        Node* camera = scene->findNode(activeCamera);
+        if (camera && camera->getCamera())
+            scene->setActiveCamera(camera->getCamera());
+    }
+
+    // Set ambient and light properties
+    Vector3 vec3;
+    if (sceneProperties->getVector3("ambientColor", &vec3))
+        scene->setAmbientColor(vec3.x, vec3.y, vec3.z);
+    if (sceneProperties->getVector3("lightColor", &vec3))
+        scene->setLightColor(vec3.x, vec3.y, vec3.z);
+    if (sceneProperties->getVector3("lightDirection", &vec3))
+        scene->setLightDirection(vec3);
+
     // Create animations for scene
     createAnimations(scene);
 
@@ -177,6 +210,8 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
     if (snp._type == SceneNodeProperty::AUDIO ||
         snp._type == SceneNodeProperty::MATERIAL ||
         snp._type == SceneNodeProperty::PARTICLE ||
+        snp._type == SceneNodeProperty::TERRAIN ||
+        snp._type == SceneNodeProperty::CAMERA ||
         snp._type == SceneNodeProperty::COLLISION_OBJECT)
     {
         // Check to make sure the referenced properties object was loaded properly.
@@ -219,6 +254,20 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             SAFE_RELEASE(particleEmitter);
             break;
         }
+        case SceneNodeProperty::TERRAIN:
+        {
+            Terrain* terrain = Terrain::create(p);
+            node->setTerrain(terrain);
+            SAFE_RELEASE(terrain);
+            break;
+        }
+        case SceneNodeProperty::CAMERA:
+        {
+            Camera* camera = Camera::create(p);
+            node->setCamera(camera);
+            SAFE_RELEASE(camera);
+            break;
+        }
         case SceneNodeProperty::COLLISION_OBJECT:
         {
             // Check to make sure the type of the namespace used to load the physics collision object is correct.
@@ -297,21 +346,21 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
         {
             Vector3 t;
             if (np && np->getVector3("translate", &t))
-                node->setTranslation(t);
+                node->translate(t);
             break;
         }
         case SceneNodeProperty::ROTATE:
         {
             Quaternion r;
             if (np && np->getQuaternionFromAxisAngle("rotate", &r))
-                node->setRotation(r);
+                node->rotate(r);
             break;
         }
         case SceneNodeProperty::SCALE:
         {
             Vector3 s;
             if (np && np->getVector3("scale", &s))
-                node->setScale(s);
+                node->scale(s);
             break;
         }
         default:
@@ -470,7 +519,8 @@ void SceneLoader::applyNodeUrls(Scene* scene)
             }
             else
             {
-                GP_ERROR("Failed to locate node with id '%s' in bundle '%s'.", sceneNode._nodeID, _gpbPath.c_str());
+                // There is no node in the scene with this ID, so create a new empty node
+                sceneNode._nodes.push_back(scene->addNode(sceneNode._nodeID));
             }
         }
     }
@@ -519,6 +569,18 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::PARTICLE, propertyUrl.c_str());
                     _properties[propertyUrl] = subns;
                 }
+                else if (strcmp(subns->getNamespace(), "terrain") == 0)
+                {
+                    propertyUrl += "terrain/" + std::string(subns->getId());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::TERRAIN, propertyUrl.c_str());
+                    _properties[propertyUrl] = subns;
+                }
+                else if (strcmp(subns->getNamespace(), "camera") == 0)
+                {
+                    propertyUrl += "camera/" + std::string(subns->getId());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::CAMERA, propertyUrl.c_str());
+                    _properties[propertyUrl] = subns;
+                }
                 else if (strcmp(subns->getNamespace(), "collisionObject") == 0)
                 {
                     propertyUrl += "collisionObject/" + std::string(subns->getId());
@@ -565,6 +627,14 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::PARTICLE, ns->getString());
                 }
+                else if (strcmp(name, "terrain") == 0)
+                {
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::TERRAIN, ns->getString());
+                }
+                else if (strcmp(name, "camera") == 0)
+                {
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::CAMERA, ns->getString());
+                }
                 else if (strcmp(name, "collisionObject") == 0)
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::COLLISION_OBJECT, ns->getString());
@@ -795,15 +865,6 @@ Scene* SceneLoader::loadMainSceneData(const Properties* sceneProperties)
         return NULL;
     }
 
-    // Go through the supported scene properties and apply them to the scene.
-    const char* name = sceneProperties->getString("activeCamera");
-    if (name)
-    {
-        Node* camera = scene->findNode(name);
-        if (camera && camera->getCamera())
-            scene->setActiveCamera(camera->getCamera());
-    }
-
     SAFE_RELEASE(bundle);
     return scene;
 }

+ 7 - 5
gameplay/src/SceneLoader.h

@@ -49,11 +49,13 @@ private:
             AUDIO = 1,
             MATERIAL = 2,
             PARTICLE = 4,
-            COLLISION_OBJECT = 8,
-            TRANSLATE = 16,
-            ROTATE = 32,
-            SCALE = 64,
-            URL = 128
+            TERRAIN = 8,
+            CAMERA = 16,
+            COLLISION_OBJECT = 32,
+            TRANSLATE = 64,
+            ROTATE = 128,
+            SCALE = 256,
+            URL = 512
         };
 
         SceneNodeProperty(Type type, const std::string& url, int index);

+ 67 - 228
gameplay/src/Terrain.cpp

@@ -1,7 +1,6 @@
 #include "Base.h"
 #include "Terrain.h"
 #include "Node.h"
-#include "Image.h"
 #include "FileSystem.h"
 
 namespace gameplay
@@ -20,11 +19,6 @@ namespace gameplay
 //
 #define DEFAULT_TERRAIN_HEIGHT_RATIO 0.3f
 
-/**
- * @script{ignore}
- */
-std::string getExtension(const char* filename);
-
 /**
  * @script{ignore}
  */
@@ -44,36 +38,42 @@ Terrain::~Terrain()
     SAFE_RELEASE(_heightfield);
 }
 
-Terrain* Terrain::create(const char* terrainFile)
+Terrain* Terrain::create(const char* path)
+{
+    return create(path, NULL);
+}
+
+Terrain* Terrain::create(Properties* properties)
+{
+    return create(properties->getNamespace(), properties);
+}
+
+Terrain* Terrain::create(const char* path, Properties* properties)
 {
     // Terrain properties
+    Properties* p = properties;
+    Properties* pTerrain = NULL;
+    bool externalProperties = (p != NULL);
     HeightField* heightfield = NULL;
     Vector3 terrainSize;
     int patchSize = 0;
     int detailLevels = 1;
     float skirtScale = 0;
-    Properties* p = NULL;
-    Properties* pTerrain = NULL;
     const char* normalMap = NULL;
 
-    std::string ext = getExtension(terrainFile);
-    if (ext == "PNG")
+    if (!p && path)
     {
-        // Load terrain directly from a heightmap image
-        heightfield = HeightField::create(terrainFile, 0, 0, 0, 1);
+        p = Properties::create(path);
     }
-    else
-    {
-        // Read terrain from properties file
-        p = Properties::create(terrainFile);
-        if (p == NULL)
-            return NULL;
 
+    if (p)
+    {
         pTerrain = strlen(p->getNamespace()) > 0 ? p : p->getNextNamespace();
         if (pTerrain == NULL)
         {
-            GP_WARN("Invalid terrain definition file.");
-            SAFE_DELETE(p);
+            GP_WARN("Invalid terrain definition.");
+            if (!externalProperties)
+                SAFE_DELETE(p);
             return NULL;
         }
 
@@ -85,36 +85,39 @@ Terrain* Terrain::create(const char* terrainFile)
             const char* heightmap = pHeightmap->getString("path");
             if (strlen(heightmap) == 0)
             {
-                GP_WARN("No 'path' property supplied in heightmap section of terrain definition file: %s", terrainFile);
-                SAFE_DELETE(p);
+                GP_WARN("No 'path' property supplied in heightmap section of terrain definition: %s", path);
+                if (!externalProperties)
+                    SAFE_DELETE(p);
                 return NULL;
             }
 
-            ext = getExtension(heightmap);
-            if (ext == "PNG")
+            std::string ext = FileSystem::getExtension(heightmap);
+            if (ext == ".PNG")
             {
                 // Read normalized height values from heightmap image
-                heightfield = HeightField::create(heightmap, 0, 0, 0, 1);
+                heightfield = HeightField::createFromImage(heightmap, 0, 1);
             }
-            else if (ext == "RAW")
+            else if (ext == ".RAW")
             {
                 // Require additional properties to be specified for RAW files
                 Vector2 imageSize;
                 if (!pHeightmap->getVector2("size", &imageSize))
                 {
-                    GP_WARN("Invalid or missing 'size' attribute in heightmap defintion of terrain file: %s", terrainFile);
-                    SAFE_DELETE(p);
+                    GP_WARN("Invalid or missing 'size' attribute in heightmap defintion of terrain definition: %s", path);
+                    if (!externalProperties)
+                        SAFE_DELETE(p);
                     return NULL;
                 }
 
                 // Read normalized height values from RAW file
-                heightfield = HeightField::create(heightmap, (unsigned int)imageSize.x, (unsigned int)imageSize.y, 0, 1);
+                heightfield = HeightField::createFromRAW(heightmap, (unsigned int)imageSize.x, (unsigned int)imageSize.y, 0, 1);
             }
             else
             {
                 // Unsupported heightmap format
-                GP_WARN("Unsupported heightmap format ('%s') in terrain definition file: %s", heightmap, terrainFile);
-                SAFE_DELETE(p);
+                GP_WARN("Unsupported heightmap format ('%s') in terrain definition: %s", heightmap, path);
+                if (!externalProperties)
+                    SAFE_DELETE(p);
                 return NULL;
             }
         }
@@ -124,27 +127,30 @@ Terrain* Terrain::create(const char* terrainFile)
             const char* heightmap = pTerrain->getString("heightmap");
             if (heightmap == NULL || strlen(heightmap) == 0)
             {
-                GP_WARN("No 'heightmap' property supplied in terrain definition file: %s", terrainFile);
-                SAFE_DELETE(p);
+                GP_WARN("No 'heightmap' property supplied in terrain definition: %s", path);
+                if (!externalProperties)
+                    SAFE_DELETE(p);
                 return NULL;
             }
 
-            ext = getExtension(heightmap);
-            if (ext == "PNG")
+            std::string ext = FileSystem::getExtension(heightmap);
+            if (ext == ".PNG")
             {
                 // Read normalized height values from heightmap image
-                heightfield = HeightField::create(heightmap, 0, 0, 0, 1);
+                heightfield = HeightField::createFromImage(heightmap, 0, 1);
             }
-            else if (ext == "RAW")
+            else if (ext == ".RAW")
             {
                 GP_WARN("RAW heightmaps must be specified inside a heightmap block with width and height properties.");
-                SAFE_DELETE(p);
+                if (!externalProperties)
+                    SAFE_DELETE(p);
                 return NULL;
             }
             else
             {
-                GP_WARN("Unsupported 'heightmap' format ('%s') in terrain definition file: %s.", heightmap, terrainFile);
-                SAFE_DELETE(p);
+                GP_WARN("Unsupported 'heightmap' format ('%s') in terrain definition: %s.", heightmap, path);
+                if (!externalProperties)
+                    SAFE_DELETE(p);
                 return NULL;
             }
         }
@@ -154,7 +160,7 @@ Terrain* Terrain::create(const char* terrainFile)
         {
             if (!pTerrain->getVector3("size", &terrainSize))
             {
-                GP_WARN("Invalid 'size' value ('%s') in terrain definition file: %s", pTerrain->getString("size"), terrainFile);
+                GP_WARN("Invalid 'size' value ('%s') in terrain definition: %s", pTerrain->getString("size"), path);
             }
         }
 
@@ -182,8 +188,9 @@ Terrain* Terrain::create(const char* terrainFile)
 
     if (heightfield == NULL)
     {
-        GP_WARN("Failed to read heightfield heights for terrain: %s", terrainFile);
-        SAFE_DELETE(p);
+        GP_WARN("Failed to read heightfield heights for terrain definition: %s", path);
+        if (!externalProperties)
+            SAFE_DELETE(p);
         return NULL;
     }
 
@@ -209,7 +216,8 @@ Terrain* Terrain::create(const char* terrainFile)
     // Create terrain
     Terrain* terrain = create(heightfield, scale, (unsigned int)patchSize, (unsigned int)detailLevels, skirtScale, normalMap, pTerrain);
 
-    SAFE_DELETE(p);
+    if (!externalProperties)
+        SAFE_DELETE(p);
 
     return terrain;
 }
@@ -371,6 +379,11 @@ bool Terrain::setLayer(int index, const char* texturePath, const Vector2& textur
     return result;
 }
 
+Node* Terrain::getNode() const
+{
+    return _node;
+}
+
 bool Terrain::isFlagSet(Flags flag) const
 {
     return (_flags & flag) == flag;
@@ -446,6 +459,15 @@ const BoundingBox& Terrain::getBoundingBox() const
     return _boundingBox;
 }
 
+float Terrain::getHeight(float x, float z) const
+{
+    // The specified point is in world-space, so we need to transform it
+    // back into local space to index into our HeightField object.
+    // TODO
+
+    return _heightfield->getHeight(x, z);
+}
+
 void Terrain::draw(bool wireframe)
 {
     for (size_t i = 0, count = _patches.size(); i < count; ++i)
@@ -494,193 +516,10 @@ const Matrix& Terrain::getWorldViewProjectionMatrix() const
     return worldViewProj;
 }
 
-// Returns the uppercase extension of a file
-std::string getExtension(const char* filename)
-{
-    const char* str = strrchr(filename, '.');
-    if (str == NULL)
-        return NULL;
-
-    std::string ext;
-    size_t len = strlen(str);
-    for (size_t i = 1; i < len; ++i)
-        ext += std::toupper(str[i]);
-
-    return ext;
-}
-
 float getDefaultHeight(unsigned int width, unsigned int height)
 {
     // When terrain height is not specified, we'll use a default height of ~ 0.3 of the image dimensions
     return ((width + height) * 0.5f) * DEFAULT_TERRAIN_HEIGHT_RATIO;
 }
 
-Terrain::HeightField::HeightField(unsigned int columns, unsigned int rows)
-    : _array(NULL), _cols(columns), _rows(rows)
-{
-    _array = new float[columns * rows];
-}
-
-Terrain::HeightField::~HeightField()
-{
-    SAFE_DELETE_ARRAY(_array);
-}
-
-Terrain::HeightField* Terrain::HeightField::create(unsigned int columns, unsigned int rows)
-{
-    return new HeightField(columns, rows);
-}
-
-/**
- * @script{ignore}
- */
-float normalizedHeightPacked(float r, float g, float b)
-{
-    // This formula is intended for 24-bit packed heightmap images (that are generated
-    // with gameplay-encoder. However, it is also compatible with normal grayscale 
-    // heightmap images, with an error of approximately 0.4%. This can be seen by
-    // setting r=g=b=x and comparing the grayscale height expression to the packed
-    // height expression: the error is 2^-8 + 2^-16 which is just under 0.4%.
-    return (256.0f*r + g + 0.00390625f*b) / 65536.0f;
-}
-
-Terrain::HeightField* Terrain::HeightField::create(const char* imagePath, unsigned int width, unsigned int height, float minHeight, float maxHeight)
-{
-    GP_ASSERT(imagePath);
-    GP_ASSERT(maxHeight >= minHeight);
-
-    // Validate input parameters
-    size_t pathLength = strlen(imagePath);
-    if (pathLength <= 4)
-    {
-        GP_WARN("Unrecognized file extension for heightfield image: %s.", imagePath);
-        return NULL;
-    }
-
-    float heightScale = maxHeight - minHeight;
-
-    HeightField* heightfield = NULL;
-
-    // Load height data from image
-    const char* ext = imagePath + (pathLength - 4);
-    if (ext[0] == '.' && toupper(ext[1]) == 'P' && toupper(ext[2]) == 'N' && toupper(ext[3]) == 'G')
-    {
-        // Normal image
-        Image* image = Image::create(imagePath);
-        if (!image)
-            return NULL;
-
-        unsigned int pixelSize = 0;
-        switch (image->getFormat())
-        {
-            case Image::RGB:
-                pixelSize = 3;
-                break;
-            case Image::RGBA:
-                pixelSize = 4;
-                break;
-            default:
-                SAFE_RELEASE(image);
-                GP_WARN("Unsupported pixel format for heightfield image: %s.", imagePath);
-                return NULL;
-        }
-
-        // Calculate the heights for each pixel.
-        heightfield = HeightField::create(image->getWidth(), image->getHeight());
-        float* heights = heightfield->getArray();
-        unsigned char* data = image->getData();
-        int idx;
-        for (int y = image->getHeight()-1, i = 0; y >= 0; --y)
-        {
-            for (unsigned int x = 0, w = image->getWidth(); x < w; ++x)
-            {
-                idx = (y*w + x) * pixelSize;
-                heights[i++] = minHeight + normalizedHeightPacked(data[idx], data[idx + 1], data[idx + 2]) * heightScale;
-            }
-        }
-
-        SAFE_RELEASE(image);
-    }
-    else if (ext[0] == '.' && toupper(ext[1]) == 'R' && toupper(ext[2]) == 'A' && toupper(ext[3]) == 'W')
-    {
-        // RAW image (headerless)
-        if (width < 2 || height < 2 || maxHeight < 0)
-        {
-            GP_WARN("Invalid 'width', 'height' or 'maxHeight' parameter for RAW heightfield image: %s.", imagePath);
-            return NULL;
-        }
-
-        // Load raw bytes
-        int fileSize = 0;
-        unsigned char* bytes = (unsigned char*)FileSystem::readAll(imagePath, &fileSize);
-        if (bytes == NULL)
-        {
-            GP_WARN("Falied to read bytes from RAW heightfield image: %s.", imagePath);
-            return NULL;
-        }
-
-        // Determine if the RAW file is 8-bit or 16-bit based on file size.
-        int bits = (fileSize / (width * height)) * 8;
-        if (bits != 8 && bits != 16)
-        {
-            GP_WARN("Invalid RAW file - must be 8-bit or 16-bit, but found neither: %s.", imagePath);
-            SAFE_DELETE_ARRAY(bytes);
-            return NULL;
-        }
-
-        heightfield = HeightField::create(width, height);
-        float* heights = heightfield->getArray();
-
-        // RAW files have an origin of bottom left, whereas our height array needs an origin of
-        // top left, so we need to flip the Y as we write height values out.
-        if (bits == 16)
-        {
-            // 16-bit (0-65535)
-            int idx;
-            for (int y = height-1, i = 0; y >= 0; --y)
-            {
-                for (unsigned int x = 0; x < width; ++x, ++i)
-                {
-                    idx = (y * width + x) << 1;
-                    heights[i] = minHeight + ((bytes[idx] | (int)bytes[idx+1] << 8) / 65535.0f) * heightScale;
-                }
-            }
-        }
-        else
-        {
-            // 8-bit (0-255)
-            for (int y = height-1, i = 0; y >= 0; --y)
-            {
-                for (unsigned int x = 0; x < width; ++x, ++i)
-                {
-                    heights[i] = minHeight + (bytes[y * width + x] / 255.0f) * heightScale;
-                }
-            }
-        }
-
-        SAFE_DELETE_ARRAY(bytes);
-    }
-    else
-    {
-        GP_WARN("Unsupported heightfield image format: %s.", imagePath);
-    }
-
-    return heightfield;
-}
-
-float* Terrain::HeightField::getArray() const
-{
-    return _array;
-}
-
-unsigned int Terrain::HeightField::getColumnCount() const
-{
-    return _cols;
-}
-
-unsigned int Terrain::HeightField::getRowCount() const
-{
-    return _rows;
-}
-
 }

+ 62 - 108
gameplay/src/Terrain.h

@@ -3,6 +3,8 @@
 
 #include "TerrainPatch.h"
 #include "Transform.h"
+#include "Properties.h"
+#include "HeightField.h"
 
 namespace gameplay
 {
@@ -80,92 +82,6 @@ class Terrain : public Ref, public Transform::Listener
 
 public:
 
-    /**
-     * Defines a reference counted class that holds heightfeild data.
-     *
-     * Heightfields can be used to construct both Terrain objects as well as PhysicsCollisionShape
-     * heightfield defintions, which are used in heightfield rigid body creation. Heightfields can
-     * be populated manually, or loaded from images and RAW files.
-     */
-    class HeightField : public Ref
-    {
-    public:
-
-        /**
-         * Creates a new HeightField of the given dimensions, with uninitialized height data.
-         *
-         * @param rows Number of rows in the height field.
-         * @param columns Number of columns in the height field.
-         *
-         * @return The new HeightField.
-         */
-        static HeightField* create(unsigned int rows, unsigned int columns);
-
-        /**
-         * Creates a HeightField from the specified heightfield image.
-         *
-         * The specified image path must refer to a valid heightfield image. Supported
-         * formats include PNG, RAW8 and RAW16. The latter two formats are simply raw,
-         * headerless height data in either 8-bit format or 16-bit format. RAW16 images
-         * must have little endian (PC) byte ordering. For images that have header structures
-         * (such as PNG), the width and hegiht parameters are ignored and are instead
-         * read from the image header.
-         *
-         * The minHeight and maxHeight parameters provides a mapping from heightfield pixel
-         * intensity to height values. The minHeight parameter is mapped to zero intensity
-         * pixel, while maxHeight maxHeight is mapped to full intensity pixels.
-         *
-         * @param imagePath Path to a heightfield image.
-         * @param width Width of the image (required for headerless/RAW files, can be zero for other image formats).
-         * @param height Height of the image (required for headerless/RAW files, can be zero for other image formats).
-         * @param minHeight Minimum height value for a zero intensity pixel.
-         * @param maxHeight Maximum height value for a full intensity heightfield pixel.
-         * 
-         * @return The new HeightField.
-         */
-        static HeightField* create(const char* imagePath, unsigned int width = 0, unsigned int height = 0, float minHeight = 0, float maxHeight = 1);
-
-        /**
-         * Returns a pointer to the underying height array.
-         *
-         * The array is packed in row major order, meaning that the data is aligned in rows,
-         * from top left to bottom right.
-         *
-         * @return The underlying height array.
-         */
-        float* getArray() const;
-
-        /**
-         * Returns the number of rows in the heightfield.
-         *
-         * @return The number of rows.
-         */
-        unsigned int getRowCount() const;
-
-        /**
-         * Returns the number of columns in the heightfield.
-         * 
-         * @return The column count.
-         */
-        unsigned int getColumnCount() const;
-
-    private:
-
-        /**
-         * Hidden constructor.
-         */
-        HeightField(unsigned int columns, unsigned int rows);
-
-        /**
-         * Hidden destructor (use Ref::release()).
-         */
-        ~HeightField();
-
-        float* _array;
-        unsigned int _rows;
-        unsigned int _cols;
-    };
-
     /**
      * Terrain flags.
      */
@@ -194,41 +110,39 @@ public:
          ENABLE_LEVEL_OF_DETAIL = 8
     };
 
-    /** 
-     * Loads a Terran from the given file.
-     *
-     * The specified file can be either a simple heightmap image, or it can be a terrain properties
-     * file containing the definition of a terrain.
-     *
-     * Only supported image types that have valid headers (i.e. not RAW) are supported if specifying
-     * an image directly. In this case, the dimensions of the unscaled terrain along each world axis
-     * will be as follows:
+    /**
+     * Loads a Terrain from the given properties file.
      *
-     *  X = image.width
-     *  Y = (image.width + image.height) / 2 * 0.3f
-     *  Z = image.height
+     * The specified properties file can contain a full terrain definition, including a 
+     * heightmap (PNG, RAW8, RAW16), level of detail information, patch size, layer texture
+     * details and vertical skirt size.
      *
-     * When specifying an image directly, there terrain will be rendered using a default white material,
-     * until layer textures are specified via the setLayer method. Only a single level of detail will
-     * be generated and terrain patches will use a default size of 32x32.
+     * @param path Path to a properties file describing the terrain.
      *
-     * If specifying a terrain properties file, the properties file can contain a full terrain definition,
-     * including an image or RAW16/RAW32 heightmap, level of detail information, patch size, layer texture
-     * details and vertical skirt size.
+     * @return A new Terrain.
+     */
+    static Terrain* create(const char* path);
+
+    /**
+     * Creates a new terrain definition from the configuration in the specified Properties object.
      *
-     * @param terrainFile Properties file describing the terrain.
+     * @param properties Properties object containing the terrain definition.
      *
      * @return A new Terrain.
+     *
+     * @see create(const char*)
      */
-    static Terrain* create(const char* terrainFile);
+    static Terrain* create(Properties* properties);
 
     /**
-     * Creates a terrain from the given height array.
+     * Creates a terrain from the given heightfield.
      *
      * Terrain geometry is loaded from the given height array, using the specified parameters for
      * size, patch size, detail levels and skirt scale.
      *
-     * @param heights Height array containing terrain height values.
+     * The newly created terrain increases the reference count of the HeightField.
+     *
+     * @param heightfield The heightfield object containing height data for the terrain.
      * @param scale A scale to apply to the terrain along the X, Y and Z axes. The terrain and any associated
      *      physics hegihtfield is scaled by this amount. Pass Vector3::one() to use the exact dimensions and heights
      *      in the supplied height array.
@@ -281,12 +195,21 @@ public:
      *
      * @return True if the layer was successfully set, false otherwise. The most common reason for failure is an
      *      invalid texture path.
+     *
+     * @script{ignore}
      */
     bool setLayer(int index,
         const char* texturePath, const Vector2& textureRepeat = Vector2::one(),
         const char* blendPath = NULL, int blendChannel = 0,
         int row = -1, int column = -1);
 
+    /**
+     * Returns the node that this terrain is bound to.
+     *
+     * @return The node this terrain is bound to, or NULL if the terrain is not bound to a node.
+     */
+    Node* getNode() const;
+
     /**
      * Determines if the specified terrain flag is currently set.
      */
@@ -343,6 +266,20 @@ public:
      */
     const BoundingBox& getBoundingBox() const;
 
+    /**
+     * Returns the world-space height of the terrain at the specified position on the X,Z plane.
+     *
+     * The specified X and Z coordinates should be in world units and may fall between height values.
+     * In this case, an interpolated value will be returned between neighboring heightfield heights.
+     * If the specified point lies outside of the terrain, it is clamped to the terrain boundaries.
+     *
+     * @param x The X coordinate, in world space.
+     * @param z The Z coordinate, in world space.
+     *
+     * @return The height at the specified point, clamped to the boundaries of the terrain.
+     */
+    float getHeight(float x, float z) const;
+
     /**
      * Draws the terrain.
      *
@@ -381,12 +318,29 @@ private:
      */
     ~Terrain();
 
+    /**
+     * Internal method for creating terrain.
+     */
     static Terrain* create(HeightField* heightfield, const Vector3& scale, unsigned int patchSize, unsigned int detailLevels, float skirtScale, const char* normalMapPath, Properties* properties);
 
+    /**
+     * Internal method for creating terrain.
+     */
+    static Terrain* create(const char* path, Properties* properties);
+
+    /**
+     * Sets the node that the terrain is attached to.
+     */
     void setNode(Node* node);
 
+    /**
+     * Returns the world matrix of the terrain, factoring in terrain local scaling.
+     */
     const Matrix& getWorldMatrix() const;
 
+    /**
+     * Returns the world view projection matrix for the terrain, factoring in terrain local scaling.
+     */
     const Matrix& getWorldViewProjectionMatrix() const;
 
     HeightField* _heightfield;

+ 40 - 4
gameplay/src/TerrainPatch.cpp

@@ -473,8 +473,9 @@ bool TerrainPatch::updateMaterial()
 
         // Set material parameter bindings
         material->getParameter("u_worldViewProjectionMatrix")->bindValue(_terrain, &Terrain::getWorldViewProjectionMatrix);
-        material->getParameter("u_lightDirection")->setValue(Vector3(-1,-1,-1));
-        material->getParameter("u_lightColor")->setValue(Vector3(1,1,1));
+        material->getParameter("u_ambientColor")->bindValue(this, &TerrainPatch::getAmbientColor);
+        material->getParameter("u_lightColor")->bindValue(this, &TerrainPatch::getLightColor);
+        material->getParameter("u_lightDirection")->bindValue(this, &TerrainPatch::getLightDirection);
         if (_layers.size() > 0)
         {
             material->getParameter("u_samplers")->setValue((const Texture::Sampler**)&_samplers[0], (unsigned int)_samplers.size());
@@ -530,6 +531,10 @@ void TerrainPatch::draw(bool wireframe)
 
 bool TerrainPatch::isVisible() const
 {
+    // If frustum culling is disabled, assume the patch is always visible
+    if ((_terrain->_flags & Terrain::ENABLE_FRUSTUM_CULLING) == 0)
+        return true;
+
     Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
     Camera* camera = scene ? scene->getActiveCamera() : NULL;
     if (!camera)
@@ -559,7 +564,7 @@ unsigned int TerrainPatch::getVisibleTriangleCount() const
 
     // Return the triangle count of the LOD level depending on the camera
     size_t lod = computeLOD(camera, bounds);
-    return _levels[0]->model->getMesh()->getPart(0)->getIndexCount() - 2;
+    return _levels[lod]->model->getMesh()->getPart(0)->getIndexCount() - 2;
 }
 
 BoundingBox TerrainPatch::getBoundingBox(bool worldSpace) const
@@ -569,10 +574,41 @@ BoundingBox TerrainPatch::getBoundingBox(bool worldSpace) const
 
     // Apply a world-space transformation to our bounding box
     BoundingBox bounds(_boundingBox);
-    bounds.transform(_terrain->getWorldMatrix());
+
+    // Transform the bounding box by the terrain node's world transform.
+    // We don't use Terrain::getWorldMatrix because that returns a matrix
+    // that has terrain->_localScale factored in - and our patche's bounding
+    // box already has local scale factored in.
+    if (_terrain->_node)
+        bounds.transform(_terrain->_node->getWorldMatrix());
+
     return bounds;
 }
 
+const Vector3& TerrainPatch::getAmbientColor() const
+{
+    Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
+    return scene ? scene->getAmbientColor() : Vector3::zero();
+}
+
+const Vector3& TerrainPatch::getLightColor() const
+{
+    Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
+    return scene ? scene->getLightColor() : Vector3::one();
+}
+
+const Vector3& TerrainPatch::getLightDirection() const
+{
+    Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
+    if (!scene)
+    {
+        static Vector3 down(0, -1, 0);
+        return down;
+    }
+
+    return scene->getLightDirection();
+}
+
 size_t TerrainPatch::computeLOD(Camera* camera, const BoundingBox& worldBounds) const
 {
     if (!_terrain->isFlagSet(Terrain::ENABLE_LEVEL_OF_DETAIL) || _levels.size() == 0)

+ 6 - 0
gameplay/src/TerrainPatch.h

@@ -141,6 +141,12 @@ private:
      */
     BoundingBox getBoundingBox(bool worldSpace) const;
 
+    const Vector3& getAmbientColor() const;
+
+    const Vector3& getLightColor() const;
+
+    const Vector3& getLightDirection() const;
+
     Terrain* _terrain;
     std::vector<Level*> _levels;
     unsigned int _row;

+ 1 - 0
gameplay/src/gameplay.h

@@ -38,6 +38,7 @@
 #include "VertexFormat.h"
 #include "VertexAttributeBinding.h"
 #include "Model.h"
+#include "HeightField.h"
 #include "Terrain.h"
 #include "Camera.h"
 #include "Light.h"

+ 53 - 0
gameplay/src/lua/lua_Camera.cpp

@@ -52,6 +52,7 @@ void luaRegister_Camera()
     };
     const luaL_Reg lua_statics[] = 
     {
+        {"create", lua_Camera_static_create},
         {"createOrthographic", lua_Camera_static_createOrthographic},
         {"createPerspective", lua_Camera_static_createPerspective},
         {NULL, NULL}
@@ -1140,6 +1141,58 @@ int lua_Camera_setZoomY(lua_State* state)
     return 0;
 }
 
+int lua_Camera_static_create(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_TUSERDATA || lua_type(state, 1) == LUA_TTABLE || lua_type(state, 1) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                bool param1Valid;
+                ScriptUtil::LuaArray<Properties> param1 = ScriptUtil::getObjectPointer<Properties>(1, "Properties", false, &param1Valid);
+                if (!param1Valid)
+                {
+                    lua_pushstring(state, "Failed to convert parameter 1 to type 'Properties'.");
+                    lua_error(state);
+                }
+
+                void* returnPtr = (void*)Camera::create(param1);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "Camera");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Camera_static_create - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Camera_static_createOrthographic(lua_State* state)
 {
     // Get the number of parameters.

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

@@ -31,6 +31,7 @@ int lua_Camera_setFieldOfView(lua_State* state);
 int lua_Camera_setNearPlane(lua_State* state);
 int lua_Camera_setZoomX(lua_State* state);
 int lua_Camera_setZoomY(lua_State* state);
+int lua_Camera_static_create(lua_State* state);
 int lua_Camera_static_createOrthographic(lua_State* state);
 int lua_Camera_static_createPerspective(lua_State* state);
 int lua_Camera_unproject(lua_State* state);

+ 38 - 0
gameplay/src/lua/lua_FileSystem.cpp

@@ -19,6 +19,7 @@ void luaRegister_FileSystem()
     {
         {"createFileFromAsset", lua_FileSystem_static_createFileFromAsset},
         {"fileExists", lua_FileSystem_static_fileExists},
+        {"getExtension", lua_FileSystem_static_getExtension},
         {"getResourcePath", lua_FileSystem_static_getResourcePath},
         {"isAbsolutePath", lua_FileSystem_static_isAbsolutePath},
         {"loadResourceAliases", lua_FileSystem_static_loadResourceAliases},
@@ -148,6 +149,43 @@ int lua_FileSystem_static_fileExists(lua_State* state)
     return 0;
 }
 
+int lua_FileSystem_static_getExtension(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);
+
+                std::string result = FileSystem::getExtension(param1);
+
+                // Push the return value onto the stack.
+                lua_pushstring(state, result.c_str());
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_FileSystem_static_getExtension - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_FileSystem_static_getResourcePath(lua_State* state)
 {
     // Get the number of parameters.

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

@@ -8,6 +8,7 @@ namespace gameplay
 int lua_FileSystem__gc(lua_State* state);
 int lua_FileSystem_static_createFileFromAsset(lua_State* state);
 int lua_FileSystem_static_fileExists(lua_State* state);
+int lua_FileSystem_static_getExtension(lua_State* state);
 int lua_FileSystem_static_getResourcePath(lua_State* state);
 int lua_FileSystem_static_isAbsolutePath(lua_State* state);
 int lua_FileSystem_static_loadResourceAliases(lua_State* state);

+ 4 - 1
gameplay/src/lua/lua_Global.cpp

@@ -74,6 +74,7 @@ void luaRegister_lua_Global()
     ScriptUtil::setGlobalHierarchyPair("Ref", "Font");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Form");
     ScriptUtil::setGlobalHierarchyPair("Ref", "FrameBuffer");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "HeightField");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Image");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Joint");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Joystick");
@@ -96,7 +97,6 @@ void luaRegister_lua_Global()
     ScriptUtil::setGlobalHierarchyPair("Ref", "Slider");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Technique");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Terrain");
-    ScriptUtil::setGlobalHierarchyPair("Ref", "Terrain::HeightField");
     ScriptUtil::setGlobalHierarchyPair("Ref", "TextBox");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Texture");
     ScriptUtil::setGlobalHierarchyPair("Ref", "Texture::Sampler");
@@ -700,6 +700,9 @@ void luaRegister_lua_Global()
         ScriptUtil::registerConstantString("CAMERA_WORLD_POSITION", "CAMERA_WORLD_POSITION", scopePath);
         ScriptUtil::registerConstantString("CAMERA_VIEW_POSITION", "CAMERA_VIEW_POSITION", scopePath);
         ScriptUtil::registerConstantString("MATRIX_PALETTE", "MATRIX_PALETTE", scopePath);
+        ScriptUtil::registerConstantString("SCENE_AMBIENT_COLOR", "SCENE_AMBIENT_COLOR", scopePath);
+        ScriptUtil::registerConstantString("SCENE_LIGHT_COLOR", "SCENE_LIGHT_COLOR", scopePath);
+        ScriptUtil::registerConstantString("SCENE_LIGHT_DIRECTION", "SCENE_LIGHT_DIRECTION", scopePath);
     }
 
     // Register enumeration RenderState::Blend.

+ 632 - 0
gameplay/src/lua/lua_HeightField.cpp

@@ -0,0 +1,632 @@
+#include "Base.h"
+#include "ScriptController.h"
+#include "lua_HeightField.h"
+#include "Base.h"
+#include "FileSystem.h"
+#include "Game.h"
+#include "HeightField.h"
+#include "Image.h"
+#include "Ref.h"
+
+namespace gameplay
+{
+
+void luaRegister_HeightField()
+{
+    const luaL_Reg lua_members[] = 
+    {
+        {"addRef", lua_HeightField_addRef},
+        {"getArray", lua_HeightField_getArray},
+        {"getColumnCount", lua_HeightField_getColumnCount},
+        {"getHeight", lua_HeightField_getHeight},
+        {"getRefCount", lua_HeightField_getRefCount},
+        {"getRowCount", lua_HeightField_getRowCount},
+        {"release", lua_HeightField_release},
+        {NULL, NULL}
+    };
+    const luaL_Reg lua_statics[] = 
+    {
+        {"create", lua_HeightField_static_create},
+        {"createFromImage", lua_HeightField_static_createFromImage},
+        {"createFromRAW", lua_HeightField_static_createFromRAW},
+        {NULL, NULL}
+    };
+    std::vector<std::string> scopePath;
+
+    ScriptUtil::registerClass("HeightField", lua_members, NULL, lua_HeightField__gc, lua_statics, scopePath);
+}
+
+static HeightField* getInstance(lua_State* state)
+{
+    void* userdata = luaL_checkudata(state, 1, "HeightField");
+    luaL_argcheck(state, userdata != NULL, 1, "'HeightField' expected.");
+    return (HeightField*)((ScriptUtil::LuaObject*)userdata)->instance;
+}
+
+int lua_HeightField__gc(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_TUSERDATA))
+            {
+                void* userdata = luaL_checkudata(state, 1, "HeightField");
+                luaL_argcheck(state, userdata != NULL, 1, "'HeightField' expected.");
+                ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)userdata;
+                if (object->owns)
+                {
+                    HeightField* instance = (HeightField*)object->instance;
+                    SAFE_RELEASE(instance);
+                }
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_HeightField__gc - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_addRef(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_TUSERDATA))
+            {
+                HeightField* instance = getInstance(state);
+                instance->addRef();
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_HeightField_addRef - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_getArray(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_TUSERDATA))
+            {
+                HeightField* instance = getInstance(state);
+                float* result = instance->getArray();
+
+                // Push the return value onto the stack.
+                lua_pushlightuserdata(state, result);
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_getArray - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_getColumnCount(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_TUSERDATA))
+            {
+                HeightField* instance = getInstance(state);
+                unsigned int result = instance->getColumnCount();
+
+                // Push the return value onto the stack.
+                lua_pushunsigned(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_getColumnCount - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_getHeight(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 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                HeightField* instance = getInstance(state);
+                float result = instance->getHeight(param1, param2);
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_getHeight - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_getRefCount(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_TUSERDATA))
+            {
+                HeightField* instance = getInstance(state);
+                unsigned int result = instance->getRefCount();
+
+                // Push the return value onto the stack.
+                lua_pushunsigned(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_getRefCount - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_getRowCount(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_TUSERDATA))
+            {
+                HeightField* instance = getInstance(state);
+                unsigned int result = instance->getRowCount();
+
+                // Push the return value onto the stack.
+                lua_pushunsigned(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_getRowCount - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_release(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_TUSERDATA))
+            {
+                HeightField* instance = getInstance(state);
+                instance->release();
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_HeightField_release - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_static_create(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 2:
+        {
+            if (lua_type(state, 1) == LUA_TNUMBER &&
+                lua_type(state, 2) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
+
+                // Get parameter 2 off the stack.
+                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
+
+                void* returnPtr = (void*)HeightField::create(param1, param2);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "HeightField");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_static_create - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_static_createFromImage(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);
+
+                void* returnPtr = (void*)HeightField::createFromImage(param1);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "HeightField");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_static_createFromImage - 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_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(1, false);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 2);
+
+                void* returnPtr = (void*)HeightField::createFromImage(param1, param2);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "HeightField");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_static_createFromImage - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        case 3:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(1, false);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 3 off the stack.
+                float param3 = (float)luaL_checknumber(state, 3);
+
+                void* returnPtr = (void*)HeightField::createFromImage(param1, param2, param3);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "HeightField");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_static_createFromImage - 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, 2 or 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_HeightField_static_createFromRAW(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 3:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(1, false);
+
+                // Get parameter 2 off the stack.
+                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
+
+                // Get parameter 3 off the stack.
+                unsigned int param3 = (unsigned int)luaL_checkunsigned(state, 3);
+
+                void* returnPtr = (void*)HeightField::createFromRAW(param1, param2, param3);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "HeightField");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_static_createFromRAW - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        case 4:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER &&
+                lua_type(state, 4) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(1, false);
+
+                // Get parameter 2 off the stack.
+                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
+
+                // Get parameter 3 off the stack.
+                unsigned int param3 = (unsigned int)luaL_checkunsigned(state, 3);
+
+                // Get parameter 4 off the stack.
+                float param4 = (float)luaL_checknumber(state, 4);
+
+                void* returnPtr = (void*)HeightField::createFromRAW(param1, param2, param3, param4);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "HeightField");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_static_createFromRAW - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        case 5:
+        {
+            if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER &&
+                lua_type(state, 4) == LUA_TNUMBER &&
+                lua_type(state, 5) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                const char* param1 = ScriptUtil::getString(1, false);
+
+                // Get parameter 2 off the stack.
+                unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
+
+                // Get parameter 3 off the stack.
+                unsigned int param3 = (unsigned int)luaL_checkunsigned(state, 3);
+
+                // Get parameter 4 off the stack.
+                float param4 = (float)luaL_checknumber(state, 4);
+
+                // Get parameter 5 off the stack.
+                float param5 = (float)luaL_checknumber(state, 5);
+
+                void* returnPtr = (void*)HeightField::createFromRAW(param1, param2, param3, param4, param5);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "HeightField");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_HeightField_static_createFromRAW - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3, 4 or 5).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+}

+ 24 - 0
gameplay/src/lua/lua_HeightField.h

@@ -0,0 +1,24 @@
+#ifndef LUA_HEIGHTFIELD_H_
+#define LUA_HEIGHTFIELD_H_
+
+namespace gameplay
+{
+
+// Lua bindings for HeightField.
+int lua_HeightField__gc(lua_State* state);
+int lua_HeightField_addRef(lua_State* state);
+int lua_HeightField_getArray(lua_State* state);
+int lua_HeightField_getColumnCount(lua_State* state);
+int lua_HeightField_getHeight(lua_State* state);
+int lua_HeightField_getRefCount(lua_State* state);
+int lua_HeightField_getRowCount(lua_State* state);
+int lua_HeightField_release(lua_State* state);
+int lua_HeightField_static_create(lua_State* state);
+int lua_HeightField_static_createFromImage(lua_State* state);
+int lua_HeightField_static_createFromRAW(lua_State* state);
+
+void luaRegister_HeightField();
+
+}
+
+#endif

+ 1 - 0
gameplay/src/lua/lua_Material.cpp

@@ -11,6 +11,7 @@
 #include "Properties.h"
 #include "Ref.h"
 #include "RenderState.h"
+#include "Scene.h"
 #include "Technique.h"
 #include "lua_RenderStateAutoBinding.h"
 #include "lua_RenderStateBlend.h"

+ 1 - 0
gameplay/src/lua/lua_Pass.cpp

@@ -8,6 +8,7 @@
 #include "Pass.h"
 #include "Ref.h"
 #include "RenderState.h"
+#include "Scene.h"
 #include "Technique.h"
 #include "lua_RenderStateAutoBinding.h"
 #include "lua_RenderStateBlend.h"

+ 228 - 0
gameplay/src/lua/lua_PhysicsCharacter.cpp

@@ -10,6 +10,9 @@
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
 #include "PhysicsGhostObject.h"
+#include "PhysicsRigidBody.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 #include "Scene.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
@@ -27,6 +30,11 @@ void luaRegister_PhysicsCharacter()
     const luaL_Reg lua_members[] = 
     {
         {"addCollisionListener", lua_PhysicsCharacter_addCollisionListener},
+        {"asCharacter", lua_PhysicsCharacter_asCharacter},
+        {"asGhostObject", lua_PhysicsCharacter_asGhostObject},
+        {"asRigidBody", lua_PhysicsCharacter_asRigidBody},
+        {"asVehicle", lua_PhysicsCharacter_asVehicle},
+        {"asVehicleWheel", lua_PhysicsCharacter_asVehicleWheel},
         {"collidesWith", lua_PhysicsCharacter_collidesWith},
         {"getCollisionShape", lua_PhysicsCharacter_getCollisionShape},
         {"getCurrentVelocity", lua_PhysicsCharacter_getCurrentVelocity},
@@ -176,6 +184,226 @@ int lua_PhysicsCharacter_addCollisionListener(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsCharacter_asCharacter(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_TUSERDATA))
+            {
+                PhysicsCharacter* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asCharacter();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsCharacter");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCharacter_asCharacter - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCharacter_asGhostObject(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_TUSERDATA))
+            {
+                PhysicsCharacter* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asGhostObject();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsGhostObject");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCharacter_asGhostObject - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCharacter_asRigidBody(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_TUSERDATA))
+            {
+                PhysicsCharacter* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asRigidBody();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsRigidBody");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCharacter_asRigidBody - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCharacter_asVehicle(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_TUSERDATA))
+            {
+                PhysicsCharacter* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicle();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicle");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCharacter_asVehicle - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCharacter_asVehicleWheel(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_TUSERDATA))
+            {
+                PhysicsCharacter* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicleWheel();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicleWheel");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCharacter_asVehicleWheel - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsCharacter_collidesWith(lua_State* state)
 {
     // Get the number of parameters.

+ 5 - 0
gameplay/src/lua/lua_PhysicsCharacter.h

@@ -6,6 +6,11 @@ namespace gameplay
 
 // Lua bindings for PhysicsCharacter.
 int lua_PhysicsCharacter_addCollisionListener(lua_State* state);
+int lua_PhysicsCharacter_asCharacter(lua_State* state);
+int lua_PhysicsCharacter_asGhostObject(lua_State* state);
+int lua_PhysicsCharacter_asRigidBody(lua_State* state);
+int lua_PhysicsCharacter_asVehicle(lua_State* state);
+int lua_PhysicsCharacter_asVehicleWheel(lua_State* state);
 int lua_PhysicsCharacter_collidesWith(lua_State* state);
 int lua_PhysicsCharacter_getCollisionShape(lua_State* state);
 int lua_PhysicsCharacter_getCurrentVelocity(lua_State* state);

+ 230 - 0
gameplay/src/lua/lua_PhysicsCollisionObject.cpp

@@ -4,8 +4,13 @@
 #include "Base.h"
 #include "Game.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
+#include "PhysicsGhostObject.h"
+#include "PhysicsRigidBody.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
 #include "lua_PhysicsCollisionObjectCollisionListenerEventType.h"
 #include "lua_PhysicsCollisionObjectType.h"
@@ -19,6 +24,11 @@ void luaRegister_PhysicsCollisionObject()
     const luaL_Reg lua_members[] = 
     {
         {"addCollisionListener", lua_PhysicsCollisionObject_addCollisionListener},
+        {"asCharacter", lua_PhysicsCollisionObject_asCharacter},
+        {"asGhostObject", lua_PhysicsCollisionObject_asGhostObject},
+        {"asRigidBody", lua_PhysicsCollisionObject_asRigidBody},
+        {"asVehicle", lua_PhysicsCollisionObject_asVehicle},
+        {"asVehicleWheel", lua_PhysicsCollisionObject_asVehicleWheel},
         {"collidesWith", lua_PhysicsCollisionObject_collidesWith},
         {"getCollisionShape", lua_PhysicsCollisionObject_getCollisionShape},
         {"getNode", lua_PhysicsCollisionObject_getNode},
@@ -192,6 +202,226 @@ int lua_PhysicsCollisionObject_addCollisionListener(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsCollisionObject_asCharacter(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_TUSERDATA))
+            {
+                PhysicsCollisionObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asCharacter();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsCharacter");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCollisionObject_asCharacter - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCollisionObject_asGhostObject(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_TUSERDATA))
+            {
+                PhysicsCollisionObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asGhostObject();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsGhostObject");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCollisionObject_asGhostObject - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCollisionObject_asRigidBody(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_TUSERDATA))
+            {
+                PhysicsCollisionObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asRigidBody();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsRigidBody");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCollisionObject_asRigidBody - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCollisionObject_asVehicle(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_TUSERDATA))
+            {
+                PhysicsCollisionObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicle();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicle");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCollisionObject_asVehicle - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsCollisionObject_asVehicleWheel(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_TUSERDATA))
+            {
+                PhysicsCollisionObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicleWheel();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicleWheel");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsCollisionObject_asVehicleWheel - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsCollisionObject_collidesWith(lua_State* state)
 {
     // Get the number of parameters.

+ 5 - 0
gameplay/src/lua/lua_PhysicsCollisionObject.h

@@ -7,6 +7,11 @@ namespace gameplay
 // Lua bindings for PhysicsCollisionObject.
 int lua_PhysicsCollisionObject__gc(lua_State* state);
 int lua_PhysicsCollisionObject_addCollisionListener(lua_State* state);
+int lua_PhysicsCollisionObject_asCharacter(lua_State* state);
+int lua_PhysicsCollisionObject_asGhostObject(lua_State* state);
+int lua_PhysicsCollisionObject_asRigidBody(lua_State* state);
+int lua_PhysicsCollisionObject_asVehicle(lua_State* state);
+int lua_PhysicsCollisionObject_asVehicleWheel(lua_State* state);
 int lua_PhysicsCollisionObject_collidesWith(lua_State* state);
 int lua_PhysicsCollisionObject_getCollisionShape(lua_State* state);
 int lua_PhysicsCollisionObject_getNode(lua_State* state);

+ 5 - 0
gameplay/src/lua/lua_PhysicsCollisionObjectCollisionListener.cpp

@@ -4,8 +4,13 @@
 #include "Base.h"
 #include "Game.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
+#include "PhysicsGhostObject.h"
+#include "PhysicsRigidBody.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
 #include "lua_PhysicsCollisionObjectCollisionListenerEventType.h"
 #include "lua_PhysicsCollisionObjectType.h"

+ 5 - 0
gameplay/src/lua/lua_PhysicsCollisionObjectCollisionPair.cpp

@@ -4,8 +4,13 @@
 #include "Base.h"
 #include "Game.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
+#include "PhysicsGhostObject.h"
+#include "PhysicsRigidBody.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
 #include "lua_PhysicsCollisionObjectCollisionListenerEventType.h"
 #include "lua_PhysicsCollisionObjectType.h"

+ 2 - 1
gameplay/src/lua/lua_PhysicsCollisionShape.cpp

@@ -4,6 +4,7 @@
 #include "Base.h"
 #include "FileSystem.h"
 #include "Game.h"
+#include "HeightField.h"
 #include "Image.h"
 #include "Node.h"
 #include "PhysicsCollisionShape.h"
@@ -569,7 +570,7 @@ int lua_PhysicsCollisionShape_static_heightfield(lua_State* state)
                 {
                     // Get parameter 1 off the stack.
                     bool param1Valid;
-                    ScriptUtil::LuaArray<Terrain::HeightField> param1 = ScriptUtil::getObjectPointer<Terrain::HeightField>(1, "TerrainHeightField", false, &param1Valid);
+                    ScriptUtil::LuaArray<HeightField> param1 = ScriptUtil::getObjectPointer<HeightField>(1, "HeightField", false, &param1Valid);
                     if (!param1Valid)
                         break;
 

+ 1 - 0
gameplay/src/lua/lua_PhysicsCollisionShapeDefinition.cpp

@@ -4,6 +4,7 @@
 #include "Base.h"
 #include "FileSystem.h"
 #include "Game.h"
+#include "HeightField.h"
 #include "Image.h"
 #include "Node.h"
 #include "PhysicsCollisionShape.h"

+ 1 - 0
gameplay/src/lua/lua_PhysicsController.cpp

@@ -10,6 +10,7 @@
 #include "PhysicsRigidBody.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
+#include "Terrain.h"
 #include "lua_PhysicsControllerListenerEventType.h"
 
 namespace gameplay

+ 1 - 0
gameplay/src/lua/lua_PhysicsControllerHitFilter.cpp

@@ -10,6 +10,7 @@
 #include "PhysicsRigidBody.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
+#include "Terrain.h"
 #include "lua_PhysicsControllerListenerEventType.h"
 
 namespace gameplay

+ 1 - 0
gameplay/src/lua/lua_PhysicsControllerHitResult.cpp

@@ -10,6 +10,7 @@
 #include "PhysicsRigidBody.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
+#include "Terrain.h"
 #include "lua_PhysicsControllerListenerEventType.h"
 
 namespace gameplay

+ 1 - 0
gameplay/src/lua/lua_PhysicsControllerListener.cpp

@@ -10,6 +10,7 @@
 #include "PhysicsRigidBody.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
+#include "Terrain.h"
 #include "lua_PhysicsControllerListenerEventType.h"
 
 namespace gameplay

+ 229 - 0
gameplay/src/lua/lua_PhysicsGhostObject.cpp

@@ -6,9 +6,13 @@
 #include "Base.h"
 #include "Game.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
 #include "PhysicsGhostObject.h"
+#include "PhysicsRigidBody.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
 #include "Transform.h"
@@ -25,6 +29,11 @@ void luaRegister_PhysicsGhostObject()
     const luaL_Reg lua_members[] = 
     {
         {"addCollisionListener", lua_PhysicsGhostObject_addCollisionListener},
+        {"asCharacter", lua_PhysicsGhostObject_asCharacter},
+        {"asGhostObject", lua_PhysicsGhostObject_asGhostObject},
+        {"asRigidBody", lua_PhysicsGhostObject_asRigidBody},
+        {"asVehicle", lua_PhysicsGhostObject_asVehicle},
+        {"asVehicleWheel", lua_PhysicsGhostObject_asVehicleWheel},
         {"collidesWith", lua_PhysicsGhostObject_collidesWith},
         {"getCollisionShape", lua_PhysicsGhostObject_getCollisionShape},
         {"getNode", lua_PhysicsGhostObject_getNode},
@@ -161,6 +170,226 @@ int lua_PhysicsGhostObject_addCollisionListener(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsGhostObject_asCharacter(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_TUSERDATA))
+            {
+                PhysicsGhostObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asCharacter();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsCharacter");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsGhostObject_asCharacter - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsGhostObject_asGhostObject(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_TUSERDATA))
+            {
+                PhysicsGhostObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asGhostObject();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsGhostObject");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsGhostObject_asGhostObject - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsGhostObject_asRigidBody(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_TUSERDATA))
+            {
+                PhysicsGhostObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asRigidBody();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsRigidBody");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsGhostObject_asRigidBody - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsGhostObject_asVehicle(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_TUSERDATA))
+            {
+                PhysicsGhostObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicle();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicle");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsGhostObject_asVehicle - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsGhostObject_asVehicleWheel(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_TUSERDATA))
+            {
+                PhysicsGhostObject* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicleWheel();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicleWheel");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsGhostObject_asVehicleWheel - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsGhostObject_collidesWith(lua_State* state)
 {
     // Get the number of parameters.

+ 5 - 0
gameplay/src/lua/lua_PhysicsGhostObject.h

@@ -6,6 +6,11 @@ namespace gameplay
 
 // Lua bindings for PhysicsGhostObject.
 int lua_PhysicsGhostObject_addCollisionListener(lua_State* state);
+int lua_PhysicsGhostObject_asCharacter(lua_State* state);
+int lua_PhysicsGhostObject_asGhostObject(lua_State* state);
+int lua_PhysicsGhostObject_asRigidBody(lua_State* state);
+int lua_PhysicsGhostObject_asVehicle(lua_State* state);
+int lua_PhysicsGhostObject_asVehicleWheel(lua_State* state);
 int lua_PhysicsGhostObject_collidesWith(lua_State* state);
 int lua_PhysicsGhostObject_getCollisionShape(lua_State* state);
 int lua_PhysicsGhostObject_getNode(lua_State* state);

+ 230 - 0
gameplay/src/lua/lua_PhysicsRigidBody.cpp

@@ -8,11 +8,16 @@
 #include "Image.h"
 #include "MeshPart.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
+#include "PhysicsGhostObject.h"
 #include "PhysicsRigidBody.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
+#include "Terrain.h"
 #include "Transform.h"
 #include "lua_CurveInterpolationType.h"
 #include "lua_PhysicsCollisionObjectCollisionListenerEventType.h"
@@ -31,6 +36,11 @@ void luaRegister_PhysicsRigidBody()
         {"applyImpulse", lua_PhysicsRigidBody_applyImpulse},
         {"applyTorque", lua_PhysicsRigidBody_applyTorque},
         {"applyTorqueImpulse", lua_PhysicsRigidBody_applyTorqueImpulse},
+        {"asCharacter", lua_PhysicsRigidBody_asCharacter},
+        {"asGhostObject", lua_PhysicsRigidBody_asGhostObject},
+        {"asRigidBody", lua_PhysicsRigidBody_asRigidBody},
+        {"asVehicle", lua_PhysicsRigidBody_asVehicle},
+        {"asVehicleWheel", lua_PhysicsRigidBody_asVehicleWheel},
         {"collidesWith", lua_PhysicsRigidBody_collidesWith},
         {"getAngularDamping", lua_PhysicsRigidBody_getAngularDamping},
         {"getAngularFactor", lua_PhysicsRigidBody_getAngularFactor},
@@ -425,6 +435,226 @@ int lua_PhysicsRigidBody_applyTorqueImpulse(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsRigidBody_asCharacter(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_TUSERDATA))
+            {
+                PhysicsRigidBody* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asCharacter();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsCharacter");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsRigidBody_asCharacter - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsRigidBody_asGhostObject(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_TUSERDATA))
+            {
+                PhysicsRigidBody* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asGhostObject();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsGhostObject");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsRigidBody_asGhostObject - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsRigidBody_asRigidBody(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_TUSERDATA))
+            {
+                PhysicsRigidBody* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asRigidBody();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsRigidBody");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsRigidBody_asRigidBody - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsRigidBody_asVehicle(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_TUSERDATA))
+            {
+                PhysicsRigidBody* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicle();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicle");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsRigidBody_asVehicle - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsRigidBody_asVehicleWheel(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_TUSERDATA))
+            {
+                PhysicsRigidBody* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicleWheel();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicleWheel");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsRigidBody_asVehicleWheel - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsRigidBody_collidesWith(lua_State* state)
 {
     // Get the number of parameters.

+ 5 - 0
gameplay/src/lua/lua_PhysicsRigidBody.h

@@ -10,6 +10,11 @@ int lua_PhysicsRigidBody_applyForce(lua_State* state);
 int lua_PhysicsRigidBody_applyImpulse(lua_State* state);
 int lua_PhysicsRigidBody_applyTorque(lua_State* state);
 int lua_PhysicsRigidBody_applyTorqueImpulse(lua_State* state);
+int lua_PhysicsRigidBody_asCharacter(lua_State* state);
+int lua_PhysicsRigidBody_asGhostObject(lua_State* state);
+int lua_PhysicsRigidBody_asRigidBody(lua_State* state);
+int lua_PhysicsRigidBody_asVehicle(lua_State* state);
+int lua_PhysicsRigidBody_asVehicleWheel(lua_State* state);
 int lua_PhysicsRigidBody_collidesWith(lua_State* state);
 int lua_PhysicsRigidBody_getAngularDamping(lua_State* state);
 int lua_PhysicsRigidBody_getAngularFactor(lua_State* state);

+ 5 - 0
gameplay/src/lua/lua_PhysicsRigidBodyParameters.cpp

@@ -8,11 +8,16 @@
 #include "Image.h"
 #include "MeshPart.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
+#include "PhysicsGhostObject.h"
 #include "PhysicsRigidBody.h"
+#include "PhysicsVehicle.h"
+#include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
 #include "ScriptTarget.h"
+#include "Terrain.h"
 #include "Transform.h"
 #include "lua_CurveInterpolationType.h"
 #include "lua_PhysicsCollisionObjectCollisionListenerEventType.h"

+ 228 - 0
gameplay/src/lua/lua_PhysicsVehicle.cpp

@@ -5,8 +5,11 @@
 #include "Game.h"
 #include "MathUtil.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
+#include "PhysicsGhostObject.h"
+#include "PhysicsRigidBody.h"
 #include "PhysicsVehicle.h"
 #include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
@@ -23,6 +26,11 @@ void luaRegister_PhysicsVehicle()
     {
         {"addCollisionListener", lua_PhysicsVehicle_addCollisionListener},
         {"addWheel", lua_PhysicsVehicle_addWheel},
+        {"asCharacter", lua_PhysicsVehicle_asCharacter},
+        {"asGhostObject", lua_PhysicsVehicle_asGhostObject},
+        {"asRigidBody", lua_PhysicsVehicle_asRigidBody},
+        {"asVehicle", lua_PhysicsVehicle_asVehicle},
+        {"asVehicleWheel", lua_PhysicsVehicle_asVehicleWheel},
         {"collidesWith", lua_PhysicsVehicle_collidesWith},
         {"getBoostGain", lua_PhysicsVehicle_getBoostGain},
         {"getBoostSpeed", lua_PhysicsVehicle_getBoostSpeed},
@@ -227,6 +235,226 @@ int lua_PhysicsVehicle_addWheel(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsVehicle_asCharacter(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_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asCharacter();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsCharacter");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicle_asCharacter - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_asGhostObject(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_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asGhostObject();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsGhostObject");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicle_asGhostObject - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_asRigidBody(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_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asRigidBody();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsRigidBody");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicle_asRigidBody - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_asVehicle(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_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicle();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicle");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicle_asVehicle - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicle_asVehicleWheel(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_TUSERDATA))
+            {
+                PhysicsVehicle* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicleWheel();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicleWheel");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicle_asVehicleWheel - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsVehicle_collidesWith(lua_State* state)
 {
     // Get the number of parameters.

+ 5 - 0
gameplay/src/lua/lua_PhysicsVehicle.h

@@ -7,6 +7,11 @@ namespace gameplay
 // Lua bindings for PhysicsVehicle.
 int lua_PhysicsVehicle_addCollisionListener(lua_State* state);
 int lua_PhysicsVehicle_addWheel(lua_State* state);
+int lua_PhysicsVehicle_asCharacter(lua_State* state);
+int lua_PhysicsVehicle_asGhostObject(lua_State* state);
+int lua_PhysicsVehicle_asRigidBody(lua_State* state);
+int lua_PhysicsVehicle_asVehicle(lua_State* state);
+int lua_PhysicsVehicle_asVehicleWheel(lua_State* state);
 int lua_PhysicsVehicle_collidesWith(lua_State* state);
 int lua_PhysicsVehicle_getBoostGain(lua_State* state);
 int lua_PhysicsVehicle_getBoostSpeed(lua_State* state);

+ 228 - 0
gameplay/src/lua/lua_PhysicsVehicleWheel.cpp

@@ -4,8 +4,11 @@
 #include "Base.h"
 #include "Game.h"
 #include "Node.h"
+#include "PhysicsCharacter.h"
 #include "PhysicsCollisionObject.h"
 #include "PhysicsController.h"
+#include "PhysicsGhostObject.h"
+#include "PhysicsRigidBody.h"
 #include "PhysicsVehicle.h"
 #include "PhysicsVehicleWheel.h"
 #include "ScriptController.h"
@@ -21,6 +24,11 @@ void luaRegister_PhysicsVehicleWheel()
     const luaL_Reg lua_members[] = 
     {
         {"addCollisionListener", lua_PhysicsVehicleWheel_addCollisionListener},
+        {"asCharacter", lua_PhysicsVehicleWheel_asCharacter},
+        {"asGhostObject", lua_PhysicsVehicleWheel_asGhostObject},
+        {"asRigidBody", lua_PhysicsVehicleWheel_asRigidBody},
+        {"asVehicle", lua_PhysicsVehicleWheel_asVehicle},
+        {"asVehicleWheel", lua_PhysicsVehicleWheel_asVehicleWheel},
         {"collidesWith", lua_PhysicsVehicleWheel_collidesWith},
         {"getCollisionShape", lua_PhysicsVehicleWheel_getCollisionShape},
         {"getFrictionBreakout", lua_PhysicsVehicleWheel_getFrictionBreakout},
@@ -183,6 +191,226 @@ int lua_PhysicsVehicleWheel_addCollisionListener(lua_State* state)
     return 0;
 }
 
+int lua_PhysicsVehicleWheel_asCharacter(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_TUSERDATA))
+            {
+                PhysicsVehicleWheel* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asCharacter();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsCharacter");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicleWheel_asCharacter - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicleWheel_asGhostObject(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_TUSERDATA))
+            {
+                PhysicsVehicleWheel* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asGhostObject();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsGhostObject");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicleWheel_asGhostObject - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicleWheel_asRigidBody(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_TUSERDATA))
+            {
+                PhysicsVehicleWheel* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asRigidBody();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsRigidBody");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicleWheel_asRigidBody - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicleWheel_asVehicle(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_TUSERDATA))
+            {
+                PhysicsVehicleWheel* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicle();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicle");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicleWheel_asVehicle - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_PhysicsVehicleWheel_asVehicleWheel(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_TUSERDATA))
+            {
+                PhysicsVehicleWheel* instance = getInstance(state);
+                void* returnPtr = (void*)instance->asVehicleWheel();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "PhysicsVehicleWheel");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_PhysicsVehicleWheel_asVehicleWheel - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_PhysicsVehicleWheel_collidesWith(lua_State* state)
 {
     // Get the number of parameters.

+ 5 - 0
gameplay/src/lua/lua_PhysicsVehicleWheel.h

@@ -6,6 +6,11 @@ namespace gameplay
 
 // Lua bindings for PhysicsVehicleWheel.
 int lua_PhysicsVehicleWheel_addCollisionListener(lua_State* state);
+int lua_PhysicsVehicleWheel_asCharacter(lua_State* state);
+int lua_PhysicsVehicleWheel_asGhostObject(lua_State* state);
+int lua_PhysicsVehicleWheel_asRigidBody(lua_State* state);
+int lua_PhysicsVehicleWheel_asVehicle(lua_State* state);
+int lua_PhysicsVehicleWheel_asVehicleWheel(lua_State* state);
 int lua_PhysicsVehicleWheel_collidesWith(lua_State* state);
 int lua_PhysicsVehicleWheel_getCollisionShape(lua_State* state);
 int lua_PhysicsVehicleWheel_getFrictionBreakout(lua_State* state);

+ 1 - 0
gameplay/src/lua/lua_RenderState.cpp

@@ -7,6 +7,7 @@
 #include "Pass.h"
 #include "Ref.h"
 #include "RenderState.h"
+#include "Scene.h"
 #include "Technique.h"
 #include "lua_RenderStateAutoBinding.h"
 #include "lua_RenderStateBlend.h"

+ 15 - 0
gameplay/src/lua/lua_RenderStateAutoBinding.cpp

@@ -18,6 +18,9 @@ static const char* luaEnumString_RenderStateAutoBinding_INVERSE_TRANSPOSE_WORLD_
 static const char* luaEnumString_RenderStateAutoBinding_CAMERA_WORLD_POSITION = "CAMERA_WORLD_POSITION";
 static const char* luaEnumString_RenderStateAutoBinding_CAMERA_VIEW_POSITION = "CAMERA_VIEW_POSITION";
 static const char* luaEnumString_RenderStateAutoBinding_MATRIX_PALETTE = "MATRIX_PALETTE";
+static const char* luaEnumString_RenderStateAutoBinding_SCENE_AMBIENT_COLOR = "SCENE_AMBIENT_COLOR";
+static const char* luaEnumString_RenderStateAutoBinding_SCENE_LIGHT_COLOR = "SCENE_LIGHT_COLOR";
+static const char* luaEnumString_RenderStateAutoBinding_SCENE_LIGHT_DIRECTION = "SCENE_LIGHT_DIRECTION";
 
 RenderState::AutoBinding lua_enumFromString_RenderStateAutoBinding(const char* s)
 {
@@ -45,6 +48,12 @@ RenderState::AutoBinding lua_enumFromString_RenderStateAutoBinding(const char* s
         return RenderState::CAMERA_VIEW_POSITION;
     if (strcmp(s, luaEnumString_RenderStateAutoBinding_MATRIX_PALETTE) == 0)
         return RenderState::MATRIX_PALETTE;
+    if (strcmp(s, luaEnumString_RenderStateAutoBinding_SCENE_AMBIENT_COLOR) == 0)
+        return RenderState::SCENE_AMBIENT_COLOR;
+    if (strcmp(s, luaEnumString_RenderStateAutoBinding_SCENE_LIGHT_COLOR) == 0)
+        return RenderState::SCENE_LIGHT_COLOR;
+    if (strcmp(s, luaEnumString_RenderStateAutoBinding_SCENE_LIGHT_DIRECTION) == 0)
+        return RenderState::SCENE_LIGHT_DIRECTION;
     GP_ERROR("Invalid enumeration value '%s' for enumeration RenderState::AutoBinding.", s);
     return RenderState::NONE;
 }
@@ -75,6 +84,12 @@ const char* lua_stringFromEnum_RenderStateAutoBinding(RenderState::AutoBinding e
         return luaEnumString_RenderStateAutoBinding_CAMERA_VIEW_POSITION;
     if (e == RenderState::MATRIX_PALETTE)
         return luaEnumString_RenderStateAutoBinding_MATRIX_PALETTE;
+    if (e == RenderState::SCENE_AMBIENT_COLOR)
+        return luaEnumString_RenderStateAutoBinding_SCENE_AMBIENT_COLOR;
+    if (e == RenderState::SCENE_LIGHT_COLOR)
+        return luaEnumString_RenderStateAutoBinding_SCENE_LIGHT_COLOR;
+    if (e == RenderState::SCENE_LIGHT_DIRECTION)
+        return luaEnumString_RenderStateAutoBinding_SCENE_LIGHT_DIRECTION;
     GP_ERROR("Invalid enumeration value '%d' for enumeration RenderState::AutoBinding.", e);
     return enumStringEmpty;
 }

+ 1 - 0
gameplay/src/lua/lua_RenderStateStateBlock.cpp

@@ -7,6 +7,7 @@
 #include "Pass.h"
 #include "Ref.h"
 #include "RenderState.h"
+#include "Scene.h"
 #include "Technique.h"
 #include "lua_RenderStateAutoBinding.h"
 #include "lua_RenderStateBlend.h"

+ 273 - 1
gameplay/src/lua/lua_Scene.cpp

@@ -26,6 +26,8 @@ void luaRegister_Scene()
         {"getAmbientColor", lua_Scene_getAmbientColor},
         {"getFirstNode", lua_Scene_getFirstNode},
         {"getId", lua_Scene_getId},
+        {"getLightColor", lua_Scene_getLightColor},
+        {"getLightDirection", lua_Scene_getLightDirection},
         {"getNodeCount", lua_Scene_getNodeCount},
         {"getRefCount", lua_Scene_getRefCount},
         {"release", lua_Scene_release},
@@ -34,12 +36,15 @@ void luaRegister_Scene()
         {"setActiveCamera", lua_Scene_setActiveCamera},
         {"setAmbientColor", lua_Scene_setAmbientColor},
         {"setId", lua_Scene_setId},
+        {"setLightColor", lua_Scene_setLightColor},
+        {"setLightDirection", lua_Scene_setLightDirection},
         {"visit", lua_Scene_visit},
         {NULL, NULL}
     };
     const luaL_Reg lua_statics[] = 
     {
         {"create", lua_Scene_static_create},
+        {"getScene", lua_Scene_static_getScene},
         {"load", lua_Scene_static_load},
         {NULL, NULL}
     };
@@ -582,6 +587,94 @@ int lua_Scene_getId(lua_State* state)
     return 0;
 }
 
+int lua_Scene_getLightColor(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_TUSERDATA))
+            {
+                Scene* instance = getInstance(state);
+                void* returnPtr = (void*)&(instance->getLightColor());
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "Vector3");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Scene_getLightColor - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_Scene_getLightDirection(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_TUSERDATA))
+            {
+                Scene* instance = getInstance(state);
+                void* returnPtr = (void*)&(instance->getLightDirection());
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "Vector3");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Scene_getLightDirection - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Scene_getNodeCount(lua_State* state)
 {
     // Get the number of parameters.
@@ -880,6 +973,92 @@ int lua_Scene_setId(lua_State* state)
     return 0;
 }
 
+int lua_Scene_setLightColor(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 4:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER &&
+                lua_type(state, 4) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                // Get parameter 3 off the stack.
+                float param3 = (float)luaL_checknumber(state, 4);
+
+                Scene* instance = getInstance(state);
+                instance->setLightColor(param1, param2, param3);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_Scene_setLightColor - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 4).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_Scene_setLightDirection(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 2:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TNIL))
+            {
+                // Get parameter 1 off the stack.
+                bool param1Valid;
+                ScriptUtil::LuaArray<Vector3> param1 = ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", true, &param1Valid);
+                if (!param1Valid)
+                {
+                    lua_pushstring(state, "Failed to convert parameter 1 to type 'Vector3'.");
+                    lua_error(state);
+                }
+
+                Scene* instance = getInstance(state);
+                instance->setLightDirection(*param1);
+                
+                return 0;
+            }
+
+            lua_pushstring(state, "lua_Scene_setLightDirection - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 2).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Scene_static_create(lua_State* state)
 {
     // Get the number of parameters.
@@ -907,9 +1086,102 @@ int lua_Scene_static_create(lua_State* state)
             return 1;
             break;
         }
+        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);
+
+                void* returnPtr = (void*)Scene::create(param1);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = true;
+                    luaL_getmetatable(state, "Scene");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Scene_static_create - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 0 or 1).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_Scene_static_getScene(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 0:
+        {
+            void* returnPtr = (void*)Scene::getScene();
+            if (returnPtr)
+            {
+                ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                object->instance = returnPtr;
+                object->owns = false;
+                luaL_getmetatable(state, "Scene");
+                lua_setmetatable(state, -2);
+            }
+            else
+            {
+                lua_pushnil(state);
+            }
+
+            return 1;
+            break;
+        }
+        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);
+
+                void* returnPtr = (void*)Scene::getScene(param1);
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "Scene");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Scene_static_getScene - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
         default:
         {
-            lua_pushstring(state, "Invalid number of parameters (expected 0).");
+            lua_pushstring(state, "Invalid number of parameters (expected 0 or 1).");
             lua_error(state);
             break;
         }

+ 5 - 0
gameplay/src/lua/lua_Scene.h

@@ -15,6 +15,8 @@ int lua_Scene_getActiveCamera(lua_State* state);
 int lua_Scene_getAmbientColor(lua_State* state);
 int lua_Scene_getFirstNode(lua_State* state);
 int lua_Scene_getId(lua_State* state);
+int lua_Scene_getLightColor(lua_State* state);
+int lua_Scene_getLightDirection(lua_State* state);
 int lua_Scene_getNodeCount(lua_State* state);
 int lua_Scene_getRefCount(lua_State* state);
 int lua_Scene_release(lua_State* state);
@@ -23,7 +25,10 @@ int lua_Scene_removeNode(lua_State* state);
 int lua_Scene_setActiveCamera(lua_State* state);
 int lua_Scene_setAmbientColor(lua_State* state);
 int lua_Scene_setId(lua_State* state);
+int lua_Scene_setLightColor(lua_State* state);
+int lua_Scene_setLightDirection(lua_State* state);
 int lua_Scene_static_create(lua_State* state);
+int lua_Scene_static_getScene(lua_State* state);
 int lua_Scene_static_load(lua_State* state);
 int lua_Scene_visit(lua_State* state);
 

+ 1 - 0
gameplay/src/lua/lua_Technique.cpp

@@ -8,6 +8,7 @@
 #include "Pass.h"
 #include "Ref.h"
 #include "RenderState.h"
+#include "Scene.h"
 #include "Technique.h"
 #include "lua_RenderStateAutoBinding.h"
 #include "lua_RenderStateBlend.h"

+ 121 - 264
gameplay/src/lua/lua_Terrain.cpp

@@ -6,7 +6,6 @@
 #include "Base.h"
 #include "FileSystem.h"
 #include "Game.h"
-#include "Image.h"
 #include "Node.h"
 #include "Ref.h"
 #include "ScriptController.h"
@@ -26,6 +25,8 @@ void luaRegister_Terrain()
         {"addRef", lua_Terrain_addRef},
         {"draw", lua_Terrain_draw},
         {"getBoundingBox", lua_Terrain_getBoundingBox},
+        {"getHeight", lua_Terrain_getHeight},
+        {"getNode", lua_Terrain_getNode},
         {"getPatchCount", lua_Terrain_getPatchCount},
         {"getRefCount", lua_Terrain_getRefCount},
         {"getTriangleCount", lua_Terrain_getTriangleCount},
@@ -34,7 +35,6 @@ void luaRegister_Terrain()
         {"isFlagSet", lua_Terrain_isFlagSet},
         {"release", lua_Terrain_release},
         {"setFlag", lua_Terrain_setFlag},
-        {"setLayer", lua_Terrain_setLayer},
         {"transformChanged", lua_Terrain_transformChanged},
         {NULL, NULL}
     };
@@ -219,6 +219,93 @@ int lua_Terrain_getBoundingBox(lua_State* state)
     return 0;
 }
 
+int lua_Terrain_getHeight(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 3:
+        {
+            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
+                lua_type(state, 2) == LUA_TNUMBER &&
+                lua_type(state, 3) == LUA_TNUMBER)
+            {
+                // Get parameter 1 off the stack.
+                float param1 = (float)luaL_checknumber(state, 2);
+
+                // Get parameter 2 off the stack.
+                float param2 = (float)luaL_checknumber(state, 3);
+
+                Terrain* instance = getInstance(state);
+                float result = instance->getHeight(param1, param2);
+
+                // Push the return value onto the stack.
+                lua_pushnumber(state, result);
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Terrain_getHeight - Failed to match the given parameters to a valid function signature.");
+            lua_error(state);
+            break;
+        }
+        default:
+        {
+            lua_pushstring(state, "Invalid number of parameters (expected 3).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
+int lua_Terrain_getNode(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_TUSERDATA))
+            {
+                Terrain* instance = getInstance(state);
+                void* returnPtr = (void*)instance->getNode();
+                if (returnPtr)
+                {
+                    ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                    object->instance = returnPtr;
+                    object->owns = false;
+                    luaL_getmetatable(state, "Node");
+                    lua_setmetatable(state, -2);
+                }
+                else
+                {
+                    lua_pushnil(state);
+                }
+
+                return 1;
+            }
+
+            lua_pushstring(state, "lua_Terrain_getNode - 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).");
+            lua_error(state);
+            break;
+        }
+    }
+    return 0;
+}
+
 int lua_Terrain_getPatchCount(lua_State* state)
 {
     // Get the number of parameters.
@@ -505,7 +592,7 @@ int lua_Terrain_setFlag(lua_State* state)
     return 0;
 }
 
-int lua_Terrain_setLayer(lua_State* state)
+int lua_Terrain_static_create(lua_State* state)
 {
     // Get the number of parameters.
     int paramCount = lua_gettop(state);
@@ -513,272 +600,42 @@ int lua_Terrain_setLayer(lua_State* state)
     // Attempt to match the parameters to a valid binding.
     switch (paramCount)
     {
-        case 3:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL))
-            {
-                // Get parameter 1 off the stack.
-                int param1 = (int)luaL_checkint(state, 2);
-
-                // Get parameter 2 off the stack.
-                const char* param2 = ScriptUtil::getString(3, false);
-
-                Terrain* instance = getInstance(state);
-                bool result = instance->setLayer(param1, param2);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Terrain_setLayer - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 4:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL) &&
-                (lua_type(state, 4) == LUA_TUSERDATA || lua_type(state, 4) == LUA_TNIL))
-            {
-                // Get parameter 1 off the stack.
-                int param1 = (int)luaL_checkint(state, 2);
-
-                // Get parameter 2 off the stack.
-                const char* param2 = ScriptUtil::getString(3, false);
-
-                // Get parameter 3 off the stack.
-                bool param3Valid;
-                ScriptUtil::LuaArray<Vector2> param3 = ScriptUtil::getObjectPointer<Vector2>(4, "Vector2", true, &param3Valid);
-                if (!param3Valid)
-                {
-                    lua_pushstring(state, "Failed to convert parameter 3 to type 'Vector2'.");
-                    lua_error(state);
-                }
-
-                Terrain* instance = getInstance(state);
-                bool result = instance->setLayer(param1, param2, *param3);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Terrain_setLayer - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 5:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL) &&
-                (lua_type(state, 4) == LUA_TUSERDATA || lua_type(state, 4) == LUA_TNIL) &&
-                (lua_type(state, 5) == LUA_TSTRING || lua_type(state, 5) == LUA_TNIL))
-            {
-                // Get parameter 1 off the stack.
-                int param1 = (int)luaL_checkint(state, 2);
-
-                // Get parameter 2 off the stack.
-                const char* param2 = ScriptUtil::getString(3, false);
-
-                // Get parameter 3 off the stack.
-                bool param3Valid;
-                ScriptUtil::LuaArray<Vector2> param3 = ScriptUtil::getObjectPointer<Vector2>(4, "Vector2", true, &param3Valid);
-                if (!param3Valid)
-                {
-                    lua_pushstring(state, "Failed to convert parameter 3 to type 'Vector2'.");
-                    lua_error(state);
-                }
-
-                // Get parameter 4 off the stack.
-                const char* param4 = ScriptUtil::getString(5, false);
-
-                Terrain* instance = getInstance(state);
-                bool result = instance->setLayer(param1, param2, *param3, param4);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Terrain_setLayer - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 6:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL) &&
-                (lua_type(state, 4) == LUA_TUSERDATA || lua_type(state, 4) == LUA_TNIL) &&
-                (lua_type(state, 5) == LUA_TSTRING || lua_type(state, 5) == LUA_TNIL) &&
-                lua_type(state, 6) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                int param1 = (int)luaL_checkint(state, 2);
-
-                // Get parameter 2 off the stack.
-                const char* param2 = ScriptUtil::getString(3, false);
-
-                // Get parameter 3 off the stack.
-                bool param3Valid;
-                ScriptUtil::LuaArray<Vector2> param3 = ScriptUtil::getObjectPointer<Vector2>(4, "Vector2", true, &param3Valid);
-                if (!param3Valid)
-                {
-                    lua_pushstring(state, "Failed to convert parameter 3 to type 'Vector2'.");
-                    lua_error(state);
-                }
-
-                // Get parameter 4 off the stack.
-                const char* param4 = ScriptUtil::getString(5, false);
-
-                // Get parameter 5 off the stack.
-                int param5 = (int)luaL_checkint(state, 6);
-
-                Terrain* instance = getInstance(state);
-                bool result = instance->setLayer(param1, param2, *param3, param4, param5);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Terrain_setLayer - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 7:
+        case 1:
         {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL) &&
-                (lua_type(state, 4) == LUA_TUSERDATA || lua_type(state, 4) == LUA_TNIL) &&
-                (lua_type(state, 5) == LUA_TSTRING || lua_type(state, 5) == LUA_TNIL) &&
-                lua_type(state, 6) == LUA_TNUMBER &&
-                lua_type(state, 7) == LUA_TNUMBER)
+            do
             {
-                // Get parameter 1 off the stack.
-                int param1 = (int)luaL_checkint(state, 2);
-
-                // Get parameter 2 off the stack.
-                const char* param2 = ScriptUtil::getString(3, false);
-
-                // Get parameter 3 off the stack.
-                bool param3Valid;
-                ScriptUtil::LuaArray<Vector2> param3 = ScriptUtil::getObjectPointer<Vector2>(4, "Vector2", true, &param3Valid);
-                if (!param3Valid)
+                if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL))
                 {
-                    lua_pushstring(state, "Failed to convert parameter 3 to type 'Vector2'.");
-                    lua_error(state);
-                }
-
-                // Get parameter 4 off the stack.
-                const char* param4 = ScriptUtil::getString(5, false);
-
-                // Get parameter 5 off the stack.
-                int param5 = (int)luaL_checkint(state, 6);
-
-                // Get parameter 6 off the stack.
-                int param6 = (int)luaL_checkint(state, 7);
-
-                Terrain* instance = getInstance(state);
-                bool result = instance->setLayer(param1, param2, *param3, param4, param5, param6);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Terrain_setLayer - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 8:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                lua_type(state, 2) == LUA_TNUMBER &&
-                (lua_type(state, 3) == LUA_TSTRING || lua_type(state, 3) == LUA_TNIL) &&
-                (lua_type(state, 4) == LUA_TUSERDATA || lua_type(state, 4) == LUA_TNIL) &&
-                (lua_type(state, 5) == LUA_TSTRING || lua_type(state, 5) == LUA_TNIL) &&
-                lua_type(state, 6) == LUA_TNUMBER &&
-                lua_type(state, 7) == LUA_TNUMBER &&
-                lua_type(state, 8) == LUA_TNUMBER)
-            {
-                // Get parameter 1 off the stack.
-                int param1 = (int)luaL_checkint(state, 2);
+                    // Get parameter 1 off the stack.
+                    const char* param1 = ScriptUtil::getString(1, false);
 
-                // Get parameter 2 off the stack.
-                const char* param2 = ScriptUtil::getString(3, false);
+                    void* returnPtr = (void*)Terrain::create(param1);
+                    if (returnPtr)
+                    {
+                        ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
+                        object->instance = returnPtr;
+                        object->owns = false;
+                        luaL_getmetatable(state, "Terrain");
+                        lua_setmetatable(state, -2);
+                    }
+                    else
+                    {
+                        lua_pushnil(state);
+                    }
 
-                // Get parameter 3 off the stack.
-                bool param3Valid;
-                ScriptUtil::LuaArray<Vector2> param3 = ScriptUtil::getObjectPointer<Vector2>(4, "Vector2", true, &param3Valid);
-                if (!param3Valid)
-                {
-                    lua_pushstring(state, "Failed to convert parameter 3 to type 'Vector2'.");
-                    lua_error(state);
+                    return 1;
                 }
+            } while (0);
 
-                // Get parameter 4 off the stack.
-                const char* param4 = ScriptUtil::getString(5, false);
-
-                // Get parameter 5 off the stack.
-                int param5 = (int)luaL_checkint(state, 6);
-
-                // Get parameter 6 off the stack.
-                int param6 = (int)luaL_checkint(state, 7);
-
-                // Get parameter 7 off the stack.
-                int param7 = (int)luaL_checkint(state, 8);
-
-                Terrain* instance = getInstance(state);
-                bool result = instance->setLayer(param1, param2, *param3, param4, param5, param6, param7);
-
-                // Push the return value onto the stack.
-                lua_pushboolean(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_Terrain_setLayer - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 3, 4, 5, 6, 7 or 8).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_Terrain_static_create(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:
-        {
             do
             {
-                if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL))
+                if ((lua_type(state, 1) == LUA_TUSERDATA || lua_type(state, 1) == LUA_TTABLE || lua_type(state, 1) == LUA_TNIL))
                 {
                     // Get parameter 1 off the stack.
-                    const char* param1 = ScriptUtil::getString(1, false);
+                    bool param1Valid;
+                    ScriptUtil::LuaArray<Properties> param1 = ScriptUtil::getObjectPointer<Properties>(1, "Properties", false, &param1Valid);
+                    if (!param1Valid)
+                        break;
 
                     void* returnPtr = (void*)Terrain::create(param1);
                     if (returnPtr)
@@ -804,7 +661,7 @@ int lua_Terrain_static_create(lua_State* state)
                 {
                     // Get parameter 1 off the stack.
                     bool param1Valid;
-                    ScriptUtil::LuaArray<Terrain::HeightField> param1 = ScriptUtil::getObjectPointer<Terrain::HeightField>(1, "TerrainHeightField", false, &param1Valid);
+                    ScriptUtil::LuaArray<HeightField> param1 = ScriptUtil::getObjectPointer<HeightField>(1, "HeightField", false, &param1Valid);
                     if (!param1Valid)
                         break;
 
@@ -839,7 +696,7 @@ int lua_Terrain_static_create(lua_State* state)
                 {
                     // Get parameter 1 off the stack.
                     bool param1Valid;
-                    ScriptUtil::LuaArray<Terrain::HeightField> param1 = ScriptUtil::getObjectPointer<Terrain::HeightField>(1, "TerrainHeightField", false, &param1Valid);
+                    ScriptUtil::LuaArray<HeightField> param1 = ScriptUtil::getObjectPointer<HeightField>(1, "HeightField", false, &param1Valid);
                     if (!param1Valid)
                         break;
 
@@ -881,7 +738,7 @@ int lua_Terrain_static_create(lua_State* state)
                 {
                     // Get parameter 1 off the stack.
                     bool param1Valid;
-                    ScriptUtil::LuaArray<Terrain::HeightField> param1 = ScriptUtil::getObjectPointer<Terrain::HeightField>(1, "TerrainHeightField", false, &param1Valid);
+                    ScriptUtil::LuaArray<HeightField> param1 = ScriptUtil::getObjectPointer<HeightField>(1, "HeightField", false, &param1Valid);
                     if (!param1Valid)
                         break;
 
@@ -927,7 +784,7 @@ int lua_Terrain_static_create(lua_State* state)
                 {
                     // Get parameter 1 off the stack.
                     bool param1Valid;
-                    ScriptUtil::LuaArray<Terrain::HeightField> param1 = ScriptUtil::getObjectPointer<Terrain::HeightField>(1, "TerrainHeightField", false, &param1Valid);
+                    ScriptUtil::LuaArray<HeightField> param1 = ScriptUtil::getObjectPointer<HeightField>(1, "HeightField", false, &param1Valid);
                     if (!param1Valid)
                         break;
 
@@ -977,7 +834,7 @@ int lua_Terrain_static_create(lua_State* state)
                 {
                     // Get parameter 1 off the stack.
                     bool param1Valid;
-                    ScriptUtil::LuaArray<Terrain::HeightField> param1 = ScriptUtil::getObjectPointer<Terrain::HeightField>(1, "TerrainHeightField", false, &param1Valid);
+                    ScriptUtil::LuaArray<HeightField> param1 = ScriptUtil::getObjectPointer<HeightField>(1, "HeightField", false, &param1Valid);
                     if (!param1Valid)
                         break;
 
@@ -1031,7 +888,7 @@ int lua_Terrain_static_create(lua_State* state)
                 {
                     // Get parameter 1 off the stack.
                     bool param1Valid;
-                    ScriptUtil::LuaArray<Terrain::HeightField> param1 = ScriptUtil::getObjectPointer<Terrain::HeightField>(1, "TerrainHeightField", false, &param1Valid);
+                    ScriptUtil::LuaArray<HeightField> param1 = ScriptUtil::getObjectPointer<HeightField>(1, "HeightField", false, &param1Valid);
                     if (!param1Valid)
                         break;
 

+ 2 - 1
gameplay/src/lua/lua_Terrain.h

@@ -9,6 +9,8 @@ int lua_Terrain__gc(lua_State* state);
 int lua_Terrain_addRef(lua_State* state);
 int lua_Terrain_draw(lua_State* state);
 int lua_Terrain_getBoundingBox(lua_State* state);
+int lua_Terrain_getHeight(lua_State* state);
+int lua_Terrain_getNode(lua_State* state);
 int lua_Terrain_getPatchCount(lua_State* state);
 int lua_Terrain_getRefCount(lua_State* state);
 int lua_Terrain_getTriangleCount(lua_State* state);
@@ -17,7 +19,6 @@ int lua_Terrain_getVisibleTriangleCount(lua_State* state);
 int lua_Terrain_isFlagSet(lua_State* state);
 int lua_Terrain_release(lua_State* state);
 int lua_Terrain_setFlag(lua_State* state);
-int lua_Terrain_setLayer(lua_State* state);
 int lua_Terrain_static_create(lua_State* state);
 int lua_Terrain_transformChanged(lua_State* state);
 

+ 0 - 535
gameplay/src/lua/lua_TerrainHeightField.cpp

@@ -1,535 +0,0 @@
-#include "Base.h"
-#include "ScriptController.h"
-#include "lua_TerrainHeightField.h"
-#include "Animation.h"
-#include "AnimationTarget.h"
-#include "Base.h"
-#include "FileSystem.h"
-#include "Game.h"
-#include "Image.h"
-#include "Node.h"
-#include "Ref.h"
-#include "ScriptController.h"
-#include "ScriptTarget.h"
-#include "Terrain.h"
-#include "Transform.h"
-#include "lua_CurveInterpolationType.h"
-#include "lua_TerrainFlags.h"
-
-namespace gameplay
-{
-
-void luaRegister_TerrainHeightField()
-{
-    const luaL_Reg lua_members[] = 
-    {
-        {"addRef", lua_TerrainHeightField_addRef},
-        {"getArray", lua_TerrainHeightField_getArray},
-        {"getColumnCount", lua_TerrainHeightField_getColumnCount},
-        {"getRefCount", lua_TerrainHeightField_getRefCount},
-        {"getRowCount", lua_TerrainHeightField_getRowCount},
-        {"release", lua_TerrainHeightField_release},
-        {NULL, NULL}
-    };
-    const luaL_Reg lua_statics[] = 
-    {
-        {"create", lua_TerrainHeightField_static_create},
-        {NULL, NULL}
-    };
-    std::vector<std::string> scopePath;
-    scopePath.push_back("Terrain");
-
-    ScriptUtil::registerClass("TerrainHeightField", lua_members, NULL, lua_TerrainHeightField__gc, lua_statics, scopePath);
-}
-
-static Terrain::HeightField* getInstance(lua_State* state)
-{
-    void* userdata = luaL_checkudata(state, 1, "TerrainHeightField");
-    luaL_argcheck(state, userdata != NULL, 1, "'TerrainHeightField' expected.");
-    return (Terrain::HeightField*)((ScriptUtil::LuaObject*)userdata)->instance;
-}
-
-int lua_TerrainHeightField__gc(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_TUSERDATA))
-            {
-                void* userdata = luaL_checkudata(state, 1, "TerrainHeightField");
-                luaL_argcheck(state, userdata != NULL, 1, "'TerrainHeightField' expected.");
-                ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)userdata;
-                if (object->owns)
-                {
-                    Terrain::HeightField* instance = (Terrain::HeightField*)object->instance;
-                    SAFE_RELEASE(instance);
-                }
-                
-                return 0;
-            }
-
-            lua_pushstring(state, "lua_TerrainHeightField__gc - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_TerrainHeightField_addRef(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_TUSERDATA))
-            {
-                Terrain::HeightField* instance = getInstance(state);
-                instance->addRef();
-                
-                return 0;
-            }
-
-            lua_pushstring(state, "lua_TerrainHeightField_addRef - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_TerrainHeightField_getArray(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_TUSERDATA))
-            {
-                Terrain::HeightField* instance = getInstance(state);
-                float* result = instance->getArray();
-
-                // Push the return value onto the stack.
-                lua_pushlightuserdata(state, result);
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_TerrainHeightField_getArray - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_TerrainHeightField_getColumnCount(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_TUSERDATA))
-            {
-                Terrain::HeightField* instance = getInstance(state);
-                unsigned int result = instance->getColumnCount();
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_TerrainHeightField_getColumnCount - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_TerrainHeightField_getRefCount(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_TUSERDATA))
-            {
-                Terrain::HeightField* instance = getInstance(state);
-                unsigned int result = instance->getRefCount();
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_TerrainHeightField_getRefCount - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_TerrainHeightField_getRowCount(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_TUSERDATA))
-            {
-                Terrain::HeightField* instance = getInstance(state);
-                unsigned int result = instance->getRowCount();
-
-                // Push the return value onto the stack.
-                lua_pushunsigned(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_TerrainHeightField_getRowCount - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_TerrainHeightField_release(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_TUSERDATA))
-            {
-                Terrain::HeightField* instance = getInstance(state);
-                instance->release();
-                
-                return 0;
-            }
-
-            lua_pushstring(state, "lua_TerrainHeightField_release - 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).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-int lua_TerrainHeightField_static_create(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:
-        {
-            do
-            {
-                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);
-
-                    void* returnPtr = (void*)Terrain::HeightField::create(param1);
-                    if (returnPtr)
-                    {
-                        ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                        object->instance = returnPtr;
-                        object->owns = false;
-                        luaL_getmetatable(state, "TerrainHeightField");
-                        lua_setmetatable(state, -2);
-                    }
-                    else
-                    {
-                        lua_pushnil(state);
-                    }
-
-                    return 1;
-                }
-            } while (0);
-
-            lua_pushstring(state, "lua_TerrainHeightField_static_create - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 2:
-        {
-            do
-            {
-                if (lua_type(state, 1) == LUA_TNUMBER &&
-                    lua_type(state, 2) == LUA_TNUMBER)
-                {
-                    // Get parameter 1 off the stack.
-                    unsigned int param1 = (unsigned int)luaL_checkunsigned(state, 1);
-
-                    // Get parameter 2 off the stack.
-                    unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                    void* returnPtr = (void*)Terrain::HeightField::create(param1, param2);
-                    if (returnPtr)
-                    {
-                        ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                        object->instance = returnPtr;
-                        object->owns = false;
-                        luaL_getmetatable(state, "TerrainHeightField");
-                        lua_setmetatable(state, -2);
-                    }
-                    else
-                    {
-                        lua_pushnil(state);
-                    }
-
-                    return 1;
-                }
-            } while (0);
-
-            do
-            {
-                if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
-                    lua_type(state, 2) == LUA_TNUMBER)
-                {
-                    // Get parameter 1 off the stack.
-                    const char* param1 = ScriptUtil::getString(1, false);
-
-                    // Get parameter 2 off the stack.
-                    unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                    void* returnPtr = (void*)Terrain::HeightField::create(param1, param2);
-                    if (returnPtr)
-                    {
-                        ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                        object->instance = returnPtr;
-                        object->owns = false;
-                        luaL_getmetatable(state, "TerrainHeightField");
-                        lua_setmetatable(state, -2);
-                    }
-                    else
-                    {
-                        lua_pushnil(state);
-                    }
-
-                    return 1;
-                }
-            } while (0);
-
-            lua_pushstring(state, "lua_TerrainHeightField_static_create - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 3:
-        {
-            do
-            {
-                if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
-                    lua_type(state, 2) == LUA_TNUMBER &&
-                    lua_type(state, 3) == LUA_TNUMBER)
-                {
-                    // Get parameter 1 off the stack.
-                    const char* param1 = ScriptUtil::getString(1, false);
-
-                    // Get parameter 2 off the stack.
-                    unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                    // Get parameter 3 off the stack.
-                    unsigned int param3 = (unsigned int)luaL_checkunsigned(state, 3);
-
-                    void* returnPtr = (void*)Terrain::HeightField::create(param1, param2, param3);
-                    if (returnPtr)
-                    {
-                        ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                        object->instance = returnPtr;
-                        object->owns = false;
-                        luaL_getmetatable(state, "TerrainHeightField");
-                        lua_setmetatable(state, -2);
-                    }
-                    else
-                    {
-                        lua_pushnil(state);
-                    }
-
-                    return 1;
-                }
-            } while (0);
-
-            lua_pushstring(state, "lua_TerrainHeightField_static_create - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 4:
-        {
-            do
-            {
-                if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
-                    lua_type(state, 2) == LUA_TNUMBER &&
-                    lua_type(state, 3) == LUA_TNUMBER &&
-                    lua_type(state, 4) == LUA_TNUMBER)
-                {
-                    // Get parameter 1 off the stack.
-                    const char* param1 = ScriptUtil::getString(1, false);
-
-                    // Get parameter 2 off the stack.
-                    unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                    // Get parameter 3 off the stack.
-                    unsigned int param3 = (unsigned int)luaL_checkunsigned(state, 3);
-
-                    // Get parameter 4 off the stack.
-                    float param4 = (float)luaL_checknumber(state, 4);
-
-                    void* returnPtr = (void*)Terrain::HeightField::create(param1, param2, param3, param4);
-                    if (returnPtr)
-                    {
-                        ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                        object->instance = returnPtr;
-                        object->owns = false;
-                        luaL_getmetatable(state, "TerrainHeightField");
-                        lua_setmetatable(state, -2);
-                    }
-                    else
-                    {
-                        lua_pushnil(state);
-                    }
-
-                    return 1;
-                }
-            } while (0);
-
-            lua_pushstring(state, "lua_TerrainHeightField_static_create - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        case 5:
-        {
-            do
-            {
-                if ((lua_type(state, 1) == LUA_TSTRING || lua_type(state, 1) == LUA_TNIL) &&
-                    lua_type(state, 2) == LUA_TNUMBER &&
-                    lua_type(state, 3) == LUA_TNUMBER &&
-                    lua_type(state, 4) == LUA_TNUMBER &&
-                    lua_type(state, 5) == LUA_TNUMBER)
-                {
-                    // Get parameter 1 off the stack.
-                    const char* param1 = ScriptUtil::getString(1, false);
-
-                    // Get parameter 2 off the stack.
-                    unsigned int param2 = (unsigned int)luaL_checkunsigned(state, 2);
-
-                    // Get parameter 3 off the stack.
-                    unsigned int param3 = (unsigned int)luaL_checkunsigned(state, 3);
-
-                    // Get parameter 4 off the stack.
-                    float param4 = (float)luaL_checknumber(state, 4);
-
-                    // Get parameter 5 off the stack.
-                    float param5 = (float)luaL_checknumber(state, 5);
-
-                    void* returnPtr = (void*)Terrain::HeightField::create(param1, param2, param3, param4, param5);
-                    if (returnPtr)
-                    {
-                        ScriptUtil::LuaObject* object = (ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(ScriptUtil::LuaObject));
-                        object->instance = returnPtr;
-                        object->owns = false;
-                        luaL_getmetatable(state, "TerrainHeightField");
-                        lua_setmetatable(state, -2);
-                    }
-                    else
-                    {
-                        lua_pushnil(state);
-                    }
-
-                    return 1;
-                }
-            } while (0);
-
-            lua_pushstring(state, "lua_TerrainHeightField_static_create - 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, 2, 3, 4 or 5).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
-}

+ 0 - 21
gameplay/src/lua/lua_TerrainHeightField.h

@@ -1,21 +0,0 @@
-#ifndef LUA_TERRAINHEIGHTFIELD_H_
-#define LUA_TERRAINHEIGHTFIELD_H_
-
-namespace gameplay
-{
-
-// Lua bindings for Terrain::HeightField.
-int lua_TerrainHeightField__gc(lua_State* state);
-int lua_TerrainHeightField_addRef(lua_State* state);
-int lua_TerrainHeightField_getArray(lua_State* state);
-int lua_TerrainHeightField_getColumnCount(lua_State* state);
-int lua_TerrainHeightField_getRefCount(lua_State* state);
-int lua_TerrainHeightField_getRowCount(lua_State* state);
-int lua_TerrainHeightField_release(lua_State* state);
-int lua_TerrainHeightField_static_create(lua_State* state);
-
-void luaRegister_TerrainHeightField();
-
-}
-
-#endif

+ 1 - 1
gameplay/src/lua/lua_all_bindings.cpp

@@ -46,6 +46,7 @@ void lua_RegisterAllBindings()
     luaRegister_Game();
     luaRegister_Gamepad();
     luaRegister_Gesture();
+    luaRegister_HeightField();
     luaRegister_Image();
     luaRegister_Joint();
     luaRegister_Joystick();
@@ -108,7 +109,6 @@ void lua_RegisterAllBindings()
     luaRegister_SpriteBatch();
     luaRegister_Technique();
     luaRegister_Terrain();
-    luaRegister_TerrainHeightField();
     luaRegister_TextBox();
     luaRegister_Texture();
     luaRegister_TextureSampler();

+ 1 - 1
gameplay/src/lua/lua_all_bindings.h

@@ -41,6 +41,7 @@
 #include "lua_Game.h"
 #include "lua_Gamepad.h"
 #include "lua_Gesture.h"
+#include "lua_HeightField.h"
 #include "lua_Image.h"
 #include "lua_Joint.h"
 #include "lua_Joystick.h"
@@ -103,7 +104,6 @@
 #include "lua_SpriteBatch.h"
 #include "lua_Technique.h"
 #include "lua_Terrain.h"
-#include "lua_TerrainHeightField.h"
 #include "lua_TextBox.h"
 #include "lua_Texture.h"
 #include "lua_TextureSampler.h"