Преглед изворни кода

GamePlay Encoder: Adds FBX support. (Disabled by default)

Darryl Gough пре 14 година
родитељ
комит
64868d431b
61 измењених фајлова са 2885 додато и 626 уклоњено
  1. 7 0
      gameplay-encoder/gameplay-encoder.vcxproj
  2. 49 14
      gameplay-encoder/gameplay-encoder.vcxproj.filters
  3. 2 2
      gameplay-encoder/src/Animation.cpp
  4. 126 2
      gameplay-encoder/src/AnimationChannel.cpp
  5. 15 0
      gameplay-encoder/src/AnimationChannel.h
  6. 2 2
      gameplay-encoder/src/Animations.cpp
  7. 1 21
      gameplay-encoder/src/Base.cpp
  8. 0 1
      gameplay-encoder/src/Base.h
  9. 1 3
      gameplay-encoder/src/DAEChannelTarget.cpp
  10. 8 8
      gameplay-encoder/src/DAEOptimizer.cpp
  11. 55 76
      gameplay-encoder/src/DAESceneEncoder.cpp
  12. 0 4
      gameplay-encoder/src/DAESceneEncoder.h
  13. 10 10
      gameplay-encoder/src/DAEUtil.cpp
  14. 1 5
      gameplay-encoder/src/DAEUtil.h
  15. 26 4
      gameplay-encoder/src/EncoderArguments.cpp
  16. 5 0
      gameplay-encoder/src/EncoderArguments.h
  17. 1341 0
      gameplay-encoder/src/FBXSceneEncoder.cpp
  18. 225 0
      gameplay-encoder/src/FBXSceneEncoder.h
  19. 38 2
      gameplay-encoder/src/FileIO.cpp
  20. 26 6
      gameplay-encoder/src/FileIO.h
  21. 2 2
      gameplay-encoder/src/GPBDecoder.cpp
  22. 0 4
      gameplay-encoder/src/GPBDecoder.h
  23. 17 10
      gameplay-encoder/src/GPBFile.cpp
  24. 0 4
      gameplay-encoder/src/GPBFile.h
  25. 11 11
      gameplay-encoder/src/Mesh.cpp
  26. 1 1
      gameplay-encoder/src/MeshPart.cpp
  27. 9 8
      gameplay-encoder/src/MeshSkin.cpp
  28. 2 2
      gameplay-encoder/src/MeshSkin.h
  29. 8 2
      gameplay-encoder/src/Node.cpp
  30. 5 0
      gameplay-encoder/src/Node.h
  31. 2 2
      gameplay-encoder/src/Object.h
  32. 0 4
      gameplay-encoder/src/Quaternion.cpp
  33. 0 4
      gameplay-encoder/src/Quaternion.h
  34. 3 3
      gameplay-encoder/src/ReferenceTable.cpp
  35. 10 3
      gameplay-encoder/src/Scene.cpp
  36. 6 1
      gameplay-encoder/src/Scene.h
  37. 20 1
      gameplay-encoder/src/StringUtil.cpp
  38. 5 1
      gameplay-encoder/src/StringUtil.h
  39. 4 4
      gameplay-encoder/src/TTFFontEncoder.cpp
  40. 20 16
      gameplay-encoder/src/Transform.h
  41. 17 69
      gameplay-encoder/src/Vector2.cpp
  42. 109 38
      gameplay-encoder/src/Vector2.h
  43. 77 0
      gameplay-encoder/src/Vector2.inl
  44. 31 76
      gameplay-encoder/src/Vector3.cpp
  45. 115 44
      gameplay-encoder/src/Vector3.h
  46. 82 0
      gameplay-encoder/src/Vector3.inl
  47. 33 69
      gameplay-encoder/src/Vector4.cpp
  48. 119 51
      gameplay-encoder/src/Vector4.h
  49. 89 0
      gameplay-encoder/src/Vector4.inl
  50. 21 26
      gameplay-encoder/src/Vertex.cpp
  51. 3 4
      gameplay-encoder/src/Vertex.h
  52. 13 0
      gameplay-encoder/src/main.cpp
  53. 1 1
      gameplay/src/Camera.cpp
  54. 0 4
      gameplay/src/Joint.cpp
  55. 1 1
      gameplay/src/Package.cpp
  56. 18 0
      gameplay/src/Vector2.h
  57. 14 0
      gameplay/src/Vector2.inl
  58. 18 0
      gameplay/src/Vector3.h
  59. 18 0
      gameplay/src/Vector3.inl
  60. 18 0
      gameplay/src/Vector4.h
  61. 25 0
      gameplay/src/Vector4.inl

+ 7 - 0
gameplay-encoder/gameplay-encoder.vcxproj

@@ -22,6 +22,7 @@
     <ClCompile Include="src\DAESceneEncoder.cpp" />
     <ClCompile Include="src\DAESceneEncoder.cpp" />
     <ClCompile Include="src\DAEUtil.cpp" />
     <ClCompile Include="src\DAEUtil.cpp" />
     <ClCompile Include="src\Effect.cpp" />
     <ClCompile Include="src\Effect.cpp" />
+    <ClCompile Include="src\FBXSceneEncoder.cpp" />
     <ClCompile Include="src\FileIO.cpp" />
     <ClCompile Include="src\FileIO.cpp" />
     <ClCompile Include="src\Font.cpp" />
     <ClCompile Include="src\Font.cpp" />
     <ClCompile Include="src\GPBFile.cpp" />
     <ClCompile Include="src\GPBFile.cpp" />
@@ -65,6 +66,7 @@
     <ClInclude Include="src\DAESceneEncoder.h" />
     <ClInclude Include="src\DAESceneEncoder.h" />
     <ClInclude Include="src\DAEUtil.h" />
     <ClInclude Include="src\DAEUtil.h" />
     <ClInclude Include="src\Effect.h" />
     <ClInclude Include="src\Effect.h" />
+    <ClInclude Include="src\FBXSceneEncoder.h" />
     <ClInclude Include="src\FileIO.h" />
     <ClInclude Include="src\FileIO.h" />
     <ClInclude Include="src\Font.h" />
     <ClInclude Include="src\Font.h" />
     <ClInclude Include="src\GPBFile.h" />
     <ClInclude Include="src\GPBFile.h" />
@@ -95,6 +97,11 @@
     <ClInclude Include="src\Vertex.h" />
     <ClInclude Include="src\Vertex.h" />
     <ClInclude Include="src\VertexElement.h" />
     <ClInclude Include="src\VertexElement.h" />
   </ItemGroup>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="src\Vector2.inl" />
+    <None Include="src\Vector3.inl" />
+    <None Include="src\Vector4.inl" />
+  </ItemGroup>
   <PropertyGroup Label="Globals">
   <PropertyGroup Label="Globals">
     <ProjectGuid>{9D69B743-4872-4DD1-8E30-0087C64298D7}</ProjectGuid>
     <ProjectGuid>{9D69B743-4872-4DD1-8E30-0087C64298D7}</ProjectGuid>
     <Keyword>Win32Proj</Keyword>
     <Keyword>Win32Proj</Keyword>

+ 49 - 14
gameplay-encoder/gameplay-encoder.vcxproj.filters

@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="src\DAESceneEncoder.cpp" />
     <ClCompile Include="src\main.cpp" />
     <ClCompile Include="src\main.cpp" />
     <ClCompile Include="src\ReferenceTable.cpp" />
     <ClCompile Include="src\ReferenceTable.cpp" />
     <ClCompile Include="src\TTFFontEncoder.cpp" />
     <ClCompile Include="src\TTFFontEncoder.cpp" />
@@ -61,10 +60,6 @@
       <Filter>Objects\Animation</Filter>
       <Filter>Objects\Animation</Filter>
     </ClCompile>
     </ClCompile>
     <ClCompile Include="src\GPBFile.cpp" />
     <ClCompile Include="src\GPBFile.cpp" />
-    <ClCompile Include="src\DAEChannelTarget.cpp" />
-    <ClCompile Include="src\Base.cpp">
-      <Filter>Objects</Filter>
-    </ClCompile>
     <ClCompile Include="src\FileIO.cpp" />
     <ClCompile Include="src\FileIO.cpp" />
     <ClCompile Include="src\StringUtil.cpp" />
     <ClCompile Include="src\StringUtil.cpp" />
     <ClCompile Include="src\Effect.cpp">
     <ClCompile Include="src\Effect.cpp">
@@ -90,15 +85,28 @@
     <ClCompile Include="src\Matrix.cpp">
     <ClCompile Include="src\Matrix.cpp">
       <Filter>Math</Filter>
       <Filter>Math</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="src\DAEOptimizer.cpp" />
-    <ClCompile Include="src\DAEUtil.cpp" />
     <ClCompile Include="src\EncoderArguments.cpp" />
     <ClCompile Include="src\EncoderArguments.cpp" />
     <ClCompile Include="src\Animations.cpp">
     <ClCompile Include="src\Animations.cpp">
       <Filter>Objects\Animation</Filter>
       <Filter>Objects\Animation</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="src\Base.cpp" />
+    <ClCompile Include="src\FBXSceneEncoder.cpp">
+      <Filter>FBX</Filter>
+    </ClCompile>
+    <ClCompile Include="src\DAEChannelTarget.cpp">
+      <Filter>DAE</Filter>
+    </ClCompile>
+    <ClCompile Include="src\DAEOptimizer.cpp">
+      <Filter>DAE</Filter>
+    </ClCompile>
+    <ClCompile Include="src\DAESceneEncoder.cpp">
+      <Filter>DAE</Filter>
+    </ClCompile>
+    <ClCompile Include="src\DAEUtil.cpp">
+      <Filter>DAE</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <ClInclude Include="src\DAESceneEncoder.h" />
     <ClInclude Include="src\ReferenceTable.h" />
     <ClInclude Include="src\ReferenceTable.h" />
     <ClInclude Include="src\TTFFontEncoder.h" />
     <ClInclude Include="src\TTFFontEncoder.h" />
     <ClInclude Include="src\CameraInstance.h">
     <ClInclude Include="src\CameraInstance.h">
@@ -157,10 +165,6 @@
       <Filter>Objects\Animation</Filter>
       <Filter>Objects\Animation</Filter>
     </ClInclude>
     </ClInclude>
     <ClInclude Include="src\GPBFile.h" />
     <ClInclude Include="src\GPBFile.h" />
-    <ClInclude Include="src\DAEChannelTarget.h" />
-    <ClInclude Include="src\Base.h">
-      <Filter>Objects</Filter>
-    </ClInclude>
     <ClInclude Include="src\FileIO.h" />
     <ClInclude Include="src\FileIO.h" />
     <ClInclude Include="src\StringUtil.h" />
     <ClInclude Include="src\StringUtil.h" />
     <ClInclude Include="src\Effect.h">
     <ClInclude Include="src\Effect.h">
@@ -186,12 +190,26 @@
     <ClInclude Include="src\Matrix.h">
     <ClInclude Include="src\Matrix.h">
       <Filter>Math</Filter>
       <Filter>Math</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="src\DAEOptimizer.h" />
-    <ClInclude Include="src\DAEUtil.h" />
     <ClInclude Include="src\EncoderArguments.h" />
     <ClInclude Include="src\EncoderArguments.h" />
     <ClInclude Include="src\Animations.h">
     <ClInclude Include="src\Animations.h">
       <Filter>Objects\Animation</Filter>
       <Filter>Objects\Animation</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="src\Base.h" />
+    <ClInclude Include="src\FBXSceneEncoder.h">
+      <Filter>FBX</Filter>
+    </ClInclude>
+    <ClInclude Include="src\DAEUtil.h">
+      <Filter>DAE</Filter>
+    </ClInclude>
+    <ClInclude Include="src\DAEChannelTarget.h">
+      <Filter>DAE</Filter>
+    </ClInclude>
+    <ClInclude Include="src\DAEOptimizer.h">
+      <Filter>DAE</Filter>
+    </ClInclude>
+    <ClInclude Include="src\DAESceneEncoder.h">
+      <Filter>DAE</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Filter Include="Objects">
     <Filter Include="Objects">
@@ -221,5 +239,22 @@
     <Filter Include="Math">
     <Filter Include="Math">
       <UniqueIdentifier>{4368ed2b-7fce-423a-a9cb-76a0fdc42858}</UniqueIdentifier>
       <UniqueIdentifier>{4368ed2b-7fce-423a-a9cb-76a0fdc42858}</UniqueIdentifier>
     </Filter>
     </Filter>
+    <Filter Include="FBX">
+      <UniqueIdentifier>{5ee87ce4-f055-46e4-a70f-f1619bae1e09}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="DAE">
+      <UniqueIdentifier>{d3b0fd39-8efe-4978-8d2d-3a74bb6a1deb}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="src\Vector2.inl">
+      <Filter>Math</Filter>
+    </None>
+    <None Include="src\Vector3.inl">
+      <Filter>Math</Filter>
+    </None>
+    <None Include="src\Vector4.inl">
+      <Filter>Math</Filter>
+    </None>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 2 - 2
gameplay-encoder/src/Animation.cpp

@@ -26,7 +26,7 @@ void Animation::writeBinary(FILE* file)
     // Animation writes its ID because it is not listed in the ref table.
     // Animation writes its ID because it is not listed in the ref table.
     write(getId(), file);
     write(getId(), file);
     write(_channels.size(), file);
     write(_channels.size(), file);
-    for (std::vector<AnimationChannel*>::iterator i = _channels.begin(); i != _channels.end(); i++)
+    for (std::vector<AnimationChannel*>::iterator i = _channels.begin(); i != _channels.end(); ++i)
     {
     {
         (*i)->writeBinary(file);
         (*i)->writeBinary(file);
     }
     }
@@ -37,7 +37,7 @@ void Animation::writeText(FILE* file)
     fprintElementStart(file);
     fprintElementStart(file);
     if (_channels.size() > 0 )
     if (_channels.size() > 0 )
     {
     {
-        for (std::vector<AnimationChannel*>::iterator i = _channels.begin(); i != _channels.end(); i++)
+        for (std::vector<AnimationChannel*>::iterator i = _channels.begin(); i != _channels.end(); ++i)
         {
         {
             (*i)->writeText(file);
             (*i)->writeText(file);
         }
         }

+ 126 - 2
gameplay-encoder/src/AnimationChannel.cpp

@@ -1,4 +1,5 @@
 #include "AnimationChannel.h"
 #include "AnimationChannel.h"
+#include "Transform.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -27,7 +28,7 @@ void AnimationChannel::writeBinary(FILE* file)
     write(_targetId, file);
     write(_targetId, file);
     write(_targetAttrib, file);
     write(_targetAttrib, file);
     write(_keytimes.size(), file);
     write(_keytimes.size(), file);
-    for (std::vector<float>::const_iterator i = _keytimes.begin(); i != _keytimes.end(); i++)
+    for (std::vector<float>::const_iterator i = _keytimes.begin(); i != _keytimes.end(); ++i)
     {
     {
         write((unsigned long)*i, file);
         write((unsigned long)*i, file);
     }
     }
@@ -35,7 +36,6 @@ void AnimationChannel::writeBinary(FILE* file)
     write(_tangentsIn, file);
     write(_tangentsIn, file);
     write(_tangentsOut, file);
     write(_tangentsOut, file);
     write(_interpolations, file);
     write(_interpolations, file);
-
 }
 }
 
 
 void AnimationChannel::writeText(FILE* file)
 void AnimationChannel::writeText(FILE* file)
@@ -51,6 +51,12 @@ void AnimationChannel::writeText(FILE* file)
     fprintElementEnd(file);
     fprintElementEnd(file);
 }
 }
 
 
+void AnimationChannel::setInterpolation(unsigned int interpolation)
+{
+    _interpolations.clear();
+    _interpolations.push_back(interpolation);
+}
+
 void AnimationChannel::setTargetId(const std::string str)
 void AnimationChannel::setTargetId(const std::string str)
 {
 {
     _targetId = str;
     _targetId = str;
@@ -91,6 +97,103 @@ const std::vector<float>& AnimationChannel::getKeyValues() const
     return _keyValues;
     return _keyValues;
 }
 }
 
 
+void AnimationChannel::removeDuplicates()
+{
+    if (_targetAttrib == Transform::ANIMATE_SCALE_ROTATE_TRANSLATE)
+    {
+        size_t prevIndex = 0;
+
+        std::vector<float>::iterator prevStart = _keyValues.begin();
+        std::vector<float>::iterator prevEnd   = _keyValues.begin() + 9;
+        
+        size_t i = 1;
+        for (i = 1; i < _keytimes.size(); ++i)
+        {
+            std::vector<float>::iterator start = _keyValues.begin() + i * 10;
+            std::vector<float>::iterator end = _keyValues.begin() + (i * 10 + 9);
+
+            if (!equal(prevStart, prevEnd, start))
+            {
+                if (i - prevIndex > 2)
+                {
+                    deleteRange(prevIndex+1, i);
+                    i = prevIndex;
+                    prevStart = _keyValues.begin() + i * 10;
+                    prevEnd = _keyValues.begin() + (i * 10 + 9);
+                }
+                else
+                {
+                    prevStart = start;
+                    prevEnd = end;
+                    prevIndex = i;
+                }
+            }
+        }
+        if (i - 1 - prevIndex >= 2)
+        {
+            deleteRange(prevIndex+1, i);
+        }
+    }
+}
+
+void AnimationChannel::convertToQuaternion()
+{
+    if (_targetAttrib == Transform::ANIMATE_ROTATE_X ||
+        _targetAttrib == Transform::ANIMATE_ROTATE_Y ||
+        _targetAttrib == Transform::ANIMATE_ROTATE_Z)
+    {
+        std::vector<float> newKeyValues;
+        newKeyValues.resize(_keyValues.size() * 4);
+        const size_t count = _keyValues.size();
+
+        float x = _targetAttrib == Transform::ANIMATE_ROTATE_X ? 1.0f : 0.0f;
+        float y = _targetAttrib == Transform::ANIMATE_ROTATE_Y ? 1.0f : 0.0f;
+        float z = _targetAttrib == Transform::ANIMATE_ROTATE_Z ? 1.0f : 0.0f;
+        for (size_t i = 0; i < count; ++i)
+        {
+            size_t j = i << 2;
+            newKeyValues[j] = x;
+            newKeyValues[j+1] = y;
+            newKeyValues[j+2] = z;
+            newKeyValues[j+3] = _keyValues[i];
+        }
+        setKeyValues(newKeyValues);
+        setTargetAttribute(Transform::ANIMATE_ROTATE);
+    }
+}
+
+void AnimationChannel::convertToTransform()
+{
+    if (_targetAttrib == Transform::ANIMATE_ROTATE_X ||
+        _targetAttrib == Transform::ANIMATE_ROTATE_Y ||
+        _targetAttrib == Transform::ANIMATE_ROTATE_Z)
+    {
+        std::vector<float> newKeyValues;
+        newKeyValues.resize(_keyValues.size() * 10);
+        const size_t count = _keyValues.size();
+
+        float x = _targetAttrib == Transform::ANIMATE_ROTATE_X ? 1.0f : 0.0f;
+        float y = _targetAttrib == Transform::ANIMATE_ROTATE_Y ? 1.0f : 0.0f;
+        float z = _targetAttrib == Transform::ANIMATE_ROTATE_Z ? 1.0f : 0.0f;
+        for (size_t i = 0; i < count; ++i)
+        {
+            size_t j = i << 2;
+            newKeyValues[j+0] = 1.0f;
+            newKeyValues[j+1] = 1.0f;
+            newKeyValues[j+2] = 1.0f;
+            newKeyValues[j+3] = x;
+            newKeyValues[j+4] = y;
+            newKeyValues[j+5] = z;
+            newKeyValues[j+6] = _keyValues[i];
+            newKeyValues[j+7] = 0.0f;
+            newKeyValues[j+8] = 0.0f;
+            newKeyValues[j+9] = 0.0f;
+        }
+        setKeyValues(newKeyValues);
+        setTargetAttribute(Transform::ANIMATE_SCALE_ROTATE_TRANSLATE);
+    }
+}
+
 unsigned int AnimationChannel::getInterpolationType(const char* str)
 unsigned int AnimationChannel::getInterpolationType(const char* str)
 {
 {
     unsigned int value = 0;
     unsigned int value = 0;
@@ -136,4 +239,25 @@ unsigned int AnimationChannel::getInterpolationType(const char* str)
     return value;
     return value;
 }
 }
 
 
+void AnimationChannel::deleteRange(size_t begin, size_t end)
+{
+    // delete range
+    printf("delete %d to %d\n", begin, end - 1);
+
+    std::vector<float>::iterator a = _keyValues.begin() + begin * 10;
+    std::vector<float>::iterator b = _keyValues.begin() + end * 10;
+    _keyValues.erase(a, b);
+
+    a = _keytimes.begin() + begin;
+    b = _keytimes.begin() + end;
+    _keytimes.erase(a, b);
+
+    if (_interpolations.size() > 1)
+    {
+        std::vector<unsigned int>::iterator a = _interpolations.begin() + begin;
+        std::vector<unsigned int>::iterator b = _interpolations.begin() + end * 10;
+        _interpolations.erase(a, b);
+    }
+}
+
 }
 }

+ 15 - 0
gameplay-encoder/src/AnimationChannel.h

@@ -35,6 +35,13 @@ public:
     virtual void writeBinary(FILE* file);
     virtual void writeBinary(FILE* file);
     virtual void writeText(FILE* file);
     virtual void writeText(FILE* file);
 
 
+    /**
+     * Sets the interpolation type of the entire animation channel.
+     * 
+     * @param interpolation The interpolation type from InterpolationTypes enum.
+     */
+    void setInterpolation(unsigned int interpolation);
+
     void setTargetId(const std::string str);
     void setTargetId(const std::string str);
     void setTargetAttribute(unsigned int attrib);
     void setTargetAttribute(unsigned int attrib);
 
 
@@ -46,6 +53,11 @@ public:
 
 
     const std::vector<float>& getKeyValues() const;
     const std::vector<float>& getKeyValues() const;
 
 
+    void removeDuplicates();
+
+    void convertToQuaternion();
+    void convertToTransform();
+
     /**
     /**
      * Returns the interpolation type value for the given string or zero if not valid.
      * Returns the interpolation type value for the given string or zero if not valid.
      * Example: "LINEAR" returns AnimationChannel::LINEAR
      * Example: "LINEAR" returns AnimationChannel::LINEAR
@@ -56,6 +68,9 @@ public:
      */
      */
     static unsigned int getInterpolationType(const char* str);
     static unsigned int getInterpolationType(const char* str);
 
 
+private:
+
+    void deleteRange(size_t begin, size_t end);
 
 
 private:
 private:
 
 

+ 2 - 2
gameplay-encoder/src/Animations.cpp

@@ -27,7 +27,7 @@ void Animations::writeBinary(FILE* file)
 {
 {
     Object::writeBinary(file);
     Object::writeBinary(file);
     write(_animations.size(), file);
     write(_animations.size(), file);
-    for (std::vector<Animation*>::iterator i = _animations.begin(); i != _animations.end(); i++)
+    for (std::vector<Animation*>::iterator i = _animations.begin(); i != _animations.end(); ++i)
     {
     {
         (*i)->writeBinary(file);
         (*i)->writeBinary(file);
     }
     }
@@ -38,7 +38,7 @@ void Animations::writeText(FILE* file)
     fprintElementStart(file);
     fprintElementStart(file);
     if (_animations.size() > 0 )
     if (_animations.size() > 0 )
     {
     {
-        for (std::vector<Animation*>::iterator i = _animations.begin(); i != _animations.end(); i++)
+        for (std::vector<Animation*>::iterator i = _animations.begin(); i != _animations.end(); ++i)
         {
         {
             (*i)->writeText(file);
             (*i)->writeText(file);
         }
         }

+ 1 - 21
gameplay-encoder/src/Base.cpp

@@ -5,30 +5,10 @@ namespace gameplay
 
 
 void fillArray(float values[], float value, size_t length)
 void fillArray(float values[], float value, size_t length)
 {
 {
-    for (size_t i = 0; i < length; i++)
+    for (size_t i = 0; i < length; ++i)
     {
     {
         values[i] = value;
         values[i] = value;
     }
     }
 }
 }
 
 
-void setIdentityMatrix(float values[])
-{
-    values[0] = 1.0f;
-    values[1] = 0.0f;
-    values[2] = 0.0f;
-    values[3] = 0.0f;
-    values[4] = 0.0f;
-    values[5] = 1.0f;
-    values[6] = 0.0f;
-    values[7] = 0.0f;
-    values[8] = 0.0f;
-    values[9] = 0.0f;
-    values[10] = 1.0f;
-    values[11] = 0.0f;
-    values[12] = 0.0f;
-    values[13] = 0.0f;
-    values[14] = 0.0f;
-    values[15] = 1.0f;
-}
-
 }
 }

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

@@ -61,7 +61,6 @@ enum VertexUsage
 
 
 
 
 void fillArray(float values[], float value, size_t length);
 void fillArray(float values[], float value, size_t length);
-void setIdentityMatrix(float values[]);
 
 
 }
 }
 #endif
 #endif

+ 1 - 3
gameplay-encoder/src/DAEChannelTarget.cpp

@@ -1,7 +1,5 @@
-
 #include "DAEChannelTarget.h"
 #include "DAEChannelTarget.h"
 
 
-
 namespace gameplay
 namespace gameplay
 {
 {
 
 
@@ -40,7 +38,7 @@ DAEChannelTarget::DAEChannelTarget(const domChannelRef channelRef) : _channel(ch
                 index = end + 1;
                 index = end + 1;
             }
             }
             _attributeIds.push_back(sub);
             _attributeIds.push_back(sub);
-        } while(end != std::string::npos);
+        } while (end != std::string::npos);
     }
     }
 
 
 }
 }

+ 8 - 8
gameplay-encoder/src/DAEOptimizer.cpp

@@ -37,7 +37,7 @@ void DAEOptimizer::combineAnimations(const std::string& nodeId, const std::strin
     // TODO: Make sure that there doesn't already exist an animation with this ID.
     // TODO: Make sure that there doesn't already exist an animation with this ID.
 
 
     // Move each of the channels to this animation
     // Move each of the channels to this animation
-    for (std::list<domChannelRef>::iterator i = channels.begin(); i != channels.end(); i++)
+    for (std::list<domChannelRef>::iterator i = channels.begin(); i != channels.end(); ++i)
     {
     {
         moveChannelAndSouresToAnimation(*i, animation);
         moveChannelAndSouresToAnimation(*i, animation);
     }
     }
@@ -56,17 +56,17 @@ void DAEOptimizer::getAnimationChannels(const domNodeRef& node, std::list<domCha
 
 
     domLibrary_animations_Array& animationLibrary = root->getLibrary_animations_array();
     domLibrary_animations_Array& animationLibrary = root->getLibrary_animations_array();
     size_t animationLibraryCount = animationLibrary.getCount();
     size_t animationLibraryCount = animationLibrary.getCount();
-    for (size_t i = 0; i < animationLibraryCount; i++)
+    for (size_t i = 0; i < animationLibraryCount; ++i)
     {
     {
         domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
         domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
         domAnimation_Array& animationArray = animationsRef->getAnimation_array();
         domAnimation_Array& animationArray = animationsRef->getAnimation_array();
         size_t animationCount = animationArray.getCount();
         size_t animationCount = animationArray.getCount();
-        for (size_t j = 0; j < animationCount; j++)
+        for (size_t j = 0; j < animationCount; ++j)
         {
         {
             domAnimationRef& animationRef = animationArray.get(j);
             domAnimationRef& animationRef = animationArray.get(j);
             domChannel_Array& channelArray = animationRef->getChannel_array();
             domChannel_Array& channelArray = animationRef->getChannel_array();
             size_t channelArrayCount = channelArray.getCount();
             size_t channelArrayCount = channelArray.getCount();
-            for (size_t k = 0; k < channelArrayCount; k++)
+            for (size_t k = 0; k < channelArrayCount; ++k)
             {
             {
                 domChannelRef& channel = channelArray.get(k);
                 domChannelRef& channel = channelArray.get(k);
                 const char* target = channel->getTarget();
                 const char* target = channel->getTarget();
@@ -84,7 +84,7 @@ void DAEOptimizer::getAnimationChannels(const domNodeRef& node, std::list<domCha
     daeTArray< daeSmartRef<daeElement> > children;
     daeTArray< daeSmartRef<daeElement> > children;
     node->getChildren(children);
     node->getChildren(children);
     size_t childCount = children.getCount();
     size_t childCount = children.getCount();
-    for (size_t i = 0; i < childCount; i++)
+    for (size_t i = 0; i < childCount; ++i)
     {
     {
         daeElementRef childElement = children[i];
         daeElementRef childElement = children[i];
         if (childElement->getElementType() == COLLADA_TYPE::NODE)
         if (childElement->getElementType() == COLLADA_TYPE::NODE)
@@ -102,12 +102,12 @@ void DAEOptimizer::deleteEmptyAnimations()
     // Get the list of empty animations
     // Get the list of empty animations
     domLibrary_animations_Array& animationLibrary = _dom->getLibrary_animations_array();
     domLibrary_animations_Array& animationLibrary = _dom->getLibrary_animations_array();
     size_t animationLibraryCount = animationLibrary.getCount();
     size_t animationLibraryCount = animationLibrary.getCount();
-    for (size_t i = 0; i < animationLibraryCount; i++)
+    for (size_t i = 0; i < animationLibraryCount; ++i)
     {
     {
         domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
         domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
         domAnimation_Array& animationArray = animationsRef->getAnimation_array();
         domAnimation_Array& animationArray = animationsRef->getAnimation_array();
         size_t animationCount = animationArray.getCount();
         size_t animationCount = animationArray.getCount();
-        for (size_t j = 0; j < animationCount; j++)
+        for (size_t j = 0; j < animationCount; ++j)
         {
         {
             domAnimationRef& animation = animationArray.get(j);
             domAnimationRef& animation = animationArray.get(j);
             if (isEmptyAnimation(animation))
             if (isEmptyAnimation(animation))
@@ -118,7 +118,7 @@ void DAEOptimizer::deleteEmptyAnimations()
     }
     }
 
 
     // Delete all of the empty animations
     // Delete all of the empty animations
-    for (std::list<domAnimationRef>::iterator i = animations.begin(); i != animations.end(); i++)
+    for (std::list<domAnimationRef>::iterator i = animations.begin(); i != animations.end(); ++i)
     {
     {
         daeElement::removeFromParent(*i);
         daeElement::removeFromParent(*i);
     }
     }

+ 55 - 76
gameplay-encoder/src/DAESceneEncoder.cpp

@@ -1,7 +1,3 @@
-/*
- * DAESceneEncoder.h
- */
-
 #include <algorithm>
 #include <algorithm>
 
 
 #include "DAESceneEncoder.h"
 #include "DAESceneEncoder.h"
@@ -20,28 +16,10 @@ DAESceneEncoder::~DAESceneEncoder()
 {
 {
 }
 }
 
 
-std::string getFilenameFromFilePath(const std::string& filepath)
-{
-    if (filepath.find_last_of("/") != std::string::npos)
-    {
-        return filepath.substr(filepath.find_last_of("/")+1);
-    }
-    return "";
-}
-
-std::string getFilenameNoExt(const std::string& filename)
-{
-    if (filename.find_last_of(".") != std::string::npos)
-    {
-        return filename.substr(0, filename.find_last_of("."));
-    }
-    return filename;
-}
-
 unsigned int getMaxOffset(domInputLocalOffset_Array& inputArray)
 unsigned int getMaxOffset(domInputLocalOffset_Array& inputArray)
 {
 {
     unsigned int maxOffset = 0;
     unsigned int maxOffset = 0;
-    for (unsigned int i = 0; i < (int)inputArray.getCount(); i++ )
+    for (unsigned int i = 0; i < (int)inputArray.getCount(); ++i)
     {
     {
         if ( inputArray[i]->getOffset() > maxOffset )
         if ( inputArray[i]->getOffset() > maxOffset )
         {
         {
@@ -62,7 +40,7 @@ void DAESceneEncoder::optimizeCOLLADA(const EncoderArguments& arguments, domCOLL
     if (size > 0)
     if (size > 0)
     {
     {
         begin();
         begin();
-        for (size_t i = 0; i < size; i++)
+        for (size_t i = 0; i < size; ++i)
         {
         {
             optimizer.combineAnimations(groupAnimatioNodeIds[i], groupAnimatioIds[i]);
             optimizer.combineAnimations(groupAnimatioNodeIds[i], groupAnimatioIds[i]);
         }
         }
@@ -82,7 +60,7 @@ void DAESceneEncoder::triangulate(DAE* dae)
     daeDatabase* dataBase = dae->getDatabase();
     daeDatabase* dataBase = dae->getDatabase();
 
 
     int geometryCount = (int)(dataBase->getElementCount(0, "geometry"));
     int geometryCount = (int)(dataBase->getElementCount(0, "geometry"));
-    for (int i = 0; i < geometryCount; i++)
+    for (int i = 0; i < geometryCount; ++i)
     {
     {
         // Find the next geometry element.
         // Find the next geometry element.
         domGeometry* domGeometry;
         domGeometry* domGeometry;
@@ -97,14 +75,14 @@ void DAESceneEncoder::triangulate(DAE* dae)
 
 
         // Loop over all the polygons elements.
         // Loop over all the polygons elements.
         int polygonsCount = (int)(domMesh->getPolygons_array().getCount());
         int polygonsCount = (int)(domMesh->getPolygons_array().getCount());
-        for (int j = 0; j < polygonsCount; j++)
+        for (int j = 0; j < polygonsCount; ++j)
         {
         {
             // Get the polygons out of the mesh.
             // Get the polygons out of the mesh.
             domPolygons* domPolygons = domMesh->getPolygons_array()[j];
             domPolygons* domPolygons = domMesh->getPolygons_array()[j];
             // Create the triangles from the polygons
             // Create the triangles from the polygons
             createTrianglesFromPolygons(domMesh, domPolygons);
             createTrianglesFromPolygons(domMesh, domPolygons);
         }
         }
-        while(domMesh->getPolygons_array().getCount() > 0)
+        while (domMesh->getPolygons_array().getCount() > 0)
         {
         {
             domPolygons* domPolygons = domMesh->getPolygons_array().get(0);
             domPolygons* domPolygons = domMesh->getPolygons_array().get(0);
             // Remove the polygons from the mesh.
             // Remove the polygons from the mesh.
@@ -113,14 +91,14 @@ void DAESceneEncoder::triangulate(DAE* dae)
 
 
         // Loop over all the polylist elements.
         // Loop over all the polylist elements.
         int polylistCount = (int)(domMesh->getPolylist_array().getCount());
         int polylistCount = (int)(domMesh->getPolylist_array().getCount());
-        for (int j = 0; j < polylistCount; j++)
+        for (int j = 0; j < polylistCount; ++j)
         {
         {
             // Get the polylist out of the mesh.
             // Get the polylist out of the mesh.
             domPolylist* domPolylist = domMesh->getPolylist_array()[j];
             domPolylist* domPolylist = domMesh->getPolylist_array()[j];
             // Create the triangles from the polygon list
             // Create the triangles from the polygon list
             createTrianglesFromPolylist(domMesh, domPolylist);
             createTrianglesFromPolylist(domMesh, domPolylist);
         }
         }
-        while(domMesh->getPolylist_array().getCount() > 0)
+        while (domMesh->getPolylist_array().getCount() > 0)
         {
         {
             domPolylist* domPolylist = domMesh->getPolylist_array().get(0);
             domPolylist* domPolylist = domMesh->getPolylist_array().get(0);
             // Remove the polylist from the mesh.
             // Remove the polylist from the mesh.
@@ -138,7 +116,7 @@ void DAESceneEncoder::createTrianglesFromPolygons(domMesh* domMesh, domPolygons*
     domP* domTrianglesP = (domP*)triangles->createAndPlace("p");
     domP* domTrianglesP = (domP*)triangles->createAndPlace("p");
     
     
     // Give the new <triangles> the same <_dae> and <parameters> as the old  <polygons>.
     // Give the new <triangles> the same <_dae> and <parameters> as the old  <polygons>.
-    for (unsigned int i = 0; i < domPolygons->getInput_array().getCount(); i++)
+    for (unsigned int i = 0; i < domPolygons->getInput_array().getCount(); ++i)
     {
     {
         triangles->placeElement(domPolygons->getInput_array()[i]->clone());
         triangles->placeElement(domPolygons->getInput_array()[i]->clone());
     }
     }
@@ -148,7 +126,7 @@ void DAESceneEncoder::createTrianglesFromPolygons(domMesh* domMesh, domPolygons*
     unsigned int primitiveCount = domPolygons->getP_array().getCount();
     unsigned int primitiveCount = domPolygons->getP_array().getCount();
     
     
     // Triangulate all the primitives, this generates all the triangles in a single <p> element.
     // Triangulate all the primitives, this generates all the triangles in a single <p> element.
-    for (unsigned int j = 0; j < primitiveCount; j++)
+    for (unsigned int j = 0; j < primitiveCount; ++j)
     {
     {
         // Check the polygons for consistancy (some exported files have had the wrong number of indices).
         // Check the polygons for consistancy (some exported files have had the wrong number of indices).
         domP* domCurrentP = domPolygons->getP_array()[j];
         domP* domCurrentP = domPolygons->getP_array()[j];
@@ -163,21 +141,21 @@ void DAESceneEncoder::createTrianglesFromPolygons(domMesh* domMesh, domPolygons*
             
             
             // Write out the primitives as triangles, just fan using the first element as the base.
             // Write out the primitives as triangles, just fan using the first element as the base.
             unsigned int index = inputCount;
             unsigned int index = inputCount;
-            for (unsigned int k = 0; k < triangleCount; k++)
+            for (unsigned int k = 0; k < triangleCount; ++k)
             {
             {
                 // First vertex.
                 // First vertex.
-                for (unsigned int l = 0; l < inputCount; l++)
+                for (unsigned int l = 0; l < inputCount; ++l)
                 {
                 {
                     domTrianglesP->getValue().append(domCurrentP->getValue()[l]);
                     domTrianglesP->getValue().append(domCurrentP->getValue()[l]);
                 }
                 }
                 // Second vertex.
                 // Second vertex.
-                for (unsigned int l = 0; l < inputCount; l++)
+                for (unsigned int l = 0; l < inputCount; ++l)
                 {
                 {
                     domTrianglesP->getValue().append(domCurrentP->getValue()[index + l]);
                     domTrianglesP->getValue().append(domCurrentP->getValue()[index + l]);
                 }
                 }
                 // Third vertex.
                 // Third vertex.
                 index += inputCount;
                 index += inputCount;
-                for (unsigned int l = 0; l < inputCount; l++)
+                for (unsigned int l = 0; l < inputCount; ++l)
                 {
                 {
                     domTrianglesP->getValue().append(domCurrentP->getValue()[index + l]);
                     domTrianglesP->getValue().append(domCurrentP->getValue()[index + l]);
                 }
                 }
@@ -195,7 +173,7 @@ void DAESceneEncoder::createTrianglesFromPolylist(domMesh* domMesh, domPolylist*
     domP* domTrianglesP = (domP*)triangles->createAndPlace("p");
     domP* domTrianglesP = (domP*)triangles->createAndPlace("p");
     
     
     // Give the new <triangles> the same <_dae> and <parameters> as the old <polylist>.
     // Give the new <triangles> the same <_dae> and <parameters> as the old <polylist>.
-    for (int i = 0; i < (int)(domPolylist->getInput_array().getCount()); i++)
+    for (int i = 0; i < (int)(domPolylist->getInput_array().getCount()); ++i)
     {
     {
         triangles->placeElement(domPolylist->getInput_array()[i]->clone());
         triangles->placeElement(domPolylist->getInput_array()[i]->clone());
     }
     }
@@ -208,27 +186,27 @@ void DAESceneEncoder::createTrianglesFromPolylist(domMesh* domMesh, domPolylist*
     unsigned int trianglesProcessed = 0;
     unsigned int trianglesProcessed = 0;
     
     
     // Triangulate all the primitives, this generates all the triangles in a single <p> element.
     // Triangulate all the primitives, this generates all the triangles in a single <p> element.
-    for (unsigned int j = 0; j < primitiveCount; j++)
+    for (unsigned int j = 0; j < primitiveCount; ++j)
     {
     {
         unsigned int triangleCount = (unsigned int)domPolylist->getVcount()->getValue()[j] - 2;
         unsigned int triangleCount = (unsigned int)domPolylist->getVcount()->getValue()[j] - 2;
         
         
         // Write out the primitives as triangles, just fan using the first element as the base.
         // Write out the primitives as triangles, just fan using the first element as the base.
         int index = inputCount;
         int index = inputCount;
-        for (unsigned int k = 0; k < triangleCount; k++)
+        for (unsigned int k = 0; k < triangleCount; ++k)
         {
         {
             // First vertex.
             // First vertex.
-            for (unsigned int l = 0; l < inputCount; l++)
+            for (unsigned int l = 0; l < inputCount; ++l)
             {
             {
                 domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + l]);
                 domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + l]);
             }
             }
             // Second vertex.
             // Second vertex.
-            for (unsigned int l = 0; l < inputCount; l++)
+            for (unsigned int l = 0; l < inputCount; ++l)
             {
             {
                 domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + index + l]);
                 domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + index + l]);
             }
             }
             // Third vertex.
             // Third vertex.
             index += inputCount;
             index += inputCount;
-            for (unsigned int l = 0; l < inputCount; l++)
+            for (unsigned int l = 0; l < inputCount; ++l)
             {
             {
                 domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + index + l]);
                 domTrianglesP->getValue().append(domPolylist->getP()->getValue()[offset + index + l]);
             }
             }
@@ -363,12 +341,12 @@ void DAESceneEncoder::loadAnimations(const domCOLLADA* dom)
     // Call loadAnimation on all <animation> elements in all <library_animations>
     // Call loadAnimation on all <animation> elements in all <library_animations>
     const domLibrary_animations_Array& animationLibrarys = dom->getLibrary_animations_array();
     const domLibrary_animations_Array& animationLibrarys = dom->getLibrary_animations_array();
     size_t animationLibrarysCount = animationLibrarys.getCount();
     size_t animationLibrarysCount = animationLibrarys.getCount();
-    for (size_t i = 0; i < animationLibrarysCount; i++)
+    for (size_t i = 0; i < animationLibrarysCount; ++i)
     {
     {
         const domLibrary_animationsRef& libraryAnimation = animationLibrarys.get(i);
         const domLibrary_animationsRef& libraryAnimation = animationLibrarys.get(i);
         const domAnimation_Array& animationArray = libraryAnimation->getAnimation_array();
         const domAnimation_Array& animationArray = libraryAnimation->getAnimation_array();
         size_t animationCount = animationArray.getCount();
         size_t animationCount = animationArray.getCount();
-        for (size_t j = 0; j < animationCount; j++)
+        for (size_t j = 0; j < animationCount; ++j)
         {
         {
             const domAnimationRef& animationRef = animationArray.get(j);
             const domAnimationRef& animationRef = animationArray.get(j);
             loadAnimation(animationRef);
             loadAnimation(animationRef);
@@ -391,7 +369,7 @@ void DAESceneEncoder::loadAnimation(const domAnimationRef animationRef)
     // <channel>
     // <channel>
     const domChannel_Array& channelArray = animationRef->getChannel_array();
     const domChannel_Array& channelArray = animationRef->getChannel_array();
     size_t channelArrayCount = channelArray.getCount();
     size_t channelArrayCount = channelArray.getCount();
-    for (size_t i = 0; i < channelArrayCount; i++)
+    for (size_t i = 0; i < channelArrayCount; ++i)
     {
     {
         AnimationChannel* animationChannel = new AnimationChannel();
         AnimationChannel* animationChannel = new AnimationChannel();
 
 
@@ -404,7 +382,7 @@ void DAESceneEncoder::loadAnimation(const domAnimationRef animationRef)
         // <input>
         // <input>
         const domInputLocal_Array& inputArray = sampler->getInput_array();
         const domInputLocal_Array& inputArray = sampler->getInput_array();
         size_t inputArrayCount = inputArray.getCount();
         size_t inputArrayCount = inputArray.getCount();
-        for (size_t j = 0; j < inputArrayCount; j++)
+        for (size_t j = 0; j < inputArrayCount; ++j)
         {
         {
             const domInputLocalRef& inputLocal = inputArray.get(j);
             const domInputLocalRef& inputLocal = inputArray.get(j);
 
 
@@ -425,7 +403,7 @@ void DAESceneEncoder::loadAnimation(const domAnimationRef animationRef)
                 if (equals(semantic, "INPUT"))
                 if (equals(semantic, "INPUT"))
                 {
                 {
                     // TODO: Ensure param name is TIME?
                     // TODO: Ensure param name is TIME?
-                    for (std::vector<float>::iterator k = floats.begin(); k != floats.end(); k++)
+                    for (std::vector<float>::iterator k = floats.begin(); k != floats.end(); ++k)
                     {
                     {
                         // Convert seconds to milliseconds
                         // Convert seconds to milliseconds
                         *k = *k * 1000.0f;
                         *k = *k * 1000.0f;
@@ -473,7 +451,7 @@ void DAESceneEncoder::loadInterpolation(const domSourceRef source, AnimationChan
     values.resize(count);
     values.resize(count);
     if (count > 0)
     if (count > 0)
     {
     {
-        for (size_t i = 0; i < count; i++)
+        for (size_t i = 0; i < count; ++i)
         {
         {
             values[i] = AnimationChannel::getInterpolationType(names.get(i));
             values[i] = AnimationChannel::getInterpolationType(names.get(i));
         }
         }
@@ -482,7 +460,7 @@ void DAESceneEncoder::loadInterpolation(const domSourceRef source, AnimationChan
         // instead of storing the same type for each key frame.
         // instead of storing the same type for each key frame.
         unsigned int firstType = values[0];
         unsigned int firstType = values[0];
         bool allEqual = true;
         bool allEqual = true;
-        for (size_t i = 1; i < count; i++)
+        for (size_t i = 1; i < count; ++i)
         {
         {
             if (firstType != values[i])
             if (firstType != values[i])
             {
             {
@@ -512,7 +490,7 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
     const char* targetId = channelTarget.getTargetId().c_str();
     const char* targetId = channelTarget.getTargetId().c_str();
 
 
     // TODO: Do we want to support more than one? If yes then this needs to be fixed.
     // TODO: Do we want to support more than one? If yes then this needs to be fixed.
-    for (size_t i = 0; i < channelTarget.getTargetAttributeCount(); i++)
+    for (size_t i = 0; i < channelTarget.getTargetAttributeCount(); ++i)
     {
     {
         std::string prop;
         std::string prop;
         channelTarget.getPropertyName(i, &prop);
         channelTarget.getPropertyName(i, &prop);
@@ -548,7 +526,7 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
                         // Convert (ANGLE ANGLE ANGLE) to (X Y Z ANGLE X Y Z ANGLE X Y Z ANGLE)
                         // Convert (ANGLE ANGLE ANGLE) to (X Y Z ANGLE X Y Z ANGLE X Y Z ANGLE)
                         std::vector<float> floats(size * 4);
                         std::vector<float> floats(size * 4);
                         // Duplicate rotation axis. We will replace only the angle that COLLADA is targeting.
                         // Duplicate rotation axis. We will replace only the angle that COLLADA is targeting.
-                        for (size_t j = 0; j < size; j++)
+                        for (size_t j = 0; j < size; ++j)
                         {
                         {
                             size_t k = j * 4;
                             size_t k = j * 4;
                             floats[k+0] = x;
                             floats[k+0] = x;
@@ -624,7 +602,7 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
                 std::vector<float> floats(newSize);
                 std::vector<float> floats(newSize);
 
 
                 size_t matrixCount = keyValues.size() / 16;
                 size_t matrixCount = keyValues.size() / 16;
-                for (size_t i = 0; i < matrixCount; i++)
+                for (size_t i = 0; i < matrixCount; ++i)
                 {
                 {
                     size_t j = i * 16;
                     size_t j = i * 16;
                     // COLLADA used row-major but the Matrix class uses column-major
                     // COLLADA used row-major but the Matrix class uses column-major
@@ -682,7 +660,7 @@ void DAESceneEncoder::copyFloats(const domFloat_array* source, std::vector<float
     size_t count = (size_t)source->getCount();
     size_t count = (size_t)source->getCount();
     t.resize(count);
     t.resize(count);
     const domListOfFloats& listOfFloats = source->getValue();
     const domListOfFloats& listOfFloats = source->getValue();
-    for (size_t i = 0; i < count; i++)
+    for (size_t i = 0; i < count; ++i)
     {
     {
         t[i] = (float)listOfFloats.get(i);
         t[i] = (float)listOfFloats.get(i);
     }
     }
@@ -695,7 +673,7 @@ void DAESceneEncoder::loadScene(const domVisual_scene* visualScene)
     const domNode_Array& nodes = visualScene->getNode_array();
     const domNode_Array& nodes = visualScene->getNode_array();
     scene->setId(visualScene->getId());
     scene->setId(visualScene->getId());
     size_t childCount = nodes.getCount();
     size_t childCount = nodes.getCount();
-    for (size_t i = 0; i < childCount; i++)
+    for (size_t i = 0; i < childCount; ++i)
     {
     {
         scene->add(loadNode(nodes[i], NULL));
         scene->add(loadNode(nodes[i], NULL));
     }
     }
@@ -717,11 +695,11 @@ Node* DAESceneEncoder::findSceneActiveCameraNode(const domVisual_scene* visualSc
     // Find the active camera
     // Find the active camera
     const domVisual_scene::domEvaluate_scene_Array& evaluateScenes = visualScene->getEvaluate_scene_array();
     const domVisual_scene::domEvaluate_scene_Array& evaluateScenes = visualScene->getEvaluate_scene_array();
     size_t evaluateSceneCount = evaluateScenes.getCount();
     size_t evaluateSceneCount = evaluateScenes.getCount();
-    for (size_t i = 0; i < evaluateSceneCount; i++)
+    for (size_t i = 0; i < evaluateSceneCount; ++i)
     {
     {
         const domVisual_scene::domEvaluate_scene::domRender_Array& renders = evaluateScenes[i]->getRender_array();
         const domVisual_scene::domEvaluate_scene::domRender_Array& renders = evaluateScenes[i]->getRender_array();
         size_t renderCount = renders.getCount();
         size_t renderCount = renders.getCount();
-        for (size_t j = 0; j < renderCount; j++)
+        for (size_t j = 0; j < renderCount; ++j)
         {
         {
             xsAnyURI cameraNodeURI = renders[i]->getCamera_node();
             xsAnyURI cameraNodeURI = renders[i]->getCamera_node();
             domNode* nodeRef = daeSafeCast<domNode>(cameraNodeURI.getElement());
             domNode* nodeRef = daeSafeCast<domNode>(cameraNodeURI.getElement());
@@ -783,7 +761,7 @@ Node* DAESceneEncoder::loadNode(domNode* n, Node* parent)
     // Load child nodes
     // Load child nodes
     const domNode_Array& childNodes = n->getNode_array();
     const domNode_Array& childNodes = n->getNode_array();
     size_t childCount = childNodes.getCount();
     size_t childCount = childNodes.getCount();
-    for (size_t i = 0; i < childCount; i++)
+    for (size_t i = 0; i < childCount; ++i)
     {
     {
         loadNode(childNodes.get(i), node);
         loadNode(childNodes.get(i), node);
     }
     }
@@ -834,7 +812,7 @@ void DAESceneEncoder::calcTransform(domNode* domNode, Matrix& dstTransform)
     daeTArray<daeSmartRef<daeElement> > children;
     daeTArray<daeSmartRef<daeElement> > children;
     domNode->getChildren(children);
     domNode->getChildren(children);
     size_t childCount = children.getCount();
     size_t childCount = children.getCount();
-    for (size_t i = 0; i < childCount; i++)
+    for (size_t i = 0; i < childCount; ++i)
     {
     {
         daeElementRef childElement = children[i];
         daeElementRef childElement = children[i];
         switch (childElement->getElementType())
         switch (childElement->getElementType())
@@ -899,7 +877,7 @@ void DAESceneEncoder::loadCameraInstance(const domNode* n, Node* node)
     // Does this node have any camera instances?
     // Does this node have any camera instances?
     const domInstance_camera_Array& instanceCameras = n->getInstance_camera_array();
     const domInstance_camera_Array& instanceCameras = n->getInstance_camera_array();
     size_t instanceCameraCount = instanceCameras.getCount();
     size_t instanceCameraCount = instanceCameras.getCount();
-    for (size_t i = 0; i < instanceCameraCount; i++)
+    for (size_t i = 0; i < instanceCameraCount; ++i)
     {
     {
         // Get the camrea object
         // Get the camrea object
         const domInstance_camera* cameraInstanceRef = instanceCameras.get(i);
         const domInstance_camera* cameraInstanceRef = instanceCameras.get(i);
@@ -926,7 +904,7 @@ void DAESceneEncoder::loadLightInstance(const domNode* n, Node* node)
     // Does this node have any light instances?
     // Does this node have any light instances?
     const domInstance_light_Array& instanceLights = n->getInstance_light_array();
     const domInstance_light_Array& instanceLights = n->getInstance_light_array();
     size_t instanceLightCount = instanceLights.getCount();
     size_t instanceLightCount = instanceLights.getCount();
-    for (size_t i = 0; i < instanceLightCount; i++)
+    for (size_t i = 0; i < instanceLightCount; ++i)
     {
     {
         // Get the camrea object
         // Get the camrea object
         const domInstance_light* lightInstanceRef = instanceLights.get(i);
         const domInstance_light* lightInstanceRef = instanceLights.get(i);
@@ -953,7 +931,7 @@ void DAESceneEncoder::loadGeometryInstance(const domNode* n, Node* node)
     // Does this node have any geometry instances?
     // Does this node have any geometry instances?
     const domInstance_geometry_Array& instanceGeometries = n->getInstance_geometry_array();
     const domInstance_geometry_Array& instanceGeometries = n->getInstance_geometry_array();
     size_t instanceGeometryCount = instanceGeometries.getCount();
     size_t instanceGeometryCount = instanceGeometries.getCount();
-    for (size_t i = 0; i < instanceGeometryCount; i++)
+    for (size_t i = 0; i < instanceGeometryCount; ++i)
     {
     {
         // Get the geometry object
         // Get the geometry object
         const domInstance_geometryRef geometryInstanceRef = instanceGeometries.get(i);
         const domInstance_geometryRef geometryInstanceRef = instanceGeometries.get(i);
@@ -981,7 +959,7 @@ void DAESceneEncoder::loadControllerInstance(const domNode* n, Node* node)
     // Does this node have any controller instances?
     // Does this node have any controller instances?
     const domInstance_controller_Array& instanceControllers = n->getInstance_controller_array();
     const domInstance_controller_Array& instanceControllers = n->getInstance_controller_array();
     size_t instanceControllerCount = instanceControllers.getCount();
     size_t instanceControllerCount = instanceControllers.getCount();
-    for (size_t i = 0; i < instanceControllerCount; i++)
+    for (size_t i = 0; i < instanceControllerCount; ++i)
     {
     {
         const domInstance_controllerRef instanceControllerRef = instanceControllers.get(i);
         const domInstance_controllerRef instanceControllerRef = instanceControllers.get(i);
         xsAnyURI controllerURI = instanceControllerRef->getUrl();
         xsAnyURI controllerURI = instanceControllerRef->getUrl();
@@ -1043,6 +1021,7 @@ CameraInstance* DAESceneEncoder::loadCamera(const domCamera* cameraRef)
             if (orthographicRef.cast())
             if (orthographicRef.cast())
             {
             {
                 camera->setOrthographic();
                 camera->setOrthographic();
+                camera->setAspectRatio((float)orthographicRef->getAspect_ratio()->getValue());
                 camera->setNearPlane((float)orthographicRef->getZnear()->getValue());
                 camera->setNearPlane((float)orthographicRef->getZnear()->getValue());
                 camera->setFarPlane((float)orthographicRef->getZfar()->getValue());
                 camera->setFarPlane((float)orthographicRef->getZfar()->getValue());
 
 
@@ -1268,7 +1247,7 @@ void DAESceneEncoder::loadSkeleton(domInstance_controller::domSkeleton* skeleton
     // Resolve and set joints array for skin
     // Resolve and set joints array for skin
     std::list<Node*> _joints;
     std::list<Node*> _joints;
     const std::list<std::string>& jointNames = skin->getJointNames();
     const std::list<std::string>& jointNames = skin->getJointNames();
-    for (std::list<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); i++)
+    for (std::list<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); ++i)
     {
     {
         Object* obj = _gamePlayFile.getFromRefTable(*i);
         Object* obj = _gamePlayFile.getFromRefTable(*i);
         if (obj)
         if (obj)
@@ -1305,7 +1284,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
 
 
     // Process "JOINT" input semantic first (we need to do this to set the joint count)
     // Process "JOINT" input semantic first (we need to do this to set the joint count)
     unsigned int jointCount = 0;
     unsigned int jointCount = 0;
-    for (unsigned int i = 0; i < jointInputs.getCount(); i++)
+    for (unsigned int i = 0; i < jointInputs.getCount(); ++i)
     {
     {
         domInputLocalRef input = jointInputs.get(i);
         domInputLocalRef input = jointInputs.get(i);
         std::string inputSemantic = std::string(input->getSemantic());
         std::string inputSemantic = std::string(input->getSemantic());
@@ -1321,7 +1300,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
 
 
             // Go through the joint list and conver them from sid to id because the sid information is
             // Go through the joint list and conver them from sid to id because the sid information is
             // lost when converting to the gameplay binary format.
             // lost when converting to the gameplay binary format.
-            for (std::list<std::string>::iterator i = list.begin(); i != list.end(); i++)
+            for (std::list<std::string>::iterator i = list.begin(); i != list.end(); ++i)
             {
             {
                 daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
                 daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
                 daeElement* element = resolver.getElement();
                 daeElement* element = resolver.getElement();
@@ -1340,7 +1319,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
             jointCount = list.size();
             jointCount = list.size();
             _jointInverseBindPoseMatrices.reserve(jointCount);
             _jointInverseBindPoseMatrices.reserve(jointCount);
             unsigned int j = 0;
             unsigned int j = 0;
-            for (std::list<std::string>::const_iterator i = list.begin(); i != list.end(); i++)
+            for (std::list<std::string>::const_iterator i = list.begin(); i != list.end(); ++i)
             {
             {
                 _jointLookupTable[*i] = j++;
                 _jointLookupTable[*i] = j++;
             }
             }
@@ -1356,7 +1335,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     }
     }
 
 
     // Process "INV_BIND_MATRIX" next
     // Process "INV_BIND_MATRIX" next
-    for (unsigned int i = 0; i < jointInputs.getCount(); i++)
+    for (unsigned int i = 0; i < jointInputs.getCount(); ++i)
     {
     {
         domInputLocalRef input = jointInputs.get(i);
         domInputLocalRef input = jointInputs.get(i);
         std::string inputSemantic = std::string(input->getSemantic());
         std::string inputSemantic = std::string(input->getSemantic());
@@ -1370,7 +1349,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
             //unsigned int matrixFloatsCount = (unsigned int)source->getFloat_array()->getCount();
             //unsigned int matrixFloatsCount = (unsigned int)source->getFloat_array()->getCount();
             unsigned int jointIndex = 0;
             unsigned int jointIndex = 0;
 
 
-            for (unsigned int j = 0; j < jointCount; j++)
+            for (unsigned int j = 0; j < jointCount; ++j)
             {
             {
                 Matrix matrix((float)matrixFloats.get(jointIndex + 0), (float)matrixFloats.get(jointIndex + 4), (float)matrixFloats.get(jointIndex + 8), (float)matrixFloats.get(jointIndex + 12),
                 Matrix matrix((float)matrixFloats.get(jointIndex + 0), (float)matrixFloats.get(jointIndex + 4), (float)matrixFloats.get(jointIndex + 8), (float)matrixFloats.get(jointIndex + 12),
                               (float)matrixFloats.get(jointIndex + 1), (float)matrixFloats.get(jointIndex + 5), (float)matrixFloats.get(jointIndex + 9), (float)matrixFloats.get(jointIndex + 13),
                               (float)matrixFloats.get(jointIndex + 1), (float)matrixFloats.get(jointIndex + 5), (float)matrixFloats.get(jointIndex + 9), (float)matrixFloats.get(jointIndex + 13),
@@ -1391,7 +1370,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     unsigned int vertexWeightsCount = (unsigned int)vertexWeights->getCount();
     unsigned int vertexWeightsCount = (unsigned int)vertexWeights->getCount();
     domListOfFloats jointWeights;
     domListOfFloats jointWeights;
 
 
-    for (unsigned int i = 0; i < jointInputs.getCount(); i++)
+    for (unsigned int i = 0; i < jointInputs.getCount(); ++i)
     {
     {
         domInputLocalOffsetRef input = vertexWeightsInputs.get(i);
         domInputLocalOffsetRef input = vertexWeightsInputs.get(i);
         std::string inputSemantic = std::string(input->getSemantic());
         std::string inputSemantic = std::string(input->getSemantic());
@@ -1437,7 +1416,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     int weightOffset = 0;
     int weightOffset = 0;
 
 
     // Go through all the skin vertex influence weights from the indexed data.
     // Go through all the skin vertex influence weights from the indexed data.
-    for (int i = 0; i < skinVertexInfluenceCountTotal; i++)
+    for (int i = 0; i < skinVertexInfluenceCountTotal; ++i)
     {
     {
         // Get the influence count and directly get the vertext blend weights and indices.
         // Get the influence count and directly get the vertext blend weights and indices.
         unsigned int vertexInfluenceCount = (unsigned int)skinVertexInfluenceCounts.get(i);
         unsigned int vertexInfluenceCount = (unsigned int)skinVertexInfluenceCounts.get(i);
@@ -1446,7 +1425,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
         //vertexInfluences.SetCapacity(vertexInfluenceCount);
         //vertexInfluences.SetCapacity(vertexInfluenceCount);
 
 
         // Get the index/weight pairs and some the weight totals while at it.
         // Get the index/weight pairs and some the weight totals while at it.
-        for (unsigned int j = 0; j < vertexInfluenceCount; j++)
+        for (unsigned int j = 0; j < vertexInfluenceCount; ++j)
         {
         {
             float weight = (float)jointWeights.get((unsigned int)skinVertexJointWeightPairIndices[vOffset + 1]);
             float weight = (float)jointWeights.get((unsigned int)skinVertexJointWeightPairIndices[vOffset + 1]);
             int index = (int)skinVertexJointWeightPairIndices[vOffset];
             int index = (int)skinVertexJointWeightPairIndices[vOffset];
@@ -1466,7 +1445,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
         }
         }
 
 
         // Get up the the maximum vertex weight influence count.
         // Get up the the maximum vertex weight influence count.
-         for (unsigned int j = 0; j < maxVertexInfluencesCount; j++)
+         for (unsigned int j = 0; j < maxVertexInfluencesCount; ++j)
         {
         {
             if (j < vertexInfluenceCount)
             if (j < vertexInfluenceCount)
             {
             {
@@ -1574,7 +1553,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     unsigned int inputCount = (unsigned int)-1;
     unsigned int inputCount = (unsigned int)-1;
 
 
     // Loop through our set of triangle lists (each list of triangles corresponds to a single MeshPart)
     // Loop through our set of triangle lists (each list of triangles corresponds to a single MeshPart)
-    for (unsigned int i = 0; i < trianglesArrayCount; i++)
+    for (unsigned int i = 0; i < trianglesArrayCount; ++i)
     {
     {
         const domTrianglesRef& triangles = trianglesArray.get(i);
         const domTrianglesRef& triangles = trianglesArray.get(i);
         const domInputLocalOffset_Array& inputArray = triangles->getInput_array();
         const domInputLocalOffset_Array& inputArray = triangles->getInput_array();
@@ -1584,7 +1563,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
         {
         {
             inputCount = (unsigned int)inputArray.getCount();
             inputCount = (unsigned int)inputArray.getCount();
 
 
-            for (unsigned int j = 0; j < inputCount; j++)
+            for (unsigned int j = 0; j < inputCount; ++j)
             {
             {
                 const domInputLocalOffsetRef& input = inputArray.get(j);
                 const domInputLocalOffsetRef& input = inputArray.get(j);
                 std::string inputSemantic = input->getSemantic();
                 std::string inputSemantic = input->getSemantic();
@@ -1593,7 +1572,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
                 if (equals(inputSemantic, "VERTEX"))
                 if (equals(inputSemantic, "VERTEX"))
                 {
                 {
                     unsigned int vertexArrayCount = (unsigned int)vertexArray.getCount();
                     unsigned int vertexArrayCount = (unsigned int)vertexArray.getCount();
-                    for (unsigned int k = 0; k < vertexArrayCount; k++)
+                    for (unsigned int k = 0; k < vertexArrayCount; ++k)
                     {
                     {
                         const domInputLocalRef& vertexInput = vertexArray.get(k);
                         const domInputLocalRef& vertexInput = vertexArray.get(k);
                         
                         
@@ -1648,7 +1627,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
             // If there is a triangle array with a different number of inputs, this is not supported.
             // If there is a triangle array with a different number of inputs, this is not supported.
             if (inputCount != (unsigned int)inputArray.getCount())
             if (inputCount != (unsigned int)inputArray.getCount())
             {
             {
-                for (size_t j = 0; j < polygonInputs.size(); j++)
+                for (size_t j = 0; j < polygonInputs.size(); ++j)
                 {
                 {
                     delete polygonInputs[j];
                     delete polygonInputs[j];
                 }
                 }
@@ -1664,7 +1643,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
     
     
     // Now we have validated that all input in all triangles are the same and in the same input layout.
     // Now we have validated that all input in all triangles are the same and in the same input layout.
     // Lets start to read them and build our subsets.
     // Lets start to read them and build our subsets.
-    for (unsigned int i = 0; i < trianglesArrayCount; i++)
+    for (unsigned int i = 0; i < trianglesArrayCount; ++i)
     {
     {
         // Subset to be built.
         // Subset to be built.
         MeshPart* subset = new MeshPart();
         MeshPart* subset = new MeshPart();

+ 0 - 4
gameplay-encoder/src/DAESceneEncoder.h

@@ -1,7 +1,3 @@
-/*
- * DAESceneEncoder.h
- */
-
 #ifndef DAESCENEEENCODER_H_
 #ifndef DAESCENEEENCODER_H_
 #define DAESCENEEENCODER_H_
 #define DAESCENEEENCODER_H_
 
 

+ 10 - 10
gameplay-encoder/src/DAEUtil.cpp

@@ -19,7 +19,7 @@ void getJointNames(const domSourceRef source, std::list<std::string>& list)
     {
     {
         domListOfNames& ids = nameArray->getValue();
         domListOfNames& ids = nameArray->getValue();
         size_t jointCount = (size_t)nameArray->getCount();
         size_t jointCount = (size_t)nameArray->getCount();
-        for (size_t j = 0; j < jointCount; j++)
+        for (size_t j = 0; j < jointCount; ++j)
         {
         {
             list.push_back(std::string(ids.get(j)));
             list.push_back(std::string(ids.get(j)));
         }
         }
@@ -32,7 +32,7 @@ void getJointNames(const domSourceRef source, std::list<std::string>& list)
         {
         {
             xsIDREFS& ids = idArray->getValue();
             xsIDREFS& ids = idArray->getValue();
             size_t jointCount = (size_t)idArray->getCount();
             size_t jointCount = (size_t)idArray->getCount();
-            for (size_t j = 0; j < jointCount; j++)
+            for (size_t j = 0; j < jointCount; ++j)
             {
             {
                 list.push_back(std::string(ids.get(j).getID()));
                 list.push_back(std::string(ids.get(j).getID()));
             }
             }
@@ -45,7 +45,7 @@ void getJointNames(const domSkin* skin, std::list<std::string>& list)
     const domSkin::domJointsRef& joints = skin->getJoints();
     const domSkin::domJointsRef& joints = skin->getJoints();
     const domInputLocal_Array& inputArray = joints->getInput_array();
     const domInputLocal_Array& inputArray = joints->getInput_array();
     size_t inputCount = inputArray.getCount();
     size_t inputCount = inputArray.getCount();
-    for (size_t i = 0; i < inputCount; i++)
+    for (size_t i = 0; i < inputCount; ++i)
     {
     {
         const domInputLocalRef input = inputArray.get(i);
         const domInputLocalRef input = inputArray.get(i);
         const char* semantic = input->getSemantic();
         const char* semantic = input->getSemantic();
@@ -69,7 +69,7 @@ domSource* getInputSource(const domChannelRef& channel)
         domSampler* sampler = daeSafeCast<domSampler>(element);
         domSampler* sampler = daeSafeCast<domSampler>(element);
         const domInputLocal_Array& inputArray = sampler->getInput_array();
         const domInputLocal_Array& inputArray = sampler->getInput_array();
         size_t inputArrayCount = inputArray.getCount();
         size_t inputArrayCount = inputArray.getCount();
-        for (size_t i = 0; i < inputArrayCount; i++)
+        for (size_t i = 0; i < inputArrayCount; ++i)
         {
         {
             const domInputLocalRef& input = inputArray.get(i);
             const domInputLocalRef& input = inputArray.get(i);
             if (strcmp(input->getSemantic(), "INPUT") == 0)
             if (strcmp(input->getSemantic(), "INPUT") == 0)
@@ -105,7 +105,7 @@ const domSamplerRef getSampler(const domChannelRef& channel)
         
         
         const domSampler_Array& samplerArray = animation->getSampler_array();
         const domSampler_Array& samplerArray = animation->getSampler_array();
         size_t count = samplerArray.getCount();
         size_t count = samplerArray.getCount();
-        for (size_t i = 0; i < count; i++)
+        for (size_t i = 0; i < count; ++i)
         {
         {
             const domSamplerRef& sampler = samplerArray.get(i);
             const domSamplerRef& sampler = samplerArray.get(i);
             if (id.compare(sampler->getId()) == 0)
             if (id.compare(sampler->getId()) == 0)
@@ -130,7 +130,7 @@ const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimat
     const std::string& id = uri.id();
     const std::string& id = uri.id();
     const domSource_Array& sourceArray = animation->getSource_array();
     const domSource_Array& sourceArray = animation->getSource_array();
     size_t count = sourceArray.getCount();
     size_t count = sourceArray.getCount();
-    for (size_t i = 0; i < count; i++)
+    for (size_t i = 0; i < count; ++i)
     {
     {
         const domSourceRef source = sourceArray.get(i);
         const domSourceRef source = sourceArray.get(i);
         if (id.compare(source->getId()) == 0)
         if (id.compare(source->getId()) == 0)
@@ -151,7 +151,7 @@ const domName_arrayRef getSourceNameArray(const domSourceRef& source)
     daeTArray<daeSmartRef<daeElement> > children;
     daeTArray<daeSmartRef<daeElement> > children;
     source->getChildren(children);
     source->getChildren(children);
     size_t childCount = children.getCount();
     size_t childCount = children.getCount();
-    for (size_t i = 0; i < childCount; i++)
+    for (size_t i = 0; i < childCount; ++i)
     {
     {
         const daeElementRef element = children.get(i);
         const daeElementRef element = children.get(i);
         if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
         if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
@@ -220,7 +220,7 @@ bool equalKeyTimes(const domSource* s1, const domSource* s2)
         const domListOfFloats& list2 = f2->getValue();
         const domListOfFloats& list2 = f2->getValue();
 
 
         size_t count = (size_t)f1->getCount();
         size_t count = (size_t)f1->getCount();
-        for (size_t i = 0; i < count; i++)
+        for (size_t i = 0; i < count; ++i)
         {
         {
             if (list1.get(i) != list2.get(i))
             if (list1.get(i) != list2.get(i))
             {
             {
@@ -256,7 +256,7 @@ void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& an
 
 
         domInputLocal_Array& inputArray = sampler->getInput_array();
         domInputLocal_Array& inputArray = sampler->getInput_array();
         size_t inputArrayCount = inputArray.getCount();
         size_t inputArrayCount = inputArray.getCount();
-        for (size_t i = 0; i < inputArrayCount; i++)
+        for (size_t i = 0; i < inputArrayCount; ++i)
         {
         {
             inputArray = sampler->getInput_array();
             inputArray = sampler->getInput_array();
             const domInputLocalRef& input = inputArray.get(i);
             const domInputLocalRef& input = inputArray.get(i);
@@ -286,7 +286,7 @@ int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, con
 {
 {
     const std::string nodeId = node->getId();
     const std::string nodeId = node->getId();
     size_t count = skeletonArray.getCount();
     size_t count = skeletonArray.getCount();
-    for (size_t i = 0; i < count; i++)
+    for (size_t i = 0; i < count; ++i)
     {
     {
         const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
         const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
         daeElementRef element = skeleton->getValue().getElement();
         daeElementRef element = skeleton->getValue().getElement();

+ 1 - 5
gameplay-encoder/src/DAEUtil.h

@@ -1,7 +1,3 @@
-/*
- * DAEUtil.h
- */
-
 #ifndef DAEUTIL_H_
 #ifndef DAEUTIL_H_
 #define DAEUTIL_H_
 #define DAEUTIL_H_
 
 
@@ -56,7 +52,7 @@ domSource* getInputSource(const domChannelRef& channel);
 const domSamplerRef getSampler(const domChannelRef& channel);
 const domSamplerRef getSampler(const domChannelRef& channel);
 
 
 /**
 /**
- * Returns the source from the given sampler input. 
+ * Returns the source from the given sampler input.
  * Searchs within the given animation.
  * Searchs within the given animation.
  * 
  * 
  * @param inputLocal The input element within a sampler.
  * @param inputLocal The input element within a sampler.

+ 26 - 4
gameplay-encoder/src/EncoderArguments.cpp

@@ -1,5 +1,5 @@
+#include <algorithm>
 #include "EncoderArguments.h"
 #include "EncoderArguments.h"
-
 #include "StringUtil.h"
 #include "StringUtil.h"
 
 
 #ifdef WIN32
 #ifdef WIN32
@@ -24,12 +24,12 @@ EncoderArguments::EncoderArguments(size_t argc, const char** argv) :
         
         
         // read the options
         // read the options
         std::vector<std::string> options;
         std::vector<std::string> options;
-        for (size_t i = 1; i < filePathIndex; i++)
+        for (size_t i = 1; i < filePathIndex; ++i)
         {
         {
             options.push_back(argv[i]);
             options.push_back(argv[i]);
         }
         }
         
         
-        for (size_t i = 0; i < options.size(); i++)
+        for (size_t i = 0; i < options.size(); ++i)
         {
         {
             if (options[i][0] == '-')
             if (options[i][0] == '-')
             {
             {
@@ -72,6 +72,24 @@ const std::vector<std::string>& EncoderArguments::getGroupAnimationAnimationId()
     return _groupAnimationAnimationId;
     return _groupAnimationAnimationId;
 }
 }
 
 
+bool EncoderArguments::containsGroupNodeId(const std::string& nodeId) const
+{
+    return find(_groupAnimationNodeId.begin(), _groupAnimationNodeId.end(), nodeId) != _groupAnimationNodeId.end();
+}
+
+const std::string EncoderArguments::getAnimationId(const std::string& nodeId) const
+{
+    std::vector<std::string>::const_iterator it = find(_groupAnimationNodeId.begin(), _groupAnimationNodeId.end(), nodeId);
+    for (size_t i = 0, size = _groupAnimationNodeId.size(); i < size; ++i)
+    {
+        if (_groupAnimationNodeId[i].compare(nodeId) == 0)
+        {
+            return _groupAnimationAnimationId[i];
+        }
+    }
+    return "";
+}
+
 bool EncoderArguments::parseErrorOccured() const
 bool EncoderArguments::parseErrorOccured() const
 {
 {
     return _parseError;
     return _parseError;
@@ -151,6 +169,10 @@ EncoderArguments::FileFormat EncoderArguments::getFileFormat() const
     {
     {
         return FILEFORMAT_DAE;
         return FILEFORMAT_DAE;
     }
     }
+    if (ext.compare("fbx") == 0 || ext.compare("FBX") == 0)
+    {
+        return FILEFORMAT_FBX;
+    }
     if (ext.compare("ttf") == 0 || ext.compare("TTF") == 0)
     if (ext.compare("ttf") == 0 || ext.compare("TTF") == 0)
     {
     {
         return FILEFORMAT_TTF;
         return FILEFORMAT_TTF;
@@ -265,7 +287,7 @@ std::string EncoderArguments::getRealPath(const std::string& filepath)
 
 
 void EncoderArguments::replace_char(char* str, char oldChar, char newChar)
 void EncoderArguments::replace_char(char* str, char oldChar, char newChar)
 {
 {
-    for (; *str != '\0'; str++)
+    for (; *str != '\0'; ++str)
     {
     {
         if (*str == oldChar)
         if (*str == oldChar)
         {
         {

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

@@ -15,6 +15,7 @@ public:
     {
     {
         FILEFORMAT_UNKNOWN,
         FILEFORMAT_UNKNOWN,
         FILEFORMAT_DAE,
         FILEFORMAT_DAE,
+        FILEFORMAT_FBX,
         FILEFORMAT_TTF,
         FILEFORMAT_TTF,
         FILEFORMAT_GPB
         FILEFORMAT_GPB
     };
     };
@@ -49,9 +50,13 @@ public:
      */
      */
     const std::string& getDAEOutputPath() const;
     const std::string& getDAEOutputPath() const;
 
 
+
     const std::vector<std::string>& getGroupAnimationNodeId() const;
     const std::vector<std::string>& getGroupAnimationNodeId() const;
     const std::vector<std::string>& getGroupAnimationAnimationId() const;
     const std::vector<std::string>& getGroupAnimationAnimationId() const;
 
 
+    bool containsGroupNodeId(const std::string& nodeId) const;
+    const std::string getAnimationId(const std::string& nodeId) const;
+
     /**
     /**
      * Returns true if an error occured while parsing the command line arguments.
      * Returns true if an error occured while parsing the command line arguments.
      */
      */

+ 1341 - 0
gameplay-encoder/src/FBXSceneEncoder.cpp

@@ -0,0 +1,1341 @@
+#ifdef USE_FBX
+
+#include <algorithm>
+#include <string>
+
+#include "FBXSceneEncoder.h"
+#include "EncoderArguments.h"
+
+using namespace gameplay;
+
+/**
+ * Returns the aspect ratio from the given camera.
+ * 
+ * @param fbxCamera The FBX camera to get the aspect ratio from.
+ * 
+ * @return The aspect ratio from the camera.
+ */
+float getAspectRatio(KFbxCamera* fbxCamera);
+
+/**
+ * Returns the field of view Y from the given camera.
+ * 
+ * @param fbxCamera The camera to get the fiew of view from.
+ * 
+ * @return The field of view Y.
+ */
+float getFieldOfView(KFbxCamera* fbxCamera);
+
+/**
+ * Loads the texture coordinates from given mesh's polygon part into the vertex.
+ * 
+ * @param fbxMesh The mesh to get the polygon from.
+ * @param polyIndex The index of the polygon.
+ * @param posInPoly The position in the polygon.
+ * @param vertex The vertex to copy the texture coordinates to.
+ */
+void loadTextureCoords(KFbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex);
+
+/**
+ * Loads the normal from the mesh and adds it to the given vertex.
+ * 
+ * @param fbxMesh The mesh to get the polygon from.
+ * @param vertexIndex The vertex index in the mesh.
+ * @param vertex The vertex to copy to.
+ */
+void loadNormal(KFbxMesh* fbxMesh, int vertexIndex, Vertex* vertex);
+
+/**
+ * Loads the tangent from the mesh and adds it to the given vertex.
+ * 
+ * @param fbxMesh The mesh to load from.
+ * @param vertexIndex The index of the vertex within fbxMesh.
+ * @param vertex The vertex to copy to.
+ */
+void loadTangent(KFbxMesh* fbxMesh, int vertexIndex, Vertex* vertex);
+
+/**
+ * Loads the binormal from the mesh and adds it to the given vertex.
+ * 
+ * @param fbxMesh The mesh to load from.
+ * @param vertexIndex The index of the vertex within fbxMesh.
+ * @param vertex The vertex to copy to.
+ */
+void loadBinormal(KFbxMesh* fbxMesh, int vertexIndex, Vertex* vertex);
+
+/**
+ * Loads the blend weight and blend indices data into the vertex.
+ * 
+ * @param vertexWeights List of vertex weights. The x member contains the blendIndices. The y member contains the blendWeights.
+ * @param vertex The vertex to copy the blend data to.
+ */
+void loadBlendData(const std::vector<Vector2>& vertexWeights, Vertex* vertex);
+
+/**
+ * Loads the blend weights and blend indices from the given mesh.
+ * 
+ * Each element of weights is a list of Vector2s where "x" is the blend index and "y" is the blend weight.
+ * 
+ * @param fbxMesh The mesh to load from.
+ * @param weights List of blend weights and blend indices for each vertex.
+ * 
+ * @return True if this mesh has a mesh skin, false otherwise.
+ */
+bool loadBlendWeights(KFbxMesh* fbxMesh, std::vector<std::vector<Vector2>>& weights);
+
+/**
+ * Copies from an FBX matrix to a float[16] array.
+ */
+void copyMatrix(const KFbxMatrix& fbxMatrix, float* matrix);
+
+/**
+ * Copies from an FBX matrix to a gameplay matrix.
+ */
+void copyMatrix(const KFbxMatrix& fbxMatrix, Matrix& matrix);
+
+/**
+ * Finds the min and max start time and stop time of the given animation curve.
+ * 
+ * startTime is updated if the animation curve contains a start time that is less than startTime.
+ * stopTime is updated if the animation curve contains a stop time that is greater than stopTime.
+ * frameRate is updated if the animation curve contains a frame rate that is greater than frameRate.
+ * 
+ * @param animCurve The animation curve to read from.
+ * @param startTime The min start time. (in/out)
+ * @param stopTime The max stop time. (in/out)
+ * @param frameRate The frame rate. (in/out)
+ */
+void findMinMaxTime(KFbxAnimCurve* animCurve, float* startTime, float* stopTime, float* frameRate);
+
+/**
+ * Appends a key frame of the given node's transform at the given time.
+ * 
+ * @param fbxNode The node to get the matrix transform from.
+ * @param time The key time to add and the time to get the transform from.
+ * @param keyTimes The list of key times to append to.
+ * @param keyValues The list of key values to append to.
+ */
+void appendKeyFrame(KFbxNode* fbxNode, float time, std::vector<float>* keyTimes, std::vector<float>* keyValues);
+
+/**
+ * Decomposes the given node's matrix transform at the given time and copies to scale, rotation and translation.
+ * 
+ * @param fbxNode The node to get the matrix transform from.
+ * @param time The time to get the matrix transform from.
+ * @param scale The scale to copy to.
+ * @param rotation The rotation to copy to.
+ * @param translation The translation to copy to.
+ */
+void decompose(KFbxNode* fbxNode, float time, Vector3* scale, Quaternion* rotation, Vector3* translation);
+
+/**
+ * Creates an animation channel that targets the given node and target attribute using the given key times and key values.
+ * 
+ * @param fbxNode The node to target.
+ * @param targetAttrib The attribute type to target.
+ * @param keyTimes The key times for the animation channel.
+ * @param keyValues The key values for the animation channel.
+ * 
+ * @return The newly created animation channel.
+ */
+AnimationChannel* createAnimationChannel(KFbxNode* fbxNode, unsigned int targetAttrib, const std::vector<float>& keyTimes, const std::vector<float>& keyValues);
+
+void addScaleChannel(Animation* animation, KFbxNode* fbxNode, float startTime, float stopTime);
+
+void addTranslateChannel(Animation* animation, KFbxNode* fbxNode, float startTime, float stopTime);
+
+
+////////////////////////////////////
+// Member Functions
+////////////////////////////////////
+
+FBXSceneEncoder::FBXSceneEncoder()
+    : _groupAnimation(NULL)
+{
+}
+
+FBXSceneEncoder::~FBXSceneEncoder()
+{
+}
+
+void FBXSceneEncoder::write(const std::string& filepath, const EncoderArguments& arguments)
+{
+    KFbxSdkManager* sdkManager = KFbxSdkManager::Create();
+    KFbxIOSettings *ios = KFbxIOSettings::Create(sdkManager, IOSROOT);
+    sdkManager->SetIOSettings(ios);
+    KFbxImporter* importer = KFbxImporter::Create(sdkManager,"");
+    
+    if (!importer->Initialize(filepath.c_str(), -1, sdkManager->GetIOSettings()))
+    {
+        printf("Call to KFbxImporter::Initialize() failed.\n");
+        printf("Error returned: %s\n\n", importer->GetLastErrorString());
+        exit(-1);
+    }
+    
+    KFbxScene* fbxScene = KFbxScene::Create(sdkManager,"__FBX_SCENE__");
+
+    print("Loading FBX file.");
+    importer->Import(fbxScene);
+    importer->Destroy();
+    print("Loading Scene.");
+    loadScene(fbxScene);
+    print("Loading animations.");
+    loadAnimations(fbxScene, arguments);
+    sdkManager->Destroy();
+
+    print("Optimizing GamePlay Binary.");
+    _gamePlayFile.adjust();
+    
+    std::string filenameOnly = getFilenameFromFilePath(filepath);
+    std::string dstFilename = filepath.substr(0, filepath.find_last_of('/'));
+    dstFilename.append(1, '/');
+    dstFilename.append(getFilenameNoExt(filenameOnly));
+
+    // TODO remove comments before submitting
+    //if (arguments.textOutputEnabled())
+    {
+        std::string outFile = dstFilename + ".xml";
+        fprintf(stderr, "Saving debug file: %s\n", outFile.c_str());
+        _gamePlayFile.saveText(outFile);
+    }
+    //else
+    {
+        std::string outFile = dstFilename + ".gpb";
+        fprintf(stderr, "Saving binary file: %s\n", outFile.c_str());
+        _gamePlayFile.saveBinary(outFile);
+    }
+}
+
+void FBXSceneEncoder::loadScene(KFbxScene* fbxScene)
+{
+    Scene* scene = new Scene();
+    scene->setId(fbxScene->GetName());
+    if (scene->getId().length() == 0)
+    {
+        scene->setId("__SCENE__");
+    }
+
+    // Load all of the nodes and their contents.
+    KFbxNode* rootNode = fbxScene->GetRootNode();
+    if (rootNode)
+    {
+        triangulateRecursive(rootNode);
+
+        // Don't include the FBX root node in the GPB.
+        const int childCount = rootNode->GetChildCount();
+        for (int i = 0; i < childCount; ++i)
+        {
+            Node* node = loadNode(rootNode->GetChild(i), NULL);
+            if (node)
+            {
+                scene->add(node);
+            }
+        }
+    }
+
+    // Load the MeshSkin information from the scene's poses.
+    loadBindShapes(fbxScene);
+
+    // Find the ambient light of the scene
+    KFbxColor ambientColor = fbxScene->GetGlobalSettings().GetAmbientColor();
+    scene->setAmbientColor((float)ambientColor.mRed, (float)ambientColor.mGreen, (float)ambientColor.mBlue);
+
+    _gamePlayFile.addScene(scene);
+}
+
+void FBXSceneEncoder::loadAnimationChannels(KFbxAnimLayer* animLayer, KFbxNode* fbxNode, Animation* animation)
+{
+    const std::string* targetId = NULL;
+
+    const char* name = fbxNode->GetName();
+    Node* node = _gamePlayFile.getNode(name);
+    if (node)
+    {
+        targetId = &node->getId();
+    }
+    
+    // Determine which properties are animated on this node
+    // Find the transform at each key frame
+    // TODO: Ignore properties that are not animated (scale, rotation, translation)
+    // This should result in only one animation channel per animated node.
+
+    float startTime = FLT_MAX, stopTime = -1.0f, frameRate = FLT_MIN;
+    bool tx = false, ty = false, tz = false, rx = false, ry = false, rz = false, sx = false, sy = false, sz = false;
+    KFbxAnimCurve* animCurve = NULL;
+    animCurve = fbxNode->LclTranslation.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_T_X);
+    if (animCurve)
+    {
+        tx = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclTranslation.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_T_Y);
+    if (animCurve)
+    {
+        ty = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclTranslation.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_T_Z);
+    if (animCurve)
+    {
+        tz = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclRotation.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_R_X);
+    if (animCurve)
+    {
+        rx = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclRotation.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_R_Y);
+    if (animCurve)
+    {
+        ry = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclRotation.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_R_Z);
+    if (animCurve)
+    {
+        rz = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclScaling.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_S_X);
+    if (animCurve)
+    {
+        sx = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclScaling.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_S_Y);
+    if (animCurve)
+    {
+        sy = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+    animCurve = fbxNode->LclScaling.GetCurve<KFbxAnimCurve>(animLayer, KFCURVENODE_S_Z);
+    if (animCurve)
+    {
+        sz = true;
+        findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
+    }
+
+    bool translate = tx | ty | tz;
+    bool scale = sx | sy | sz;
+    bool rotate = rx | ry | rz;
+
+    if (translate || rotate || scale)
+    {
+        assert(startTime != FLT_MAX);
+        assert(stopTime >= 0.0f);
+        AnimationChannel* channel = new AnimationChannel();
+        channel->setTargetId(name);
+        channel->setTargetAttribute(Transform::ANIMATE_SCALE_ROTATE_TRANSLATE);
+        
+        float increment = 1000.0f / frameRate;
+        std::vector<float> keyTimes;
+        std::vector<float> keyValues;
+        for (float time = startTime; time < stopTime; time += increment)
+        {
+            appendKeyFrame(fbxNode, time, &keyTimes, &keyValues);
+        }
+        // Add the last key frame at exactly stopTime
+        appendKeyFrame(fbxNode, stopTime, &keyTimes, &keyValues);
+
+        channel->setKeyTimes(keyTimes);
+        /*
+        std::vector<float> newKeyValues;
+        for (size_t i = 0, size = keyValues.size(); i < size; i += 10)
+        {
+            if (translate)
+            {
+                newKeyValues.push_back(keyValues[i+0]);
+                newKeyValues.push_back(keyValues[i+1]);
+                newKeyValues.push_back(keyValues[i+2]);
+            }
+            if (rotate)
+            {
+                newKeyValues.push_back(keyValues[i+3]);
+                newKeyValues.push_back(keyValues[i+4]);
+                newKeyValues.push_back(keyValues[i+5]);
+                newKeyValues.push_back(keyValues[i+6]);
+            }
+            if (scale)
+            {
+                newKeyValues.push_back(keyValues[i+7]);
+                newKeyValues.push_back(keyValues[i+8]);
+                newKeyValues.push_back(keyValues[i+9]);
+            }
+        }
+        channel->setKeyValues(newKeyValues);
+        */
+        channel->setKeyValues(keyValues);
+        channel->setInterpolation(AnimationChannel::LINEAR);
+        animation->add(channel);
+        /*
+        if (!translate)
+        {
+            addTranslateChannel(animation, fbxNode, startTime, stopTime);
+        }
+        if (!rotate)
+        {
+            printf("rotate?\n"); // TODO
+        }
+        if (!scale)
+        {
+            addScaleChannel(animation, fbxNode, startTime, stopTime);
+        }
+        */
+        if (_groupAnimation != animation)
+        {
+            // TODO explains
+            _gamePlayFile.addAnimation(animation);
+        }
+    }
+}
+
+void FBXSceneEncoder::loadAnimationLayer(KFbxAnimLayer* fbxAnimLayer, KFbxNode* fbxNode, const EncoderArguments& arguments)
+{
+    bool animationGroupId = false;
+    const char* name = fbxNode->GetName();
+    // Check if this node's animations are supposed to be grouped
+    if (name)
+    {
+        std::string str = name;
+        if (arguments.containsGroupNodeId(str))
+        {
+            animationGroupId = true;
+            _groupAnimation = new Animation();
+            _groupAnimation->setId(arguments.getAnimationId(str));
+        }
+    }
+    Animation* animation = _groupAnimation;
+    if (!_groupAnimation)
+    {
+        animation = new Animation();
+        animation->setId(name);
+    }
+    loadAnimationChannels(fbxAnimLayer, fbxNode, animation);
+
+    const int childCount = fbxNode->GetChildCount();
+    for (int modelCount = 0; modelCount < childCount; ++modelCount)
+    {
+        loadAnimationLayer(fbxAnimLayer, fbxNode->GetChild(modelCount), arguments);
+    }
+    if (animationGroupId)
+    {
+        _gamePlayFile.addAnimation(_groupAnimation);
+        _groupAnimation = NULL;
+    }
+}
+
+void FBXSceneEncoder::loadAnimations(KFbxScene* fbxScene, const EncoderArguments& arguments)
+{
+    KFbxAnimEvaluator* evaluator = fbxScene->GetEvaluator();
+    if (!evaluator)
+        return;
+    KFbxAnimStack* animStack = evaluator->GetContext();
+    if (!animStack)
+        return;
+
+    for (int i = 0; i < fbxScene->GetSrcObjectCount(FBX_TYPE(KFbxAnimStack)); ++i)
+    {
+        KFbxAnimStack* animStack = KFbxCast<KFbxAnimStack>(fbxScene->GetSrcObject(FBX_TYPE(KFbxAnimStack), i));
+        int nbAnimLayers = animStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer));
+        for (int l = 0; l < nbAnimLayers; ++l)
+        {
+            KFbxAnimLayer* animLayer = animStack->GetMember(FBX_TYPE(KFbxAnimLayer), l);
+            loadAnimationLayer(animLayer, fbxScene->GetRootNode(), arguments);
+        }
+    }
+}
+
+Node* FBXSceneEncoder::loadNode(KFbxNode* fbxNode, Node* parent)
+{
+    Node* node = NULL;
+
+    // Check if this node has already been loaded
+    const char* id = fbxNode->GetName();
+    if (id && strlen(id) > 0)
+    {
+        node = _gamePlayFile.getNode(fbxNode->GetName());
+        if (node)
+        {
+            return node;
+        }
+    }
+    node = new Node();
+    if (id)
+    {
+        node->setId(id);
+    }
+    if (parent)
+    {
+        parent->addChild(node);
+    }
+    _gamePlayFile.addNode(node);
+
+    transformNode(fbxNode, node);
+    
+    loadCamera(fbxNode, node);
+    loadLight(fbxNode, node);
+    loadModel(fbxNode, node);
+
+    if (fbxNode->GetSkeleton())
+    {
+        // Indicate that this is a joint node for the purpose of debugging.
+        // The XML debug output will print that this node is a joint.
+        node->setIsJoint(true);
+    }
+
+    // Load child nodes
+    const int childCount = fbxNode->GetChildCount();
+    for (int i = 0; i < childCount; ++i)
+    {
+        loadNode(fbxNode->GetChild(i), node);
+    }
+    return node;
+}
+
+Mesh* FBXSceneEncoder::getMesh(size_t meshId)
+{
+    // Check if this mesh was already loaded.
+    std::map<size_t, Mesh*>::iterator it = _meshes.find(meshId);
+    if (it != _meshes.end())
+    {
+        return it->second;
+    }
+    return NULL;
+}
+
+void FBXSceneEncoder::saveMesh(size_t meshId, Mesh* mesh)
+{
+    assert(mesh);
+    if (!getMesh(meshId))
+    {
+        _meshes[meshId] = mesh;
+    }
+}
+
+void FBXSceneEncoder::print(const char* str)
+{
+    fprintf(stderr,"%s\n", str);
+}
+
+void FBXSceneEncoder::transformNode(KFbxNode* fbxNode, Node* node)
+{
+    KFbxXMatrix matrix;
+    if (fbxNode->GetCamera() || fbxNode->GetLight())
+    {
+        // TODO: Why is this necessary for Camera and Light?
+        matrix.SetTRS(fbxNode->LclTranslation.Get(), fbxNode->LclRotation.Get(), fbxNode->LclScaling.Get());
+    }
+    else
+    {
+        matrix = fbxNode->EvaluateLocalTransform();
+    }
+
+    float m[16];
+    copyMatrix(matrix, m);
+    int i = 0;
+    for (int row = 0; row < 4; ++row)
+    {
+        for (int col = 0; col < 4; ++col)
+        {
+            m[i++] = (float)matrix.Get(row, col);
+        }
+    }
+    node->setTransformMatrix(m);
+}
+
+void FBXSceneEncoder::loadBindShapes(KFbxScene* fbxScene)
+{
+    float m[16];
+    const int poseCount = fbxScene->GetPoseCount();
+    for (int i = 0; i < poseCount; ++i)
+    {
+        KFbxPose* pose = fbxScene->GetPose(i);
+        assert(pose);
+        if (pose->IsBindPose() && pose->GetCount() > 0)
+        {
+            KFbxNode* fbxNode = pose->GetNode(0);
+            if (fbxNode->GetMesh() != NULL)
+            {
+                Node* node = _gamePlayFile.getNode(fbxNode->GetName());
+                assert(node && node->getModel());
+
+                Model* model = node->getModel();
+                if (model && model->getSkin())
+                {
+                    MeshSkin* skin = model->getSkin();
+                    copyMatrix(pose->GetMatrix(0), m);
+                    skin->setBindShape(m);
+                }
+            }
+        }
+    }
+}
+
+void FBXSceneEncoder::loadCamera(KFbxNode* fbxNode, Node* node)
+{
+    KFbxCamera* fbxCamera = fbxNode->GetCamera();
+    if (!fbxCamera)
+    {
+        return;
+    }
+    Camera* camera = new Camera();
+    const char* name = fbxNode->GetName();
+    if (name)
+    {
+        std::string id(name);
+        id.append("_Camera");
+        camera->setId(id);
+    }
+    camera->setAspectRatio(getAspectRatio(fbxCamera));
+    camera->setNearPlane((float)fbxCamera->NearPlane.Get());
+    camera->setFarPlane((float)fbxCamera->FarPlane.Get());
+
+    if (fbxCamera->ProjectionType.Get() == KFbxCamera::eORTHOGONAL)
+    {
+        camera->setOrthographic();
+        camera->setViewportWidth((float)fbxCamera->GetApertureWidth());
+        camera->setViewportWidth((float)fbxCamera->GetApertureHeight());
+        // xmag in FBX can be calculated from: OrthoZoom * 30.0 / 2.0
+        camera->setViewportWidth((float)fbxCamera->OrthoZoom.Get() * 15.0f);
+    }
+    else if (fbxCamera->ProjectionType.Get() == KFbxCamera::ePERSPECTIVE)
+    {
+        camera->setPerspective();
+        camera->setFieldOfView(getFieldOfView(fbxCamera));
+    }
+    else
+    {
+        warning("Unknown camera type in node");
+        return;
+    }
+    _gamePlayFile.addCamera(camera);
+    CameraInstance* cameraInstance = new CameraInstance();
+    cameraInstance->setCamera(camera);
+    node->setCameraInstance(cameraInstance);
+}
+
+void FBXSceneEncoder::loadLight(KFbxNode* fbxNode, Node* node)
+{
+    KFbxLight* fbxLight = fbxNode->GetLight();
+    if (!fbxLight)
+    {
+        return;
+    }
+    Light* light = new Light();
+    const char* name = fbxNode->GetName();
+    if (name)
+    {
+        std::string id(name);
+        id.append("_Light");
+        light->setId(id);
+    }
+
+    fbxDouble3 color = fbxLight->Color.Get();
+    light->setColor((float)color[0], (float)color[1], (float)color[2]);
+    
+    if (fbxLight->LightType.Get() == KFbxLight::ePOINT)
+    {
+        light->setPointLight();
+        // TODO: range
+    }
+    else if (fbxLight->LightType.Get() == KFbxLight::eDIRECTIONAL)
+    {
+        light->setDirectionalLight();
+    }
+    else if (fbxLight->LightType.Get() == KFbxLight::eSPOT)
+    {
+        light->setSpotLight();
+        // TODO: range and angles
+    }
+    else
+    {
+        warning("Unknown light type in node.");
+        return;
+    }
+
+    _gamePlayFile.addLight(light);
+    LightInstance* lightInstance = new LightInstance();
+    lightInstance->setLight(light);
+    node->setLightInstance(lightInstance);
+}
+
+void FBXSceneEncoder::loadModel(KFbxNode* fbxNode, Node* node)
+{
+    KFbxMesh* fbxMesh = fbxNode->GetMesh();
+    if (!fbxMesh)
+    {
+        return;
+    }
+    if (fbxMesh->IsTriangleMesh())
+    {
+        Mesh* mesh = loadMesh(fbxMesh);
+        Model* model = new Model();
+        model->setMesh(mesh);
+        node->setModel(model);
+        loadSkin(fbxMesh, model);
+        if (model->getSkin())
+        {
+            // TODO: explain
+            node->resetTransformMatrix();
+        }
+    }
+}
+
+void FBXSceneEncoder::loadSkin(KFbxMesh* fbxMesh, Model* model)
+{
+    const int deformerCount = fbxMesh->GetDeformerCount();
+    for (int i = 0; i < deformerCount; ++i)
+    {
+        KFbxDeformer* deformer = fbxMesh->GetDeformer(i);
+        if (deformer->GetDeformerType() == KFbxDeformer::eSKIN)
+        {
+            KFbxSkin* fbxSkin = static_cast<KFbxSkin*>(deformer);
+
+            MeshSkin* skin = new MeshSkin();
+
+            std::list<std::string> jointNames;
+            std::list<Node*> joints;
+            std::vector<Matrix> bindPoses;
+
+            const int clusterCount = fbxSkin->GetClusterCount();
+            for (int j = 0; j < clusterCount; ++j)
+            {
+                KFbxCluster* cluster = fbxSkin->GetCluster(j);
+                assert(cluster);
+                KFbxNode* linkedNode = cluster->GetLink();
+                assert(linkedNode);
+                if (linkedNode->GetSkeleton())
+                {
+                    const char* jointName = linkedNode->GetName();
+                    assert(jointName);
+                    jointNames.push_back(jointName);
+                    Node* joint = _gamePlayFile.getNode(jointName);
+                    assert(joint);
+                    joints.push_back(joint);
+
+                    KFbxXMatrix matrix;
+                    cluster->GetTransformLinkMatrix(matrix);
+                    Matrix m;
+                    copyMatrix(matrix.Inverse(), m);
+                    bindPoses.push_back(m);
+                }
+            }
+            skin->setJointNames(jointNames);
+            skin->setJoints(joints);
+            skin->setBindPoses(bindPoses);
+            model->setSkin(skin);
+            break;
+        }
+    }
+}
+
+Mesh* FBXSceneEncoder::loadMesh(KFbxMesh* fbxMesh)
+{
+    // Check if this mesh has already been loaded.
+    Mesh* mesh = getMesh(fbxMesh->GetUniqueID());
+    if (mesh)
+    {
+        return mesh;
+    }
+    print("Loading mesh.");
+    mesh = new Mesh();
+    // GamePlay requires that a mesh have a unique ID but KFbxMesh doesn't have a string ID.
+    const char* name = fbxMesh->GetNode()->GetName();
+    if (name)
+    {
+        std::string id(name);
+        id.append("_Mesh");
+        mesh->setId(id);
+    }
+
+    // The number of mesh parts is equal to the number of materials that affect this mesh.
+    // There is always at least one mesh part.
+    std::vector<MeshPart*> meshParts;
+    const int materialCount = fbxMesh->GetNode()->GetMaterialCount();
+    int meshPartSize = (materialCount > 0) ? materialCount : 1;
+    for (int i = 0; i < meshPartSize; ++i)
+    {
+        meshParts.push_back(new MeshPart());
+    }
+
+    // Find the blend weights and blend indices if this mesh is skinned.
+    std::vector<std::vector<Vector2>> weights;
+    bool hasSkin = loadBlendWeights(fbxMesh, weights);
+    
+    int vertexIndex = 0;
+    KFbxVector4* controlPoints = fbxMesh->GetControlPoints();
+    const int polygonCount = fbxMesh->GetPolygonCount();
+    for (int polyIndex = 0; polyIndex < polygonCount; ++polyIndex)
+    {
+        const int polygonSize = fbxMesh->GetPolygonSize(polyIndex);
+        for (int posInPoly = 0; posInPoly < polygonSize; ++posInPoly)
+        {
+            int controlPointIndex = fbxMesh->GetPolygonVertex(polyIndex, posInPoly);
+            Vertex vertex;
+
+            KFbxVector4& position = controlPoints[controlPointIndex];
+            vertex.position.x = (float)position[0];
+            vertex.position.y = (float)position[1];
+            vertex.position.z = (float)position[2];
+
+            loadTextureCoords(fbxMesh, polyIndex, posInPoly, &vertex);
+            loadNormal(fbxMesh, vertexIndex, &vertex);
+            loadTangent(fbxMesh, vertexIndex, &vertex);
+            loadBinormal(fbxMesh, vertexIndex, &vertex);
+            // TODO: loadDiffuseColors
+
+            if (hasSkin)
+            {
+                loadBlendData(weights[controlPointIndex], &vertex);
+            }
+
+            // Determine which mesh part this vertex index should be added to based on the material that affects it.
+            int meshPartIndex = 0;
+            const int elementMatrialCount = fbxMesh->GetElementMaterialCount();
+            for (int k = 0; k < elementMatrialCount; ++k)
+            {
+                KFbxGeometryElementMaterial* elementMaterial = fbxMesh->GetElementMaterial(k);
+                meshPartIndex = elementMaterial->GetIndexArray().GetAt(polyIndex);
+            }
+
+            // Add the vertex to the mesh if it hasn't already been added and find the vertex index.
+            unsigned int index;
+            if (mesh->contains(vertex))
+            {
+                index = mesh->getVertexIndex(vertex);
+            }
+            else
+            {
+                index = mesh->addVertex(vertex);
+            }
+            meshParts[meshPartIndex]->addIndex(index);
+            vertexIndex++;
+        }
+    }
+
+    const size_t meshpartsSize = meshParts.size();
+    for (size_t i = 0; i < meshpartsSize; ++i)
+    {
+        mesh->addMeshPart(meshParts[i]);
+    }
+
+    // The order that the vertex elements are add to the list matters.
+    // It should be the same order as how the Vertex data is written.
+
+    // Position
+    mesh->addVetexAttribute(POSITION, 3);
+
+    const Vertex& vertex = mesh->vertices[0];
+    // Normals
+    if (vertex.hasNormal)
+    {
+        mesh->addVetexAttribute(NORMAL, 3);
+    }
+    // Tangents
+    if (vertex.hasTangent)
+    {
+        mesh->addVetexAttribute(TANGENT, 3);
+    }
+    // Binormals
+    if (vertex.hasBinormal)
+    {
+        mesh->addVetexAttribute(BINORMAL, 3);
+    }
+    // Texture Coordinates
+    if (vertex.hasTexCoord)
+    {
+        mesh->addVetexAttribute(TEXCOORD0, 2);
+    }
+    // Diffuse Color
+    if (vertex.hasColor)
+    {
+        mesh->addVetexAttribute(COLOR, 3);
+    }
+    // Skinning BlendWeights BlendIndices
+    if (vertex.hasWeights)
+    {
+        mesh->addVetexAttribute(BLENDWEIGHTS, 4);
+        mesh->addVetexAttribute(BLENDINDICES, 4);
+    }
+
+    _gamePlayFile.addMesh(mesh);
+    saveMesh(fbxMesh->GetUniqueID(), mesh);
+    return mesh;
+}
+
+void FBXSceneEncoder::triangulateRecursive(KFbxNode* fbxNode)
+{
+    // Triangulate all NURBS, patch and mesh under this node recursively.
+    KFbxNodeAttribute* nodeAttribute = fbxNode->GetNodeAttribute();
+
+    if (nodeAttribute)
+    {
+        if (nodeAttribute->GetAttributeType() == KFbxNodeAttribute::eMESH ||
+            nodeAttribute->GetAttributeType() == KFbxNodeAttribute::eNURB ||
+            nodeAttribute->GetAttributeType() == KFbxNodeAttribute::eNURBS_SURFACE ||
+            nodeAttribute->GetAttributeType() == KFbxNodeAttribute::ePATCH)
+        {
+            KFbxGeometryConverter converter(fbxNode->GetFbxSdkManager());
+            converter.TriangulateInPlace(fbxNode);
+        }
+    }
+
+    const int childCount = fbxNode->GetChildCount();
+    for (int childIndex = 0; childIndex < childCount; ++childIndex)
+    {
+        triangulateRecursive(fbxNode->GetChild(childIndex));
+    }
+}
+
+void FBXSceneEncoder::warning(const std::string& message)
+{
+    printf("Warning: %s\n", message.c_str());
+}
+
+void FBXSceneEncoder::warning(const char* message)
+{
+    printf("Warning: %s\n", message);
+}
+
+////////////////////////////////////
+// Functions
+////////////////////////////////////
+
+float getAspectRatio(KFbxCamera* fbxCamera)
+{
+    return (float)fbxCamera->FilmAspectRatio.Get();
+    /*
+    KFbxCamera::ECameraAspectRatioMode camAspectRatioMode = fbxCamera->GetAspectRatioMode();
+    double aspectX = fbxCamera->AspectWidth.Get();
+    double aspectY = fbxCamera->AspectHeight.Get();
+    double aspectRatio = 1.333333;
+    switch ( camAspectRatioMode)
+    {
+    case KFbxCamera::eWINDOW_SIZE:
+        aspectRatio = aspectX / aspectY;
+        break;
+    case KFbxCamera::eFIXED_RATIO:
+        aspectRatio = aspectX;
+        break;
+    case KFbxCamera::eFIXED_RESOLUTION:
+        aspectRatio = aspectX / aspectY * fbxCamera->GetPixelRatio();
+        break;
+    case KFbxCamera::eFIXED_WIDTH:
+        aspectRatio = fbxCamera->GetPixelRatio() / aspectY;
+        break;
+    case KFbxCamera::eFIXED_HEIGHT:
+        aspectRatio = fbxCamera->GetPixelRatio() * aspectX;
+        break;
+    default:
+        break;
+    }
+    return (float)aspectRatio;
+    */
+}
+
+inline double vfov(double hfov, double aspect)
+{
+    static const double MATH_PI_180 = 0.01745329251994329576923690768489;
+    static const double MATH_180_PI = 57.295779513082320876798154814105;
+    return (2.0 * atan((aspect) * tan( (hfov * MATH_PI_180) * 0.5)) * MATH_180_PI);
+}
+
+float getFieldOfView(KFbxCamera* fbxCamera)
+{
+    double fieldOfViewX = 0.0;
+    double fieldOfViewY = 0.0;
+    double filmHeight = fbxCamera->GetApertureHeight();
+    double filmWidth = fbxCamera->GetApertureWidth() * fbxCamera->GetSqueezeRatio();
+    double apertureRatio = filmHeight / filmWidth;
+    if ( fbxCamera->GetApertureMode() == KFbxCamera::eVERTICAL)
+    {
+        fieldOfViewY = fbxCamera->FieldOfView.Get();
+    }
+    else if (fbxCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL)
+    {
+        fieldOfViewX = fbxCamera->FieldOfView.Get();
+        fieldOfViewY = vfov( fieldOfViewX, apertureRatio);
+    }
+    else if (fbxCamera->GetApertureMode() == KFbxCamera::eFOCAL_LENGTH)
+    {
+        fieldOfViewX = fbxCamera->ComputeFieldOfView(fbxCamera->FocalLength.Get());
+        fieldOfViewY = vfov( fieldOfViewX, apertureRatio);
+    }
+    else if (fbxCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL_AND_VERTICAL)
+    {
+        fieldOfViewY = fbxCamera->FieldOfViewY.Get();
+    }
+    else
+    {
+        fieldOfViewY = 45.0;
+    }
+    return (float)fieldOfViewY;
+}
+
+void loadTextureCoords(KFbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex)
+{
+    assert(fbxMesh && polyIndex >=0 && posInPoly >= 0);
+    if (fbxMesh->GetElementUVCount() > 0)
+    {
+        // Get only the first UV coordinates.
+        KFbxGeometryElementUV* leUV = fbxMesh->GetElementUV(0);
+        switch (leUV->GetMappingMode())
+        {
+        case KFbxGeometryElement::eBY_CONTROL_POINT:
+            switch (leUV->GetReferenceMode())
+            {
+            case KFbxGeometryElement::eDIRECT:
+                vertex->hasTexCoord = true;
+                vertex->texCoord.x = (float)leUV->GetDirectArray().GetAt(polyIndex)[0];
+                vertex->texCoord.y = (float)leUV->GetDirectArray().GetAt(polyIndex)[1];
+                break;
+            case KFbxGeometryElement::eINDEX_TO_DIRECT:
+                {
+                    int id = leUV->GetIndexArray().GetAt(polyIndex);
+                    vertex->hasTexCoord = true;
+                    vertex->texCoord.x = (float)leUV->GetDirectArray().GetAt(id)[0];
+                    vertex->texCoord.y = (float)leUV->GetDirectArray().GetAt(id)[1];
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+        case KFbxGeometryElement::eBY_POLYGON_VERTEX:
+            {
+                int lTextureUVIndex = fbxMesh->GetTextureUVIndex(polyIndex, posInPoly);
+                switch (leUV->GetReferenceMode())
+                {
+                case KFbxGeometryElement::eDIRECT:
+                case KFbxGeometryElement::eINDEX_TO_DIRECT:
+                    vertex->hasTexCoord = true;
+                    vertex->texCoord.x = (float)leUV->GetDirectArray().GetAt(lTextureUVIndex)[0];
+                    vertex->texCoord.y = (float)leUV->GetDirectArray().GetAt(lTextureUVIndex)[1];
+                    break;
+                default:
+                    break;
+                }
+            }
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void loadNormal(KFbxMesh* fbxMesh, int vertexIndex, Vertex* vertex)
+{
+    if (fbxMesh->GetElementNormalCount() > 0)
+    {
+        // Get only the first
+        KFbxGeometryElementNormal* leNormal = fbxMesh->GetElementNormal(0);
+        if (leNormal->GetMappingMode() == KFbxGeometryElement::eBY_POLYGON_VERTEX)
+        {
+            switch (leNormal->GetReferenceMode())
+            {
+            case KFbxGeometryElement::eDIRECT:
+                {
+                    KFbxVector4 vec4 = leNormal->GetDirectArray().GetAt(vertexIndex);
+                    vertex->hasNormal = true;
+                    vertex->normal.x = (float)vec4[0];
+                    vertex->normal.y = (float)vec4[1];
+                    vertex->normal.z = (float)vec4[2];
+                }
+                break;
+            case KFbxGeometryElement::eINDEX_TO_DIRECT:
+                {
+                    int id = leNormal->GetIndexArray().GetAt(vertexIndex);
+                    KFbxVector4 vec4 = leNormal->GetDirectArray().GetAt(id);
+                    vertex->hasNormal = true;
+                    vertex->normal.x = (float)vec4[0];
+                    vertex->normal.y = (float)vec4[1];
+                    vertex->normal.z = (float)vec4[2];
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+}
+
+void loadTangent(KFbxMesh* fbxMesh, int vertexIndex, Vertex* vertex)
+{
+    if (fbxMesh->GetElementTangentCount() > 0)
+    {
+        // Get only the first tangent
+        KFbxGeometryElementTangent* leTangent = fbxMesh->GetElementTangent(0);
+        if (leTangent->GetMappingMode() == KFbxGeometryElement::eBY_POLYGON_VERTEX)
+        {
+            switch (leTangent->GetReferenceMode())
+            {
+            case KFbxGeometryElement::eDIRECT:
+                {
+                    KFbxVector4 vec4 = leTangent->GetDirectArray().GetAt(vertexIndex);
+                    vertex->hasTangent = true;
+                    vertex->tangent.x = (float)vec4[0];
+                    vertex->tangent.y = (float)vec4[1];
+                    vertex->tangent.z = (float)vec4[2];
+                }
+                break;
+            case KFbxGeometryElement::eINDEX_TO_DIRECT:
+                {
+                    int id = leTangent->GetIndexArray().GetAt(vertexIndex);
+                    KFbxVector4 vec4 = leTangent->GetDirectArray().GetAt(id);
+                    vertex->hasTangent = true;
+                    vertex->tangent.x = (float)vec4[0];
+                    vertex->tangent.y = (float)vec4[1];
+                    vertex->tangent.z = (float)vec4[2];
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+}
+
+void loadBinormal(KFbxMesh* fbxMesh, int vertexIndex, Vertex* vertex)
+{
+    if (fbxMesh->GetElementBinormalCount() > 0)
+    {
+        // Get only the first binormal.
+        KFbxGeometryElementBinormal* leBinormal = fbxMesh->GetElementBinormal(0);
+        if (leBinormal->GetMappingMode() == KFbxGeometryElement::eBY_POLYGON_VERTEX)
+        {
+            switch (leBinormal->GetReferenceMode())
+            {
+            case KFbxGeometryElement::eDIRECT:
+                {
+                    KFbxVector4 vec4 = leBinormal->GetDirectArray().GetAt(vertexIndex);
+                    vertex->hasBinormal = true;
+                    vertex->binormal.x = (float)vec4[0];
+                    vertex->binormal.y = (float)vec4[1];
+                    vertex->binormal.z = (float)vec4[2];
+                }
+                break;
+            case KFbxGeometryElement::eINDEX_TO_DIRECT:
+                {
+                    int id = leBinormal->GetIndexArray().GetAt(vertexIndex);
+                    KFbxVector4 vec4 = leBinormal->GetDirectArray().GetAt(id);
+                    vertex->hasBinormal = true;
+                    vertex->binormal.x = (float)vec4[0];
+                    vertex->binormal.y = (float)vec4[1];
+                    vertex->binormal.z = (float)vec4[2];
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+}
+
+void loadBlendData(const std::vector<Vector2>& vertexWeights, Vertex* vertex)
+{
+    size_t size = vertexWeights.size();
+
+    if (size >= 1)
+    {
+        vertex->hasWeights= true;
+        vertex->blendIndices.x = vertexWeights[0].x;
+        vertex->blendWeights.x = vertexWeights[0].y;
+    }
+    if (size >= 2)
+    {
+        vertex->blendIndices.y = vertexWeights[1].x;
+        vertex->blendWeights.y = vertexWeights[1].y;
+    }
+    if (size >= 3)
+    {
+        vertex->blendIndices.z = vertexWeights[2].x;
+        vertex->blendWeights.z = vertexWeights[2].y;
+    }
+    if (size >= 4)
+    {
+        vertex->blendIndices.w = vertexWeights[3].x;
+        vertex->blendWeights.w = vertexWeights[3].y;
+    }
+}
+
+bool loadBlendWeights(KFbxMesh* fbxMesh, std::vector<std::vector<Vector2>>& weights)
+{
+    assert(fbxMesh);
+    const int vertexCount = fbxMesh->GetControlPointsCount();
+
+    KFbxSkin* fbxSkin = NULL;
+    const int deformerCount = fbxMesh->GetDeformerCount();
+    for (int i = 0; i < deformerCount; ++i)
+    {
+        KFbxDeformer* deformer = fbxMesh->GetDeformer(i);
+        if (deformer->GetDeformerType() == KFbxDeformer::eSKIN)
+        {
+            fbxSkin = static_cast<KFbxSkin*>(deformer);
+            weights.resize(vertexCount);
+
+            const int clusterCount = fbxSkin->GetClusterCount();
+            for (int j = 0; j < clusterCount; ++j)
+            {
+                KFbxCluster* cluster = fbxSkin->GetCluster(j);
+                assert(cluster);
+                KFbxNode* linkedNode = cluster->GetLink();
+                assert(linkedNode);
+
+                const int vertexIndexCount = cluster->GetControlPointIndicesCount();
+                for (int k = 0; k < vertexIndexCount; ++k)
+                {
+                    int index = cluster->GetControlPointIndices()[k];
+                    if (index >= vertexCount)
+                    {
+                        continue;
+                    }
+
+                    double weight = cluster->GetControlPointWeights()[k];
+                    if (weight == 0.0)
+                    {
+                        continue;
+                    }
+                    weights[index].push_back(Vector2((float)j, (float)weight));
+                }
+            }
+            // Only the first skin deformer will be loaded.
+            // There probably won't be more than one.
+            break;
+        }
+    }
+    return fbxSkin != NULL;
+}
+
+void findMinMaxTime(KFbxAnimCurve* animCurve, float* startTime, float* stopTime, float* frameRate)
+{
+    KTime start, stop;
+    animCurve->GetTimeInterval(start, stop);
+    *startTime = std::min(*startTime, (float)start.GetMilliSeconds());
+    *stopTime = std::max(*stopTime, (float)stop.GetMilliSeconds());
+    *frameRate = std::max(*frameRate, (float)stop.GetFrameRate(KTime::eDEFAULT_MODE));
+}
+
+void appendKeyFrame(KFbxNode* fbxNode, float time, std::vector<float>* keyTimes, std::vector<float>* keyValues)
+{
+    KFbxXMatrix fbxMatrix;
+    Matrix matrix;
+    KTime kTime;
+    kTime.SetMilliSeconds((kLongLong)time);
+    fbxMatrix = fbxNode->EvaluateLocalTransform(kTime);
+    copyMatrix(fbxMatrix, matrix);
+
+    Vector3 scale;
+    Quaternion rotation;
+    Vector3 translation;
+    matrix.decompose(&scale, &rotation, &translation);
+
+    keyTimes->push_back(time);
+    keyValues->push_back(scale.x);
+    keyValues->push_back(scale.y);
+    keyValues->push_back(scale.z);
+    keyValues->push_back(rotation.x);
+    keyValues->push_back(rotation.y);
+    keyValues->push_back(rotation.z);
+    keyValues->push_back(rotation.w);
+    keyValues->push_back(translation.x);
+    keyValues->push_back(translation.y);
+    keyValues->push_back(translation.z);
+}
+
+void decompose(KFbxNode* fbxNode, float time, Vector3* scale, Quaternion* rotation, Vector3* translation)
+{
+    KFbxXMatrix fbxMatrix;
+    Matrix matrix;
+    KTime kTime;
+    kTime.SetMilliSeconds((kLongLong)time);
+    fbxMatrix = fbxNode->EvaluateLocalTransform(kTime);
+    copyMatrix(fbxMatrix, matrix);
+    matrix.decompose(scale, rotation, translation);
+}
+
+AnimationChannel* createAnimationChannel(KFbxNode* fbxNode, unsigned int targetAttrib, const std::vector<float>& keyTimes, const std::vector<float>& keyValues)
+{
+    AnimationChannel* channel = new AnimationChannel();
+    channel->setTargetId(fbxNode->GetName());
+    channel->setKeyTimes(keyTimes);
+    channel->setKeyValues(keyValues);
+    channel->setInterpolation(AnimationChannel::LINEAR);
+    channel->setTargetAttribute(targetAttrib);
+    return channel;
+}
+
+void addScaleChannel(Animation* animation, KFbxNode* fbxNode, float startTime, float stopTime)
+{
+    std::vector<float> keyTimes;
+    std::vector<float> keyValues;
+    Vector3 scale;
+    Quaternion rotation;
+    Vector3 translation;
+
+    decompose(fbxNode, startTime, &scale, &rotation, &translation);
+    keyTimes.push_back(startTime);
+    keyValues.push_back(scale.x);
+    keyValues.push_back(scale.y);
+    keyValues.push_back(scale.z);
+
+    decompose(fbxNode, stopTime, &scale, &rotation, &translation);
+    keyTimes.push_back(stopTime);
+    keyValues.push_back(scale.x);
+    keyValues.push_back(scale.y);
+    keyValues.push_back(scale.z);
+
+    AnimationChannel* channel = createAnimationChannel(fbxNode, Transform::ANIMATE_SCALE, keyTimes, keyValues);
+    animation->add(channel);
+}
+
+void addTranslateChannel(Animation* animation, KFbxNode* fbxNode, float startTime, float stopTime)
+{
+    std::vector<float> keyTimes;
+    std::vector<float> keyValues;
+    Vector3 scale;
+    Quaternion rotation;
+    Vector3 translation;
+
+    decompose(fbxNode, startTime, &scale, &rotation, &translation);
+    keyTimes.push_back(startTime);
+    keyValues.push_back(translation.x);
+    keyValues.push_back(translation.y);
+    keyValues.push_back(translation.z);
+
+    decompose(fbxNode, stopTime, &scale, &rotation, &translation);
+    keyTimes.push_back(stopTime);
+    keyValues.push_back(translation.x);
+    keyValues.push_back(translation.y);
+    keyValues.push_back(translation.z);
+
+    AnimationChannel* channel = createAnimationChannel(fbxNode, Transform::ANIMATE_TRANSLATE, keyTimes, keyValues);
+    animation->add(channel);
+}
+
+void copyMatrix(const KFbxMatrix& fbxMatrix, float* matrix)
+{
+    int i = 0;
+    for (int row = 0; row < 4; ++row)
+    {
+        for (int col = 0; col < 4; ++col)
+        {
+            matrix[i++] = (float)fbxMatrix.Get(row, col);
+        }
+    }
+}
+
+void copyMatrix(const KFbxMatrix& fbxMatrix, Matrix& matrix)
+{
+    int i = 0;
+    for (int row = 0; row < 4; ++row)
+    {
+        for (int col = 0; col < 4; ++col)
+        {
+            matrix.m[i++] = (float)fbxMatrix.Get(row, col);
+        }
+    }
+}
+
+#endif

+ 225 - 0
gameplay-encoder/src/FBXSceneEncoder.h

@@ -0,0 +1,225 @@
+#ifndef FBXSCENEEENCODER_H_
+#define FBXSCENEEENCODER_H_
+
+#ifdef USE_FBX
+
+#include <iostream>
+#include <list>
+#include <vector>
+#include <ctime>
+#ifdef WIN32
+    #pragma warning( disable : 4100 )
+    #pragma warning( disable : 4512 )
+#endif
+#include <fbxsdk.h>
+
+#include "Base.h"
+#include "StringUtil.h"
+#include "Object.h"
+#include "Node.h"
+#include "Camera.h"
+#include "CameraInstance.h"
+#include "Light.h"
+#include "LightInstance.h"
+#include "Mesh.h"
+#include "MeshPart.h"
+#include "MeshSkin.h"
+#include "Model.h"
+#include "Scene.h"
+#include "Animation.h"
+#include "AnimationChannel.h"
+#include "Vertex.h"
+#include "Matrix.h"
+#include "Transform.h"
+#include "GPBFile.h"
+#include "EncoderArguments.h"
+
+using namespace gameplay;
+
+/**
+ * Class for binary encoding an FBX file.
+ */
+class FBXSceneEncoder
+{
+public:
+
+    static const unsigned int SCENE_SKIN_VERTEXINFLUENCES_MAX = 4;
+    
+    /**
+     * Constructor.
+     */
+    FBXSceneEncoder();
+
+    /**
+     * Destructor.
+     */
+    ~FBXSceneEncoder();
+    
+    /**
+     * Writes out encoded FBX file.
+     */
+    void write(const std::string& filepath, const EncoderArguments& arguments);
+
+private:
+
+    /**
+     * Loads the scene.
+     * 
+     * @param fbxScene The FBX scene to load.
+     */
+    void loadScene(KFbxScene* fbxScene);
+
+    /**
+     * Loads all of the animatiosn from the given FBX scene.
+     * 
+     * @param fbxScene The scene to load animations from.
+     * @param arguments The command line arguments passed to the encoder.
+     */
+    void loadAnimations(KFbxScene* fbxScene, const EncoderArguments& arguments);
+
+    /**
+     * Loads the animations from the given FBX animation layer recursively starting from fbxNode.
+     * 
+     * @param fbxAnimLayer The FBX animation layer to load from.
+     * @param fbxNode The node to start loading animations from.
+     * @param arguments The command line arguments passed to the encoder.
+     */
+    void loadAnimationLayer(KFbxAnimLayer* fbxAnimLayer, KFbxNode* fbxNode, const EncoderArguments& arguments);
+
+    /**
+     * Loads animation channels from the given node and adds the channels to the given animation.
+     * 
+     * @param pAnimLayer The FBX animation layer to load from.
+     * @param fbxNode The node to load animation channels from.
+     * @param animation The animation to add the channels to.
+     */
+    void loadAnimationChannels(KFbxAnimLayer* pAnimLayer, KFbxNode* fbxNode, Animation* animation);
+
+    /**
+     * Loads the bind shape for all mesh skins that have be loaded so far.
+     * 
+     * @param fbxScene The FBX scene to read the bind shapes from.
+     */
+    void loadBindShapes(KFbxScene* fbxScene);
+
+    /**
+     * Loads the camera from the given FBX node and adds to it to the given GamePlay node.
+     * 
+     * @param fbxNode The FBX node to load from.
+     * @param node The GamePlay node to add to.
+     */
+    void loadCamera(KFbxNode* fbxNode, Node* node);
+
+    /**
+     * Loads the light from the given FBX node and adds to it to the given GamePlay node.
+     * 
+     * @param fbxNode The FBX node to load from.
+     * @param node The GamePlay node to add to.
+     */
+    void loadLight(KFbxNode* fbxNode, Node* node);
+    
+    /**
+     * Loads the model from the given FBX node and adds to it to the given GamePlay node.
+     *
+     * @param fbxNode The FBX node to load from.
+     * @param node The GamePlay node to add to.
+     */
+    void loadModel(KFbxNode* fbxNode, Node* node);
+
+    /**
+     * Loads the mesh skin from the given FBX mesh and adds it to the given GamePlay model.
+     *
+     * @param fbxMesh The FBX mesh to load the skin from.
+     * @param model The model to add the skin to.
+     */
+    void loadSkin(KFbxMesh* fbxMesh, Model* model);
+    
+    /**
+     * Loads the FBX Node and creates a GamePlay Node.
+     * 
+     * @param fbxNode The FBX Node to load.
+     * @param parent The parent node that the newly created node should be added to. May be NULL.
+     * 
+     * @return The newly created Node or NULL if the node could not be loaded.
+     */
+    Node* loadNode(KFbxNode* fbxNode, Node* parent);
+    
+    /**
+     * Loads the FbxMesh and returns a GamePlay mesh.
+     * If the fbxMesh has already been loaded then the same instance of mesh will be returned.
+     * 
+     * @param fbxMesh The FBX Mesh to load.
+     * 
+     * @return The GamePlay mesh that was loaded from the FBX Mesh.
+     */
+    Mesh* loadMesh(KFbxMesh* fbxMesh);
+
+    /**
+     * Gets the Mesh that was saved with the given ID. Returns NULL if a match is not found.
+     * 
+     * @param meshId The ID of the FbxMesh to search for.
+     * 
+     * @return The mesh that was saved with the ID or NULL if none was found.
+     */
+    Mesh* getMesh(size_t meshId);
+
+    /**
+     * Saves the Mesh with the given id.
+     * 
+     * @param meshId The ID of the FbxMesh to use as a key.
+     * @param mesh The mesh to save.
+     */
+    void saveMesh(size_t meshId, Mesh* mesh);
+    
+    /**
+     * Prints a message.
+     *
+     * @param str The string to print.
+     */
+    void print(const char* str);
+
+    /**
+     * Transforms the GamePlay Node using the transform data from the FBX Node.
+     * 
+     * @param fbxNode The FBX node to get the transfrom data from
+     * @param node The GamePlay Node to copy the transform to.
+     */
+    void transformNode(KFbxNode* fbxNode, Node* node);
+
+    /**
+     * Recursively triangules the meshes starting from the given node.
+     * 
+     * @param fbxNode The node to start triangulating from.
+     */
+    static void triangulateRecursive(KFbxNode* fbxNode);
+
+    /**
+     * Prints a warning message.
+     */
+    static void warning(const std::string& message);
+
+    /**
+     * Prints a warning message.
+     */
+    static void warning(const char* message);
+
+private:
+
+    /**
+     * The GamePlay file that is populated while reading the FBX file.
+     */
+    GPBFile _gamePlayFile;
+
+    /**
+     * The collection of meshes for the purpose of making sure that the same model is not loaded twice. (Mesh instancing)
+     */
+    std::map<size_t, Mesh*> _meshes;
+
+    /**
+     * The animation that channels should be added to it the user is using the -groupAnimation command line argument. May be NULL.
+     */
+    Animation* _groupAnimation;
+};
+
+#endif
+#endif

+ 38 - 2
gameplay-encoder/src/FileIO.cpp

@@ -55,7 +55,7 @@ void write(float value, FILE* file)
 }
 }
 void write(const float* values, int length, FILE* file)
 void write(const float* values, int length, FILE* file)
 {
 {
-    for (int i = 0; i < length; i++)
+    for (int i = 0; i < length; ++i)
     {
     {
         write(values[i], file);
         write(values[i], file);
     }
     }
@@ -78,7 +78,7 @@ void writeZero(FILE* file)
 void fprintfElement(FILE* file, const char* elementName, const float values[], int length)
 void fprintfElement(FILE* file, const char* elementName, const float values[], int length)
 {
 {
     fprintf(file, "<%s>", elementName);
     fprintf(file, "<%s>", elementName);
-    for (int i = 0; i < length; i++)
+    for (int i = 0; i < length; ++i)
     {
     {
         fprintf(file, "%f ", values[i]);
         fprintf(file, "%f ", values[i]);
     }
     }
@@ -144,4 +144,40 @@ void skipUint(FILE* file)
     fseek(file, sizeof(unsigned int), SEEK_CUR);
     fseek(file, sizeof(unsigned int), SEEK_CUR);
 }
 }
 
 
+void writeVectorBinary(const Vector2& v, FILE* file)
+{
+    write(v.x, file);
+    write(v.y, file);
+}
+
+void writeVectorText(const Vector2& v, FILE* file)
+{
+    fprintf(file, "%f %f\n", v.x, v.y);
+}
+
+void writeVectorBinary(const Vector3& v, FILE* file)
+{
+    write(v.x, file);
+    write(v.y, file);
+    write(v.z, file);
+}
+
+void writeVectorText(const Vector3& v, FILE* file)
+{
+    fprintf(file, "%f %f %f\n", v.x, v.y, v.z);
+}
+
+void writeVectorBinary(const Vector4& v, FILE* file)
+{
+    write(v.x, file);
+    write(v.y, file);
+    write(v.z, file);
+    write(v.w, file);
+}
+
+void writeVectorText(const Vector4& v, FILE* file)
+{
+    fprintf(file, "%f %f %f %f\n", v.x, v.y, v.z, v.w);
+}
+
 }
 }

+ 26 - 6
gameplay-encoder/src/FileIO.h

@@ -2,12 +2,16 @@
 #define FILEIO_H_
 #define FILEIO_H_
 
 
 #include "Base.h"
 #include "Base.h"
+#include "Vector2.h"
+#include "Vector3.h"
+#include "Vector4.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
 
 
 /**
 /**
  * Writes an XML element to the specified file stream.
  * Writes an XML element to the specified file stream.
+ * 
  * @param file Pointer to a FILE object that identifies the stream.
  * @param file Pointer to a FILE object that identifies the stream.
  * @param elementName Name of the XML element to write.
  * @param elementName Name of the XML element to write.
  * @param value Value to write.
  * @param value Value to write.
@@ -24,7 +28,7 @@ void fprintfElement(FILE* file, const char* format, const char* elementName, std
 {
 {
     fprintf(file, "<%s>", elementName);
     fprintf(file, "<%s>", elementName);
     typename std::vector<T>::const_iterator i;
     typename std::vector<T>::const_iterator i;
-    for (i = list.begin(); i != list.end(); i++)
+    for (i = list.begin(); i != list.end(); ++i)
     {
     {
         fprintf(file, format, *i);
         fprintf(file, format, *i);
     }
     }
@@ -36,7 +40,7 @@ void fprintfElement(FILE* file, const char* format, const char* elementName, std
 {
 {
     fprintf(file, "<%s>", elementName);
     fprintf(file, "<%s>", elementName);
     typename std::list<T>::const_iterator i;
     typename std::list<T>::const_iterator i;
-    for (i = list.begin(); i != list.end(); i++)
+    for (i = list.begin(); i != list.end(); ++i)
     {
     {
         fprintf(file, format, *i);
         fprintf(file, format, *i);
     }
     }
@@ -47,6 +51,7 @@ void fprintfMatrix4f(FILE* file, const float* m);
 
 
 /**
 /**
  * Writes binary data to the given file stream.
  * Writes binary data to the given file stream.
+ * 
  * @param value The value to be written
  * @param value The value to be written
  * @param file The binary file stream.
  * @param file The binary file stream.
  */
  */
@@ -59,6 +64,7 @@ void write(unsigned short value, FILE* file);
 void write(bool value, FILE* file);
 void write(bool value, FILE* file);
 void write(float value, FILE* file);
 void write(float value, FILE* file);
 void write(const float* values, int length, FILE* file);
 void write(const float* values, int length, FILE* file);
+
 /**
 /**
  * Writes the length of the string and the string bytes to the binary file stream.
  * Writes the length of the string and the string bytes to the binary file stream.
  */
  */
@@ -68,6 +74,7 @@ void writeZero(FILE* file);
 
 
 /**
 /**
  * Writes the length of the list and writes each element value to the binary file stream.
  * Writes the length of the list and writes each element value to the binary file stream.
+ * 
  * @param list The list to write.
  * @param list The list to write.
  * @param file The binary file stream.
  * @param file The binary file stream.
  */
  */
@@ -78,7 +85,7 @@ void write(std::list<T> list, FILE* file)
     write(list.size(), file);
     write(list.size(), file);
     // Then write each element
     // Then write each element
     typename std::list<T>::const_iterator i;
     typename std::list<T>::const_iterator i;
-    for (i = list.begin(); i != list.end(); i++)
+    for (i = list.begin(); i != list.end(); ++i)
     {
     {
         write(*i, file);
         write(*i, file);
     }
     }
@@ -86,6 +93,7 @@ void write(std::list<T> list, FILE* file)
 
 
 /**
 /**
  * Writes the length of the vector and writes each element value to the binary file stream.
  * Writes the length of the vector and writes each element value to the binary file stream.
+ * 
  * @param vector The vector to write.
  * @param vector The vector to write.
  * @param file The binary file stream.
  * @param file The binary file stream.
  */
  */
@@ -96,23 +104,35 @@ void write(std::vector<T> vector, FILE* file)
     write(vector.size(), file);
     write(vector.size(), file);
     // Then write each element
     // Then write each element
     typename std::vector<T>::const_iterator i;
     typename std::vector<T>::const_iterator i;
-    for (i = vector.begin(); i != vector.end(); i++)
+    for (i = vector.begin(); i != vector.end(); ++i)
     {
     {
         write(*i, file);
         write(*i, file);
     }
     }
 }
 }
 
 
-
 /**
 /**
  * Skips over the string at the current file stream offset by moving the file position.
  * Skips over the string at the current file stream offset by moving the file position.
  * Assumes the current position points to the unsigned int length of the string.
  * Assumes the current position points to the unsigned int length of the string.
  * The string is assumed to be a char array.
  * The string is assumed to be a char array.
- * @param The file stream.
+ * 
+ * @param file The file stream.
  */
  */
 void skipString(FILE* file);
 void skipString(FILE* file);
 
 
 void skipUint(FILE* file);
 void skipUint(FILE* file);
 
 
+void writeVectorBinary(const Vector2& v, FILE* file);
+
+void writeVectorText(const Vector2& v, FILE* file);
+
+void writeVectorBinary(const Vector3& v, FILE* file);
+
+void writeVectorText(const Vector3& v, FILE* file);
+
+void writeVectorBinary(const Vector4& v, FILE* file);
+
+void writeVectorText(const Vector4& v, FILE* file);
+
 }
 }
 #endif
 #endif
 
 

+ 2 - 2
gameplay-encoder/src/GPBDecoder.cpp

@@ -42,7 +42,7 @@ bool GPBDecoder::validateHeading()
     const char identifier[] = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' };
     const char identifier[] = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' };
 
 
     char heading[HEADING_SIZE];
     char heading[HEADING_SIZE];
-    for (size_t i = 0; i < HEADING_SIZE; i++)
+    for (size_t i = 0; i < HEADING_SIZE; ++i)
     {
     {
         if (heading[i] != identifier[i])
         if (heading[i] != identifier[i])
         {
         {
@@ -63,7 +63,7 @@ void GPBDecoder::readRefs()
     // read number of refs
     // read number of refs
     unsigned int refCount;
     unsigned int refCount;
     assert(read(&refCount));
     assert(read(&refCount));
-    for (size_t i = 0; i < refCount; i++)
+    for (size_t i = 0; i < refCount; ++i)
     {
     {
         readRef();
         readRef();
     }
     }

+ 0 - 4
gameplay-encoder/src/GPBDecoder.h

@@ -1,7 +1,3 @@
-/*
- * GamePlayFile.h
- */
-
 #ifndef GPBDECODER_H_
 #ifndef GPBDECODER_H_
 #define GPBDECODER_H_
 #define GPBDECODER_H_
 
 

+ 17 - 10
gameplay-encoder/src/GPBFile.cpp

@@ -28,14 +28,14 @@ void GPBFile::saveBinary(const std::string& filepath)
 
 
     // meshes
     // meshes
     write(_geometry.size(), _file);
     write(_geometry.size(), _file);
-    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); i++)
+    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
     {
     {
         (*i)->writeBinary(_file);
         (*i)->writeBinary(_file);
     }
     }
 
 
     // Objects
     // Objects
     write(_objects.size(), _file);
     write(_objects.size(), _file);
-    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); i++)
+    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
     {
     {
         (*i)->writeBinary(_file);
         (*i)->writeBinary(_file);
     }
     }
@@ -55,13 +55,13 @@ void GPBFile::saveText(const std::string& filepath)
     _refTable.writeText(_file);
     _refTable.writeText(_file);
 
 
     // meshes
     // meshes
-    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); i++)
+    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
     {
     {
         (*i)->writeText(_file);
         (*i)->writeText(_file);
     }
     }
 
 
     // Objects
     // Objects
-    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); i++)
+    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
     {
     {
         (*i)->writeText(_file);
         (*i)->writeText(_file);
     }
     }
@@ -146,8 +146,10 @@ bool GPBFile::idExists(const std::string& id)
 
 
 Camera* GPBFile::getCamera(const char* id)
 Camera* GPBFile::getCamera(const char* id)
 {
 {
+    if (!id)
+        return NULL;
     // TODO: O(n) search is not ideal
     // TODO: O(n) search is not ideal
-    for (std::list<Camera*>::const_iterator i = _cameras.begin(); i != _cameras.end(); i++)
+    for (std::list<Camera*>::const_iterator i = _cameras.begin(); i != _cameras.end(); ++i)
     {
     {
         const std::string& _id = (*i)->getId();
         const std::string& _id = (*i)->getId();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -160,8 +162,10 @@ Camera* GPBFile::getCamera(const char* id)
 
 
 Light* GPBFile::getLight(const char* id)
 Light* GPBFile::getLight(const char* id)
 {
 {
+    if (!id)
+        return NULL;
     // TODO: O(n) search is not ideal
     // TODO: O(n) search is not ideal
-    for (std::list<Light*>::const_iterator i = _lights.begin(); i != _lights.end(); i++)
+    for (std::list<Light*>::const_iterator i = _lights.begin(); i != _lights.end(); ++i)
     {
     {
         const std::string& _id = (*i)->getId();
         const std::string& _id = (*i)->getId();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -174,8 +178,10 @@ Light* GPBFile::getLight(const char* id)
 
 
 Mesh* GPBFile::getMesh(const char* id)
 Mesh* GPBFile::getMesh(const char* id)
 {
 {
+    if (!id)
+        return NULL;
     // TODO: O(n) search is not ideal
     // TODO: O(n) search is not ideal
-    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); i++)
+    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
     {
     {
         const std::string& _id = (*i)->getId();
         const std::string& _id = (*i)->getId();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -188,8 +194,10 @@ Mesh* GPBFile::getMesh(const char* id)
 
 
 Node* GPBFile::getNode(const char* id)
 Node* GPBFile::getNode(const char* id)
 {
 {
+    if (!id)
+        return NULL;
     // TODO: O(n) search is not ideal
     // TODO: O(n) search is not ideal
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); i++)
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
     {
     {
         const std::string& _id = (*i)->getId();
         const std::string& _id = (*i)->getId();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -203,7 +211,7 @@ Node* GPBFile::getNode(const char* id)
 void GPBFile::adjust()
 void GPBFile::adjust()
 {
 {
     // calculate the ambient color for each scene
     // calculate the ambient color for each scene
-    for (std::list<Object*>::iterator i = _objects.begin(); i != _objects.end(); i++)
+    for (std::list<Object*>::iterator i = _objects.begin(); i != _objects.end(); ++i)
     {
     {
         Object* obj = *i;
         Object* obj = *i;
         if (obj->getTypeId() == Object::SCENE_ID)
         if (obj->getTypeId() == Object::SCENE_ID)
@@ -227,5 +235,4 @@ void GPBFile::adjust()
     //   This can be merged into one animation. Same for scale animations.
     //   This can be merged into one animation. Same for scale animations.
 }
 }
 
 
-
 }
 }

+ 0 - 4
gameplay-encoder/src/GPBFile.h

@@ -1,7 +1,3 @@
-/*
- * GPBFile.h
- */
-
 #ifndef GPBFILE_H_
 #ifndef GPBFILE_H_
 #define GPBFILE_H_
 #define GPBFILE_H_
 
 

+ 11 - 11
gameplay-encoder/src/Mesh.cpp

@@ -26,7 +26,7 @@ void Mesh::writeBinary(FILE* file)
     Object::writeBinary(file);
     Object::writeBinary(file);
     // vertex formats
     // vertex formats
     write(_vertexFormats.size(), file);
     write(_vertexFormats.size(), file);
-    for (std::vector<VertexElement>::iterator i = _vertexFormats.begin(); i != _vertexFormats.end(); i++)
+    for (std::vector<VertexElement>::iterator i = _vertexFormats.begin(); i != _vertexFormats.end(); ++i)
     {
     {
         i->writeBinary(file);
         i->writeBinary(file);
     }
     }
@@ -46,7 +46,7 @@ void Mesh::writeBinaryVertices(FILE* file)
         write(vertices.size() * vertex.byteSize(), file); // (vertex count) * (vertex size)
         write(vertices.size() * vertex.byteSize(), file); // (vertex count) * (vertex size)
 
 
         // for each vertex
         // for each vertex
-        for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); i++)
+        for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
         {
         {
             // Write this vertex
             // Write this vertex
             i->writeBinary(file);
             i->writeBinary(file);
@@ -73,7 +73,7 @@ void Mesh::writeText(FILE* file)
     // for each VertexFormat
     // for each VertexFormat
     if (vertices.size() > 0 )
     if (vertices.size() > 0 )
     {
     {
-        for (std::vector<VertexElement>::iterator i = _vertexFormats.begin(); i != _vertexFormats.end(); i++)
+        for (std::vector<VertexElement>::iterator i = _vertexFormats.begin(); i != _vertexFormats.end(); ++i)
         {
         {
             i->writeText(file);
             i->writeText(file);
         }
         }
@@ -81,7 +81,7 @@ void Mesh::writeText(FILE* file)
 
 
     // for each Vertex
     // for each Vertex
     fprintf(file, "<vertices count=\"%lu\">\n", vertices.size());
     fprintf(file, "<vertices count=\"%lu\">\n", vertices.size());
-    for (std::vector<Vertex>::iterator i = vertices.begin(); i != vertices.end(); i++)
+    for (std::vector<Vertex>::iterator i = vertices.begin(); i != vertices.end(); ++i)
     {
     {
         i->writeText(file);
         i->writeText(file);
     }
     }
@@ -91,19 +91,19 @@ void Mesh::writeText(FILE* file)
     computeBounds();
     computeBounds();
     fprintf(file, "<bounds>\n");
     fprintf(file, "<bounds>\n");
     fprintf(file, "<min>\n");
     fprintf(file, "<min>\n");
-    bounds.min.writeText(file);
+    writeVectorText(bounds.min, file);
     fprintf(file, "</min>\n");
     fprintf(file, "</min>\n");
     fprintf(file, "<max>\n");
     fprintf(file, "<max>\n");
-    bounds.max.writeText(file);
+    writeVectorText(bounds.max, file);
     fprintf(file, "</max>\n");
     fprintf(file, "</max>\n");
     fprintf(file, "<center>\n");
     fprintf(file, "<center>\n");
-    bounds.center.writeText(file);
+    writeVectorText(bounds.center, file);
     fprintf(file, "</center>\n");
     fprintf(file, "</center>\n");
     fprintf(file, "<radius>%f</radius>\n", bounds.radius);
     fprintf(file, "<radius>%f</radius>\n", bounds.radius);
     fprintf(file, "</bounds>\n");
     fprintf(file, "</bounds>\n");
 
 
     // for each MeshPart
     // for each MeshPart
-    for (std::vector<MeshPart*>::iterator i = parts.begin(); i != parts.end(); i++)
+    for (std::vector<MeshPart*>::iterator i = parts.begin(); i != parts.end(); ++i)
     {
     {
         (*i)->writeText(file);
         (*i)->writeText(file);
     }
     }
@@ -161,7 +161,7 @@ void Mesh::computeBounds()
     
     
     // for each vertex
     // for each vertex
     Vector3 avgPos;
     Vector3 avgPos;
-    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); i++)
+    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
     {
     {
         // Update min/max for this vertex
         // Update min/max for this vertex
         if (i->position.x < bounds.min.x)
         if (i->position.x < bounds.min.x)
@@ -189,9 +189,9 @@ void Mesh::computeBounds()
 
 
     // Compute radius by looping through all points again and finding the max
     // Compute radius by looping through all points again and finding the max
     // distance between the center point and each vertex position
     // distance between the center point and each vertex position
-    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); i++)
+    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
     {
     {
-        float d = Vector3::distanceSquared(bounds.center, i->position);
+        float d = bounds.center.distanceSquared(i->position);
         if (d > bounds.radius)
         if (d > bounds.radius)
         {
         {
             bounds.radius = d;
             bounds.radius = d;

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

@@ -31,7 +31,7 @@ void MeshPart::writeBinary(FILE* file)
     // write the number of bytes
     // write the number of bytes
     write(indicesByteSize(), file);
     write(indicesByteSize(), file);
     // for each index
     // for each index
-    for (std::vector<unsigned int>::const_iterator i = _indices.begin(); i != _indices.end(); i++)
+    for (std::vector<unsigned int>::const_iterator i = _indices.begin(); i != _indices.end(); ++i)
     {
     {
         writeBinaryIndex(*i, file);
         writeBinaryIndex(*i, file);
     }
     }

+ 9 - 8
gameplay-encoder/src/MeshSkin.cpp

@@ -1,6 +1,7 @@
 #include "MeshSkin.h"
 #include "MeshSkin.h"
 #include "Node.h"
 #include "Node.h"
 #include "StringUtil.h"
 #include "StringUtil.h"
+#include "Matrix.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -8,7 +9,7 @@ namespace gameplay
 MeshSkin::MeshSkin(void) :
 MeshSkin::MeshSkin(void) :
     _vertexInfluenceCount(0)
     _vertexInfluenceCount(0)
 {
 {
-    setIdentityMatrix(_bindShape);
+    Matrix::setIdentity(_bindShape);
 }
 }
 
 
 MeshSkin::~MeshSkin(void)
 MeshSkin::~MeshSkin(void)
@@ -30,7 +31,7 @@ void MeshSkin::writeBinary(FILE* file)
     Object::writeBinary(file);
     Object::writeBinary(file);
     write(_bindShape, 16, file);
     write(_bindShape, 16, file);
     write(_joints.size(), file);
     write(_joints.size(), file);
-    for (std::list<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); i++)
+    for (std::list<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); ++i)
     {
     {
         (*i)->writeBinaryXref(file);
         (*i)->writeBinaryXref(file);
     }
     }
@@ -44,13 +45,13 @@ void MeshSkin::writeText(FILE* file)
     fprintfMatrix4f(file, _bindShape);
     fprintfMatrix4f(file, _bindShape);
     fprintf(file, "</bindShape>");
     fprintf(file, "</bindShape>");
     fprintf(file, "<joints>");
     fprintf(file, "<joints>");
-    for (std::list<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); i++)
+    for (std::list<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
     {
     {
         fprintf(file, "%s ", i->c_str());
         fprintf(file, "%s ", i->c_str());
     }
     }
     fprintf(file, "</joints>\n");
     fprintf(file, "</joints>\n");
     fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size());
     fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size());
-    for (std::list<float>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); i++)
+    for (std::list<float>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
     {
     {
         fprintf(file, "%f ", *i);
         fprintf(file, "%f ", *i);
     }
     }
@@ -60,7 +61,7 @@ void MeshSkin::writeText(FILE* file)
 
 
 void MeshSkin::setBindShape(const float data[])
 void MeshSkin::setBindShape(const float data[])
 {
 {
-    for (int i = 0; i < 16; i++)
+    for (int i = 0; i < 16; ++i)
     {
     {
         _bindShape[i] = data[i];
         _bindShape[i] = data[i];
     }
     }
@@ -88,10 +89,10 @@ void MeshSkin::setJoints(const std::list<Node*>& list)
 
 
 void MeshSkin::setBindPoses(std::vector<Matrix>& list)
 void MeshSkin::setBindPoses(std::vector<Matrix>& list)
 {
 {
-    for (std::vector<Matrix>::iterator i = list.begin(); i != list.end(); i++)
+    for (std::vector<Matrix>::iterator i = list.begin(); i != list.end(); ++i)
     {
     {
         float* a = i->m;
         float* a = i->m;
-        for (int j = 0; j < 16; j++)
+        for (int j = 0; j < 16; ++j)
         {
         {
             _bindPoses.push_back(a[j]);
             _bindPoses.push_back(a[j]);
         }
         }
@@ -100,7 +101,7 @@ void MeshSkin::setBindPoses(std::vector<Matrix>& list)
 
 
 bool MeshSkin::hasJoint(const char* id)
 bool MeshSkin::hasJoint(const char* id)
 {
 {
-    for (std::list<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); i++)
+    for (std::list<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
     {
     {
         if (equals(*i, id))
         if (equals(*i, id))
         {
         {

+ 2 - 2
gameplay-encoder/src/MeshSkin.h

@@ -32,14 +32,14 @@ public:
     virtual void writeBinary(FILE* file);
     virtual void writeBinary(FILE* file);
     virtual void writeText(FILE* file);
     virtual void writeText(FILE* file);
 
 
+    const std::list<std::string>& getJointNames();
+
     void setBindShape(const float data[]);
     void setBindShape(const float data[]);
 
 
     void setVertexInfluenceCount(unsigned int count);
     void setVertexInfluenceCount(unsigned int count);
 
 
     void setJointNames(const std::list<std::string>& list);
     void setJointNames(const std::list<std::string>& list);
 
 
-    const std::list<std::string>& getJointNames();
-
     void setJoints(const std::list<Node*>& list);
     void setJoints(const std::list<Node*>& list);
 
 
     void setBindPoses(std::vector<Matrix>& list);
     void setBindPoses(std::vector<Matrix>& list);

+ 8 - 2
gameplay-encoder/src/Node.cpp

@@ -1,4 +1,5 @@
 #include "Node.h"
 #include "Node.h"
+#include "Matrix.h"
 
 
 #define NODE 1
 #define NODE 1
 #define JOINT 2
 #define JOINT 2
@@ -12,7 +13,7 @@ Node::Node(void) :
     _firstChild(NULL), _lastChild(NULL), _parent(NULL),
     _firstChild(NULL), _lastChild(NULL), _parent(NULL),
     _camera(NULL), _light(NULL), _model(NULL), _joint(false)
     _camera(NULL), _light(NULL), _model(NULL), _joint(false)
 {
 {
-    setIdentityMatrix(_transform);
+    Matrix::setIdentity(_transform);
 }
 }
 
 
 Node::~Node(void)
 Node::~Node(void)
@@ -234,12 +235,17 @@ void Node::setModel(Model* model)
 
 
 void Node::setTransformMatrix(float matrix[])
 void Node::setTransformMatrix(float matrix[])
 {
 {
-    for (int i = 0; i < 16; i++)
+    for (int i = 0; i < 16; ++i)
     {
     {
         _transform[i] = matrix[i];
         _transform[i] = matrix[i];
     }
     }
 }
 }
 
 
+void Node::resetTransformMatrix()
+{
+    Matrix::setIdentity(_transform);
+}
+
 void Node::setIsJoint(bool value)
 void Node::setIsJoint(bool value)
 {
 {
     _joint = value;
     _joint = value;

+ 5 - 0
gameplay-encoder/src/Node.h

@@ -130,6 +130,11 @@ public:
      */
      */
     void setTransformMatrix(float matrix[]);
     void setTransformMatrix(float matrix[]);
 
 
+    /**
+     * Resets the node's transform matrix to the identity matrix.
+     */
+    void resetTransformMatrix();
+
     void setCameraInstance(CameraInstance* cameraInstance);
     void setCameraInstance(CameraInstance* cameraInstance);
     void setLightInstance(LightInstance* lightInstance);
     void setLightInstance(LightInstance* lightInstance);
     void setModel(Model* model);
     void setModel(Model* model);

+ 2 - 2
gameplay-encoder/src/Object.h

@@ -114,7 +114,7 @@ public:
         write(list.size(), file);
         write(list.size(), file);
         // Then write each element
         // Then write each element
         typename std::list<T>::const_iterator i;
         typename std::list<T>::const_iterator i;
-        for (i = list.begin(); i != list.end(); i++)
+        for (i = list.begin(); i != list.end(); ++i)
         {
         {
             (*i)->writeBinary(file);
             (*i)->writeBinary(file);
         }
         }
@@ -130,7 +130,7 @@ public:
         write(vector.size(), file);
         write(vector.size(), file);
         // Then write each element
         // Then write each element
         typename std::vector<T>::const_iterator i;
         typename std::vector<T>::const_iterator i;
-        for (i = vector.begin(); i != vector.end(); i++)
+        for (i = vector.begin(); i != vector.end(); ++i)
         {
         {
             (*i)->writeBinary(file);
             (*i)->writeBinary(file);
         }
         }

+ 0 - 4
gameplay-encoder/src/Quaternion.cpp

@@ -1,7 +1,3 @@
-/*
- * Quaternion.cpp
- */
-
 #include "Base.h"
 #include "Base.h"
 #include "Quaternion.h"
 #include "Quaternion.h"
 
 

+ 0 - 4
gameplay-encoder/src/Quaternion.h

@@ -1,7 +1,3 @@
-/*
- * Quaternion.h
- */
-
 #ifndef QUATERNION_H_
 #ifndef QUATERNION_H_
 #define QUATERNION_H_
 #define QUATERNION_H_
 
 

+ 3 - 3
gameplay-encoder/src/ReferenceTable.cpp

@@ -30,7 +30,7 @@ Object* ReferenceTable::get(const std::string& xref)
 void ReferenceTable::writeBinary(FILE* file)
 void ReferenceTable::writeBinary(FILE* file)
 {
 {
     write(_table.size(), file);
     write(_table.size(), file);
-    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); i++ )
+    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); ++i)
     {
     {
         i->second.writeBinary(file);
         i->second.writeBinary(file);
     }
     }
@@ -39,7 +39,7 @@ void ReferenceTable::writeBinary(FILE* file)
 void ReferenceTable::writeText(FILE* file)
 void ReferenceTable::writeText(FILE* file)
 {
 {
     fprintf(file, "<RefTable>\n");
     fprintf(file, "<RefTable>\n");
-    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); i++ )
+    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); ++i)
     {
     {
         i->second.writeText(file);
         i->second.writeText(file);
     }
     }
@@ -48,7 +48,7 @@ void ReferenceTable::writeText(FILE* file)
 
 
 void ReferenceTable::updateOffsets(FILE* file)
 void ReferenceTable::updateOffsets(FILE* file)
 {
 {
-    for (std::map<std::string, Reference>::iterator i = _table.begin(); i != _table.end(); i++)
+    for (std::map<std::string, Reference>::iterator i = _table.begin(); i != _table.end(); ++i)
     {
     {
         Reference& ref = i->second;
         Reference& ref = i->second;
         ref.updateOffset(file);
         ref.updateOffset(file);

+ 10 - 3
gameplay-encoder/src/Scene.cpp

@@ -43,7 +43,7 @@ void Scene::writeBinary(FILE* file)
 void Scene::writeText(FILE* file)
 void Scene::writeText(FILE* file)
 {
 {
     fprintElementStart(file);
     fprintElementStart(file);
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); i++)
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
     {
     {
         (*i)->writeText(file);
         (*i)->writeText(file);
     }
     }
@@ -67,7 +67,7 @@ void Scene::setActiveCameraNode(Node* node)
 
 
 Node* Scene::getFirstCameraNode() const
 Node* Scene::getFirstCameraNode() const
 {
 {
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); i++)
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
     {
     {
         Node* n = (*i)->getFirstCameraNode();
         Node* n = (*i)->getFirstCameraNode();
         if (n)
         if (n)
@@ -81,7 +81,7 @@ Node* Scene::getFirstCameraNode() const
 void Scene::calcAmbientColor()
 void Scene::calcAmbientColor()
 {
 {
     float values[3] = {0.0f, 0.0f, 0.0f};
     float values[3] = {0.0f, 0.0f, 0.0f};
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); i++)
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
     {
     {
         calcAmbientColor(*i, values);
         calcAmbientColor(*i, values);
     }
     }
@@ -91,6 +91,13 @@ void Scene::calcAmbientColor()
     _ambientColor[2] = std::min(values[2], 1.0f);
     _ambientColor[2] = std::min(values[2], 1.0f);
 }
 }
 
 
+void Scene::setAmbientColor(float red, float green, float blue)
+{
+    _ambientColor[0] = red;
+    _ambientColor[1] = green;
+    _ambientColor[2] = blue;
+}
+
 void Scene::calcAmbientColor(const Node* node, float* values) const
 void Scene::calcAmbientColor(const Node* node, float* values) const
 {
 {
     if (!node)
     if (!node)

+ 6 - 1
gameplay-encoder/src/Scene.h

@@ -50,6 +50,11 @@ public:
      */
      */
     void calcAmbientColor();
     void calcAmbientColor();
 
 
+    /**
+     * Sets the scene's ambient color.
+     */
+    void setAmbientColor(float red, float green, float blue);
+
 private:
 private:
 
 
     /**
     /**
@@ -68,4 +73,4 @@ private:
 };
 };
 
 
 }
 }
-#endif
+#endif

+ 20 - 1
gameplay-encoder/src/StringUtil.cpp

@@ -90,7 +90,7 @@ bool equalsIgnoreCase(const std::string& a, const char* b)
     {
     {
         return false;
         return false;
     }
     }
-    for (size_t i = 0; i < bLength; i++)
+    for (size_t i = 0; i < bLength; ++i)
     {
     {
         if (lowercase(a[i]) != lowercase(b[i]))
         if (lowercase(a[i]) != lowercase(b[i]))
         {
         {
@@ -100,4 +100,23 @@ bool equalsIgnoreCase(const std::string& a, const char* b)
     return true;
     return true;
 }
 }
 
 
+std::string getFilenameFromFilePath(const std::string& filepath)
+{
+    if (filepath.find_last_of("/") != std::string::npos)
+    {
+        return filepath.substr(filepath.find_last_of("/")+1);
+    }
+    return "";
+}
+
+
+std::string getFilenameNoExt(const std::string& filename)
+{
+    if (filename.find_last_of(".") != std::string::npos)
+    {
+        return filename.substr(0, filename.find_last_of("."));
+    }
+    return filename;
+}
+
 }
 }

+ 5 - 1
gameplay-encoder/src/StringUtil.h

@@ -19,5 +19,9 @@ bool equals(const std::string& a, const char* b);
  */
  */
 bool equalsIgnoreCase(const std::string& a, const char* b);
 bool equalsIgnoreCase(const std::string& a, const char* b);
 
 
+std::string getFilenameFromFilePath(const std::string& filepath);
+
+std::string getFilenameNoExt(const std::string& filename);
+
 }
 }
-#endif
+#endif

+ 4 - 4
gameplay-encoder/src/TTFFontEncoder.cpp

@@ -6,7 +6,7 @@ void drawBitmap(unsigned char* dstBitmap, int x, int y, int dstWidth, unsigned c
     // offset dst bitmap by x,y.
     // offset dst bitmap by x,y.
     dstBitmap +=  (x + (y * dstWidth));
     dstBitmap +=  (x + (y * dstWidth));
 
 
-    for (int i = 0; i < srcHeight; i++)
+    for (int i = 0; i < srcHeight; ++i)
     {
     {
         memcpy(dstBitmap, (const void*)srcBitmap, srcWidth);
         memcpy(dstBitmap, (const void*)srcBitmap, srcWidth);
         srcBitmap += srcWidth;
         srcBitmap += srcWidth;
@@ -87,7 +87,7 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     int rowSize = 0; // Stores the total number of rows required to all glyphs.
     int rowSize = 0; // Stores the total number of rows required to all glyphs.
     
     
     // Find the width of the image.
     // Find the width of the image.
-    for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ascii++)
+    for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
     {
     {
         // Load glyph image into the slot (erase previous one)
         // Load glyph image into the slot (erase previous one)
         error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
         error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
@@ -132,7 +132,7 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
 
 
         // Find out the squared texture size that would fit all the require font glyphs.
         // Find out the squared texture size that would fit all the require font glyphs.
         i = 0;
         i = 0;
-        for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ascii++)
+        for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
         {
         {
             // Load glyph image into the slot (erase the previous one).
             // Load glyph image into the slot (erase the previous one).
             error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
             error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
@@ -199,7 +199,7 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     penY = 0;
     penY = 0;
     row = 0;
     row = 0;
     i = 0;
     i = 0;
-    for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ascii++)
+    for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
     {
     {
         // Load glyph image into the slot (erase the previous one).
         // Load glyph image into the slot (erase the previous one).
         error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
         error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);

+ 20 - 16
gameplay-encoder/src/Transform.h

@@ -14,37 +14,41 @@ public:
          * Scale animation property. Data=sx,sy,sz
          * Scale animation property. Data=sx,sy,sz
          */
          */
         ANIMATE_SCALE = 1,
         ANIMATE_SCALE = 1,
-        ANIMATE_SCALE_X,
-        ANIMATE_SCALE_Y,
-        ANIMATE_SCALE_Z,
-        ANIMATE_SCALE_XY,
-        ANIMATE_SCALE_XZ,
-        ANIMATE_SCALE_YZ,
+        ANIMATE_SCALE_X = 2,
+        ANIMATE_SCALE_Y = 3,
+        ANIMATE_SCALE_Z = 4,
+        ANIMATE_SCALE_XY = 5,
+        ANIMATE_SCALE_XZ = 6,
+        ANIMATE_SCALE_YZ = 7,
 
 
         /**
         /**
          * Rotation animation property. Data=qx,qy,qz,qw (as quaternion).
          * Rotation animation property. Data=qx,qy,qz,qw (as quaternion).
          */
          */
-        ANIMATE_ROTATE,
+        ANIMATE_ROTATE = 8,
 
 
         /**
         /**
          * Translation animation property. Data=tx,ty,tz
          * Translation animation property. Data=tx,ty,tz
          */
          */
-        ANIMATE_TRANSLATE,
-        ANIMATE_TRANSLATE_X,
-        ANIMATE_TRANSLATE_Y,
-        ANIMATE_TRANSLATE_Z,
-        ANIMATE_TRANSLATE_XY,
-        ANIMATE_TRANSLATE_XZ,
-        ANIMATE_TRANSLATE_YZ,
+        ANIMATE_TRANSLATE = 9,
+        ANIMATE_TRANSLATE_X = 10,
+        ANIMATE_TRANSLATE_Y = 11,
+        ANIMATE_TRANSLATE_Z = 12,
+        ANIMATE_TRANSLATE_XY = 13,
+        ANIMATE_TRANSLATE_XZ = 14,
+        ANIMATE_TRANSLATE_YZ = 15,
 
 
         /**
         /**
          * Rotation + Translation animation property(Rigid Body). Data=qx,qy,qz,qw,tx,ty,tz
          * Rotation + Translation animation property(Rigid Body). Data=qx,qy,qz,qw,tx,ty,tz
          */
          */
-        ANIMATE_ROTATE_TRANSLATE,
+        ANIMATE_ROTATE_TRANSLATE = 16,
         /**
         /**
          * Scale, Rotation + Translation animation property. Data=sx,sy,sz,qx,qy,qz,qw,tx,ty,tz
          * Scale, Rotation + Translation animation property. Data=sx,sy,sz,qx,qy,qz,qw,tx,ty,tz
          */
          */
-        ANIMATE_SCALE_ROTATE_TRANSLATE
+        ANIMATE_SCALE_ROTATE_TRANSLATE = 17,
+
+        ANIMATE_ROTATE_X = 18,
+        ANIMATE_ROTATE_Y = 19,
+        ANIMATE_ROTATE_Z = 20
     };
     };
 };
 };
 
 

+ 17 - 69
gameplay-encoder/src/Vector2.cpp

@@ -1,10 +1,5 @@
-/*
- * Vector2.cpp
- */
-
 #include "Base.h"
 #include "Base.h"
 #include "Vector2.h"
 #include "Vector2.h"
-#include "FileIO.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -14,90 +9,76 @@ Vector2::Vector2()
 {
 {
 }
 }
 
 
-
 Vector2::Vector2(float x, float y)
 Vector2::Vector2(float x, float y)
 {
 {
     set(x, y);
     set(x, y);
 }
 }
 
 
-
 Vector2::Vector2(float* array)
 Vector2::Vector2(float* array)
 {
 {
     set(array);
     set(array);
 }
 }
 
 
-
 Vector2::Vector2(const Vector2& p1, const Vector2& p2)
 Vector2::Vector2(const Vector2& p1, const Vector2& p2)
 {
 {
     set(p1, p2);
     set(p1, p2);
 }
 }
 
 
-
 Vector2::Vector2(const Vector2& copy)
 Vector2::Vector2(const Vector2& copy)
 {
 {
     set(copy);
     set(copy);
 }
 }
 
 
-
 Vector2::~Vector2()
 Vector2::~Vector2()
 {
 {
 }
 }
 
 
-
 const Vector2& Vector2::zero()
 const Vector2& Vector2::zero()
 {
 {
-    static Vector2* value = new Vector2(0.0f, 0.0f);
-    return *value;
+    static Vector2 value(0.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector2& Vector2::one()
 const Vector2& Vector2::one()
 {
 {
-    static Vector2* value = new Vector2(1.0f, 1.0f);
-    return *value;
+    static Vector2 value(1.0f, 1.0f);
+    return value;
 }
 }
 
 
-
 const Vector2& Vector2::unitX()
 const Vector2& Vector2::unitX()
 {
 {
-    static Vector2* value = new Vector2(1.0f, 0.0f);
-    return *value;
+    static Vector2 value(1.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector2& Vector2::unitY()
 const Vector2& Vector2::unitY()
 {
 {
-    static Vector2* value = new Vector2(0.0f, 1.0f);
-    return *value;
+    static Vector2 value(0.0f, 1.0f);
+    return value;
 }
 }
 
 
-
 bool Vector2::isZero() const
 bool Vector2::isZero() const
 {
 {
     return x == 0.0f && y == 0.0f;
     return x == 0.0f && y == 0.0f;
 }
 }
 
 
-
 bool Vector2::isOne() const
 bool Vector2::isOne() const
 {
 {
     return x == 1.0f && y == 1.0f;
     return x == 1.0f && y == 1.0f;
 }
 }
 
 
-
 float Vector2::angle(const Vector2& v1, const Vector2& v2)
 float Vector2::angle(const Vector2& v1, const Vector2& v2)
 {
 {
     float dz = v1.x * v2.y - v1.y * v2.x;
     float dz = v1.x * v2.y - v1.y * v2.x;
     return atan2f(fabsf(dz) + MATH_FLOAT_SMALL, dot(v1, v2));
     return atan2f(fabsf(dz) + MATH_FLOAT_SMALL, dot(v1, v2));
 }
 }
 
 
-
 void Vector2::add(const Vector2& v)
 void Vector2::add(const Vector2& v)
 {
 {
     x += v.x;
     x += v.x;
     y += v.y;
     y += v.y;
 }
 }
 
 
-
 void Vector2::add(const Vector2& v1, const Vector2& v2, Vector2* dst)
 void Vector2::add(const Vector2& v1, const Vector2& v2, Vector2* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -106,7 +87,6 @@ void Vector2::add(const Vector2& v1, const Vector2& v2, Vector2* dst)
     dst->y = v1.y + v2.y;
     dst->y = v1.y + v2.y;
 }
 }
 
 
-
 void Vector2::clamp(const Vector2& min, const Vector2& max)
 void Vector2::clamp(const Vector2& min, const Vector2& max)
 {
 {
     assert(!( min.x > max.x || min.y > max.y ));
     assert(!( min.x > max.x || min.y > max.y ));
@@ -124,13 +104,12 @@ void Vector2::clamp(const Vector2& min, const Vector2& max)
         y = max.y;
         y = max.y;
 }
 }
 
 
-
 void Vector2::clamp(const Vector2& v, const Vector2& min, const Vector2& max, Vector2* dst)
 void Vector2::clamp(const Vector2& v, const Vector2& min, const Vector2& max, Vector2* dst)
 {
 {
     assert(dst);
     assert(dst);
     assert(!( min.x > max.x || min.y > max.y ));
     assert(!( min.x > max.x || min.y > max.y ));
 
 
-    // Clamp the y value.
+    // Clamp the x value.
     dst->x = v.x;
     dst->x = v.x;
     if ( dst->x < min.x )
     if ( dst->x < min.x )
         dst->x = min.x;
         dst->x = min.x;
@@ -145,8 +124,7 @@ void Vector2::clamp(const Vector2& v, const Vector2& min, const Vector2& max, Ve
         dst->y = max.y;
         dst->y = max.y;
 }
 }
 
 
-
-float Vector2::distance(const Vector2& v)
+float Vector2::distance(const Vector2& v) const
 {
 {
     float dx = v.x - x;
     float dx = v.x - x;
     float dy = v.y - y;
     float dy = v.y - y;
@@ -154,52 +132,44 @@ float Vector2::distance(const Vector2& v)
     return sqrtf(dx * dx + dy * dy);
     return sqrtf(dx * dx + dy * dy);
 }
 }
 
 
-
-float Vector2::distanceSquared(const Vector2& v)
+float Vector2::distanceSquared(const Vector2& v) const
 {
 {
     float dx = v.x - x;
     float dx = v.x - x;
     float dy = v.y - y;
     float dy = v.y - y;
     return (dx * dx + dy * dy);
     return (dx * dx + dy * dy);
 }
 }
 
 
-
 float Vector2::dot(const Vector2& v)
 float Vector2::dot(const Vector2& v)
 {
 {
     return (x * v.x + y * v.y);
     return (x * v.x + y * v.y);
 }
 }
 
 
-
 float Vector2::dot(const Vector2& v1, const Vector2& v2)
 float Vector2::dot(const Vector2& v1, const Vector2& v2)
 {
 {
     return (v1.x * v2.x + v1.y * v2.y);
     return (v1.x * v2.x + v1.y * v2.y);
 }
 }
 
 
-
-float Vector2::length()
+float Vector2::length() const
 {
 {
     return sqrtf(x * x + y * y);
     return sqrtf(x * x + y * y);
 }
 }
 
 
-
-float Vector2::lengthSquared()
+float Vector2::lengthSquared() const
 {
 {
     return (x * x + y * y);
     return (x * x + y * y);
 }
 }
 
 
-
 void Vector2::negate()
 void Vector2::negate()
 {
 {
     x = -x;
     x = -x;
     y = -y;
     y = -y;
 }
 }
 
 
-
 void Vector2::normalize()
 void Vector2::normalize()
 {
 {
     normalize(this);
     normalize(this);
 }
 }
 
 
-
 void Vector2::normalize(Vector2* dst)
 void Vector2::normalize(Vector2* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -211,12 +181,12 @@ void Vector2::normalize(Vector2* dst)
     }
     }
 
 
     float n = x * x + y * y;
     float n = x * x + y * y;
-    // already normalized
+    // Already normalized.
     if (n == 1.0f)
     if (n == 1.0f)
         return;
         return;
 
 
     n = sqrtf(n);
     n = sqrtf(n);
-    // too close to zero
+    // Too close to zero.
     if (n < MATH_TOLERANCE)
     if (n < MATH_TOLERANCE)
         return;
         return;
 
 
@@ -225,25 +195,22 @@ void Vector2::normalize(Vector2* dst)
     dst->y *= n;
     dst->y *= n;
 }
 }
 
 
-
 void Vector2::scale(float scalar)
 void Vector2::scale(float scalar)
 {
 {
     x *= scalar;
     x *= scalar;
     y *= scalar;
     y *= scalar;
 }
 }
 
 
-
 void Vector2::scale(const Vector2& scale)
 void Vector2::scale(const Vector2& scale)
 {
 {
     x *= scale.x;
     x *= scale.x;
     y *= scale.y;
     y *= scale.y;
 }
 }
 
 
-
 void Vector2::rotate(const Vector2& point, float angle)
 void Vector2::rotate(const Vector2& point, float angle)
 {
 {
-    float sinAngle = sin(angle);
-    float cosAngle = cos(angle);
+    double sinAngle = sin(angle);
+    double cosAngle = cos(angle);
 
 
     if (point.isZero())
     if (point.isZero())
     {
     {
@@ -261,14 +228,12 @@ void Vector2::rotate(const Vector2& point, float angle)
     }
     }
 }
 }
 
 
-
 void Vector2::set(float x, float y)
 void Vector2::set(float x, float y)
 {
 {
     this->x = x;
     this->x = x;
     this->y = y;
     this->y = y;
 }
 }
 
 
-
 void Vector2::set(float* array)
 void Vector2::set(float* array)
 {
 {
     assert(array);
     assert(array);
@@ -277,28 +242,24 @@ void Vector2::set(float* array)
     y = array[1];
     y = array[1];
 }
 }
 
 
-
 void Vector2::set(const Vector2& v)
 void Vector2::set(const Vector2& v)
 {
 {
     this->x = v.x;
     this->x = v.x;
     this->y = v.y;
     this->y = v.y;
 }
 }
 
 
-
 void Vector2::set(const Vector2& p1, const Vector2& p2)
 void Vector2::set(const Vector2& p1, const Vector2& p2)
 {
 {
      x = p2.x - p1.x;
      x = p2.x - p1.x;
      y = p2.y - p1.y;
      y = p2.y - p1.y;
 }
 }
 
 
-
 void Vector2::subtract(const Vector2& v)
 void Vector2::subtract(const Vector2& v)
 {
 {
     x -= v.x;
     x -= v.x;
     y -= v.y;
     y -= v.y;
 }
 }
 
 
-
 void Vector2::subtract(const Vector2& v1, const Vector2& v2, Vector2* dst)
 void Vector2::subtract(const Vector2& v1, const Vector2& v2, Vector2* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -307,17 +268,4 @@ void Vector2::subtract(const Vector2& v1, const Vector2& v2, Vector2* dst)
     dst->y = v1.y - v2.y;
     dst->y = v1.y - v2.y;
 }
 }
 
 
-void Vector2::writeBinary(FILE* file) const
-{
-    write(x, file);
-    write(y, file);
 }
 }
-
-void Vector2::writeText(FILE* file) const
-{
-    fprintf(file, "%f %f\n", x, y);
-}
-
-}
-
-

+ 109 - 38
gameplay-encoder/src/Vector2.h

@@ -1,14 +1,9 @@
-/*
- * Vector2.h
- */
-
 #ifndef VECTOR2_H_
 #ifndef VECTOR2_H_
 #define VECTOR2_H_
 #define VECTOR2_H_
 
 
-
 namespace gameplay
 namespace gameplay
 {
 {
-// Forward declare
+
 class Matrix;
 class Matrix;
 
 
 /**
 /**
@@ -69,44 +64,44 @@ public:
     ~Vector2();
     ~Vector2();
 
 
     /**
     /**
-     * The zero vector
+     * Returns the zero vector.
      *
      *
      * @return The 2-element vector of 0s.
      * @return The 2-element vector of 0s.
      */
      */
     static const Vector2& zero();
     static const Vector2& zero();
 
 
     /**
     /**
-     * The one vector.
+     * Returns the one vector.
      *
      *
      * @return The 2-element vector of 1s.
      * @return The 2-element vector of 1s.
      */
      */
     static const Vector2& one();
     static const Vector2& one();
 
 
     /**
     /**
-     * The unit x vector.
+     * Returns the unit x vector.
      *
      *
      * @return The 2-element unit vector along the x axis.
      * @return The 2-element unit vector along the x axis.
      */
      */
     static const Vector2& unitX();
     static const Vector2& unitX();
 
 
     /**
     /**
-     * The unit y vector.
+     * Returns the unit y vector.
      *
      *
      * @return The 2-element unit vector along the y axis.
      * @return The 2-element unit vector along the y axis.
      */
      */
     static const Vector2& unitY();
     static const Vector2& unitY();
 
 
     /**
     /**
-     * Is this vector the all zeros.
+     * Indicates whether this vector contains all zeros.
      *
      *
-     * @return true if all zeros, false if otherwise.
+     * @return true if this vector contains all zeros, false otherwise.
      */
      */
     bool isZero() const;
     bool isZero() const;
 
 
     /**
     /**
-     * Is this vector all ones.
+     * Indicates whether this vector contains all ones.
      *
      *
-     * @return true if all ones, false if otherwise.
+     * @return true if this vector contains all ones, false otherwise.
      */
      */
     bool isOne() const;
     bool isOne() const;
 
 
@@ -116,7 +111,7 @@ public:
      * @param v1 The first vector.
      * @param v1 The first vector.
      * @param v2 The second vector.
      * @param v2 The second vector.
      * 
      * 
-     * @return The angle between the two vectors, in radians.
+     * @return The angle between the two vectors (in radians).
      */
      */
     static float angle(const Vector2& v1, const Vector2& v2);
     static float angle(const Vector2& v1, const Vector2& v2);
 
 
@@ -160,9 +155,10 @@ public:
      * @param v The other vector.
      * @param v The other vector.
      * 
      * 
      * @return The distance between this vector and v.
      * @return The distance between this vector and v.
+     * 
      * @see distanceSquared
      * @see distanceSquared
      */
      */
-    float distance(const Vector2& v);
+    float distance(const Vector2& v) const;
 
 
     /**
     /**
      * Returns the squared distance between this vector and v.
      * Returns the squared distance between this vector and v.
@@ -175,9 +171,10 @@ public:
      * @param v The other vector.
      * @param v The other vector.
      * 
      * 
      * @return The squared distance between this vector and v.
      * @return The squared distance between this vector and v.
+     * 
      * @see distance
      * @see distance
      */
      */
-    float distanceSquared(const Vector2& v);
+    float distanceSquared(const Vector2& v) const;
 
 
     /**
     /**
      * Returns the dot product of this vector and the specified vector.
      * Returns the dot product of this vector and the specified vector.
@@ -202,9 +199,10 @@ public:
      * Computes the length of this vector.
      * Computes the length of this vector.
      *
      *
      * @return The length of the vector.
      * @return The length of the vector.
+     * 
      * @see lengthSquared
      * @see lengthSquared
      */
      */
-    float length();
+    float length() const;
 
 
     /**
     /**
      * Returns the squared length of this vector.
      * Returns the squared length of this vector.
@@ -215,9 +213,10 @@ public:
      * instead of length.
      * instead of length.
      *
      *
      * @return The squared length of the vector.
      * @return The squared length of the vector.
+     * 
      * @see length
      * @see length
      */
      */
-    float lengthSquared();
+    float lengthSquared() const;
 
 
     /**
     /**
      * Negates this vector.
      * Negates this vector.
@@ -242,7 +241,7 @@ public:
      * of the vector is zero, this method simply copies the
      * of the vector is zero, this method simply copies the
      * current vector into dst.
      * current vector into dst.
      *
      *
-     * @param dst the destination vector
+     * @param dst The destination vector.
      */
      */
     void normalize(Vector2* dst);
     void normalize(Vector2* dst);
 
 
@@ -264,7 +263,7 @@ public:
      * Rotates this vector by angle (specified in radians) around the given point.
      * Rotates this vector by angle (specified in radians) around the given point.
      *
      *
      * @param point The point to rotate around.
      * @param point The point to rotate around.
-     * @param angle The angle to rotate by, in radians.
+     * @param angle The angle to rotate by (in radians).
      */
      */
     void rotate(const Vector2& point, float angle);
     void rotate(const Vector2& point, float angle);
 
 
@@ -292,12 +291,15 @@ public:
 
 
     /**
     /**
      * Sets this vector to the directional vector between the specified points.
      * Sets this vector to the directional vector between the specified points.
+     * 
+     * @param p1 The first point.
+     * @param p2 The second point.
      */
      */
     void set(const Vector2& p1, const Vector2& p2);
     void set(const Vector2& p1, const Vector2& p2);
 
 
     /**
     /**
      * Subtracts this vector and the specified vector as (this - v)
      * Subtracts this vector and the specified vector as (this - v)
-     * and stores the result in this.
+     * and stores the result in this vector.
      *
      *
      * @param v The vector to subtract.
      * @param v The vector to subtract.
      */
      */
@@ -313,30 +315,99 @@ public:
      */
      */
     static void subtract(const Vector2& v1, const Vector2& v2, Vector2* dst);
     static void subtract(const Vector2& v1, const Vector2& v2, Vector2* dst);
 
 
-    inline bool operator<(const Vector2& v) const
-    {
-        if (x == v.x)
-        {
-            return y < v.y;
-        }
-        return x < v.x;
-    }
-    inline bool operator==(const Vector2& v) const
-    {
-        return x==v.x && y==v.y;
-    }
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector2 operator+(const Vector2& v);
+
+    /**
+     * Adds the given vector to this vector.
+     * 
+     * @param v The vector to add.
+     * @return This vector, after the addition occurs.
+     */
+    inline Vector2& operator+=(const Vector2& v);
 
 
     /**
     /**
-     * Writes this vector to the binary file stream.
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
      */
      */
-    void writeBinary(FILE* file) const;
+    inline Vector2 operator-(const Vector2& v);
 
 
     /**
     /**
-     * Writes this vector to a text file stream.
+     * Subtracts the given vector from this vector.
+     * 
+     * @param v The vector to subtract.
+     * @return This vector, after the subtraction occurs.
      */
      */
-    void writeText(FILE* file) const;
+    inline Vector2& operator-=(const Vector2& v);
+
+    /**
+     * Calculates the negation of this vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @return The negation of this vector.
+     */
+    inline Vector2 operator-();
+
+    /**
+     * Calculates the scalar product of this vector with the given value.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param x The value to scale by.
+     * @return The scaled vector.
+     */
+    inline Vector2 operator*(float x);
+
+    /**
+     * Scales this vector by the given value.
+     * 
+     * @param x The value to scale by.
+     * @return This vector, after the scale occurs.
+     */
+    inline Vector2& operator*=(float x);
+
+    /**
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
+     */
+    inline bool operator<(const Vector2& v) const;
+
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector2& v) const;
 };
 };
 
 
+/**
+ * Calculates the scalar product of the given vector with the given value.
+ * 
+ * @param x The value to scale by.
+ * @param v The vector to scale.
+ * @return The scaled vector.
+ */
+inline Vector2 operator*(float x, const Vector2& v);
+
 }
 }
 
 
+#include "Vector2.inl"
+
 #endif
 #endif

+ 77 - 0
gameplay-encoder/src/Vector2.inl

@@ -0,0 +1,77 @@
+/** 
+ * Vector2.inl
+ */
+
+#include "Vector2.h"
+
+namespace gameplay
+{
+
+inline Vector2 Vector2::operator+(const Vector2& v)
+{
+    Vector2 result(*this);
+    result.add(v);
+    return result;
+}
+
+inline Vector2& Vector2::operator+=(const Vector2& v)
+{
+    add(v);
+    return *this;
+}
+
+inline Vector2 Vector2::operator-(const Vector2& v)
+{
+    Vector2 result(*this);
+    result.subtract(v);
+    return result;
+}
+
+inline Vector2& Vector2::operator-=(const Vector2& v)
+{
+    subtract(v);
+    return *this;
+}
+
+inline Vector2 Vector2::operator-()
+{
+    Vector2 result(*this);
+    result.negate();
+    return result;
+}
+
+inline Vector2 Vector2::operator*(float x)
+{
+    Vector2 result(*this);
+    result.scale(x);
+    return result;
+}
+
+inline Vector2& Vector2::operator*=(float x)
+{
+    scale(x);
+    return *this;
+}
+
+inline bool Vector2::operator<(const Vector2& v) const
+{
+    if (x == v.x)
+    {
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector2::operator==(const Vector2& v) const
+{
+    return x==v.x && y==v.y;
+}
+
+inline Vector2 operator*(float x, const Vector2& v)
+{
+    Vector2 result(v);
+    result.scale(x);
+    return result;
+}
+
+}

+ 31 - 76
gameplay-encoder/src/Vector3.cpp

@@ -1,10 +1,5 @@
-/*
- * Vector3.cpp
- */
-
 #include "Base.h"
 #include "Base.h"
 #include "Vector3.h"
 #include "Vector3.h"
-#include "FileIO.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -14,77 +9,80 @@ Vector3::Vector3()
 {
 {
 }
 }
 
 
-
 Vector3::Vector3(float x, float y, float z)
 Vector3::Vector3(float x, float y, float z)
 {
 {
     set(x, y, z);
     set(x, y, z);
 }
 }
 
 
-
 Vector3::Vector3(float* array)
 Vector3::Vector3(float* array)
 {
 {
     set(array);
     set(array);
 }
 }
 
 
-
 Vector3::Vector3(const Vector3& p1, const Vector3& p2)
 Vector3::Vector3(const Vector3& p1, const Vector3& p2)
 {
 {
     set(p1, p2);
     set(p1, p2);
 }
 }
 
 
-
 Vector3::Vector3(const Vector3& copy)
 Vector3::Vector3(const Vector3& copy)
 {
 {
     set(copy);
     set(copy);
 }
 }
 
 
+Vector3 Vector3::fromColor(unsigned int color)
+{
+    float components[3];
+    int componentIndex = 0;
+    for (int i = 2; i >= 0; --i)
+    {
+        int component = (color >> i*8) & 0x0000ff;
+
+        components[componentIndex++] = static_cast<float>(component) / 255.0f;
+    }
+
+    Vector3 value(components);
+    return value;
+}
 
 
 Vector3::~Vector3()
 Vector3::~Vector3()
 {
 {
 }
 }
 
 
-
 const Vector3& Vector3::zero()
 const Vector3& Vector3::zero()
 {
 {
-    static Vector3* value = new Vector3(0.0f, 0.0f, 0.0f);
-    return *value;
+    static Vector3 value(0.0f, 0.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector3& Vector3::one()
 const Vector3& Vector3::one()
 {
 {
-    static Vector3* value = new Vector3(1.0f, 1.0f, 1.0f);
-    return *value;
+    static Vector3 value(1.0f, 1.0f, 1.0f);
+    return value;
 }
 }
 
 
-
 const Vector3& Vector3::unitX()
 const Vector3& Vector3::unitX()
 {
 {
-    static Vector3* value = new Vector3(1.0f, 0.0f, 0.0f);
-    return *value;
+    static Vector3 value(1.0f, 0.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector3& Vector3::unitY()
 const Vector3& Vector3::unitY()
 {
 {
-    static Vector3* value = new Vector3(0.0f, 1.0f, 0.0f);
-    return *value;
+    static Vector3 value(0.0f, 1.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector3& Vector3::unitZ()
 const Vector3& Vector3::unitZ()
 {
 {
-    static Vector3* value = new Vector3(0.0f, 0.0f, 1.0f);
-    return *value;
+    static Vector3 value(0.0f, 0.0f, 1.0f);
+    return value;
 }
 }
 
 
-
 bool Vector3::isZero() const
 bool Vector3::isZero() const
 {
 {
     return x == 0.0f && y == 0.0f && z == 0.0f;
     return x == 0.0f && y == 0.0f && z == 0.0f;
 }
 }
 
 
-
 bool Vector3::isOne() const
 bool Vector3::isOne() const
 {
 {
     return x == 1.0f && y == 1.0f && z == 1.0f;
     return x == 1.0f && y == 1.0f && z == 1.0f;
@@ -99,7 +97,6 @@ float Vector3::angle(const Vector3& v1, const Vector3& v2)
     return atan2f(sqrtf(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
     return atan2f(sqrtf(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
 }
 }
 
 
-
 void Vector3::add(const Vector3& v)
 void Vector3::add(const Vector3& v)
 {
 {
     x += v.x;
     x += v.x;
@@ -107,7 +104,6 @@ void Vector3::add(const Vector3& v)
     z += v.z;
     z += v.z;
 }
 }
 
 
-
 void Vector3::add(const Vector3& v1, const Vector3& v2, Vector3* dst)
 void Vector3::add(const Vector3& v1, const Vector3& v2, Vector3* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -117,7 +113,6 @@ void Vector3::add(const Vector3& v1, const Vector3& v2, Vector3* dst)
     dst->z = v1.z + v2.z;
     dst->z = v1.z + v2.z;
 }
 }
 
 
-
 void Vector3::clamp(const Vector3& min, const Vector3& max)
 void Vector3::clamp(const Vector3& min, const Vector3& max)
 {
 {
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
@@ -141,13 +136,12 @@ void Vector3::clamp(const Vector3& min, const Vector3& max)
         z = max.z;
         z = max.z;
 }
 }
 
 
-
 void Vector3::clamp(const Vector3& v, const Vector3& min, const Vector3& max, Vector3* dst)
 void Vector3::clamp(const Vector3& v, const Vector3& min, const Vector3& max, Vector3* dst)
 {
 {
     assert(dst);
     assert(dst);
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
 
 
-    // Clamp the y value.
+    // Clamp the x value.
     dst->x = v.x;
     dst->x = v.x;
     if ( dst->x < min.x )
     if ( dst->x < min.x )
         dst->x = min.x;
         dst->x = min.x;
@@ -169,7 +163,6 @@ void Vector3::clamp(const Vector3& v, const Vector3& min, const Vector3& max, Ve
         dst->z = max.z;
         dst->z = max.z;
 }
 }
 
 
-
 void Vector3::cross(const Vector3& v)
 void Vector3::cross(const Vector3& v)
 {
 {
     float tx = (y * v.z) - (z * v.y);
     float tx = (y * v.z) - (z * v.y);
@@ -180,7 +173,6 @@ void Vector3::cross(const Vector3& v)
     z = tz;
     z = tz;
 }
 }
 
 
-
 void Vector3::cross(const Vector3& v1, const Vector3& v2, Vector3* dst)
 void Vector3::cross(const Vector3& v1, const Vector3& v2, Vector3* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -193,8 +185,7 @@ void Vector3::cross(const Vector3& v1, const Vector3& v2, Vector3* dst)
     dst->z = z;
     dst->z = z;
 }
 }
 
 
-
-float Vector3::distance(const Vector3& v)
+float Vector3::distance(const Vector3& v) const
 {
 {
     float dx = v.x - x;
     float dx = v.x - x;
     float dy = v.y - y;
     float dy = v.y - y;
@@ -203,8 +194,7 @@ float Vector3::distance(const Vector3& v)
     return sqrtf(dx * dx + dy * dy + dz * dz);
     return sqrtf(dx * dx + dy * dy + dz * dz);
 }
 }
 
 
-
-float Vector3::distanceSquared(const Vector3& v)
+float Vector3::distanceSquared(const Vector3& v) const
 {
 {
     float dx = v.x - x;
     float dx = v.x - x;
     float dy = v.y - y;
     float dy = v.y - y;
@@ -213,31 +203,26 @@ float Vector3::distanceSquared(const Vector3& v)
     return (dx * dx + dy * dy + dz * dz);
     return (dx * dx + dy * dy + dz * dz);
 }
 }
 
 
-
 float Vector3::dot(const Vector3& v)
 float Vector3::dot(const Vector3& v)
 {
 {
     return (x * v.x + y * v.y + z * v.z);
     return (x * v.x + y * v.y + z * v.z);
 }
 }
 
 
-
 float Vector3::dot(const Vector3& v1, const Vector3& v2)
 float Vector3::dot(const Vector3& v1, const Vector3& v2)
 {
 {
     return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
     return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
 }
 }
 
 
-
-float Vector3::length()
+float Vector3::length() const
 {
 {
     return sqrtf(x * x + y * y + z * z);
     return sqrtf(x * x + y * y + z * z);
 }
 }
 
 
-
-float Vector3::lengthSquared()
+float Vector3::lengthSquared() const
 {
 {
     return (x * x + y * y + z * z);
     return (x * x + y * y + z * z);
 }
 }
 
 
-
 void Vector3::negate()
 void Vector3::negate()
 {
 {
     x = -x;
     x = -x;
@@ -245,13 +230,11 @@ void Vector3::negate()
     z = -z;
     z = -z;
 }
 }
 
 
-
 void Vector3::normalize()
 void Vector3::normalize()
 {
 {
     normalize(this);
     normalize(this);
 }
 }
 
 
-
 void Vector3::normalize(Vector3* dst) const
 void Vector3::normalize(Vector3* dst) const
 {
 {
     assert(dst);
     assert(dst);
@@ -264,12 +247,12 @@ void Vector3::normalize(Vector3* dst) const
     }
     }
 
 
     float n = x * x + y * y + z * z;
     float n = x * x + y * y + z * z;
-    // already normalized
+    // Already normalized.
     if (n == 1.0f)
     if (n == 1.0f)
         return;
         return;
 
 
     n = sqrt(n);
     n = sqrt(n);
-    // too close to zero
+    // Too close to zero.
     if (n < MATH_TOLERANCE)
     if (n < MATH_TOLERANCE)
         return;
         return;
 
 
@@ -279,7 +262,6 @@ void Vector3::normalize(Vector3* dst) const
     dst->z *= n;
     dst->z *= n;
 }
 }
 
 
-
 void Vector3::scale(float scalar)
 void Vector3::scale(float scalar)
 {
 {
     x *= scalar;
     x *= scalar;
@@ -287,7 +269,6 @@ void Vector3::scale(float scalar)
     z *= scalar;
     z *= scalar;
 }
 }
 
 
-
 void Vector3::set(float x, float y, float z)
 void Vector3::set(float x, float y, float z)
 {
 {
     this->x = x;
     this->x = x;
@@ -295,7 +276,6 @@ void Vector3::set(float x, float y, float z)
     this->z = z;
     this->z = z;
 }
 }
 
 
-
 void Vector3::set(float* array)
 void Vector3::set(float* array)
 {
 {
     assert(array);
     assert(array);
@@ -305,7 +285,6 @@ void Vector3::set(float* array)
     z = array[2];
     z = array[2];
 }
 }
 
 
-
 void Vector3::set(const Vector3& v)
 void Vector3::set(const Vector3& v)
 {
 {
     this->x = v.x;
     this->x = v.x;
@@ -313,7 +292,6 @@ void Vector3::set(const Vector3& v)
     this->z = v.z;
     this->z = v.z;
 }
 }
 
 
-
 void Vector3::set(const Vector3& p1, const Vector3& p2)
 void Vector3::set(const Vector3& p1, const Vector3& p2)
 {
 {
     x = p2.x - p1.x;
     x = p2.x - p1.x;
@@ -321,7 +299,6 @@ void Vector3::set(const Vector3& p1, const Vector3& p2)
     z = p2.z - p1.z;
     z = p2.z - p1.z;
 }
 }
 
 
-
 void Vector3::subtract(const Vector3& v)
 void Vector3::subtract(const Vector3& v)
 {
 {
     x -= v.x;
     x -= v.x;
@@ -329,7 +306,6 @@ void Vector3::subtract(const Vector3& v)
     z -= v.z;
     z -= v.z;
 }
 }
 
 
-
 void Vector3::subtract(const Vector3& v1, const Vector3& v2, Vector3* dst)
 void Vector3::subtract(const Vector3& v1, const Vector3& v2, Vector3* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -339,25 +315,4 @@ void Vector3::subtract(const Vector3& v1, const Vector3& v2, Vector3* dst)
     dst->z = v1.z - v2.z;
     dst->z = v1.z - v2.z;
 }
 }
 
 
-float Vector3::distanceSquared(const Vector3& v1, const Vector3& v2)
-{
-    float dx = v2.x - v1.x;
-    float dy = v2.y - v1.y;
-    float dz = v2.z - v1.z;
-
-    return (dx * dx + dy * dy + dz * dz);
-}
-
-void Vector3::writeBinary(FILE* file) const
-{
-    write(x, file);
-    write(y, file);
-    write(z, file);
-}
-
-void Vector3::writeText(FILE* file) const
-{
-    fprintf(file, "%f %f %f\n", x, y, z);
-}
-
 }
 }

+ 115 - 44
gameplay-encoder/src/Vector3.h

@@ -1,15 +1,9 @@
-/*
- * Vector3.h
- */
-
 #ifndef VECTOR3_H_
 #ifndef VECTOR3_H_
 #define VECTOR3_H_
 #define VECTOR3_H_
 
 
-
 namespace gameplay
 namespace gameplay
 {
 {
 
 
-// Forward declare
 class Matrix;
 class Matrix;
 class Quaternion;
 class Quaternion;
 
 
@@ -19,7 +13,7 @@ class Quaternion;
  * When using a vector to represent a surface normal,
  * When using a vector to represent a surface normal,
  * the vector should typically be normalized.
  * the vector should typically be normalized.
  * Other uses of directional vectors may wish to leave
  * Other uses of directional vectors may wish to leave
- * the magnitude of the vector in-tact. When used as a point,
+ * the magnitude of the vector intact. When used as a point,
  * the elements of the vector represent a position in 3D space.
  * the elements of the vector represent a position in 3D space.
  */
  */
 class Vector3
 class Vector3
@@ -77,57 +71,67 @@ public:
      */
      */
     Vector3(const Vector3& copy);
     Vector3(const Vector3& copy);
 
 
+    /**
+     * Creates a new vector from an integer interpreted as an RGB value.
+     * E.g. 0xff0000 represents red or the vector (1, 0, 0).
+     *
+     * @param color The integer to interpret as an RGB value.
+     *
+     * @return A vector corresponding to the interpreted RGB color.
+     */
+    static Vector3 fromColor(unsigned int color);
+
     /**
     /**
      * Destructor.
      * Destructor.
      */
      */
     ~Vector3();
     ~Vector3();
 
 
     /**
     /**
-     * The zero vector
+     * Returns the zero vector.
      *
      *
      * @return The 3-element vector of 0s.
      * @return The 3-element vector of 0s.
      */
      */
     static const Vector3& zero();
     static const Vector3& zero();
 
 
     /**
     /**
-     * The one vector.
+     * Returns the one vector.
      *
      *
      * @return The 3-element vector of 1s.
      * @return The 3-element vector of 1s.
      */
      */
     static const Vector3& one();
     static const Vector3& one();
 
 
     /**
     /**
-     * The unit x vector.
+     * Returns the unit x vector.
      *
      *
      * @return The 3-element unit vector along the x axis.
      * @return The 3-element unit vector along the x axis.
      */
      */
     static const Vector3& unitX();
     static const Vector3& unitX();
 
 
     /**
     /**
-     * The unit y vector.
+     * Returns the unit y vector.
      *
      *
      * @return The 3-element unit vector along the y axis.
      * @return The 3-element unit vector along the y axis.
      */
      */
     static const Vector3& unitY();
     static const Vector3& unitY();
 
 
     /**
     /**
-     * The unit z vector.
+     * Returns the unit z vector.
      *
      *
      * @return The 3-element unit vector along the z axis.
      * @return The 3-element unit vector along the z axis.
      */
      */
     static const Vector3& unitZ();
     static const Vector3& unitZ();
 
 
     /**
     /**
-     * Is this vector the all zeros.
+     * Indicates whether this vector contains all zeros.
      *
      *
-     * @return true if all zeros, false if otherwise.
+     * @return true if this vector contains all zeros, false otherwise.
      */
      */
     bool isZero() const;
     bool isZero() const;
 
 
     /**
     /**
-     * Is this vector all ones.
+     * Indicates whether this vector contains all ones.
      *
      *
-     * @return true if all ones, false if otherwise.
+     * @return true if this vector contains all ones, false otherwise.
      */
      */
     bool isOne() const;
     bool isOne() const;
 
 
@@ -137,7 +141,7 @@ public:
      * @param v1 The first vector.
      * @param v1 The first vector.
      * @param v2 The second vector.
      * @param v2 The second vector.
      * 
      * 
-     * @return The angle between the two vectors, in radians.
+     * @return The angle between the two vectors (in radians).
      */
      */
     static float angle(const Vector3& v1, const Vector3& v2);
     static float angle(const Vector3& v1, const Vector3& v2);
 
 
@@ -179,7 +183,7 @@ public:
     /**
     /**
      * Sets this vector to the cross product between itself and the specified vector.
      * Sets this vector to the cross product between itself and the specified vector.
      *
      *
-     * @param v the vector to compute the cross product with.
+     * @param v The vector to compute the cross product with.
      */
      */
     void cross(const Vector3& v);
     void cross(const Vector3& v);
 
 
@@ -198,9 +202,10 @@ public:
      * @param v The other vector.
      * @param v The other vector.
      * 
      * 
      * @return The distance between this vector and v.
      * @return The distance between this vector and v.
+     * 
      * @see distanceSquared
      * @see distanceSquared
      */
      */
-    float distance(const Vector3& v);
+    float distance(const Vector3& v) const;
 
 
     /**
     /**
      * Returns the squared distance between this vector and v.
      * Returns the squared distance between this vector and v.
@@ -213,9 +218,10 @@ public:
      * @param v The other vector.
      * @param v The other vector.
      * 
      * 
      * @return The squared distance between this vector and v.
      * @return The squared distance between this vector and v.
+     * 
      * @see distance
      * @see distance
      */
      */
-    float distanceSquared(const Vector3& v);
+    float distanceSquared(const Vector3& v) const;
 
 
     /**
     /**
      * Returns the dot product of this vector and the specified vector.
      * Returns the dot product of this vector and the specified vector.
@@ -240,9 +246,10 @@ public:
      * Computes the length of this vector.
      * Computes the length of this vector.
      *
      *
      * @return The length of the vector.
      * @return The length of the vector.
+     * 
      * @see lengthSquared
      * @see lengthSquared
      */
      */
-    float length();
+    float length() const;
 
 
     /**
     /**
      * Returns the squared length of this vector.
      * Returns the squared length of this vector.
@@ -253,9 +260,10 @@ public:
      * instead of length.
      * instead of length.
      *
      *
      * @return The squared length of the vector.
      * @return The squared length of the vector.
+     * 
      * @see length
      * @see length
      */
      */
-    float lengthSquared();
+    float lengthSquared() const;
 
 
     /**
     /**
      * Negates this vector.
      * Negates this vector.
@@ -280,7 +288,7 @@ public:
      * of the vector is zero, this method simply copies the
      * of the vector is zero, this method simply copies the
      * current vector into dst.
      * current vector into dst.
      *
      *
-     * @param dst the destination vector
+     * @param dst The destination vector.
      */
      */
     void normalize(Vector3* dst) const;
     void normalize(Vector3* dst) const;
 
 
@@ -321,7 +329,7 @@ public:
 
 
     /**
     /**
      * Subtracts this vector and the specified vector as (this - v)
      * Subtracts this vector and the specified vector as (this - v)
-     * and stores the result in this.
+     * and stores the result in this vector.
      *
      *
      * @param v The vector to subtract.
      * @param v The vector to subtract.
      */
      */
@@ -337,36 +345,99 @@ public:
      */
      */
     static void subtract(const Vector3& v1, const Vector3& v2, Vector3* dst);
     static void subtract(const Vector3& v1, const Vector3& v2, Vector3* dst);
 
 
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector3 operator+(const Vector3& v);
+
+    /**
+     * Adds the given vector to this vector.
+     * 
+     * @param v The vector to add.
+     * @return This vector, after the addition occurs.
+     */
+    inline Vector3& operator+=(const Vector3& v);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector3 operator-(const Vector3& v);
 
 
+    /**
+     * Subtracts the given vector from this vector.
+     * 
+     * @param v The vector to subtract.
+     * @return This vector, after the subtraction occurs.
+     */
+    inline Vector3& operator-=(const Vector3& v);
 
 
-    inline bool operator<(const Vector3& v) const
-    {
-        if (x == v.x)
-        {
-            if (y == v.y)
-            {
-                return z < v.z;
-            }
-            return y < v.y;
-        }
-        return x < v.x;
-    }
+    /**
+     * Calculates the negation of this vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @return The negation of this vector.
+     */
+    inline Vector3 operator-();
 
 
-    inline bool operator==(const Vector3& v) const
-    {
-        return x==v.x && y==v.y && z==v.z;
-    }
+    /**
+     * Calculates the scalar product of this vector with the given value.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param x The value to scale by.
+     * @return The scaled vector.
+     */
+    inline Vector3 operator*(float x);
 
 
-    static float distanceSquared(const Vector3& v1, const Vector3& v2);
+    /**
+     * Scales this vector by the given value.
+     * 
+     * @param x The value to scale by.
+     * @return This vector, after the scale occurs.
+     */
+    inline Vector3& operator*=(float x);
 
 
     /**
     /**
-     * Writes this vector to the binary file stream.
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
      */
      */
-    void writeBinary(FILE* file) const;
+    inline bool operator<(const Vector3& v) const;
 
 
-    void writeText(FILE* file) const;
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector3& v) const;
 };
 };
 
 
+/**
+ * Calculates the scalar product of the given vector with the given value.
+ * 
+ * @param x The value to scale by.
+ * @param v The vector to scale.
+ * @return The scaled vector.
+ */
+inline Vector3 operator*(float x, const Vector3& v);
+
 }
 }
 
 
+#include "Vector3.inl"
+
 #endif
 #endif

+ 82 - 0
gameplay-encoder/src/Vector3.inl

@@ -0,0 +1,82 @@
+/** 
+ * Vector3.inl
+ */
+
+#include "Vector3.h"
+#include "Matrix.h"
+
+namespace gameplay
+{
+
+inline Vector3 Vector3::operator+(const Vector3& v)
+{
+    Vector3 result(*this);
+    result.add(v);
+    return result;
+}
+
+inline Vector3& Vector3::operator+=(const Vector3& v)
+{
+    add(v);
+    return *this;
+}
+
+inline Vector3 Vector3::operator-(const Vector3& v)
+{
+    Vector3 result(*this);
+    result.subtract(v);
+    return result;
+}
+
+inline Vector3& Vector3::operator-=(const Vector3& v)
+{
+    subtract(v);
+    return *this;
+}
+
+inline Vector3 Vector3::operator-()
+{
+    Vector3 result(*this);
+    result.negate();
+    return result;
+}
+
+inline Vector3 Vector3::operator*(float x)
+{
+    Vector3 result(*this);
+    result.scale(x);
+    return result;
+}
+
+inline Vector3& Vector3::operator*=(float x)
+{
+    scale(x);
+    return *this;
+}
+
+inline bool Vector3::operator<(const Vector3& v) const
+{
+    if (x == v.x)
+    {
+        if (y == v.y)
+        {
+            return z < v.z;
+        }
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector3::operator==(const Vector3& v) const
+{
+    return x==v.x && y==v.y && z==v.z;
+}
+
+inline Vector3 operator*(float x, const Vector3& v)
+{
+    Vector3 result(v);
+    result.scale(x);
+    return result;
+}
+
+}

+ 33 - 69
gameplay-encoder/src/Vector4.cpp

@@ -1,10 +1,5 @@
-/*
- * Vector4.cpp
- */
-
 #include "Base.h"
 #include "Base.h"
 #include "Vector4.h"
 #include "Vector4.h"
-#include "FileIO.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -14,90 +9,91 @@ Vector4::Vector4()
 {
 {
 }
 }
 
 
-
 Vector4::Vector4(float x, float y, float z, float w)
 Vector4::Vector4(float x, float y, float z, float w)
 {
 {
     set(x, y, z, w);
     set(x, y, z, w);
 }
 }
 
 
-
 Vector4::Vector4(float* src)
 Vector4::Vector4(float* src)
 {
 {
     set(src);
     set(src);
 }
 }
 
 
-
 Vector4::Vector4(const Vector4& p1, const Vector4& p2)
 Vector4::Vector4(const Vector4& p1, const Vector4& p2)
 {
 {
     set(p1, p2);
     set(p1, p2);
 }
 }
 
 
-
 Vector4::Vector4(const Vector4& copy)
 Vector4::Vector4(const Vector4& copy)
 {
 {
     set(copy);
     set(copy);
 }
 }
 
 
+Vector4 Vector4::fromColor(unsigned int color)
+{
+    float components[4];
+    int componentIndex = 0;
+    for (int i = 3; i >= 0; --i)
+    {
+        int component = (color >> i*8) & 0x000000ff;
+
+        components[componentIndex++] = static_cast<float>(component) / 255.0f;
+    }
+
+    Vector4 value(components);
+    return value;
+}
 
 
 Vector4::~Vector4()
 Vector4::~Vector4()
 {
 {
 }
 }
 
 
-
 const Vector4& Vector4::zero()
 const Vector4& Vector4::zero()
 {
 {
-    static Vector4* value = new Vector4(0.0f, 0.0f, 0.0f, 0.0f);
-    return *value;
+    static Vector4 value(0.0f, 0.0f, 0.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector4& Vector4::one()
 const Vector4& Vector4::one()
 {
 {
-    static Vector4* value = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
-    return *value;
+    static Vector4 value(1.0f, 1.0f, 1.0f, 1.0f);
+    return value;
 }
 }
 
 
-
 const Vector4& Vector4::unitX()
 const Vector4& Vector4::unitX()
 {
 {
-    static Vector4* value = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
-    return *value;
+    static Vector4 value(1.0f, 0.0f, 0.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector4& Vector4::unitY()
 const Vector4& Vector4::unitY()
 {
 {
-    static Vector4* value = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
-    return *value;
+    static Vector4 value(0.0f, 1.0f, 0.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector4& Vector4::unitZ()
 const Vector4& Vector4::unitZ()
 {
 {
-    static Vector4* value = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
-    return *value;
+    static Vector4 value(0.0f, 0.0f, 1.0f, 0.0f);
+    return value;
 }
 }
 
 
-
 const Vector4& Vector4::unitW()
 const Vector4& Vector4::unitW()
 {
 {
-    static Vector4* value = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
-    return *value;
+    static Vector4 value(0.0f, 0.0f, 0.0f, 1.0f);
+    return value;
 }
 }
 
 
-
 bool Vector4::isZero() const
 bool Vector4::isZero() const
 {
 {
     return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
     return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
 }
 }
 
 
-
 bool Vector4::isOne() const
 bool Vector4::isOne() const
 {
 {
     return x == 1.0f && y == 1.0f && z == 1.0f && z == 1.0f;
     return x == 1.0f && y == 1.0f && z == 1.0f && z == 1.0f;
 }
 }
 
 
-
 float Vector4::angle(const Vector4& v1, const Vector4& v2)
 float Vector4::angle(const Vector4& v1, const Vector4& v2)
 {
 {
     float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y;
     float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y;
@@ -107,7 +103,6 @@ float Vector4::angle(const Vector4& v1, const Vector4& v2)
     return atan2f(sqrtf(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
     return atan2f(sqrtf(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
 }
 }
 
 
-
 void Vector4::add(const Vector4& v)
 void Vector4::add(const Vector4& v)
 {
 {
     x += v.x;
     x += v.x;
@@ -116,7 +111,6 @@ void Vector4::add(const Vector4& v)
     w += v.w;
     w += v.w;
 }
 }
 
 
-
 void Vector4::add(const Vector4& v1, const Vector4& v2, Vector4* dst)
 void Vector4::add(const Vector4& v1, const Vector4& v2, Vector4* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -127,7 +121,6 @@ void Vector4::add(const Vector4& v1, const Vector4& v2, Vector4* dst)
     dst->w = v1.w + v2.w;
     dst->w = v1.w + v2.w;
 }
 }
 
 
-
 void Vector4::clamp(const Vector4& min, const Vector4& max)
 void Vector4::clamp(const Vector4& min, const Vector4& max)
 {
 {
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
@@ -157,13 +150,12 @@ void Vector4::clamp(const Vector4& min, const Vector4& max)
         w = max.w;
         w = max.w;
 }
 }
 
 
-
 void Vector4::clamp(const Vector4& v, const Vector4& min, const Vector4& max, Vector4* dst)
 void Vector4::clamp(const Vector4& v, const Vector4& min, const Vector4& max, Vector4* dst)
 {
 {
     assert(dst);
     assert(dst);
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
     assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
 
 
-    // Clamp the y value.
+    // Clamp the x value.
     dst->x = v.x;
     dst->x = v.x;
     if ( dst->x < min.x )
     if ( dst->x < min.x )
         dst->x = min.x;
         dst->x = min.x;
@@ -192,8 +184,7 @@ void Vector4::clamp(const Vector4& v, const Vector4& min, const Vector4& max, Ve
         dst->w = max.w;
         dst->w = max.w;
 }
 }
 
 
-
-float Vector4::distance(const Vector4& v)
+float Vector4::distance(const Vector4& v) const
 {
 {
     float dx = v.x - x;
     float dx = v.x - x;
     float dy = v.y - y;
     float dy = v.y - y;
@@ -203,8 +194,7 @@ float Vector4::distance(const Vector4& v)
     return sqrtf(dx * dx + dy * dy + dz * dz + dw * dw);
     return sqrtf(dx * dx + dy * dy + dz * dz + dw * dw);
 }
 }
 
 
-
-float Vector4::distanceSquared(const Vector4& v)
+float Vector4::distanceSquared(const Vector4& v) const
 {
 {
     float dx = v.x - x;
     float dx = v.x - x;
     float dy = v.y - y;
     float dy = v.y - y;
@@ -214,31 +204,27 @@ float Vector4::distanceSquared(const Vector4& v)
     return (dx * dx + dy * dy + dz * dz + dw * dw);
     return (dx * dx + dy * dy + dz * dz + dw * dw);
 }
 }
 
 
-
 float Vector4::dot(const Vector4& v)
 float Vector4::dot(const Vector4& v)
 {
 {
     return (x * v.x + y * v.y + z * v.z + w * v.w);
     return (x * v.x + y * v.y + z * v.z + w * v.w);
 }
 }
 
 
-
 float Vector4::dot(const Vector4& v1, const Vector4& v2)
 float Vector4::dot(const Vector4& v1, const Vector4& v2)
 {
 {
     return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w);
     return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w);
 }
 }
 
 
-
-float Vector4::length()
+float Vector4::length() const
 {
 {
     return sqrtf(x * x + y * y + z * z + w * w);
     return sqrtf(x * x + y * y + z * z + w * w);
 }
 }
 
 
 
 
-float Vector4::lengthSquared()
+float Vector4::lengthSquared() const
 {
 {
     return (x * x + y * y + z * z + w * w);
     return (x * x + y * y + z * z + w * w);
 }
 }
 
 
-
 void Vector4::negate()
 void Vector4::negate()
 {
 {
     x = -x;
     x = -x;
@@ -247,13 +233,11 @@ void Vector4::negate()
     w = -w;
     w = -w;
 }
 }
 
 
-
 void Vector4::normalize()
 void Vector4::normalize()
 {
 {
     normalize(this);
     normalize(this);
 }
 }
 
 
-
 void Vector4::normalize(Vector4* dst)
 void Vector4::normalize(Vector4* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -267,12 +251,12 @@ void Vector4::normalize(Vector4* dst)
     }
     }
 
 
     float n = x * x + y * y + z * z + w * w;
     float n = x * x + y * y + z * z + w * w;
-    // already normalized
+    // Already normalized.
     if (n == 1.0f)
     if (n == 1.0f)
         return;
         return;
 
 
     n = sqrt(n);
     n = sqrt(n);
-    // too close to zero
+    // Too close to zero.
     if (n < MATH_TOLERANCE)
     if (n < MATH_TOLERANCE)
         return;
         return;
 
 
@@ -283,7 +267,6 @@ void Vector4::normalize(Vector4* dst)
     dst->w *= n;
     dst->w *= n;
 }
 }
 
 
-
 void Vector4::scale(float scalar)
 void Vector4::scale(float scalar)
 {
 {
     x *= scalar;
     x *= scalar;
@@ -292,7 +275,6 @@ void Vector4::scale(float scalar)
     w *= scalar;
     w *= scalar;
 }
 }
 
 
-
 void Vector4::set(float x, float y, float z, float w)
 void Vector4::set(float x, float y, float z, float w)
 {
 {
     this->x = x;
     this->x = x;
@@ -301,7 +283,6 @@ void Vector4::set(float x, float y, float z, float w)
     this->w = w;
     this->w = w;
 }
 }
 
 
-
 void Vector4::set(float* array)
 void Vector4::set(float* array)
 {
 {
     assert(array);
     assert(array);
@@ -312,7 +293,6 @@ void Vector4::set(float* array)
     w = array[3];
     w = array[3];
 }
 }
 
 
-
 void Vector4::set(const Vector4& v)
 void Vector4::set(const Vector4& v)
 {
 {
     this->x = v.x;
     this->x = v.x;
@@ -321,7 +301,6 @@ void Vector4::set(const Vector4& v)
     this->w = v.w;
     this->w = v.w;
 }
 }
 
 
-
 void Vector4::set(const Vector4& p1, const Vector4& p2)
 void Vector4::set(const Vector4& p1, const Vector4& p2)
 {
 {
     x = p2.x - p1.x;
     x = p2.x - p1.x;
@@ -330,7 +309,6 @@ void Vector4::set(const Vector4& p1, const Vector4& p2)
     w = p2.w - p1.w;
     w = p2.w - p1.w;
 }
 }
 
 
-
 void Vector4::subtract(const Vector4& v)
 void Vector4::subtract(const Vector4& v)
 {
 {
     x -= v.x;
     x -= v.x;
@@ -339,7 +317,6 @@ void Vector4::subtract(const Vector4& v)
     w -= v.w;
     w -= v.w;
 }
 }
 
 
-
 void Vector4::subtract(const Vector4& v1, const Vector4& v2, Vector4* dst)
 void Vector4::subtract(const Vector4& v1, const Vector4& v2, Vector4* dst)
 {
 {
     assert(dst);
     assert(dst);
@@ -350,17 +327,4 @@ void Vector4::subtract(const Vector4& v1, const Vector4& v2, Vector4* dst)
     dst->w = v1.w - v2.w;
     dst->w = v1.w - v2.w;
 }
 }
 
 
-void Vector4::writeBinary(FILE* file) const
-{
-    write(x, file);
-    write(y, file);
-    write(z, file);
-    write(w, file);
-}
-
-void Vector4::writeText(FILE* file) const
-{
-    fprintf(file, "%f %f %f %f\n", x, y, z, w);
-}
-
 }
 }

+ 119 - 51
gameplay-encoder/src/Vector4.h

@@ -1,16 +1,9 @@
-/*
- * Vector4.h
- */
-
 #ifndef VECTOR4_H_
 #ifndef VECTOR4_H_
 #define VECTOR4_H_
 #define VECTOR4_H_
 
 
-#include "FileIO.h"
-
 namespace gameplay
 namespace gameplay
 {
 {
 
 
-// Forward declare
 class Matrix;
 class Matrix;
 
 
 /**
 /**
@@ -79,64 +72,74 @@ public:
      */
      */
     Vector4(const Vector4& copy);
     Vector4(const Vector4& copy);
 
 
+    /**
+     * Creates a new vector from an integer interpreted as an RGBA value.
+     * E.g. 0xff0000ff represents opaque red or the vector (1, 0, 0, 1).
+     *
+     * @param color The integer to interpret as an RGBA value.
+     *
+     * @return A vector corresponding to the interpreted RGBA color.
+     */
+    static Vector4 fromColor(unsigned int color);
+
     /**
     /**
      * Destructor.
      * Destructor.
      */
      */
     ~Vector4();
     ~Vector4();
 
 
     /**
     /**
-     * The zero vector
+     * Returns the zero vector.
      *
      *
      * @return The 4-element vector of 0s.
      * @return The 4-element vector of 0s.
      */
      */
     static const Vector4& zero();
     static const Vector4& zero();
 
 
     /**
     /**
-     * The one vector.
+     * Returns the one vector.
      *
      *
      * @return The 4-element vector of 1s.
      * @return The 4-element vector of 1s.
      */
      */
     static const Vector4& one();
     static const Vector4& one();
 
 
     /**
     /**
-     * The unit x vector.
+     * Returns the unit x vector.
      *
      *
      * @return The 4-element unit vector along the x axis.
      * @return The 4-element unit vector along the x axis.
      */
      */
     static const Vector4& unitX();
     static const Vector4& unitX();
 
 
     /**
     /**
-     * The unit y vector.
+     * Returns the unit y vector.
      *
      *
      * @return The 4-element unit vector along the y axis.
      * @return The 4-element unit vector along the y axis.
      */
      */
     static const Vector4& unitY();
     static const Vector4& unitY();
 
 
     /**
     /**
-     * The unit z vector.
+     * Returns the unit z vector.
      *
      *
      * @return The 4-element unit vector along the z axis.
      * @return The 4-element unit vector along the z axis.
      */
      */
     static const Vector4& unitZ();
     static const Vector4& unitZ();
 
 
     /**
     /**
-     * The unit w vector.
+     * Returns the unit w vector.
      *
      *
      * @return The 4-element unit vector along the w axis.
      * @return The 4-element unit vector along the w axis.
      */
      */
     static const Vector4& unitW();
     static const Vector4& unitW();
 
 
     /**
     /**
-     * Is this vector the all zeros.
+     * Indicates whether this vector contains all zeros.
      *
      *
-     * @return true if all zeros, false if otherwise.
+     * @return true if this vector contains all zeros, false otherwise.
      */
      */
     bool isZero() const;
     bool isZero() const;
 
 
     /**
     /**
-     * Is this vector all ones.
+     * Indicates whether this vector contains all ones.
      *
      *
-     * @return true if all ones, false if otherwise.
+     * @return true if this vector contains all ones, false otherwise.
      */
      */
     bool isOne() const;
     bool isOne() const;
 
 
@@ -146,7 +149,7 @@ public:
      * @param v1 The first vector.
      * @param v1 The first vector.
      * @param v2 The second vector.
      * @param v2 The second vector.
      * 
      * 
-     * @return The angle between the two vectors, in radians.
+     * @return The angle between the two vectors (in radians).
      */
      */
     static float angle(const Vector4& v1, const Vector4& v2);
     static float angle(const Vector4& v1, const Vector4& v2);
 
 
@@ -190,9 +193,10 @@ public:
      * @param v The other vector.
      * @param v The other vector.
      * 
      * 
      * @return The distance between this vector and v.
      * @return The distance between this vector and v.
+     * 
      * @see distanceSquared
      * @see distanceSquared
      */
      */
-    float distance(const Vector4& v);
+    float distance(const Vector4& v) const;
 
 
     /**
     /**
      * Returns the squared distance between this vector and v.
      * Returns the squared distance between this vector and v.
@@ -205,9 +209,10 @@ public:
      * @param v The other vector.
      * @param v The other vector.
      * 
      * 
      * @return The squared distance between this vector and v.
      * @return The squared distance between this vector and v.
+     * 
      * @see distance
      * @see distance
      */
      */
-    float distanceSquared(const Vector4& v);
+    float distanceSquared(const Vector4& v) const;
 
 
     /**
     /**
      * Returns the dot product of this vector and the specified vector.
      * Returns the dot product of this vector and the specified vector.
@@ -232,9 +237,10 @@ public:
      * Computes the length of this vector.
      * Computes the length of this vector.
      *
      *
      * @return The length of the vector.
      * @return The length of the vector.
+     * 
      * @see lengthSquared
      * @see lengthSquared
      */
      */
-    float length();
+    float length() const;
 
 
     /**
     /**
      * Returns the squared length of this vector.
      * Returns the squared length of this vector.
@@ -245,9 +251,10 @@ public:
      * instead of length.
      * instead of length.
      *
      *
      * @return The squared length of the vector.
      * @return The squared length of the vector.
+     * 
      * @see length
      * @see length
      */
      */
-    float lengthSquared();
+    float lengthSquared() const;
 
 
     /**
     /**
      * Negates this vector.
      * Negates this vector.
@@ -272,7 +279,7 @@ public:
      * of the vector is zero, this method simply copies the
      * of the vector is zero, this method simply copies the
      * current vector into dst.
      * current vector into dst.
      *
      *
-     * @param dst the destination vector
+     * @param dst The destination vector.
      */
      */
     void normalize(Vector4* dst);
     void normalize(Vector4* dst);
 
 
@@ -309,12 +316,15 @@ public:
 
 
     /**
     /**
      * Sets this vector to the directional vector between the specified points.
      * Sets this vector to the directional vector between the specified points.
+     * 
+     * @param p1 The first point.
+     * @param p2 The second point.
      */
      */
     void set(const Vector4& p1, const Vector4& p2);
     void set(const Vector4& p1, const Vector4& p2);
 
 
     /**
     /**
      * Subtracts this vector and the specified vector as (this - v)
      * Subtracts this vector and the specified vector as (this - v)
-     * and stores the result in this.
+     * and stores the result in this vector.
      *
      *
      * @param v The vector to subtract.
      * @param v The vector to subtract.
      */
      */
@@ -330,41 +340,99 @@ public:
      */
      */
     static void subtract(const Vector4& v1, const Vector4& v2, Vector4* dst);
     static void subtract(const Vector4& v1, const Vector4& v2, Vector4* dst);
 
 
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector4 operator+(const Vector4& v);
+
+    /**
+     * Adds the given vector to this vector.
+     * 
+     * @param v The vector to add.
+     * @return This vector, after the addition occurs.
+     */
+    inline Vector4& operator+=(const Vector4& v);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector4 operator-(const Vector4& v);
+
+    /**
+     * Subtracts the given vector from this vector.
+     * 
+     * @param v The vector to subtract.
+     * @return This vector, after the subtraction occurs.
+     */
+    inline Vector4& operator-=(const Vector4& v);
 
 
+    /**
+     * Calculates the negation of this vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @return The negation of this vector.
+     */
+    inline Vector4 operator-();
 
 
-    inline bool operator<(const Vector4& v) const
-    {
-        if (x == v.x)
-        {
-            if (y == v.y)
-            {
-                if (z < v.z)
-                {
-                    if (w < v.w)
-                    {
-                        return w < v.w;
-                    }
-                }
-                return z < v.z;
-            }
-            return y < v.y;
-        }
-        return x < v.x;
-    }
+    /**
+     * Calculates the scalar product of this vector with the given value.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param x The value to scale by.
+     * @return The scaled vector.
+     */
+    inline Vector4 operator*(float x);
 
 
-    inline bool operator==(const Vector4& v) const
-    {
-        return x==v.x && y==v.y && z==v.z && w==v.w;
-    }
+    /**
+     * Scales this vector by the given value.
+     * 
+     * @param x The value to scale by.
+     * @return This vector, after the scale occurs.
+     */
+    inline Vector4& operator*=(float x);
 
 
     /**
     /**
-     * Writes this vector to the binary file stream.
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
      */
      */
-    void writeBinary(FILE* file) const;
+    inline bool operator<(const Vector4& v) const;
 
 
-    void writeText(FILE* file) const;
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector4& v) const;
 };
 };
 
 
+/**
+ * Calculates the scalar product of the given vector with the given value.
+ * 
+ * @param x The value to scale by.
+ * @param v The vector to scale.
+ * @return The scaled vector.
+ */
+inline Vector4 operator*(float x, const Vector4& v);
+
 }
 }
 
 
-#endif
+#include "Vector4.inl"
+
+#endif

+ 89 - 0
gameplay-encoder/src/Vector4.inl

@@ -0,0 +1,89 @@
+/** 
+ * Vector4.inl
+ */
+
+#include "Matrix.h"
+#include "Vector4.h"
+
+namespace gameplay
+{
+
+inline Vector4 Vector4::operator+(const Vector4& v)
+{
+    Vector4 result(*this);
+    result.add(v);
+    return result;
+}
+
+inline Vector4& Vector4::operator+=(const Vector4& v)
+{
+    add(v);
+    return *this;
+}
+
+inline Vector4 Vector4::operator-(const Vector4& v)
+{
+    Vector4 result(*this);
+    result.subtract(v);
+    return result;
+}
+
+inline Vector4& Vector4::operator-=(const Vector4& v)
+{
+    subtract(v);
+    return *this;
+}
+
+inline Vector4 Vector4::operator-()
+{
+    Vector4 result(*this);
+    result.negate();
+    return result;
+}
+
+inline Vector4 Vector4::operator*(float x)
+{
+    Vector4 result(*this);
+    result.scale(x);
+    return result;
+}
+
+inline Vector4& Vector4::operator*=(float x)
+{
+    scale(x);
+    return *this;
+}
+
+inline bool Vector4::operator<(const Vector4& v) const
+{
+    if (x == v.x)
+    {
+        if (y == v.y)
+        {
+            if (z < v.z)
+            {
+                if (w < v.w)
+                {
+                    return w < v.w;
+                }
+            }
+            return z < v.z;
+        }
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector4::operator==(const Vector4& v) const
+{
+    return x==v.x && y==v.y && z==v.z && w==v.w;
+}
+
+inline Vector4 operator*(float x, const Vector4& v)
+{
+    Vector4 result(v);
+    result.scale(x);
+    return result;
+}
+
+}

+ 21 - 26
gameplay-encoder/src/Vertex.cpp

@@ -4,24 +4,14 @@ namespace gameplay
 {
 {
 
 
 Vertex::Vertex(void)
 Vertex::Vertex(void)
+    : hasNormal(false), hasTangent(false), hasBinormal(false), hasTexCoord(false), hasColor(false), hasWeights(false)
 {
 {
-    reset();
 }
 }
 
 
 Vertex::~Vertex(void)
 Vertex::~Vertex(void)
 {
 {
 }
 }
 
 
-void Vertex::reset()
-{
-    hasNormal = false;
-    hasTangent = false;
-    hasBinormal = false;
-    hasTexCoord = false;
-    hasColor = false;
-    hasWeights = false;
-}
-
 unsigned int Vertex::byteSize() const
 unsigned int Vertex::byteSize() const
 {
 {
     unsigned int count = 3;
     unsigned int count = 3;
@@ -40,66 +30,71 @@ unsigned int Vertex::byteSize() const
 
 
 void Vertex::writeBinary(FILE* file) const
 void Vertex::writeBinary(FILE* file) const
 {
 {
-    position.writeBinary(file);
+    writeVectorBinary(position, file);
     if (hasNormal)
     if (hasNormal)
     {
     {
-        normal.writeBinary(file);
+        writeVectorBinary(normal, file);
     }
     }
     if (hasTangent)
     if (hasTangent)
     {
     {
-        tangent.writeBinary(file);
+        writeVectorBinary(tangent, file);
     }
     }
     if (hasBinormal)
     if (hasBinormal)
     {
     {
-        binormal.writeBinary(file);
+        writeVectorBinary(binormal, file);
     }
     }
     if (hasTexCoord)
     if (hasTexCoord)
     {
     {
-        texCoord.writeBinary(file);
+        writeVectorBinary(texCoord, file);
     }
     }
     // TODO add vertex color?
     // TODO add vertex color?
     //if (hasColor)
     //if (hasColor)
     //{
     //{
-    //    color.writeBinary(file);
+    //    writeVectorBinary(color, file);
     //}
     //}
     if (hasWeights)
     if (hasWeights)
     {
     {
-        blendWeights.writeBinary(file);
-        blendIndices.writeBinary(file);
+        writeVectorBinary(blendWeights, file);
+        writeVectorBinary(blendIndices, file);
     }
     }
 }
 }
 
 
 void Vertex::writeText(FILE* file) const
 void Vertex::writeText(FILE* file) const
 {
 {
     write("// position\n", file);
     write("// position\n", file);
-    position.writeText(file);
+    writeVectorText(position, file);
     if (hasNormal)
     if (hasNormal)
     {
     {
         write("// normal\n", file);
         write("// normal\n", file);
-        normal.writeText(file);
+        writeVectorText(normal, file);
     }
     }
     if (hasTangent)
     if (hasTangent)
     {
     {
         write("// tanget\n", file);
         write("// tanget\n", file);
-        tangent.writeText(file);
+        writeVectorText(tangent, file);
     }
     }
     if (hasBinormal)
     if (hasBinormal)
     {
     {
         write("// binormal\n", file);
         write("// binormal\n", file);
-        binormal.writeText(file);
+        writeVectorText(binormal, file);
     }
     }
     if (hasTexCoord)
     if (hasTexCoord)
     {
     {
         write("// texCoord\n", file);
         write("// texCoord\n", file);
-        texCoord.writeText(file);
+        writeVectorText(texCoord, file);
     }
     }
     if (hasWeights)
     if (hasWeights)
     {
     {
         write("// blendWeights\n", file);
         write("// blendWeights\n", file);
-        blendWeights.writeText(file);
+        writeVectorText(blendWeights, file);
         write("// blendIndices\n", file);
         write("// blendIndices\n", file);
-        blendIndices.writeText(file);
+        writeVectorText(blendIndices, file);
     }
     }
 }
 }
 
 
+float Vertex::getTotalWeight() const
+{
+    return blendWeights.x + blendWeights.y + blendWeights.z + blendWeights.w;
+}
+
 }
 }

+ 3 - 4
gameplay-encoder/src/Vertex.h

@@ -21,7 +21,7 @@ public:
     /**
     /**
      * Destructor.
      * Destructor.
      */
      */
-    virtual ~Vertex(void);
+    ~Vertex(void);
 
 
     Vector3 position;
     Vector3 position;
     Vector3 normal;
     Vector3 normal;
@@ -73,8 +73,6 @@ public:
             blendWeights==v.blendWeights && blendIndices==v.blendIndices;
             blendWeights==v.blendWeights && blendIndices==v.blendIndices;
     }
     }
 
 
-    void reset();
-
     /**
     /**
      * Returns the size of this vertex in bytes.
      * Returns the size of this vertex in bytes.
      */
      */
@@ -89,7 +87,8 @@ public:
      * Writes this vertex to a text file stream.
      * Writes this vertex to a text file stream.
      */
      */
     void writeText(FILE* file) const;
     void writeText(FILE* file) const;
-};
 
 
+    float getTotalWeight() const;
+};
 }
 }
 #endif
 #endif

+ 13 - 0
gameplay-encoder/src/main.cpp

@@ -1,6 +1,7 @@
 #include <string>
 #include <string>
 
 
 #include "DAESceneEncoder.h"
 #include "DAESceneEncoder.h"
+#include "FBXSceneEncoder.h"
 #include "TTFFontEncoder.h"
 #include "TTFFontEncoder.h"
 #include "GPBDecoder.h"
 #include "GPBDecoder.h"
 #include "EncoderArguments.h"
 #include "EncoderArguments.h"
@@ -60,6 +61,18 @@ int main(int argc, const char** argv)
             daeEncoder.write(realpath, arguments);
             daeEncoder.write(realpath, arguments);
             break;
             break;
         }
         }
+    case EncoderArguments::FILEFORMAT_FBX:
+        {
+#ifdef USE_FBX
+            std::string realpath = arguments.getFilePath();
+            FBXSceneEncoder fbxEncoder;
+            fbxEncoder.write(realpath, arguments);
+            break;
+#else
+            fprintf(stderr, "Error: FBX not enabled. Install the FBX SDK and use the preprocessor definition USE_FBX.\n");
+            return -1;
+#endif
+        }
     case EncoderArguments::FILEFORMAT_TTF:
     case EncoderArguments::FILEFORMAT_TTF:
         {
         {
             std::string realpath = arguments.getFilePath();
             std::string realpath = arguments.getFilePath();

+ 1 - 1
gameplay/src/Camera.cpp

@@ -164,7 +164,7 @@ const Matrix& Camera::getViewMatrix() const
         if (_node)
         if (_node)
         {
         {
             // The view matrix is the inverse of our transform matrix.
             // The view matrix is the inverse of our transform matrix.
-            _node->getMatrix().invert(&_view);
+            _node->getWorldMatrix().invert(&_view);
         }
         }
         else
         else
         {
         {

+ 0 - 4
gameplay/src/Joint.cpp

@@ -30,15 +30,11 @@ Node::Type Joint::getType() const
 void Joint::transformChanged()
 void Joint::transformChanged()
 {
 {
     Node::transformChanged();
     Node::transformChanged();
-
-    //const char* id = _id.c_str();
     _jointMatrixDirty = true;
     _jointMatrixDirty = true;
 }
 }
 
 
 void Joint::updateJointMatrix(const Matrix& bindShape, Vector4* matrixPalette)
 void Joint::updateJointMatrix(const Matrix& bindShape, Vector4* matrixPalette)
 {
 {
-    //const char* id = _id.c_str();
-
     if (_jointMatrixDirty)
     if (_jointMatrixDirty)
     {
     {
         _jointMatrixDirty = false;
         _jointMatrixDirty = false;

+ 1 - 1
gameplay/src/Package.cpp

@@ -858,7 +858,7 @@ Animation* Package::readAnimationChannel(Scene* scene, Animation* animation, con
     float* values = NULL;
     float* values = NULL;
     float* tangentsIn = NULL;
     float* tangentsIn = NULL;
     float* tangentsOut = NULL;
     float* tangentsOut = NULL;
-    float* interpolation = NULL;
+    unsigned int* interpolation = NULL;
 
 
     // length of the arrays
     // length of the arrays
     unsigned int keyTimesCount;
     unsigned int keyTimesCount;

+ 18 - 0
gameplay/src/Vector2.h

@@ -381,6 +381,24 @@ public:
      * @return This vector, after the scale occurs.
      * @return This vector, after the scale occurs.
      */
      */
     inline Vector2& operator*=(float x);
     inline Vector2& operator*=(float x);
+
+    /**
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
+     */
+    inline bool operator<(const Vector2& v) const;
+
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector2& v) const;
 };
 };
 
 
 /**
 /**

+ 14 - 0
gameplay/src/Vector2.inl

@@ -53,6 +53,20 @@ inline Vector2& Vector2::operator*=(float x)
     return *this;
     return *this;
 }
 }
 
 
+inline bool Vector2::operator<(const Vector2& v) const
+{
+    if (x == v.x)
+    {
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector2::operator==(const Vector2& v) const
+{
+    return x==v.x && y==v.y;
+}
+
 inline Vector2 operator*(float x, const Vector2& v)
 inline Vector2 operator*(float x, const Vector2& v)
 {
 {
     Vector2 result(v);
     Vector2 result(v);

+ 18 - 0
gameplay/src/Vector3.h

@@ -411,6 +411,24 @@ public:
      * @return This vector, after the scale occurs.
      * @return This vector, after the scale occurs.
      */
      */
     inline Vector3& operator*=(float x);
     inline Vector3& operator*=(float x);
+
+    /**
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
+     */
+    inline bool operator<(const Vector3& v) const;
+
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector3& v) const;
 };
 };
 
 
 /**
 /**

+ 18 - 0
gameplay/src/Vector3.inl

@@ -54,6 +54,24 @@ inline Vector3& Vector3::operator*=(float x)
     return *this;
     return *this;
 }
 }
 
 
+inline bool Vector3::operator<(const Vector3& v) const
+{
+    if (x == v.x)
+    {
+        if (y == v.y)
+        {
+            return z < v.z;
+        }
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector3::operator==(const Vector3& v) const
+{
+    return x==v.x && y==v.y && z==v.z;
+}
+
 inline Vector3 operator*(float x, const Vector3& v)
 inline Vector3 operator*(float x, const Vector3& v)
 {
 {
     Vector3 result(v);
     Vector3 result(v);

+ 18 - 0
gameplay/src/Vector4.h

@@ -406,6 +406,24 @@ public:
      * @return This vector, after the scale occurs.
      * @return This vector, after the scale occurs.
      */
      */
     inline Vector4& operator*=(float x);
     inline Vector4& operator*=(float x);
+
+    /**
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
+     */
+    inline bool operator<(const Vector4& v) const;
+
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector4& v) const;
 };
 };
 
 
 /**
 /**

+ 25 - 0
gameplay/src/Vector4.inl

@@ -54,6 +54,31 @@ inline Vector4& Vector4::operator*=(float x)
     return *this;
     return *this;
 }
 }
 
 
+inline bool Vector4::operator<(const Vector4& v) const
+{
+    if (x == v.x)
+    {
+        if (y == v.y)
+        {
+            if (z < v.z)
+            {
+                if (w < v.w)
+                {
+                    return w < v.w;
+                }
+            }
+            return z < v.z;
+        }
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector4::operator==(const Vector4& v) const
+{
+    return x==v.x && y==v.y && z==v.z && w==v.w;
+}
+
 inline Vector4 operator*(float x, const Vector4& v)
 inline Vector4 operator*(float x, const Vector4& v)
 {
 {
     Vector4 result(v);
     Vector4 result(v);