Răsfoiți Sursa

- Working changes for physics development.

Chris Culy 14 ani în urmă
părinte
comite
6605b00bb4
100 a modificat fișierele cu 3559 adăugiri și 1314 ștergeri
  1. 6 3
      gameplay-encoder/gameplay-binary.txt
  2. 8 0
      gameplay-encoder/gameplay-encoder.vcxproj
  3. 12 0
      gameplay-encoder/gameplay-encoder.vcxproj.filters
  4. 2 1
      gameplay-encoder/gameplay-encoder.vcxproj.user
  5. 9 8
      gameplay-encoder/src/Animation.cpp
  6. 1 1
      gameplay-encoder/src/Animation.h
  7. 23 23
      gameplay-encoder/src/AnimationChannel.cpp
  8. 13 12
      gameplay-encoder/src/AnimationChannel.h
  9. 54 0
      gameplay-encoder/src/Animations.cpp
  10. 39 0
      gameplay-encoder/src/Animations.h
  11. 2 0
      gameplay-encoder/src/Base.cpp
  12. 32 32
      gameplay-encoder/src/Camera.cpp
  13. 7 8
      gameplay-encoder/src/Camera.h
  14. 13 7
      gameplay-encoder/src/CameraInstance.cpp
  15. 1 1
      gameplay-encoder/src/CameraInstance.h
  16. 16 16
      gameplay-encoder/src/DAEChannelTarget.cpp
  17. 6 6
      gameplay-encoder/src/DAEChannelTarget.h
  18. 125 0
      gameplay-encoder/src/DAEOptimizer.cpp
  19. 63 0
      gameplay-encoder/src/DAEOptimizer.h
  20. 197 242
      gameplay-encoder/src/DAESceneEncoder.cpp
  21. 27 24
      gameplay-encoder/src/DAESceneEncoder.h
  22. 303 0
      gameplay-encoder/src/DAEUtil.cpp
  23. 126 0
      gameplay-encoder/src/DAEUtil.h
  24. 4 4
      gameplay-encoder/src/Effect.cpp
  25. 3 2
      gameplay-encoder/src/Effect.h
  26. 262 0
      gameplay-encoder/src/EncoderArguments.cpp
  27. 120 0
      gameplay-encoder/src/EncoderArguments.h
  28. 6 0
      gameplay-encoder/src/FileIO.cpp
  29. 20 20
      gameplay-encoder/src/GPBDecoder.cpp
  30. 2 2
      gameplay-encoder/src/GPBDecoder.h
  31. 48 67
      gameplay-encoder/src/GPBFile.cpp
  32. 17 16
      gameplay-encoder/src/GPBFile.h
  33. 47 47
      gameplay-encoder/src/Light.cpp
  34. 8 8
      gameplay-encoder/src/Light.h
  35. 12 9
      gameplay-encoder/src/LightInstance.cpp
  36. 1 1
      gameplay-encoder/src/LightInstance.h
  37. 5 5
      gameplay-encoder/src/Material.cpp
  38. 3 2
      gameplay-encoder/src/Material.h
  39. 5 5
      gameplay-encoder/src/MaterialParameter.cpp
  40. 3 2
      gameplay-encoder/src/MaterialParameter.h
  41. 7 3
      gameplay-encoder/src/Matrix.cpp
  42. 5 5
      gameplay-encoder/src/Matrix.h
  43. 6 4
      gameplay-encoder/src/Mesh.cpp
  44. 2 1
      gameplay-encoder/src/Mesh.h
  45. 20 16
      gameplay-encoder/src/MeshPart.cpp
  46. 3 3
      gameplay-encoder/src/MeshPart.h
  47. 18 58
      gameplay-encoder/src/MeshSkin.cpp
  48. 6 24
      gameplay-encoder/src/MeshSkin.h
  49. 19 15
      gameplay-encoder/src/Model.cpp
  50. 4 3
      gameplay-encoder/src/Model.h
  51. 38 34
      gameplay-encoder/src/Node.cpp
  52. 6 5
      gameplay-encoder/src/Node.h
  53. 16 8
      gameplay-encoder/src/Object.cpp
  54. 17 8
      gameplay-encoder/src/Object.h
  55. 2 0
      gameplay-encoder/src/Quaternion.h
  56. 17 17
      gameplay-encoder/src/Reference.cpp
  57. 6 4
      gameplay-encoder/src/Reference.h
  58. 9 9
      gameplay-encoder/src/ReferenceTable.cpp
  59. 14 1
      gameplay-encoder/src/ReferenceTable.h
  60. 19 19
      gameplay-encoder/src/Scene.cpp
  61. 4 3
      gameplay-encoder/src/Scene.h
  62. 32 1
      gameplay-encoder/src/StringUtil.cpp
  63. 1 0
      gameplay-encoder/src/StringUtil.h
  64. 14 2
      gameplay-encoder/src/TTFFontEncoder.cpp
  65. 1 1
      gameplay-encoder/src/TTFFontEncoder.h
  66. 7 0
      gameplay-encoder/src/Vector2.h
  67. 5 0
      gameplay-encoder/src/Vector3.h
  68. 5 0
      gameplay-encoder/src/Vector4.h
  69. 1 1
      gameplay-encoder/src/Vertex.h
  70. 21 169
      gameplay-encoder/src/main.cpp
  71. 101 28
      gameplay-resources/res/shaders/bumped-specular.fsh
  72. 79 17
      gameplay-resources/res/shaders/bumped-specular.vsh
  73. 90 20
      gameplay-resources/res/shaders/bumped.fsh
  74. 82 19
      gameplay-resources/res/shaders/bumped.vsh
  75. 96 22
      gameplay-resources/res/shaders/colored-specular.fsh
  76. 175 15
      gameplay-resources/res/shaders/colored-specular.vsh
  77. 87 13
      gameplay-resources/res/shaders/colored.fsh
  78. 168 10
      gameplay-resources/res/shaders/colored.vsh
  79. 97 26
      gameplay-resources/res/shaders/diffuse-specular.fsh
  80. 176 17
      gameplay-resources/res/shaders/diffuse-specular.vsh
  81. 88 14
      gameplay-resources/res/shaders/diffuse.fsh
  82. 173 14
      gameplay-resources/res/shaders/diffuse.vsh
  83. 3 3
      gameplay-resources/res/shaders/textured.fsh
  84. 65 5
      gameplay-resources/res/shaders/textured.vsh
  85. 12 3
      gameplay/gameplay.vcxproj
  86. 41 14
      gameplay/gameplay.vcxproj.filters
  87. 5 1
      gameplay/src/Animation.cpp
  88. 1 0
      gameplay/src/Animation.h
  89. 3 1
      gameplay/src/AnimationClip.cpp
  90. 1 2
      gameplay/src/AnimationClip.h
  91. 2 0
      gameplay/src/AnimationController.cpp
  92. 3 1
      gameplay/src/AnimationTarget.cpp
  93. 3 20
      gameplay/src/AudioBuffer.cpp
  94. 5 26
      gameplay/src/AudioController.cpp
  95. 1 2
      gameplay/src/AudioController.h
  96. 1 1
      gameplay/src/AudioSource.cpp
  97. 2 9
      gameplay/src/Base.h
  98. 9 9
      gameplay/src/BoundingBox.cpp
  99. 4 4
      gameplay/src/BoundingBox.h
  100. 10 10
      gameplay/src/BoundingSphere.cpp

+ 6 - 3
gameplay-encoder/gameplay-binary.txt

@@ -142,10 +142,14 @@ Reference
                 light                   Light
                 model                   Model
 ------------------------------------------------------------------------------------------------------
-3->Animation
+3->Animations
+                animations              Animation[]
+------------------------------------------------------------------------------------------------------
+4->Animation
+                id                      string
                 channels                AnimationChannel[]
 -----------------------------------------------------------------------------------------------------
-4->AnimationChannel
+5->AnimationChannel
                 targetId                string
                 targetAttribute         uint
                 keyTimes                float[]  (milliseconds)
@@ -209,7 +213,6 @@ Reference
 ------------------------------------------------------------------------------------------------------
 36->MeshSkin
                 bindShape               float[16]
-                rootJoint               string
                 joints                  xref:Node[]
                 jointsBindPoses         float[] // 16 * joints.length
 ------------------------------------------------------------------------------------------------------

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

@@ -16,14 +16,18 @@
     <ClCompile Include="src\Base.cpp" />
     <ClCompile Include="src\Camera.cpp" />
     <ClCompile Include="src\CameraInstance.cpp" />
+    <ClCompile Include="src\EncoderArguments.cpp" />
     <ClCompile Include="src\DAEChannelTarget.cpp" />
+    <ClCompile Include="src\DAEOptimizer.cpp" />
     <ClCompile Include="src\DAESceneEncoder.cpp" />
+    <ClCompile Include="src\DAEUtil.cpp" />
     <ClCompile Include="src\Effect.cpp" />
     <ClCompile Include="src\FileIO.cpp" />
     <ClCompile Include="src\Font.cpp" />
     <ClCompile Include="src\GPBFile.cpp" />
     <ClCompile Include="src\Glyph.cpp" />
     <ClCompile Include="src\GPBDecoder.cpp" />
+    <ClCompile Include="src\Animations.cpp" />
     <ClCompile Include="src\Light.cpp" />
     <ClCompile Include="src\LightInstance.cpp" />
     <ClCompile Include="src\main.cpp" />
@@ -55,14 +59,18 @@
     <ClInclude Include="src\Base.h" />
     <ClInclude Include="src\Camera.h" />
     <ClInclude Include="src\CameraInstance.h" />
+    <ClInclude Include="src\EncoderArguments.h" />
     <ClInclude Include="src\DAEChannelTarget.h" />
+    <ClInclude Include="src\DAEOptimizer.h" />
     <ClInclude Include="src\DAESceneEncoder.h" />
+    <ClInclude Include="src\DAEUtil.h" />
     <ClInclude Include="src\Effect.h" />
     <ClInclude Include="src\FileIO.h" />
     <ClInclude Include="src\Font.h" />
     <ClInclude Include="src\GPBFile.h" />
     <ClInclude Include="src\Glyph.h" />
     <ClInclude Include="src\GPBDecoder.h" />
+    <ClInclude Include="src\Animations.h" />
     <ClInclude Include="src\Light.h" />
     <ClInclude Include="src\LightInstance.h" />
     <ClInclude Include="src\Material.h" />

+ 12 - 0
gameplay-encoder/gameplay-encoder.vcxproj.filters

@@ -90,6 +90,12 @@
     <ClCompile Include="src\Matrix.cpp">
       <Filter>Math</Filter>
     </ClCompile>
+    <ClCompile Include="src\DAEOptimizer.cpp" />
+    <ClCompile Include="src\DAEUtil.cpp" />
+    <ClCompile Include="src\EncoderArguments.cpp" />
+    <ClCompile Include="src\Animations.cpp">
+      <Filter>Objects\Animation</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\DAESceneEncoder.h" />
@@ -180,6 +186,12 @@
     <ClInclude Include="src\Matrix.h">
       <Filter>Math</Filter>
     </ClInclude>
+    <ClInclude Include="src\DAEOptimizer.h" />
+    <ClInclude Include="src\DAEUtil.h" />
+    <ClInclude Include="src\EncoderArguments.h" />
+    <ClInclude Include="src\Animations.h">
+      <Filter>Objects\Animation</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Objects">

+ 2 - 1
gameplay-encoder/gameplay-encoder.vcxproj.user

@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LocalDebuggerCommandArguments>C:\svn\gaming\gameplay\gameplay-samples\sample03-character\res\meshes\test_Collada_DAE.dae</LocalDebuggerCommandArguments>
+    <LocalDebuggerCommandArguments>
+    </LocalDebuggerCommandArguments>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
 </Project>

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

@@ -23,20 +23,21 @@ const char* Animation::getElementName(void) const
 void Animation::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    // Write AnimationChannels
-    write(channels.size(), file);
-    for (std::vector<AnimationChannel*>::iterator i = channels.begin(); i != channels.end(); i++)
+    // Animation writes its ID because it is not listed in the ref table.
+    write(getId(), file);
+    write(_channels.size(), file);
+    for (std::vector<AnimationChannel*>::iterator i = _channels.begin(); i != _channels.end(); i++)
     {
         (*i)->writeBinary(file);
     }
 }
 
 void Animation::writeText(FILE* 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);
         }
@@ -46,12 +47,12 @@ void Animation::writeText(FILE* file)
 
 void Animation::add(AnimationChannel* animationChannel)
 {
-    channels.push_back(animationChannel);
+    _channels.push_back(animationChannel);
 }
 
 unsigned int Animation::getAnimationChannelCount() const
 {
-    return channels.size();
+    return _channels.size();
 }
 
 }

+ 1 - 1
gameplay-encoder/src/Animation.h

@@ -35,7 +35,7 @@ public:
     unsigned int getAnimationChannelCount() const;
 
 private:
-    std::vector<AnimationChannel*> channels;
+    std::vector<AnimationChannel*> _channels;
 };
 
 }

+ 23 - 23
gameplay-encoder/src/AnimationChannel.cpp

@@ -4,7 +4,7 @@ namespace gameplay
 {
 
 AnimationChannel::AnimationChannel(void) :
-    targetAttrib(0)
+    _targetAttrib(0)
 {
 }
 
@@ -24,66 +24,66 @@ const char* AnimationChannel::getElementName(void) const
 void AnimationChannel::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    write(targetId, file);
-    write(targetAttrib, file);
-    write(keytimes, file);
-    write(keyValues, file);
-    write(tangentsIn, file);
-    write(tangentsOut, file);
-    write(interpolations, file);
+    write(_targetId, file);
+    write(_targetAttrib, file);
+    write(_keytimes, file);
+    write(_keyValues, file);
+    write(_tangentsIn, file);
+    write(_tangentsOut, file);
+    write(_interpolations, file);
 }
 
 void AnimationChannel::writeText(FILE* file)
 {
     fprintElementStart(file);
-    fprintfElement(file, "targetId", targetId);
-    fprintfElement(file, "targetAttrib", targetAttrib);
-    fprintfElement(file, "%f ", "keytimes", keytimes);
-    fprintfElement(file, "%f ", "values", keyValues);
-    fprintfElement(file, "%f ", "tangentsIn", tangentsIn);
-    fprintfElement(file, "%f ", "tangentsOut", tangentsOut);
-    fprintfElement(file, "%u ", "interpolations", interpolations);
+    fprintfElement(file, "targetId", _targetId);
+    fprintfElement(file, "targetAttrib", _targetAttrib);
+    fprintfElement(file, "%f ", "keytimes", _keytimes);
+    fprintfElement(file, "%f ", "values", _keyValues);
+    fprintfElement(file, "%f ", "tangentsIn", _tangentsIn);
+    fprintfElement(file, "%f ", "tangentsOut", _tangentsOut);
+    fprintfElement(file, "%u ", "interpolations", _interpolations);
     fprintElementEnd(file);
 }
 
 void AnimationChannel::setTargetId(const std::string str)
 {
-    targetId = str;
+    _targetId = str;
 }
 
 void AnimationChannel::setTargetAttribute(unsigned int attrib)
 {
-    targetAttrib = attrib;
+    _targetAttrib = attrib;
 }
 
 void AnimationChannel::setKeyTimes(const std::vector<float>& values)
 {
-    keytimes = values;
+    _keytimes = values;
 }
 
 void AnimationChannel::setKeyValues(const std::vector<float>& values)
 {
-    keyValues = values;
+    _keyValues = values;
 }
 
 void AnimationChannel::setTangentsIn(const std::vector<float>& values)
 {
-    tangentsIn = values;
+    _tangentsIn = values;
 }
 
 void AnimationChannel::setTangentsOut(const std::vector<float>& values)
 {
-    tangentsOut = values;
+    _tangentsOut = values;
 }
 
 void AnimationChannel::setInterpolations(const std::vector<unsigned int>& values)
 {
-    interpolations = values;
+    _interpolations = values;
 }
 
 const std::vector<float>& AnimationChannel::getKeyValues() const
 {
-    return keyValues;
+    return _keyValues;
 }
 
 unsigned int AnimationChannel::getInterpolationType(const char* str)

+ 13 - 12
gameplay-encoder/src/AnimationChannel.h

@@ -12,11 +12,11 @@ public:
 
     enum InterpolationTypes
     {
-        LINEAR = 1, 
-        BEZIER = 2, 
-        CARDINAL = 3, 
-        HERMITE = 4, 
-        BSPLINE = 5, 
+        LINEAR = 1,
+        BEZIER = 2,
+        CARDINAL = 3,
+        HERMITE = 4,
+        BSPLINE = 5,
         STEP = 6
     };
 
@@ -51,6 +51,7 @@ public:
      * Example: "LINEAR" returns AnimationChannel::LINEAR
      * 
      * @param str Interpolation such as "LINEAR" or "BSPLINE".
+     * 
      * @return A value from InterpolationTypes enum or zero if not valid.
      */
     static unsigned int getInterpolationType(const char* str);
@@ -58,13 +59,13 @@ public:
 
 private:
 
-    std::string targetId;
-    unsigned int targetAttrib;
-    std::vector<float> keytimes;
-    std::vector<float> keyValues;
-    std::vector<float> tangentsIn;
-    std::vector<float> tangentsOut;
-    std::vector<unsigned int> interpolations;
+    std::string _targetId;
+    unsigned int _targetAttrib;
+    std::vector<float> _keytimes;
+    std::vector<float> _keyValues;
+    std::vector<float> _tangentsIn;
+    std::vector<float> _tangentsOut;
+    std::vector<unsigned int> _interpolations;
 };
 
 

+ 54 - 0
gameplay-encoder/src/Animations.cpp

@@ -0,0 +1,54 @@
+#include "Animations.h"
+
+namespace gameplay
+{
+
+Animations::Animations(void)
+{
+    // There will only be one Animations.
+    // It requires an ID because it will be stores in the ref table.
+    setId("__Animations__");
+}
+
+Animations::~Animations(void)
+{
+}
+
+unsigned int Animations::getTypeId(void) const
+{
+    return ANIMATIONS_ID;
+}
+const char* Animations::getElementName(void) const
+{
+    return "Animations";
+}
+
+void Animations::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+    write(_animations.size(), file);
+    for (std::vector<Animation*>::iterator i = _animations.begin(); i != _animations.end(); i++)
+    {
+        (*i)->writeBinary(file);
+    }
+}
+
+void Animations::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    if (_animations.size() > 0 )
+    {
+        for (std::vector<Animation*>::iterator i = _animations.begin(); i != _animations.end(); i++)
+        {
+            (*i)->writeText(file);
+        }
+    }
+    fprintElementEnd(file);
+}
+
+void Animations::add(Animation* animation)
+{
+    _animations.push_back(animation);
+}
+
+}

+ 39 - 0
gameplay-encoder/src/Animations.h

@@ -0,0 +1,39 @@
+#ifndef LIBRARYANIMATIONS_H_
+#define LIBRARYANIMATIONS_H_
+
+#include "Object.h"
+#include "Animation.h"
+
+namespace gameplay
+{
+
+/**
+ * Animations contains all of the animations in the GamePlay Binary file.
+ */
+class Animations : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    Animations(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Animations(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    void add(Animation* animation);
+
+private:
+    std::vector<Animation*> _animations;
+};
+
+}
+#endif

+ 2 - 0
gameplay-encoder/src/Base.cpp

@@ -6,7 +6,9 @@ namespace gameplay
 void fillArray(float values[], float value, size_t length)
 {
     for (size_t i = 0; i < length; i++)
+    {
         values[i] = value;
+    }
 }
 
 void setIdentityMatrix(float values[])

+ 32 - 32
gameplay-encoder/src/Camera.cpp

@@ -5,12 +5,12 @@ namespace gameplay
 {
 
 Camera::Camera(void) :
-    fieldOfView(0.0f),
-    aspectRatio(0.0f),
-    nearPlane(0.0f),
-    farPlane(0.0f),
-    viewportWidth(0.0f),
-    viewportHeight(0.0f)
+    _fieldOfView(0.0f),
+    _aspectRatio(0.0f),
+    _nearPlane(0.0f),
+    _farPlane(0.0f),
+    _viewportWidth(0.0f),
+    _viewportHeight(0.0f)
 {
 }
 
@@ -20,25 +20,25 @@ Camera::~Camera(void)
 
 void Camera::setFieldOfView(float value)
 {
-    fieldOfView = value;
+    _fieldOfView = value;
 }
 
 
 void Camera::setAspectRatio(float value)
 {
-    aspectRatio = value;
+    _aspectRatio = value;
 }
 
 
 void Camera::setNearPlane(float value)
 {
-    nearPlane = value;
+    _nearPlane = value;
 }
 
 
 void Camera::setFarPlane(float value)
 {
-    farPlane = value;
+    _farPlane = value;
 }
 
 unsigned int Camera::getTypeId(void) const
@@ -53,16 +53,16 @@ const char* Camera::getElementName(void) const
 void Camera::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    write(cameraType, file);
-    write(aspectRatio, file);
-    write(nearPlane, file);
-    write(farPlane, file);
+    write(_cameraType, file);
+    write(_aspectRatio, file);
+    write(_nearPlane, file);
+    write(_farPlane, file);
 
-    if (cameraType == CameraPerspective)
+    if (_cameraType == CameraPerspective)
     {
-        write(fieldOfView, file);
+        write(_fieldOfView, file);
     }
-    else if (cameraType == CameraOrthographic)
+    else if (_cameraType == CameraOrthographic)
     {
         write(getViewPortWidth(), file);
         write(getViewPortHeight(), file);
@@ -75,19 +75,19 @@ void Camera::writeBinary(FILE* file)
 void Camera::writeText(FILE* file)
 {
     fprintElementStart(file);
-    fprintfElement(file, "cameraType", cameraType == CameraPerspective ? "CameraPerspective" : "CameraOrthographic");
-    fprintfElement(file, "aspectRatio", aspectRatio);
-    fprintfElement(file, "nearPlane", nearPlane);
-    fprintfElement(file, "farPlane", farPlane);
+    fprintfElement(file, "cameraType", _cameraType == CameraPerspective ? "CameraPerspective" : "CameraOrthographic");
+    fprintfElement(file, "aspectRatio", _aspectRatio);
+    fprintfElement(file, "nearPlane", _nearPlane);
+    fprintfElement(file, "farPlane", _farPlane);
 
-    if (cameraType == CameraPerspective)
+    if (_cameraType == CameraPerspective)
     {
-        fprintfElement(file, "fieldOfView", fieldOfView);
+        fprintfElement(file, "fieldOfView", _fieldOfView);
     }
-    else if (cameraType == CameraOrthographic)
+    else if (_cameraType == CameraOrthographic)
     {
-        fprintfElement(file, "viewportWidth", viewportWidth);
-        fprintfElement(file, "viewportHeight", viewportHeight);
+        fprintfElement(file, "viewportWidth", _viewportWidth);
+        fprintfElement(file, "viewportHeight", _viewportHeight);
     }
     else
     {
@@ -98,28 +98,28 @@ void Camera::writeText(FILE* file)
 
 void Camera::setPerspective()
 {
-    cameraType = CameraPerspective;
+    _cameraType = CameraPerspective;
 }
 void Camera::setOrthographic()
 {
-    cameraType = CameraOrthographic;
+    _cameraType = CameraOrthographic;
 }
 void Camera::setViewportWidth(float width)
 {
-    viewportWidth = width;
+    _viewportWidth = width;
 }
 void Camera::setViewportHeight(float height)
 {
-    viewportHeight = height;
+    _viewportHeight = height;
 }
 
 float Camera::getViewPortWidth()
 {
-    return viewportWidth;
+    return _viewportWidth;
 }
 float Camera::getViewPortHeight()
 {
-    return viewportHeight;
+    return _viewportHeight;
 }
 
 }

+ 7 - 8
gameplay-encoder/src/Camera.h

@@ -44,14 +44,13 @@ public:
     };
 
 private:
-    unsigned char cameraType;
-    float viewport[4];
-    float fieldOfView;
-    float aspectRatio;
-    float nearPlane;
-    float farPlane;
-    float viewportWidth;
-    float viewportHeight;
+    unsigned char _cameraType;
+    float _fieldOfView;
+    float _aspectRatio;
+    float _nearPlane;
+    float _farPlane;
+    float _viewportWidth;
+    float _viewportHeight;
 };
 
 }

+ 13 - 7
gameplay-encoder/src/CameraInstance.cpp

@@ -3,7 +3,7 @@
 namespace gameplay
 {
 
-CameraInstance::CameraInstance(void) : ref(NULL)
+CameraInstance::CameraInstance(void) : _ref(NULL)
 {
 
 }
@@ -23,25 +23,31 @@ const char* CameraInstance::getElementName(void) const
 
 void CameraInstance::writeBinary(FILE* file)
 {
-    if (ref != NULL)
-        ref->writeBinary(file);
+    if (_ref != NULL)
+    {
+        _ref->writeBinary(file);
+    }
     else
+    {
         write((unsigned int)0, file);
+    }
 }
 void CameraInstance::writeText(FILE* file)
 {
-    if (ref != NULL)
-        ref->writeText(file);
+    if (_ref != NULL)
+    {
+        _ref->writeText(file);
+    }
 }
 
 Camera* CameraInstance::getCamera()
 {
-    return ref;
+    return _ref;
 }
 
 void CameraInstance::setCamera(Camera* camera)
 {
-    ref = camera;
+    _ref = camera;
 }
 
 }

+ 1 - 1
gameplay-encoder/src/CameraInstance.h

@@ -29,7 +29,7 @@ public:
     Camera* getCamera();
     void setCamera(Camera* camera);
 private:
-    Camera* ref;
+    Camera* _ref;
 };
 
 }

+ 16 - 16
gameplay-encoder/src/DAEChannelTarget.cpp

@@ -5,21 +5,21 @@
 namespace gameplay
 {
 
-DAEChannelTarget::DAEChannelTarget(const domChannel* channelRef) : channel(NULL), targetElement(NULL)
+DAEChannelTarget::DAEChannelTarget(const domChannel* channelRef) : _channel(NULL), _targetElement(NULL)
 {
-    channel = channelRef;
+    _channel = channelRef;
     const std::string target = channelRef->getTarget();
     size_t index = target.find('/');
     if (index == std::string::npos)
     {
         // If the string doesn't contain a '/' then the whole string is the id
         // and there are no sid's being targeted.
-        targetId = target;
+        _targetId = target;
     }
     else
     {
         // The targetId is the part before the first '/'
-        targetId = target.substr(0, index);
+        _targetId = target.substr(0, index);
 
         // each '/' denotes another sid
         size_t start;
@@ -40,7 +40,7 @@ DAEChannelTarget::DAEChannelTarget(const domChannel* channelRef) : channel(NULL)
                 sub = target.substr(start, end - start);
                 index = end + 1;
             }
-            attributeIds.push_back(sub);
+            _attributeIds.push_back(sub);
         } while(end != std::string::npos);
     }
 
@@ -52,31 +52,31 @@ DAEChannelTarget::~DAEChannelTarget(void)
 
 daeElement* DAEChannelTarget::getTargetElement()
 {
-    if (!targetElement && targetId.length() > 0)
+    if (!_targetElement && _targetId.length() > 0)
     {
-        daeSIDResolver resolver(channel->getDocument()->getDomRoot(), targetId.c_str());
-        targetElement = resolver.getElement();
+        daeSIDResolver resolver(_channel->getDocument()->getDomRoot(), _targetId.c_str());
+        _targetElement = resolver.getElement();
     }
-    return targetElement;
+    return _targetElement;
 }
 
 const std::string& DAEChannelTarget::getTargetId() const
 {
-    return targetId;
+    return _targetId;
 }
 
 size_t DAEChannelTarget::getTargetAttributeCount() const
 {
-    return attributeIds.size();
+    return _attributeIds.size();
 }
 
 daeElement* DAEChannelTarget::getTargetAttribute(size_t index)
 {
-    if (index >= attributeIds.size())
+    if (index >= _attributeIds.size())
     {
         return NULL;
     }
-    const std::string& att = attributeIds[index];
+    const std::string& att = _attributeIds[index];
     std::string sid = att.substr(0, att.find('.'));
     daeSIDResolver resolver(getTargetElement(), sid.c_str());
     return resolver.getElement();
@@ -84,14 +84,14 @@ daeElement* DAEChannelTarget::getTargetAttribute(size_t index)
 
 void DAEChannelTarget::getPropertyName(size_t index, std::string* str)
 {
-    if (index < attributeIds.size())
+    if (index < _attributeIds.size())
     {
         // The property name is the string segment after the '.'
         // The propery is optional so it might not be found.
-        const std::string& att = attributeIds[index];
+        const std::string& att = _attributeIds[index];
         size_t i = att.find('.');
         if (i != std::string::npos && i < att.size())
-        {   
+        {
             str->assign(att.substr(i+1));
             return;
         }

+ 6 - 6
gameplay-encoder/src/DAEChannelTarget.h

@@ -68,17 +68,17 @@ public:
 
 private:
     /**
-     * Pointer to the <channel> element. 
+     * Pointer to the <channel> element.
      */
-    const domChannel* channel;
+    const domChannel* _channel;
 
-    domElement* targetElement;
+    domElement* _targetElement;
 
     /**
-     * The first part is the id attribute of an element in the instance document 
+     * The first part is the id attribute of an element in the instance document
      * or a dot segment (".") indicating that this is a relative address.
      */
-    std::string targetId;
+    std::string _targetId;
 
     /**
      * A channel target can have zero or more target attributes.
@@ -87,7 +87,7 @@ private:
      * Result: attributeIds will contain 2 elements. "Translate.X" and "Translate.Y"
      * Refer to the COLLADA spec "COLLADA Target Addressing".
      */
-    std::vector<std::string> attributeIds;
+    std::vector<std::string> _attributeIds;
 };
 
 }

+ 125 - 0
gameplay-encoder/src/DAEOptimizer.cpp

@@ -0,0 +1,125 @@
+#include "DAEOptimizer.h"
+
+#include <algorithm>
+
+#include "StringUtil.h"
+
+DAEOptimizer::DAEOptimizer(domCOLLADA* dom)
+{
+    _dom = dom;
+}
+
+DAEOptimizer::~DAEOptimizer()
+{   
+}
+
+void DAEOptimizer::combineAnimations(const std::string& nodeId, const std::string& animationId)
+{
+    std::list<domChannelRef> channels;
+
+    daeSIDResolver resolver(_dom, nodeId.c_str());
+    daeElement* element = resolver.getElement();
+    if (element && element->getElementType() == COLLADA_TYPE::NODE)
+    {
+        domNodeRef node = daeSafeCast<domNode>(resolver.getElement());
+        getAnimationChannels(node, channels);
+    }
+
+    // Get the <library_animations>
+    domLibrary_animations_Array& animationsLibraryArray = _dom->getLibrary_animations_array();
+    assert(animationsLibraryArray.getCount() > 0);
+    domLibrary_animationsRef& animationsLibrary = animationsLibraryArray.get(0);
+
+    // Add a new animation
+    domAnimationRef animation = daeSafeCast<domAnimation>(animationsLibrary->createAndPlace("animation"));
+    assert(animation);
+    animation->setId(animationId.c_str());
+    // TODO: Make sure that there doesn't already exist an animation with this ID.
+
+    // Move each of the channels to this animation
+    for (std::list<domChannelRef>::iterator i = channels.begin(); i != channels.end(); i++)
+    {
+        moveChannelAndSouresToAnimation(*i, animation);
+    }
+
+    // Clean up the empty animations
+    deleteEmptyAnimations();
+}
+
+void DAEOptimizer::getAnimationChannels(const domNodeRef& node, std::list<domChannelRef>& channels)
+{
+    assert(node->getId());
+    std::string nodeIdSlash (node->getId());
+    nodeIdSlash.append("/");
+
+    domCOLLADA* root = (domCOLLADA*)node->getDocument()->getDomRoot();
+
+    domLibrary_animations_Array& animationLibrary = root->getLibrary_animations_array();
+    size_t animationLibraryCount = animationLibrary.getCount();
+    for (size_t i = 0; i < animationLibraryCount; i++)
+    {
+        domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
+        domAnimation_Array& animationArray = animationsRef->getAnimation_array();
+        size_t animationCount = animationArray.getCount();
+        for (size_t j = 0; j < animationCount; j++)
+        {
+            domAnimationRef& animationRef = animationArray.get(j);
+            domChannel_Array& channelArray = animationRef->getChannel_array();
+            size_t channelArrayCount = channelArray.getCount();
+            for (size_t k = 0; k < channelArrayCount; k++)
+            {
+                domChannelRef& channel = channelArray.get(k);
+                const char* target = channel->getTarget();
+
+                // TODO: Assumes only one target per channel?
+                if (startsWith(target, nodeIdSlash.c_str()))
+                {
+                    channels.push_back(channel);
+                }
+            }
+        }
+    }
+
+    // Recursively do the same for all nodes
+    daeTArray<daeSmartRef<daeElement>> children;
+    node->getChildren(children);
+    size_t childCount = children.getCount();
+    for (size_t i = 0; i < childCount; i++)
+    {
+        daeElementRef childElement = children[i];
+        if (childElement->getElementType() == COLLADA_TYPE::NODE)
+        {
+            domNodeRef childNode = daeSafeCast<domNode>(childElement);
+            getAnimationChannels(childNode, channels);
+        }
+    }
+}
+
+void DAEOptimizer::deleteEmptyAnimations()
+{
+    std::list<domAnimationRef> animations;
+    
+    // Get the list of empty animations
+    domLibrary_animations_Array& animationLibrary = _dom->getLibrary_animations_array();
+    size_t animationLibraryCount = animationLibrary.getCount();
+    for (size_t i = 0; i < animationLibraryCount; i++)
+    {
+        domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
+        domAnimation_Array& animationArray = animationsRef->getAnimation_array();
+        size_t animationCount = animationArray.getCount();
+        for (size_t j = 0; j < animationCount; j++)
+        {
+            domAnimationRef& animation = animationArray.get(j);
+            if (isEmptyAnimation(animation))
+            {
+                animations.push_back(animation);
+            }
+        }
+    }
+
+    // Delete all of the empty animations
+    for (std::list<domAnimationRef>::iterator i = animations.begin(); i != animations.end(); i++)
+    {
+        daeElement::removeFromParent(*i);
+    }
+}

+ 63 - 0
gameplay-encoder/src/DAEOptimizer.h

@@ -0,0 +1,63 @@
+#ifndef DAEOPTIMIZER_H_
+#define DAEOPTIMIZER_H_
+
+#include <dae.h>
+#include <dae/daeSIDResolver.h>
+#include <dae/domAny.h>
+#include <dom/domCOLLADA.h>
+#include <dom/domConstants.h>
+#include <dom/domElements.h>
+#include <dom/domProfile_COMMON.h>
+
+#include <vector>
+
+#include "Base.h"
+#include "DAEUtil.h"
+
+/**
+ * The DAEOptimizer optimizes a COLLADA dom.
+ */
+class DAEOptimizer
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    DAEOptimizer(domCOLLADA* dom);
+
+    /**
+     * Destructor.
+     */
+    ~DAEOptimizer(void);
+
+    /**
+     * Combines all of the animations that target the node and all of its child nodes into a new animation with the given ID.
+     * 
+     * @param nodeId The ID of the node.
+     * @param animationId The ID of the new animation to create.
+     */
+    void combineAnimations(const std::string& nodeId, const std::string& animationId);
+
+private:
+
+    /**
+     * Gets all of the animation channels that target the given node and appends them to the list.
+     * 
+     * @param node The node that the animation channels target.
+     * @param channels The list of channels to append to.
+     */
+    void getAnimationChannels(const domNodeRef& node, std::list<domChannelRef>& channels);
+
+    /**
+     * Deletes all of the empty animations in the dom.
+     */
+    void deleteEmptyAnimations();
+
+private:
+    
+    domCOLLADA* _dom;
+    std::string _inputPath;
+};
+
+#endif

+ 197 - 242
gameplay-encoder/src/DAESceneEncoder.cpp

@@ -5,11 +5,14 @@
 #include <algorithm>
 
 #include "DAESceneEncoder.h"
+#include "DAEOptimizer.h"
+
+//#define ENCODER_PRINT_TIME 1
 
 using namespace gameplay;
 
 DAESceneEncoder::DAESceneEncoder()
-    : _collada(NULL), file(NULL), vertexBlendWeights(NULL), vertexBlendIndices(NULL)
+    : _collada(NULL), _dom(NULL), file(NULL), _vertexBlendWeights(NULL), _vertexBlendIndices(NULL)
 {
 }
 
@@ -49,6 +52,31 @@ unsigned int getMaxOffset(domInputLocalOffset_Array& inputArray)
     return maxOffset;
 }
 
+void DAESceneEncoder::optimizeCOLLADA(const EncoderArguments& arguments, domCOLLADA* dom)
+{
+    DAEOptimizer optimizer(dom);
+    const std::vector<std::string>& groupAnimatioNodeIds = arguments.getGroupAnimationNodeId();
+    const std::vector<std::string>& groupAnimatioIds = arguments.getGroupAnimationAnimationId();
+    assert(groupAnimatioNodeIds.size() == groupAnimatioIds.size());
+    size_t size = groupAnimatioNodeIds.size();
+    if (size > 0)
+    {
+        begin();
+        for (size_t i = 0; i < size; i++)
+        {
+            optimizer.combineAnimations(groupAnimatioNodeIds[i], groupAnimatioIds[i]);
+        }
+        end("groupAnimation");
+    }
+    if (arguments.DAEOutputEnabled())
+    {
+        if (!_collada->writeTo(arguments.getFilePath(), arguments.getDAEOutputPath()))
+        {
+            fprintf(stderr,"Error: COLLADA failed to write the dom for file:%s\n", arguments.getDAEOutputPath().c_str());
+        }
+    }
+}
+
 void DAESceneEncoder::triangulate(DAE* dae)
 {
     daeDatabase* dataBase = dae->getDatabase();
@@ -213,14 +241,21 @@ void DAESceneEncoder::createTrianglesFromPolylist(domMesh* domMesh, domPolylist*
     triangles->setCount(trianglesProcessed);
 }
 
-void DAESceneEncoder::write(const std::string& filepath, const char* nodeId, bool text)
+void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments& arguments)
 {
+    _begin = std::clock();
+    const char* nodeId = arguments.getNodeId();
+    bool text = arguments.textOutputEnabled();
+
     std::string filenameOnly = getFilenameFromFilePath(filepath);
     std::string dstPath = filepath.substr(0, filepath.find_last_of('/'));
     
     // Load the collada document
     _collada = new DAE();
-    if (_collada->load(filepath.c_str()) != DAE_OK)
+    begin();
+    _dom = _collada->open(filepath);
+    end("Open file");
+    if (!_dom)
     {
         fprintf(stderr,"Error: COLLADA failed to open file:%s\n", filepath.c_str());
         if (_collada)
@@ -230,35 +265,35 @@ void DAESceneEncoder::write(const std::string& filepath, const char* nodeId, boo
         }
         return;
     }
-
-    // Get the dom tree
-    domCOLLADA* dom = _collada->getDom(filepath.c_str());
-    if (!dom)
-    {
-        fprintf(stderr,"Error: COLLADA failed to the dom for file:%s\n", filepath.c_str());
-        if (_collada)
-        {
-            delete _collada;
-            _collada = NULL;
-        }
-        return;
-    }
     
     // Run collada conditioners
+    begin();
     triangulate(_collada);
+    end("triangulate");
+
+    // Optimize the dom before encoding
+    optimizeCOLLADA(arguments, _dom);
 
     // Find the <visual_scene> element within the <scene>
-    const domCOLLADA::domSceneRef& domScene = dom->getScene();
+    const domCOLLADA::domSceneRef& domScene = _dom->getScene();
     daeElement* scene = NULL;
     if (domScene && domScene->getInstance_visual_scene())
     {
         scene = domScene->getInstance_visual_scene()->getUrl().getElement();
+        if (scene->getElementType() != COLLADA_TYPE::VISUAL_SCENE)
+        {
+            // This occured once where Maya exported a Node and Scene element with the same ID.
+            fprintf(stderr,"Error: instance_visual_scene does not reference visual_scene for file:%s\n", filepath.c_str());
+            return;
+        }
         if (scene)
         {
             if (nodeId == NULL)
             {
                 // If the -n <node_id> parameter was not passed then write out the entire scene.
+                begin();
                 loadScene((domVisual_scene*)scene);
+                end("load scene");
             }
             else
             {
@@ -286,7 +321,9 @@ void DAESceneEncoder::write(const std::string& filepath, const char* nodeId, boo
     }
     
     // The animations should be loaded last
-    loadAnimations(dom);
+    begin();
+    loadAnimations(_dom);
+    end("loadAnimations");
 
     std::string dstFilename = dstPath;
     dstFilename.append(1, '/');
@@ -296,11 +333,17 @@ void DAESceneEncoder::write(const std::string& filepath, const char* nodeId, boo
 
     if (text)
     {
-        _gamePlayFile.saveText(dstFilename + ".xml");
+        std::string outFile = dstFilename + ".xml";
+        fprintf(stderr, "Saving debug file: %s\n", outFile.c_str());
+        _gamePlayFile.saveText(outFile);
     }
     else
     {
-        _gamePlayFile.saveBinary(dstFilename + ".gpb");
+        std::string outFile = dstFilename + ".gpb";
+        fprintf(stderr, "Saving binary file: %s\n", outFile.c_str());
+        begin();
+        _gamePlayFile.saveBinary(outFile);
+        end("save binary");
     }
     
     // Cleanup
@@ -325,21 +368,25 @@ void DAESceneEncoder::loadAnimations(const domCOLLADA* dom)
         const domLibrary_animationsRef& animationsRef = animationLibrary.get(i);
         const domAnimation_Array& animationArray = animationsRef->getAnimation_array();
         size_t animationCount = animationArray.getCount();
-        for (size_t i = 0; i < animationCount; i++)
+        for (size_t j = 0; j < animationCount; j++)
         {
-            const domAnimationRef& animationRef = animationArray.get(i);
+            const domAnimationRef& animationRef = animationArray.get(j);
             loadAnimation(animationRef);
         }
     }
 }
 
-void DAESceneEncoder::loadAnimation(const domAnimation* animationRef)
+void DAESceneEncoder::loadAnimation(const domAnimationRef animationRef)
 {
     // <channel> points to one <sampler>
     // <sampler> points to multiple <input> elements
 
     Animation* animation = new Animation();
-    animation->setId(findAnimationId(animationRef));
+    const char* str = animationRef->getId();
+    if (str)
+    {
+        animation->setId(str);
+    }
 
     // <channel>
     const domChannel_Array& channelArray = animationRef->getChannel_array();
@@ -351,20 +398,18 @@ void DAESceneEncoder::loadAnimation(const domAnimation* animationRef)
         const domChannelRef& channelRef = channelArray.get(i);
 
         // <sampler>
-        daeElement* samplerElement = channelRef->getSource().getElement();
-        assert(samplerElement);
-        const domSampler* sampler = static_cast<domSampler*>(samplerElement);
+        const domSamplerRef sampler = getSampler(channelRef);
+        assert(sampler);
 
         // <input>
         const domInputLocal_Array& inputArray = sampler->getInput_array();
         size_t inputArrayCount = inputArray.getCount();
-        for (size_t i = 0; i < inputArrayCount; i++)
+        for (size_t j = 0; j < inputArrayCount; j++)
         {
-            const domInputLocalRef& inputLocal = inputArray.get(i);
+            const domInputLocalRef& inputLocal = inputArray.get(j);
 
             // <source>
-            daeElement* sourceElement = inputLocal->getSource().getElement();
-            const domSource* source = static_cast<domSource*>(sourceElement);
+            const domSourceRef source = getSource(inputLocal, animationRef);
 
             std::string semantic = inputLocal->getSemantic();
             if (equals(semantic, "INTERPOLATION"))
@@ -380,10 +425,10 @@ void DAESceneEncoder::loadAnimation(const domAnimation* animationRef)
                 if (equals(semantic, "INPUT"))
                 {
                     // TODO: Ensure param name is TIME?
-                    for (std::vector<float>::iterator i = floats.begin(); i != floats.end(); i++)
+                    for (std::vector<float>::iterator k = floats.begin(); k != floats.end(); k++)
                     {
                         // Convert seconds to milliseconds
-                        *i = *i * 1000.0f;
+                        *k = *k * 1000.0f;
                     }
                     animationChannel->setKeyTimes(floats);
                 }
@@ -403,43 +448,6 @@ void DAESceneEncoder::loadAnimation(const domAnimation* animationRef)
         }
         // get target attribute enum value
         loadTarget(channelRef, animationChannel);
-        
-        // Set the ID of the AnimationChannel
-        std::string channelId = channelRef->getTarget();
-        replace(channelId.begin(), channelId.end(), '/', '_');
-        // ensure no duplicate IDs
-        while (_gamePlayFile.idExists(channelId))
-        {
-            channelId.append("_");
-        }
-        animationChannel->setId(channelId);
-
-        // Animations that target a joint should be grouped with the other animations for that skin.
-        // If this animation channel targets a joint then add the animation channel to the skin's animation instead.
-        DAEChannelTarget channelTarget(channelRef);
-        daeElement* element = channelTarget.getTargetElement();
-        daeInt type = element->typeID();
-        if (type == domNode::ID())
-        {
-            const domNode* node = daeSafeCast<domNode>(element);
-            if (node->getType() == NODETYPE_JOINT)
-            {
-                const char* id = node->getId();
-                if (id)
-                {
-                    Animation* skinAnimation = _gamePlayFile.findAnimationForJoint(id);
-                    if (skinAnimation)
-                    {
-                        // TODO: Assert will fail if <controller> doesn't have an ID.
-                        assert(skinAnimation->getId().length() > 0);
-                        skinAnimation->add(animationChannel);
-                        _gamePlayFile.addAnimation(skinAnimation);
-                        continue;
-                    }
-                }
-            }
-        }
-
         animation->add(animationChannel);
     }
     if (animation->getAnimationChannelCount() > 0)
@@ -452,11 +460,13 @@ void DAESceneEncoder::loadAnimation(const domAnimation* animationRef)
     }
 }
 
-void DAESceneEncoder::loadInterpolation(const domSource* source, AnimationChannel* animationChannel)
+void DAESceneEncoder::loadInterpolation(const domSourceRef source, AnimationChannel* animationChannel)
 {
     // COLLADA stores the interpolations as a list of strings while GBP uses unsigned int
     std::vector<unsigned int> values;
-    const domListOfNames& names = source->getName_array()->getValue();
+    const domName_arrayRef nameArray = getSourceNameArray(source);
+    assert(nameArray);
+    const domListOfNames& names = nameArray->getValue();
     size_t count = (size_t)names.getCount();
     values.resize(count);
     if (count > 0)
@@ -597,9 +607,9 @@ void DAESceneEncoder::loadTarget(const domChannel* channelRef, AnimationChannel*
                     size_t j = i * 16;
                     // COLLADA used row-major but the Matrix class uses column-major
                     Matrix matrix(
-                        keyValues[j+0], keyValues[j+4], keyValues[j+8], keyValues[j+12], 
-                        keyValues[j+1], keyValues[j+5], keyValues[j+9], keyValues[j+13], 
-                        keyValues[j+2], keyValues[j+6], keyValues[j+10], keyValues[j+14], 
+                        keyValues[j+0], keyValues[j+4], keyValues[j+8], keyValues[j+12],
+                        keyValues[j+1], keyValues[j+5], keyValues[j+9], keyValues[j+13],
+                        keyValues[j+2], keyValues[j+6], keyValues[j+10], keyValues[j+14],
                         keyValues[j+3], keyValues[j+7], keyValues[j+11], keyValues[j+15]);
                     Vector3 scale;
                     Quaternion rotation;
@@ -626,30 +636,19 @@ void DAESceneEncoder::loadTarget(const domChannel* channelRef, AnimationChannel*
     animationChannel->setTargetId(channelTarget.getTargetId());
 }
 
-std::string DAESceneEncoder::findAnimationId(const domAnimation* animationRef)
+void DAESceneEncoder::begin()
 {
-    std::string animationId;
-    const char* str = animationRef->getId();
-    if (str)
-    {
-        animationId = str;
-        // check if this ID already exists
-        if (_gamePlayFile.idExists(animationId))
-        {
-            // choose a different id
-            animationId.append("_animation");
-        }
-    }
-    if (animationId.length() == 0)
-    {
-        animationId.assign("animation"); // TODO: Remove this later
-    }
-    // ensure no duplicate IDs
-    while (_gamePlayFile.idExists(animationId))
-    {
-        animationId.append("_");
-    }
-    return animationId;
+    #ifdef ENCODER_PRINT_TIME
+    _begin = std::clock();
+    #endif
+}
+
+void DAESceneEncoder::end(const char* str)
+{
+    #ifdef ENCODER_PRINT_TIME
+    clock_t time = std::clock() - _begin;
+    fprintf(stderr,"%5d %s\n", time, str);
+    #endif
 }
 
 void DAESceneEncoder::copyFloats(const domFloat_array* source, std::vector<float>* target)
@@ -660,7 +659,7 @@ void DAESceneEncoder::copyFloats(const domFloat_array* source, std::vector<float
     t.resize(count);
     const domListOfFloats& listOfFloats = source->getValue();
     for (size_t i = 0; i < count; i++)
-    {   
+    {
         t[i] = (float)listOfFloats.get(i);
     }
 }
@@ -727,7 +726,9 @@ Node* DAESceneEncoder::loadNode(domNode* n, Node* parent)
     {
         node = _gamePlayFile.getNode(n->getID());
         if (node)
+        {
             return node;
+        }
     }
     
     // Load the node
@@ -774,7 +775,9 @@ void DAESceneEncoder::transformNode(domNode* domNode, Node* node)
     {
         const domMatrixRef& matrix = matrixArray.get(0);
         if (!matrix)
+        {
             return;
+        }
         const domFloat4x4& tx = matrix->getValue();
         float transform[] = {(float)tx.get(0), (float)tx.get(4), (float)tx.get(8), (float)tx.get(12),
                               (float)tx.get(1), (float)tx.get(5), (float)tx.get(9), (float)tx.get(13),
@@ -857,11 +860,9 @@ void DAESceneEncoder::calcTransform(domNode* domNode, Matrix& dstTransform)
             }
             case COLLADA_TYPE::SKEW:
             case COLLADA_TYPE::LOOKAT:
-            default:
-            {
                 warning("Skew or lookat transform found but not supported.");
+            default:
                 break;
-            }
         }
     }
 }
@@ -955,8 +956,8 @@ void DAESceneEncoder::loadControllerInstance(const domNode* n, Node* node)
     size_t instanceControllerCount = instanceControllers.getCount();
     for (size_t i = 0; i < instanceControllerCount; i++)
     {
-        const domInstance_controllerRef controllerInstanceRef = instanceControllers.get(i);
-        xsAnyURI controllerURI = controllerInstanceRef->getUrl();
+        const domInstance_controllerRef instanceControllerRef = instanceControllers.get(i);
+        xsAnyURI controllerURI = instanceControllerRef->getUrl();
         domController* controllerRef = daeSafeCast<domController>(controllerURI.getElement());
 
         if (controllerRef)
@@ -967,25 +968,19 @@ void DAESceneEncoder::loadControllerInstance(const domNode* n, Node* node)
                 Model* model = loadSkin(skinElement);
                 if (model)
                 {
-                    // use only the first skeleton
-                    domInstance_controller::domSkeleton_Array& skeletons = controllerInstanceRef->getSkeleton_array();
+                    domInstance_controller::domSkeleton_Array& skeletons = instanceControllerRef->getSkeleton_array();
                     if (skeletons.getCount() == 0)
                     {
                         warning("No skeletons found for instance controller: ");
                         delete model;
                         continue;
                     }
-                    else if (skeletons.getCount() > 1)
-                    {
-                        // Only log a warning, don't exit
-                        warning("More than one skeleton found for instance controller. Using first skeleton only.");
-                    }
                     // Load the skeleton for this skin
-                    loadSkeleton((domInstance_controller::domSkeleton*)skeletons.get((size_t)0), model->getSkin());
+                    domInstance_controller::domSkeletonRef skeleton = getSkeleton(instanceControllerRef);
+                    assert(skeleton);
+                    loadSkeleton(skeleton, model->getSkin());
 
                     node->setModel(model);
-
-                    // TODO: Load animations
                 }
             }
         }
@@ -993,8 +988,8 @@ void DAESceneEncoder::loadControllerInstance(const domNode* n, Node* node)
         {
             // warning
         }
-        jointLookupTable.clear();
-        jointInverseBindPoseMatrices.clear();
+        _jointLookupTable.clear();
+        _jointInverseBindPoseMatrices.clear();
     }
 }
 
@@ -1118,7 +1113,7 @@ LightInstance* DAESceneEncoder::loadLight(const domLight* lightRef)
         {
             const domLight::domTechnique_common::domSpotRef spotRef = techRef->getSpot();
             if (spotRef.cast())
-            {   
+            {
                 light->setSpotLight();
                 // color
                 const domTargetableFloat3Ref float3Ref = spotRef->getColor();
@@ -1198,20 +1193,19 @@ LightInstance* DAESceneEncoder::loadLight(const domLight* lightRef)
 
 void DAESceneEncoder::loadSkeleton(domInstance_controller::domSkeleton* skeletonElement, MeshSkin* skin)
 {
-    xsAnyURI skeletonUri = skeletonElement->getValue(); 
+    xsAnyURI skeletonUri = skeletonElement->getValue();
     daeString skeletonId = skeletonUri.getID();
     daeSIDResolver resolver(skeletonUri.getElement(), skeletonId);
     domNode* rootNode = daeSafeCast<domNode>(resolver.getElement());
     
-    // Get the lookup scene id (sid) and joint index.     
-    std::string sid = std::string(rootNode->getSid());
-    std::string id = std::string(skeletonId);   
+    // Get the lookup scene id (sid) and joint index.
+    std::string id = std::string(skeletonId);
 
-    // Has the root joint been loaded yet?
-    Node* rootJoint = (Node*)_gamePlayFile.getFromRefTable(id);
+    // Has the skeleton (root joint) been loaded yet?
+    Node* skeleton = (Node*)_gamePlayFile.getFromRefTable(id);
 
-    // The root node is not loaded yet, so let's load it now
-    if (rootJoint == NULL)
+    // The skeleton node is not loaded yet, so let's load it now
+    if (skeleton == NULL)
     {
         // Find the top most parent of rootNode that has not yet been loaded
         domNode* topLevelParent = rootNode;
@@ -1225,29 +1219,27 @@ void DAESceneEncoder::loadSkeleton(domInstance_controller::domSkeleton* skeleton
 
         // Is the parent of this node loaded yet?
         Node* parentNode = NULL;
-        if (topLevelParent->getParent() && 
+        if (topLevelParent->getParent() &&
             topLevelParent->getParent()->getElementType() == COLLADA_TYPE::NODE &&
             _gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID()) != NULL)
         {
             parentNode = (Node*)_gamePlayFile.getFromRefTable(topLevelParent->getParent()->getID());
         }
 
-        // Finally, load the node hierarchy that includes the root node
-        rootJoint = loadNode(topLevelParent, parentNode);
+        // Finally, load the node hierarchy that includes the skeleton
+        skeleton = loadNode(topLevelParent, parentNode);
     }
-    
-    if (rootJoint == NULL)
+
+    if (skeleton == NULL)
     {
         // This shouldn't really happen..
-        rootJoint = new Node();
-        rootJoint->setId(id);
-        _gamePlayFile.addNode(rootJoint);
+        skeleton = new Node();
+        skeleton->setId(id);
+        _gamePlayFile.addNode(skeleton);
     }
 
-    skin->setNode(rootJoint);
-    
     // Resolve and set joints array for skin
-    std::list<Node*> joints;
+    std::list<Node*> _joints;
     const std::list<std::string>& jointNames = skin->getJointNames();
     for (std::list<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); i++)
     {
@@ -1255,10 +1247,10 @@ void DAESceneEncoder::loadSkeleton(domInstance_controller::domSkeleton* skeleton
         if (obj)
         {
             Node* node = (Node*)obj;
-            joints.push_back(node);
+            _joints.push_back(node);
         }
     }
-    skin->setJoints(joints);
+    skin->setJoints(_joints);
 }
 
 Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
@@ -1267,20 +1259,6 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     Model* model = new Model();
     MeshSkin* skin = new MeshSkin();
 
-    // MeshSkins have an animation container but we need to find an appropriate ID for it.
-    // If the <controller> has an ID, use that ID as the animation's ID.
-    // Need to break const qualified in order to get the parent.
-    daeElement* e = ((domSkin*)skinElement)->getParent();
-    if (e->getElementType() == COLLADA_TYPE::CONTROLLER)
-    {
-        const domController* controller = (domController*)e;
-        const char* controllerId = controller->getId();
-        if (controllerId)
-        {
-            skin->setAnimationId(controllerId);
-        }
-    }
-
     // Bind Shape Matrix
     const domSkin::domBind_shape_matrix* bindShapeMatrix = skinElement->getBind_shape_matrix();
     if (bindShapeMatrix)
@@ -1294,19 +1272,19 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     }
 
     // Read and set our joints
-    domSkin::domJointsRef joints = skinElement->getJoints();
-    domInputLocal_Array& jointInputs = joints->getInput_array();
+    domSkin::domJointsRef _joints = skinElement->getJoints();
+    domInputLocal_Array& jointInputs = _joints->getInput_array();
 
 
     // Process "JOINT" input semantic first (we need to do this to set the joint count)
     unsigned int jointCount = 0;
     for (unsigned int i = 0; i < jointInputs.getCount(); i++)
     {
-        domInputLocalRef input = jointInputs.get(i);    
-        std::string inputSemantic = std::string(input->getSemantic());                
+        domInputLocalRef input = jointInputs.get(i);
+        std::string inputSemantic = std::string(input->getSemantic());
         domURIFragmentType* sourceURI = &input->getSource();
-        sourceURI->resolveElement();                
-        domSource* source = (domSource*)(daeElement*)sourceURI->getElement();
+        sourceURI->resolveElement();
+        const domSource* source = (domSource*)(daeElement*)sourceURI->getElement();
 
         if (equals(inputSemantic, "JOINT"))
         {
@@ -1317,7 +1295,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
             // 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.
             for (std::list<std::string>::iterator i = list.begin(); i != list.end(); i++)
-            {   
+            {
                 daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
                 daeElement* element = resolver.getElement();
                 if (element && element->getElementType() == COLLADA_TYPE::NODE)
@@ -1333,11 +1311,11 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
 
             // Get the joint count and set the capacities for both the
             jointCount = list.size();
-            jointInverseBindPoseMatrices.reserve(jointCount);
+            _jointInverseBindPoseMatrices.reserve(jointCount);
             unsigned int j = 0;
             for (std::list<std::string>::const_iterator i = list.begin(); i != list.end(); i++)
             {
-                jointLookupTable[*i] = j++;
+                _jointLookupTable[*i] = j++;
             }
             skin->setJointNames(list);
         }
@@ -1353,10 +1331,10 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     // Process "INV_BIND_MATRIX" next
     for (unsigned int i = 0; i < jointInputs.getCount(); i++)
     {
-        domInputLocalRef input = jointInputs.get(i);    
-        std::string inputSemantic = std::string(input->getSemantic());                
+        domInputLocalRef input = jointInputs.get(i);
+        std::string inputSemantic = std::string(input->getSemantic());
         domURIFragmentType* sourceURI = &input->getSource();
-        sourceURI->resolveElement();                
+        sourceURI->resolveElement();
         domSource* source = (domSource*)(daeElement*)sourceURI->getElement();
 
         if (equals(inputSemantic, "INV_BIND_MATRIX"))
@@ -1367,50 +1345,52 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
 
             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), 
-                              (float)matrixFloats.get(jointIndex + 1), (float)matrixFloats.get(jointIndex + 5), (float)matrixFloats.get(jointIndex + 9), (float)matrixFloats.get(jointIndex + 13), 
-                              (float)matrixFloats.get(jointIndex + 2), (float)matrixFloats.get(jointIndex + 6), (float)matrixFloats.get(jointIndex + 10), (float)matrixFloats.get(jointIndex + 14), 
-                              (float)matrixFloats.get(jointIndex + 3), (float)matrixFloats.get(jointIndex + 7), (float)matrixFloats.get(jointIndex + 11), (float)matrixFloats.get(jointIndex + 15));    
+                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 + 2), (float)matrixFloats.get(jointIndex + 6), (float)matrixFloats.get(jointIndex + 10), (float)matrixFloats.get(jointIndex + 14),
+                              (float)matrixFloats.get(jointIndex + 3), (float)matrixFloats.get(jointIndex + 7), (float)matrixFloats.get(jointIndex + 11), (float)matrixFloats.get(jointIndex + 15));
 
-                jointInverseBindPoseMatrices.push_back(matrix);
+                _jointInverseBindPoseMatrices.push_back(matrix);
                 jointIndex += 16;
             }
         }
     }
 
-    skin->setBindPoses(jointInverseBindPoseMatrices);
+    skin->setBindPoses(_jointInverseBindPoseMatrices);
 
     // Get the vertex weights inputs
-    domSkin::domVertex_weights* vertexWeights =  skinElement->getVertex_weights();        
+    domSkin::domVertex_weights* vertexWeights =  skinElement->getVertex_weights();
     domInputLocalOffset_Array& vertexWeightsInputs = vertexWeights->getInput_array();
-    unsigned int vertexWeightsCount = (unsigned int)vertexWeights->getCount();    
-    domListOfFloats jointWeights;    
+    unsigned int vertexWeightsCount = (unsigned int)vertexWeights->getCount();
+    domListOfFloats jointWeights;
 
     for (unsigned int i = 0; i < jointInputs.getCount(); i++)
     {
         domInputLocalOffsetRef input = vertexWeightsInputs.get(i);
-        std::string inputSemantic = std::string(input->getSemantic());                
+        std::string inputSemantic = std::string(input->getSemantic());
         domURIFragmentType* sourceURI = &input->getSource();
-        sourceURI->resolveElement();                
-        domSource* source = (domSource*)(daeElement*)sourceURI->getElement();                
+        sourceURI->resolveElement();
+        domSource* source = (domSource*)(daeElement*)sourceURI->getElement();
 
         if (equals(inputSemantic, "WEIGHT"))
         {
             domFloat_array* weights = source->getFloat_array();
             if (weights)
+            {
                 jointWeights = weights->getValue();
+            }
         }
-    }    
+    }
     
     // Get the number of joint influences per vertex
-    domSkin::domVertex_weights::domVcount* vCountElement = vertexWeights->getVcount();    
-    domListOfUInts skinVertexInfluenceCounts = vCountElement->getValue();                
+    domSkin::domVertex_weights::domVcount* vCountElement = vertexWeights->getVcount();
+    domListOfUInts skinVertexInfluenceCounts = vCountElement->getValue();
     // Get the joint/weight pair data.
     domSkin::domVertex_weights::domV* vElement = vertexWeights->getV();
     domListOfInts skinVertexJointWeightPairIndices = vElement->getValue();
         
     // Get the vertex influence count for any given vertex (up to max of 4)
-    unsigned int maxVertexInfluencesCount = SCENE_SKIN_VERTEXINFLUENCES_MAX;    
+    unsigned int maxVertexInfluencesCount = SCENE_SKIN_VERTEXINFLUENCES_MAX;
     skin->setVertexInfluenceCount(maxVertexInfluencesCount);
 
     // Get the vertex blend weights and joint indices and
@@ -1418,31 +1398,31 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     // These will be used and cleaned up later in LoadMesh
     int skinVertexInfluenceCountTotal = skinVertexInfluenceCounts.getCount();
     int totalVertexInfluencesCount = vertexWeightsCount * maxVertexInfluencesCount;
-    vertexBlendWeights = new float[totalVertexInfluencesCount];
-    vertexBlendIndices = new unsigned int[totalVertexInfluencesCount];
+    _vertexBlendWeights = new float[totalVertexInfluencesCount];
+    _vertexBlendIndices = new unsigned int[totalVertexInfluencesCount];
 
     // Preset the default blend weights to 0.0f (no effect) and blend indices to 0 (uses the first which when multiplied
     // will have no effect anyhow.
-    memset(vertexBlendWeights, 0, totalVertexInfluencesCount * sizeof(float));        
-    memset(vertexBlendIndices , 0, totalVertexInfluencesCount * sizeof(unsigned int));    
+    memset(_vertexBlendWeights, 0, totalVertexInfluencesCount * sizeof(float));
+    memset(_vertexBlendIndices , 0, totalVertexInfluencesCount * sizeof(unsigned int));
     
-    int vOffset = 0;        
-    int weightOffset = 0;    
+    int vOffset = 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++)
-    {            
-        // Get the influence count and directly get the vertext blend weights and indices.        
-        unsigned int vertexInfluenceCount = (unsigned int)skinVertexInfluenceCounts.get(i);        
+    {
+        // Get the influence count and directly get the vertext blend weights and indices.
+        unsigned int vertexInfluenceCount = (unsigned int)skinVertexInfluenceCounts.get(i);
         float vertexInfluencesTotalWeights = 0.0f;
         std::vector<SkinnedVertexWeightPair> vertexInfluences;
         //vertexInfluences.SetCapacity(vertexInfluenceCount);
 
         // Get the index/weight pairs and some the weight totals while at it.
         for (unsigned int j = 0; j < vertexInfluenceCount; j++)
-        {        
+        {
             float weight = (float)jointWeights.get((unsigned int)skinVertexJointWeightPairIndices[vOffset + 1]);
-            int index = (int)skinVertexJointWeightPairIndices[vOffset];            
+            int index = (int)skinVertexJointWeightPairIndices[vOffset];
             
             // Set invalid index corresponding weights to zero
             if (index < 0 || index > (int)vertexWeightsCount)
@@ -1460,25 +1440,25 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
 
         // Get up the the maximum vertex weight influence count.
          for (unsigned int j = 0; j < maxVertexInfluencesCount; j++)
-        {            
-            if (j < vertexInfluenceCount)                
-            {        
+        {
+            if (j < vertexInfluenceCount)
+            {
                 SkinnedVertexWeightPair pair = vertexInfluences[j];
-                vertexBlendIndices[weightOffset] = pair.BlendIndex;
+                _vertexBlendIndices[weightOffset] = pair.BlendIndex;
                     
-                if (vertexInfluencesTotalWeights > 0.0f)        
-                {                
-                    vertexBlendWeights[weightOffset] = pair.BlendWeight;
+                if (vertexInfluencesTotalWeights > 0.0f)
+                {
+                    _vertexBlendWeights[weightOffset] = pair.BlendWeight;
                 }
                 else
                 {
                     if (j == 0)
                     {
-                        vertexBlendWeights[weightOffset] = 1.0f;
+                        _vertexBlendWeights[weightOffset] = 1.0f;
                     }
                     else
                     {
-                        vertexBlendWeights[weightOffset] = 0.0f;
+                        _vertexBlendWeights[weightOffset] = 0.0f;
                     }
                 }
             }
@@ -1641,8 +1621,10 @@ 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 (inputCount != (unsigned int)inputArray.getCount())
             {
-                for (size_t i = 0; i < polygonInputs.size(); i++)
-                    delete polygonInputs[i];
+                for (size_t j = 0; j < polygonInputs.size(); j++)
+                {
+                    delete polygonInputs[j];
+                }
                 warning(std::string("Triangles do not all have the same number of input sources for geometry mesh: ") + geometryId);
                 return false;
             }
@@ -1684,7 +1666,9 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
             const domListOfFloats& source = polygonInputs[k]->sourceValues;
             unsigned int offset = polygonInputs[k]->offset;
             if (offset > maxOffset)
+            {
                 maxOffset = offset;
+            }
             int type = polygonInputs[k]->type;
 
             unsigned int polyIndex = (unsigned int) polyInts.get(poly + offset);
@@ -1692,19 +1676,19 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
             {
             case POSITION:
                 vertex.reset();
-                if (vertexBlendWeights && vertexBlendIndices)
+                if (_vertexBlendWeights && _vertexBlendIndices)
                 {
                     vertex.hasWeights = true;
 
-                    vertex.blendWeights.x =  vertexBlendWeights[polyIndex * 4];
-                    vertex.blendWeights.y =  vertexBlendWeights[polyIndex * 4 + 1];
-                    vertex.blendWeights.z =  vertexBlendWeights[polyIndex * 4 + 2];
-                    vertex.blendWeights.w =  vertexBlendWeights[polyIndex * 4 + 3];
+                    vertex.blendWeights.x =  _vertexBlendWeights[polyIndex * 4];
+                    vertex.blendWeights.y =  _vertexBlendWeights[polyIndex * 4 + 1];
+                    vertex.blendWeights.z =  _vertexBlendWeights[polyIndex * 4 + 2];
+                    vertex.blendWeights.w =  _vertexBlendWeights[polyIndex * 4 + 3];
 
-                    vertex.blendIndices.x =  (float)vertexBlendIndices[polyIndex * 4];
-                    vertex.blendIndices.y =  (float)vertexBlendIndices[polyIndex * 4 + 1];
-                    vertex.blendIndices.z =  (float)vertexBlendIndices[polyIndex * 4 + 2];
-                    vertex.blendIndices.w =  (float)vertexBlendIndices[polyIndex * 4 + 3];
+                    vertex.blendIndices.x =  (float)_vertexBlendIndices[polyIndex * 4];
+                    vertex.blendIndices.y =  (float)_vertexBlendIndices[polyIndex * 4 + 1];
+                    vertex.blendIndices.z =  (float)_vertexBlendIndices[polyIndex * 4 + 2];
+                    vertex.blendIndices.w =  (float)_vertexBlendIndices[polyIndex * 4 + 3];
                 }
 
                 vertex.position.x = (float)source.get(polyIndex * 3);
@@ -1829,7 +1813,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
         mesh->addVetexAttribute(COLOR, 3);
     }
     // Skinning BlendWeights BlendIndices
-    if (hasWeights /*vertexBlendWeights && vertexBlendIndices*/)
+    if (hasWeights /*_vertexBlendWeights && _vertexBlendIndices*/)
     {
         mesh->addVetexAttribute(BLENDWEIGHTS, 4);
         mesh->addVetexAttribute(BLENDINDICES, 4);
@@ -1849,35 +1833,6 @@ void DAESceneEncoder::warning(const char* message)
     printf("Warning: %s\n", message);
 }
 
-void DAESceneEncoder::getJointNames(domSource* source, std::list<std::string>& list)
-{
-    // BLENDER used name_array
-    const domName_arrayRef& nameArray = source->getName_array();
-    if (nameArray.cast())
-    {
-        domListOfNames& ids = nameArray->getValue();
-        size_t jointCount = (size_t)nameArray->getCount();
-        for (size_t j = 0; j < jointCount; j++)
-        {
-            list.push_back(std::string(ids.get(j)));
-        }
-    }
-    else
-    {
-        // Seymour used IDREF_array
-        const domIDREF_arrayRef& idArray = source->getIDREF_array();
-        if (idArray.cast())
-        {
-            xsIDREFS& ids = idArray->getValue();
-            size_t jointCount = (size_t)idArray->getCount();
-            for (size_t j = 0; j < jointCount; j++)
-            {
-                list.push_back(std::string(ids.get(j).getID()));
-            }
-        }
-    }
-}
-
 int DAESceneEncoder::getVertexUsageType(const std::string& semantic)
 {
     int type = -1;

+ 27 - 24
gameplay-encoder/src/DAESceneEncoder.h

@@ -8,6 +8,7 @@
 #include <iostream>
 #include <list>
 #include <vector>
+#include <ctime>
 
 #include <dae.h>
 #include <dae/daeSIDResolver.h>
@@ -38,6 +39,8 @@
 #include "Transform.h"
 #include "DAEChannelTarget.h"
 #include "GPBFile.h"
+#include "DAEUtil.h"
+#include "EncoderArguments.h"
 
 using namespace gameplay;
 
@@ -63,7 +66,7 @@ public:
     /**
      * Writes out encoded Collada 1.4 file.
      */
-    void write(const std::string& filepath, const char* nodeId, bool text);
+    void write(const std::string& filepath, const EncoderArguments& arguments);
 
 private:
 
@@ -89,14 +92,22 @@ private:
         unsigned int BlendIndex;
 
         SkinnedVertexWeightPair(float blendWeight, unsigned int blendIndex) : BlendWeight(blendWeight), BlendIndex(blendIndex)
-        {                
-        }            
+        {
+        }
 
         bool operator < (const SkinnedVertexWeightPair& value) const
         {
             return value.BlendWeight < BlendWeight;
         }
     };
+
+    /**
+     * Optimizes the COLLADA dom based on the arguments passed to the encoder.
+     * 
+     * @param arguments The command line arguments passed to the encoder.
+     * @param dom The COLLADA dom.
+     */
+    void optimizeCOLLADA(const EncoderArguments& arguments, domCOLLADA* dom);
     
     void triangulate(DAE* dae);
     
@@ -119,9 +130,9 @@ private:
     /**
      * Loads a COLLADA animation element.
      * 
-     * @param animationRef Pointer to the animation dom element to load from.
+     * @param animationRef The animation dom element to load from.
      */
-    void loadAnimation(const domAnimation* animationRef);
+    void loadAnimation(const domAnimationRef animationRef);
 
     CameraInstance* loadCamera(const domCamera* cameraRef);
     LightInstance* loadLight(const domLight* lightRef);
@@ -136,13 +147,14 @@ private:
      * @param source The source dom element to load interpolation curves from.
      * @param animation The destination animation to copy to.
      */
-    void loadInterpolation(const domSource* source, AnimationChannel* animation);
+    void loadInterpolation(const domSourceRef source, AnimationChannel* animation);
 
     /**
      * Returns the active camera node for the given scene.
      * 
      * @param visualScene The collada visual scene node.
      * @param scene The gameplay scene node.
+     * 
      * @return The active camera node or NULL if one was not found.
      */
     Node* findSceneActiveCameraNode(const domVisual_scene* visualScene, Scene* scene);
@@ -162,11 +174,6 @@ private:
      */
     void calcTransform(domNode* domNode, Matrix& dstTransform);
 
-    /**
-     * Gets the joint names for the given source and appends them to the given list.
-     */
-    void getJointNames(domSource* source, std::list<std::string>& list);
-
     void warning(const std::string& message);
     void warning(const char* message);
 
@@ -181,15 +188,8 @@ private:
      */
     void loadTarget(const domChannel* channelRef, AnimationChannel* animation);
 
-    /**
-     * Finds the ID for an animation.
-     * If the COLLADA animation element doesn't have an ID then this method will trying 
-     * to find an appropriate ID for the animation.
-     * 
-     * @param animationRef The COLLADA animation element to find an ID for.
-     * @return The ID string for the animation.
-     */
-    std::string findAnimationId(const domAnimation* animationRef);
+    void begin();
+    void end(const char* str);
 
     /**
      * Copies float values from a domFloat_array to a std::vector<float>.
@@ -207,15 +207,18 @@ private:
      */
     static int getVertexUsageType(const std::string& semantic);
     
+private:
     DAE* _collada;        // Collada datastore in memory to read from.
+    domCOLLADA* _dom;
     FILE* file;        // Output file to write to.
     GPBFile _gamePlayFile;
 
-    std::map<std::string, int> jointLookupTable;
-    std::vector<Matrix>jointInverseBindPoseMatrices;
-    float* vertexBlendWeights;
-    unsigned int* vertexBlendIndices;
+    std::map<std::string, int> _jointLookupTable;
+    std::vector<Matrix>_jointInverseBindPoseMatrices;
+    float* _vertexBlendWeights;
+    unsigned int* _vertexBlendIndices;
 
+    clock_t _begin;
 };
 
 #endif

+ 303 - 0
gameplay-encoder/src/DAEUtil.cpp

@@ -0,0 +1,303 @@
+
+#include "DAEUtil.h"
+
+/**
+ * Returns the index of the skeleton in skeletonArray that points to the given node.
+ * 
+ * @param skeletonArray The array of skeletons to search.
+ * @param node The target node.
+ * 
+ * @return The index in skeletonArray or -1 if not found.
+ */
+int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node);
+
+void getJointNames(const domSource* source, std::list<std::string>& list)
+{
+    // BLENDER used name_array
+    const domName_arrayRef& nameArray = source->getName_array();
+    if (nameArray.cast())
+    {
+        domListOfNames& ids = nameArray->getValue();
+        size_t jointCount = (size_t)nameArray->getCount();
+        for (size_t j = 0; j < jointCount; j++)
+        {
+            list.push_back(std::string(ids.get(j)));
+        }
+    }
+    else
+    {
+        // Seymour used IDREF_array
+        const domIDREF_arrayRef& idArray = source->getIDREF_array();
+        if (idArray.cast())
+        {
+            xsIDREFS& ids = idArray->getValue();
+            size_t jointCount = (size_t)idArray->getCount();
+            for (size_t j = 0; j < jointCount; j++)
+            {
+                list.push_back(std::string(ids.get(j).getID()));
+            }
+        }
+    }
+}
+
+void getJointNames(const domSkin* skin, std::list<std::string>& list)
+{
+    const domSkin::domJointsRef& joints = skin->getJoints();
+    const domInputLocal_Array& inputArray = joints->getInput_array();
+    size_t inputCount = inputArray.getCount();
+    for (size_t i = 0; i < inputCount; i++)
+    {
+        const domInputLocalRef input = inputArray.get(i);
+        const char* semantic = input->getSemantic();
+        if (strcmp(semantic, "JOINT") == 0)
+        {
+            daeElement* sourceElement = input->getSource().getElement();
+            if (sourceElement)
+            {
+                const domSource* source = static_cast<domSource*>(sourceElement);
+                getJointNames(source, list);
+            }
+        }
+    }
+}
+
+domSource* getInputSource(const domChannelRef& channel)
+{
+    daeElement* element = channel->getSource().getElement();
+    if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
+    {
+        domSampler* sampler = daeSafeCast<domSampler>(element);
+        const domInputLocal_Array& inputArray = sampler->getInput_array();
+        size_t inputArrayCount = inputArray.getCount();
+        for (size_t i = 0; i < inputArrayCount; i++)
+        {
+            const domInputLocalRef& input = inputArray.get(i);
+            if (strcmp(input->getSemantic(), "INPUT") == 0)
+            {
+                daeElement* e = input->getSource().getElement();
+                if (e && e->getElementType() == COLLADA_TYPE::SOURCE)
+                {
+                    domSource* source = daeSafeCast<domSource>(e);
+                    assert(source);
+                    return source;
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+const domSamplerRef getSampler(const domChannelRef& channel)
+{
+    const domURIFragmentType& uri = channel->getSource();
+    daeElementRef element = uri.getElement();
+    if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
+    {
+        const domSamplerRef sampler = daeSafeCast<domSampler>(element);
+        return sampler;
+    }
+    // resolve the source manually by searching for the sampler in the animation that the channel is a child of.
+    const std::string& id = uri.id();
+    const daeElementRef& parent = channel->getParent();
+    if (parent && parent->getElementType() == COLLADA_TYPE::ANIMATION)
+    {
+        const domAnimationRef animation = daeSafeCast<domAnimation>(parent);
+        
+        const domSampler_Array& samplerArray = animation->getSampler_array();
+        size_t count = samplerArray.getCount();
+        for (size_t i = 0; i < count; i++)
+        {
+            const domSamplerRef& sampler = samplerArray.get(i);
+            if (id.compare(sampler->getId()) == 0)
+            {
+                return sampler;
+            }
+        }
+    }
+    return NULL;
+}
+
+const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimationRef& animation)
+{
+    const domURIFragmentType& uri = inputLocal->getSource();
+    daeElementRef element = uri.getElement();
+    if (element && element->getElementType() == COLLADA_TYPE::SAMPLER)
+    {
+        const domSourceRef source = daeSafeCast<domSource>(element);
+        return source;
+    }
+    // Resolve the URI by searching through the animation's list of sources
+    const std::string& id = uri.id();
+    const domSource_Array& sourceArray = animation->getSource_array();
+    size_t count = sourceArray.getCount();
+    for (size_t i = 0; i < count; i++)
+    {
+        const domSourceRef source = sourceArray.get(i);
+        if (id.compare(source->getId()) == 0)
+        {
+            return source;
+        }
+    }
+    return NULL;
+}
+
+const domName_arrayRef getSourceNameArray(const domSourceRef& source)
+{
+    const domName_arrayRef& nameArray = source->getName_array();
+    if (nameArray)
+    {
+        return nameArray;
+    }
+    daeTArray<daeSmartRef<daeElement>> children;
+    source->getChildren(children);
+    size_t childCount = children.getCount();
+    for (size_t i = 0; i < childCount; i++)
+    {
+        const daeElementRef element = children.get(i);
+        if (element->getElementType() == COLLADA_TYPE::NAME_ARRAY)
+        {
+            return daeSafeCast<domName_array>(element);
+        }
+    }
+    return NULL;
+}
+
+const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_controllerRef& instanceController)
+{
+    domInstance_controller::domSkeleton_Array& skeletonArray = instanceController->getSkeleton_array();
+    size_t count = skeletonArray.getCount();
+    if (count == 0)
+    {
+        return NULL;
+    }
+    if (count == 1)
+    {
+        return skeletonArray.get(0);
+    }
+    // Maya sometimes outputs multiple skeleton elements.
+    // Find the skeleton element that points to the root most node.
+    const domInstance_controller::domSkeletonRef& currentSkeleton = skeletonArray.get(0);
+    const daeElementRef element = currentSkeleton->getValue().getElement();
+    if (element && element->getElementType() == COLLADA_TYPE::NODE)
+    {
+        domNode* node = daeSafeCast<domNode>(element);
+        int index = 0;
+        bool loop = true;
+        do
+        {
+            daeElementRef parent = node->getParent();
+            if (parent && parent->getElementType() == COLLADA_TYPE::NODE)
+            {
+                domNodeRef parentNode = daeSafeCast<domNode>(parent);
+                int result = getIndex(skeletonArray, parentNode);
+                if (result >= 0)
+                {
+                    index = result;
+                }
+                node = parentNode;
+            }
+            else
+            {
+                loop = false;
+            }
+        } while (loop);
+        if (index >= 0)
+        {
+            return skeletonArray.get(index);
+        }
+    }
+    return NULL;
+}
+
+bool equalKeyTimes(const domSource* s1, const domSource* s2)
+{
+    // TODO: shouldn't assume that the source has a float array.
+    const domFloat_arrayRef& f1 = s1->getFloat_array();
+    const domFloat_arrayRef& f2 = s2->getFloat_array();
+    if (f1->getCount() == f2->getCount())
+    {
+        const domListOfFloats& list1 = f1->getValue();
+        const domListOfFloats& list2 = f2->getValue();
+
+        size_t count = (size_t)f1->getCount();
+        for (size_t i = 0; i < count; i++)
+        {
+            if (list1.get(i) != list2.get(i))
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
+bool equalKeyTimes(const domChannelRef& c1, const domChannelRef& c2)
+{
+    domSource* s1 = getInputSource(c1);
+    domSource* s2 = getInputSource(c2);
+    assert(s1);
+    assert(s2);
+    return equalKeyTimes(s1, s2);
+}
+
+void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& animation)
+{
+    assert(channel);
+    assert(animation);
+
+    daeElement::removeFromParent(channel);
+    animation->add(channel); // move channel
+
+    daeElementRef element = channel->getSource().getElement();
+    if (element)
+    {
+        domSamplerRef sampler = daeSafeCast<domSampler>(element);
+
+        domInputLocal_Array& inputArray = sampler->getInput_array();
+        size_t inputArrayCount = inputArray.getCount();
+        for (size_t i = 0; i < inputArrayCount; i++)
+        {
+            inputArray = sampler->getInput_array();
+            const domInputLocalRef& input = inputArray.get(i);
+            daeElementRef element = input->getSource().getElement();
+            if (element && element->getElementType() == COLLADA_TYPE::SOURCE)
+            {
+                domSourceRef source = daeSafeCast<domSource>(element);
+                assert(source);
+                daeElement::removeFromParent(source);
+                animation->add(source); // move source
+            }
+        }
+        daeElement::removeFromParent(sampler);
+        animation->add(sampler); // move sampler
+    }
+}
+
+bool isEmptyAnimation(domAnimationRef& animation)
+{
+    return animation->getAnimation_array().getCount() == 0 &&
+           animation->getChannel_array().getCount() == 0 &&
+           animation->getSampler_array().getCount() == 0 &&
+           animation->getSource_array().getCount() == 0;
+}
+
+int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node)
+{
+    const std::string nodeId = node->getId();
+    size_t count = skeletonArray.getCount();
+    for (size_t i = 0; i < count; i++)
+    {
+        const domInstance_controller::domSkeletonRef& skeleton = skeletonArray.get(i);
+        daeElementRef element = skeleton->getValue().getElement();
+        if (element->getElementType() == COLLADA_TYPE::NODE)
+        {
+            domNodeRef targetNode = daeSafeCast<domNode>(element);
+            if (nodeId.compare(targetNode->getId()) == 0)
+            {
+                return i;
+            }
+        }
+    }
+    return -1;
+}

+ 126 - 0
gameplay-encoder/src/DAEUtil.h

@@ -0,0 +1,126 @@
+/*
+ * DAEUtil.h
+ */
+
+#ifndef DAEUTIL_H_
+#define DAEUTIL_H_
+
+#include <iostream>
+#include <list>
+#include <vector>
+
+#include <dae.h>
+#include <dae/daeSIDResolver.h>
+#include <dae/domAny.h>
+#include <dom/domCOLLADA.h>
+#include <dom/domConstants.h>
+#include <dom/domElements.h>
+#include <dom/domProfile_COMMON.h>
+
+#include "Base.h"
+
+using namespace gameplay;
+
+/**
+ * Gets the joint names for the given source and appends them to the given list.
+ * 
+ * @param source The source element to search in.
+ * @param list The list to append the joint names to.
+ */
+void getJointNames(const domSource* source, std::list<std::string>& list);
+
+/**
+ * Gets the joint names for the given skin and appends them to the given list.
+ * 
+ * @param skin The skin element to search in.
+ * @param list The list to append the joint names to.
+ */
+void getJointNames(const domSkin* skin, std::list<std::string>& list);
+
+/**
+ * Gets the input source from the given channel.
+ * 
+ * @param channel The channel to search in.
+ * 
+ * @return The source element or NULL if not found.
+ */
+domSource* getInputSource(const domChannelRef& channel);
+
+/**
+ * Returns the sampler from the given channel.
+ * 
+ * @param channel The channel dom element.
+ * 
+ * @return The sampler or NULL if not found.
+ */
+const domSamplerRef getSampler(const domChannelRef& channel);
+
+/**
+ * Returns the source from the given sampler input. 
+ * Searchs within the given animation.
+ * 
+ * @param inputLocal The input element within a sampler.
+ * @param animation The animation to search within.
+ * 
+ * @return The source or NULL if not found.
+ */
+const domSourceRef getSource(const domInputLocalRef& inputLocal, const domAnimationRef& animation);
+
+/**
+ * Returns the name array from the given source.
+ * 
+ * @param source The source element.
+ * 
+ * @return The name array or NULL if not found.
+ */
+const domName_arrayRef getSourceNameArray(const domSourceRef& source);
+
+/**
+ * Returns one skeleton from the given instance controller.
+ * The COLLADA spec says that instance_controller can have multiple skeletons but we only need one.
+ * Maya sometimes exports multiple skeleton nodes so this function will try to find the correct one.
+ * 
+ * @param instanceController The instance_controller element.
+ * 
+ * @return The skeleton or NULL if not found.
+ */
+const domInstance_controller::domSkeletonRef getSkeleton(const domInstance_controllerRef& instanceController);
+
+/**
+ * Returns true if the two given animation channels have equal key time input source.
+ * 
+ * @param c1 Channel one to compare.
+ * @param c2 Channel two to compare.
+ * 
+ * @return True if the channels have the same key times, false otherwise.
+ */
+bool equalKeyTimes(const domChannelRef& c1, const domChannelRef& c2);
+
+/**
+ * Returns true if the two sources have the same key times.
+ * 
+ * @param s1 Source one.
+ * @param s2 Source two.
+ * 
+ * @return True true if the key times are equal, false otherwise.
+ */
+bool equalKeyTimes(const domSource* s1, const domSource* s2);
+
+/**
+ * Moves a channel and the sources it uses to the destination animation.
+ * 
+ * @param channel The channel to move.
+ * @param animation The destination animation to copy to.
+ */
+void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& animation);
+
+/**
+ * Returns true if the given animation is empty and contains no children.
+ * 
+ * @param animation The animation element to check.
+ * 
+ * @return True if the animation has no children, false otherwise.
+ */
+bool isEmptyAnimation(domAnimationRef& animation);
+
+#endif

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

@@ -23,14 +23,14 @@ const char* Effect::getElementName(void) const
 void Effect::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    write(vertexShader, file);
-    write(fragmentShader, file);
+    write(_vertexShader, file);
+    write(_fragmentShader, file);
 }
 void Effect::writeText(FILE* file)
 {
     fprintElementStart(file);
-    fprintfElement(file, "vertexShader", vertexShader);
-    fprintfElement(file, "fragmentShader", fragmentShader);
+    fprintfElement(file, "vertexShader", _vertexShader);
+    fprintfElement(file, "fragmentShader", _fragmentShader);
     fprintElementEnd(file);
 }
 

+ 3 - 2
gameplay-encoder/src/Effect.h

@@ -28,8 +28,9 @@ public:
 
     virtual void writeText(FILE* file);
 
-    std::string vertexShader;
-    std::string fragmentShader;
+private:
+    std::string _vertexShader;
+    std::string _fragmentShader;
 };
 
 

+ 262 - 0
gameplay-encoder/src/EncoderArguments.cpp

@@ -0,0 +1,262 @@
+#include "EncoderArguments.h"
+
+#include "StringUtil.h"
+
+#ifdef WIN32
+    #define PATH_MAX    _MAX_PATH
+    #define realpath(A,B)    _fullpath(B,A,PATH_MAX)
+#endif
+
+EncoderArguments::EncoderArguments(size_t argc, const char** argv) :
+    _fontSize(0),
+    _parseError(false),
+    _fontPreview(false),
+    _textOutput(false),
+    _daeOutput(false)
+{
+    if (argc > 1)
+    {
+        size_t filePathIndex = argc - 1;
+        if (argv[filePathIndex])
+        {
+            _filePath.assign(getRealPath(argv[filePathIndex]));
+        }
+        
+        // read the options
+        std::vector<std::string> options;
+        for (size_t i = 1; i < filePathIndex; i++)
+        {
+            options.push_back(argv[i]);
+        }
+        
+        for (size_t i = 0; i < options.size(); i++)
+        {
+            if (options[i][0] == '-')
+            {
+                readOption(options, &i);
+            }
+        }
+    }
+    else
+    {
+        _parseError = true;
+    }
+}
+
+EncoderArguments::~EncoderArguments(void)
+{
+}
+
+const std::string& EncoderArguments::getFilePath() const
+{
+    return _filePath;
+}
+
+const char* EncoderArguments::getFilePathPointer() const
+{
+    return _filePath.c_str();
+}
+
+const std::string& EncoderArguments::getDAEOutputPath() const
+{
+    return _daeOutputPath;
+}
+
+const std::vector<std::string>& EncoderArguments::getGroupAnimationNodeId() const
+{
+    return _groupAnimationNodeId;
+}
+
+const std::vector<std::string>& EncoderArguments::getGroupAnimationAnimationId() const
+{
+    return _groupAnimationAnimationId;
+}
+
+bool EncoderArguments::parseErrorOccured() const
+{
+    return _parseError;
+}
+
+bool EncoderArguments::fileExists() const
+{
+    if (_filePath.length() > 0)
+    {
+        struct stat buf;
+        if (stat(_filePath.c_str(), &buf) != -1)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void EncoderArguments::printUsage() const
+{
+    fprintf(stderr,"Usage: gameplay-encoder [options] <filepath>\n");
+    fprintf(stderr,".dae file options:\n");
+    fprintf(stderr," -i <id>\tFilter by node ID\n");
+    fprintf(stderr," -t\tWrite text/xml\n");
+    fprintf(stderr," -groupAnimations <nodeID> <animationID>\tGroup all animation channels targetting the nodes into a new animation\n");
+    fprintf(stderr," -dae <filepath>\tOutput optimized DAE\n");
+    fprintf(stderr,".ttf file options:\n");
+    fprintf(stderr," -s <size of font> -p \n");
+    exit(8);
+}
+
+bool EncoderArguments::fontPreviewEnabled() const
+{
+    return _fontPreview;
+}
+
+bool EncoderArguments::textOutputEnabled() const
+{
+    return _textOutput;
+}
+
+bool EncoderArguments::DAEOutputEnabled() const
+{
+    return _daeOutput;
+}
+
+const char* EncoderArguments::getNodeId() const
+{
+    if (_nodeId.length() == 0)
+    {
+        return NULL;
+    }
+    return _nodeId.c_str();
+}
+
+unsigned int EncoderArguments::getFontSize() const
+{
+    return _fontSize;
+}
+
+EncoderArguments::FileFormat EncoderArguments::getFileFormat() const
+{
+    if (_filePath.length() < 5)
+    {
+        return FILEFORMAT_UNKNOWN;
+    }
+    // Extract the extension
+    std::string ext = "";
+    size_t pos = _filePath.find_last_of(".");
+    if (pos != std::string::npos)
+    {
+        ext = _filePath.substr(pos + 1);
+    }
+    
+    // Match every supported extension with its format constant
+    if (ext.compare("dae") == 0 || ext.compare("DAE") == 0)
+    {
+        return FILEFORMAT_DAE;
+    }
+    if (ext.compare("ttf") == 0 || ext.compare("TTF") == 0)
+    {
+        return FILEFORMAT_TTF;
+    }
+    if (ext.compare("gpb") == 0 || ext.compare("GPB") == 0)
+    {
+        return FILEFORMAT_GPB;
+    }
+
+    return FILEFORMAT_UNKNOWN;
+}
+
+void EncoderArguments::readOption(const std::vector<std::string>& options, size_t *index)
+{
+    const std::string& str = options[*index];
+    if (str.length() == 0 && str[0] != '-')
+    {
+        return;
+    }
+    switch (str[1])
+    {
+    case 'd':
+        if (str.compare("-dae") == 0)
+        {
+            // read one string, make sure not to go out of bounds
+            if ((*index + 1) >= options.size())
+            {
+                fprintf(stderr, "Error: -dae requires 1 argument.\n");
+                _parseError = true;
+                return;
+            }
+            (*index)++;
+            _daeOutputPath = options[*index];
+            _daeOutput = true;
+        }
+        break;
+    case 'g':
+        if (str.compare("-groupAnimations") == 0)
+        {
+            // read two strings, make sure not to go out of bounds
+            if ((*index + 2) >= options.size())
+            {
+                fprintf(stderr, "Error: -groupAnimations requires 2 arguments.\n");
+                _parseError = true;
+                return;
+            }
+            (*index)++;
+            _groupAnimationNodeId.push_back(options[*index]);
+            (*index)++;
+            _groupAnimationAnimationId.push_back(options[*index]);
+        }
+        break;
+    case 'i':
+    case 'o':
+        // Node ID
+        (*index)++;
+        if (*index < options.size())
+        {
+            _nodeId.assign(options[*index]);
+        }
+        else
+        {
+            fprintf(stderr, "Error: missing arguemnt for -%c.\n", str[1]);
+            _parseError = true;
+            return;
+        }
+    case 'p':
+        _fontPreview = true;
+        break;
+    case 's':
+        // Font Size
+        (*index)++;
+        if (*index < options.size())
+        {
+            _fontSize = atoi(options[*index].c_str());
+        }
+        else
+        {
+            fprintf(stderr, "Error: missing arguemnt for -%c.\n", str[1]);
+            _parseError = true;
+            return;
+        }
+        break;
+    case 't':
+        _textOutput = true;
+        break;
+    default:
+        break;
+    }
+}
+
+std::string EncoderArguments::getRealPath(const std::string& filepath)
+{
+    char path[PATH_MAX + 1]; /* not sure about the "+ 1" */
+    realpath(filepath.c_str(), path);
+    replace_char(path, '\\', '/');
+    return std::string(path);
+}
+
+void EncoderArguments::replace_char(char* str, char oldChar, char newChar)
+{
+    for (; *str != '\0'; str++)
+    {
+        if (*str == oldChar)
+        {
+            *str = newChar;
+        }
+    }
+}

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

@@ -0,0 +1,120 @@
+#ifndef COMMANDLINEARGS_H_
+#define COMMANDLINEARGS_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <string>
+#include <sys/stat.h>
+#include <vector>
+
+#include "Base.h"
+
+/**
+ * EncoderArguments handles parsing the command line arguments for the GamePlay Encoder.
+ */
+class EncoderArguments
+{
+public:
+
+    enum FileFormat
+    {
+        FILEFORMAT_UNKNOWN,
+        FILEFORMAT_DAE,
+        FILEFORMAT_TTF,
+        FILEFORMAT_GPB
+    };
+
+    /**
+     * Constructor.
+     */
+    EncoderArguments(size_t argc, const char** argv);
+
+    /**
+     * Destructor.
+     */
+    ~EncoderArguments(void);
+
+    /**
+     * Gets the file format from the file path based on the extension.
+     */
+    FileFormat getFileFormat() const;
+
+    /**
+     * Returns the file path.
+     */
+    const std::string& getFilePath() const;
+
+    /**
+     * Returns the char pointer to the file path string.
+     */
+    const char* EncoderArguments::getFilePathPointer() const;
+
+    /**
+     * Returns the path to where the DAE output should be written to.
+     */
+    const std::string& EncoderArguments::getDAEOutputPath() const;
+
+    const std::vector<std::string>& getGroupAnimationNodeId() const;
+    const std::vector<std::string>& getGroupAnimationAnimationId() const;
+
+    /**
+     * Returns true if an error occured while parsing the command line arguments.
+     */
+    bool parseErrorOccured() const;
+
+    /**
+     * Tests if a file exists on the file system.
+     * 
+     * @return True if the file exists; false otherwise.
+     */
+    bool fileExists() const;
+
+    /**
+     * Prints the usage information.
+     */
+    void printUsage() const;
+
+    bool fontPreviewEnabled() const;
+    bool textOutputEnabled() const;
+    bool DAEOutputEnabled() const;
+
+    const char* getNodeId() const;
+    unsigned int getFontSize() const;
+
+private:
+
+    /**
+     * Reads the command line option from the list of options starting at the given index.
+     * 
+     * @param options The list of command line options.
+     * @param index Pointer to the index within the options list. The index will be changed
+     *              if an option takes multiple arguments.
+     */
+    void readOption(const std::vector<std::string>& options, size_t *index);
+
+    static std::string getRealPath(const std::string& filepath);
+
+    /**
+     * Replaces all instance of oldChar with newChar in str.
+     */
+    static void replace_char(char* str, char oldChar, char newChar);
+
+private:
+    
+    std::string _filePath;
+    std::string _nodeId;
+    std::string _daeOutputPath;
+
+    unsigned int _fontSize;
+
+    bool _parseError;
+    bool _fontPreview;
+    bool _textOutput;
+    bool _daeOutput;
+
+    std::vector<std::string> _groupAnimationNodeId;
+    std::vector<std::string> _groupAnimationAnimationId;
+};
+
+#endif

+ 6 - 0
gameplay-encoder/src/FileIO.cpp

@@ -105,11 +105,17 @@ void fprintfMatrix4f(FILE* file, const float* m)
     {
         float v = m[i];
         if (v == 1.0f)
+        {
             fprintf(file, "1.0 ");
+        }
         else if (v == 0.0)
+        {
             fprintf(file, "0.0 ");
+        }
         else
+        {
             fprintf(file, "%f ",v);
+        }
     }
 }
 void skipString(FILE* file)

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

@@ -3,7 +3,7 @@
 namespace gameplay
 {
 
-GPBDecoder::GPBDecoder(void) : file(NULL), outFile(NULL)
+GPBDecoder::GPBDecoder(void) : _file(NULL), _outFile(NULL)
 {
 }
 
@@ -15,25 +15,25 @@ GPBDecoder::~GPBDecoder(void)
 void GPBDecoder::readBinary(const std::string& filepath)
 {
     // open files
-    file = fopen(filepath.c_str(), "rb");
+    _file = fopen(filepath.c_str(), "rb");
     std::string outfilePath = filepath;
     outfilePath += ".xml";
-    outFile = fopen(outfilePath.c_str(), "w");
+    _outFile = fopen(outfilePath.c_str(), "w");
 
     // read and write files
     assert(validateHeading());
 
-    fprintf(outFile, "<root>\n");
+    fprintf(_outFile, "<root>\n");
     readRefs();
-    fprintf(outFile, "</root>\n");
+    fprintf(_outFile, "</root>\n");
 
 
     // close files
-    fclose(outFile);
-    outFile = NULL;
+    fclose(_outFile);
+    _outFile = NULL;
 
-    fclose(file);
-    file = NULL;
+    fclose(_file);
+    _file = NULL;
 }
 
 bool GPBDecoder::validateHeading()
@@ -51,7 +51,7 @@ bool GPBDecoder::validateHeading()
     }
     // read version
     unsigned char version[2];
-    fread(version, sizeof(unsigned char), 2, file);
+    fread(version, sizeof(unsigned char), 2, _file);
     // don't care about version
 
     return true;
@@ -59,7 +59,7 @@ bool GPBDecoder::validateHeading()
 
 void GPBDecoder::readRefs()
 {
-    fprintf(outFile, "<RefTable>\n");
+    fprintf(_outFile, "<RefTable>\n");
     // read number of refs
     unsigned int refCount;
     assert(read(&refCount));
@@ -67,26 +67,26 @@ void GPBDecoder::readRefs()
     {
         readRef();
     }
-    fprintf(outFile, "</RefTable>\n");
+    fprintf(_outFile, "</RefTable>\n");
 }
 
 void GPBDecoder::readRef()
-{   
-    std::string xref = readString(file);
+{
+    std::string xref = readString(_file);
     unsigned int type, offset;
     assert(read(&type));
     assert(read(&offset));
     
-    fprintf(outFile, "<Reference>\n");
-    fprintfElement(outFile, "xref", xref);
-    fprintfElement(outFile, "type", type);
-    fprintfElement(outFile, "offset", offset);
-    fprintf(outFile, "</Reference>\n");
+    fprintf(_outFile, "<Reference>\n");
+    fprintfElement(_outFile, "xref", xref);
+    fprintfElement(_outFile, "type", type);
+    fprintfElement(_outFile, "offset", offset);
+    fprintf(_outFile, "</Reference>\n");
 }
 
 bool GPBDecoder::read(unsigned int* ptr)
 {
-    return fread(ptr, sizeof(unsigned int), 1, file) == 1;
+    return fread(ptr, sizeof(unsigned int), 1, _file) == 1;
 }
 
 std::string GPBDecoder::readString(FILE* fp)

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

@@ -40,8 +40,8 @@ public:
     std::string readString(FILE* fp);
 
 private:
-    FILE* file;
-    FILE* outFile;
+    FILE* _file;
+    FILE* _outFile;
 };
 
 }

+ 48 - 67
gameplay-encoder/src/GPBFile.cpp

@@ -4,7 +4,7 @@ namespace gameplay
 {
 
 GPBFile::GPBFile(void)
-    : file(NULL)
+    : _file(NULL), _animationsAdded(false)
 {
 }
 
@@ -14,104 +14,108 @@ GPBFile::~GPBFile(void)
 
 void GPBFile::saveBinary(const std::string& filepath)
 {
-    file = fopen(filepath.c_str(), "w+b");
+    _file = fopen(filepath.c_str(), "w+b");
 
     // identifier
     char identifier[] = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' };
-    fwrite(identifier, 1, sizeof(identifier), file);
+    fwrite(identifier, 1, sizeof(identifier), _file);
 
     // version
-    fwrite(VERSION, 1, sizeof(VERSION), file);
+    fwrite(VERSION, 1, sizeof(VERSION), _file);
 
     // write refs
-    refTable.writeBinary(file);
+    _refTable.writeBinary(_file);
 
     // meshes
-    write(geometry.size(), file);
-    for (std::list<Mesh*>::const_iterator i = geometry.begin(); i != geometry.end(); i++)
+    write(_geometry.size(), _file);
+    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); i++)
     {
-        (*i)->writeBinary(file);
+        (*i)->writeBinary(_file);
     }
 
     // Objects
-    write(objects.size(), file);
-    for (std::list<Object*>::const_iterator i = objects.begin(); i != objects.end(); i++)
+    write(_objects.size(), _file);
+    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); i++)
     {
-        (*i)->writeBinary(file);
+        (*i)->writeBinary(_file);
     }
 
-    refTable.updateOffsets(file);
+    _refTable.updateOffsets(_file);
     
-    fclose(file);
+    fclose(_file);
 }
 
 void GPBFile::saveText(const std::string& filepath)
 {
-    file = fopen(filepath.c_str(), "w");
+    _file = fopen(filepath.c_str(), "w");
 
-    fprintf(file, "<root>\n");
+    fprintf(_file, "<root>\n");
 
     // write refs
-    refTable.writeText(file);
+    _refTable.writeText(_file);
 
     // 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
-    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);
     }
 
-    fprintf(file, "</root>");
+    fprintf(_file, "</root>");
 
-    fclose(file);
+    fclose(_file);
 }
 
 void GPBFile::add(Object* obj)
 {
-    objects.push_back(obj);
+    _objects.push_back(obj);
 }
 
 void GPBFile::addScene(Scene* scene)
 {
     addToRefTable(scene);
-    objects.push_back(scene);
+    _objects.push_back(scene);
 }
 
 void GPBFile::addCamera(Camera* camera)
 {
     addToRefTable(camera);
-    cameras.push_back(camera);
+    _cameras.push_back(camera);
 }
 
 void GPBFile::addLight(Light* light)
 {
     addToRefTable(light);
-    lights.push_back(light);
+    _lights.push_back(light);
 }
 
 void GPBFile::addMesh(Mesh* mesh)
 {
     addToRefTable(mesh);
-    geometry.push_back(mesh);
+    _geometry.push_back(mesh);
 }
 
 void GPBFile::addNode(Node* node)
 {
     addToRefTable(node);
-    nodes.push_back(node);
+    _nodes.push_back(node);
 }
 
 void GPBFile::addAnimation(Animation* animation)
 {
-    if (!idExists(animation->getId()))
+    _animations.add(animation);
+
+    if (!_animationsAdded)
     {
-        addToRefTable(animation);
-        objects.push_back(animation);
+        // The animations container should only be added once and only if the file has at least one animation.
+        _animationsAdded = true;
+        addToRefTable(&_animations);
+        add(&_animations);
     }
 }
 
@@ -122,26 +126,28 @@ void GPBFile::addToRefTable(Object* obj)
         const std::string& id = obj->getId();
         if (id.length() > 0)
         {
-            if (refTable.get(id) == NULL)
-                refTable.add(id, obj);
+            if (_refTable.get(id) == NULL)
+            {
+                _refTable.add(id, obj);
+            }
         }
     }
 }
 
 Object* GPBFile::getFromRefTable(const std::string& id)
 {
-    return refTable.get(id);
+    return _refTable.get(id);
 }
 
 bool GPBFile::idExists(const std::string& id)
 {
-    return refTable.get(id) != NULL;
+    return _refTable.get(id) != NULL;
 }
 
 Camera* GPBFile::getCamera(const char* id)
 {
     // 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();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -155,7 +161,7 @@ Camera* GPBFile::getCamera(const char* id)
 Light* GPBFile::getLight(const char* id)
 {
     // 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();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -169,7 +175,7 @@ Light* GPBFile::getLight(const char* id)
 Mesh* GPBFile::getMesh(const char* id)
 {
     // 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();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -183,7 +189,7 @@ Mesh* GPBFile::getMesh(const char* id)
 Node* GPBFile::getNode(const char* id)
 {
     // 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();
         if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
@@ -197,7 +203,7 @@ Node* GPBFile::getNode(const char* id)
 void GPBFile::adjust()
 {
     // 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;
         if (obj->getTypeId() == Object::SCENE_ID)
@@ -208,43 +214,18 @@ void GPBFile::adjust()
     }
 
     // TODO:
-    // remove ambient lights
+    // remove ambient _lights
     // for each node
     //   if node has ambient light
     //     if node has no camera, mesh or children but 1 ambient light
     //       delete node and remove from ref table
     //     delete light and remove from ref table
-    // 
+    //
     // merge animations if possible
     //   Search for animations that have the same target and key times and see if they can be merged.
     //   Blender will output a simple translation animation to 3 separate animations with the same key times but targetting X, Y and Z.
     //   This can be merged into one animation. Same for scale animations.
 }
 
-Animation* GPBFile::findAnimationForJoint(const char* id)
-{
-    for (std::map<std::string, Reference>::iterator i = refTable.begin(); i != refTable.end(); i++)
-    {
-        Reference& ref = i->second;
-        Object* obj = ref.getObj();
-        if (obj->getTypeId() == Object::NODE_ID)
-        {
-            Node* node = (Node*)obj;
-            Model* model = node->getModel();
-            if (model)
-            {
-                MeshSkin* skin = model->getSkin();
-                if (skin)
-                {
-                    if (skin->hasJoint(id))
-                    {
-                        return skin->getAnimation();
-                    }
-                }
-            }
-        }
-    }
-    return NULL;
-}
 
 }

+ 17 - 16
gameplay-encoder/src/GPBFile.h

@@ -17,6 +17,7 @@
 #include "Mesh.h"
 #include "Reference.h"
 #include "ReferenceTable.h"
+#include "Animations.h"
 #include "Animation.h"
 #include "AnimationChannel.h"
 
@@ -28,6 +29,9 @@ namespace gameplay
      */
     const unsigned char VERSION[2] = {1, 0};
 
+/**
+ * The GamePlay Binary file class handles writing the GamePlay Binary file.
+ */
 class GPBFile
 {
 public:
@@ -48,8 +52,9 @@ public:
      * @param filepath The file name and path to save to.
      */
     void saveBinary(const std::string& filepath);
+
     /**
-     * Saves the GPBFile as a text file at filepath.
+     * Saves the GPBFile as a text file at filepath. Useful for debugging.
      *
      * @param filepath The file name and path to save to.
      */
@@ -67,6 +72,7 @@ public:
      * Adds the given object to the ref table.
      */
     void addToRefTable(Object* obj);
+
     /**
      * Returns the object with the given id. Returns NULL if not found.
      */
@@ -87,23 +93,18 @@ public:
      */
     void adjust();
 
-    /**
-     * Returns the animation that the given joint's animation channel's should be added to.
-     * 
-     * @param id The ID of the joint.
-     * @return The animation belonging to the skin that the joint is part of.
-     */
-    Animation* findAnimationForJoint(const char* id);
-
 private:
 
-    FILE* file;
-    std::list<Object*> objects;
-    std::list<Camera*> cameras;
-    std::list<Light*> lights;
-    std::list<Mesh*> geometry;
-    std::list<Node*> nodes; 
-    ReferenceTable refTable;
+    FILE* _file;
+    std::list<Object*> _objects;
+    std::list<Camera*> _cameras;
+    std::list<Light*> _lights;
+    std::list<Mesh*> _geometry;
+    std::list<Node*> _nodes;
+    Animations _animations;
+    bool _animationsAdded;
+
+    ReferenceTable _refTable;
 };
 
 }

+ 47 - 47
gameplay-encoder/src/Light.cpp

@@ -4,14 +4,14 @@ namespace gameplay
 {
 
 Light::Light(void) :
-    lightType(0),
-    constantAttenuation(0.0f),
-    linearAttenuation(0.0f),
-    quadraticAttenuation(0.0f),
-    falloffAngle(0.0f),
-    falloffExponent(0.0f)
+    _lightType(0),
+    _constantAttenuation(0.0f),
+    _linearAttenuation(0.0f),
+    _quadraticAttenuation(0.0f),
+    _falloffAngle(0.0f),
+    _falloffExponent(0.0f)
 {
-    fillArray(color, 0.0f, COLOR_SIZE);
+    fillArray(_color, 0.0f, COLOR_SIZE);
 }
 
 Light::~Light(void)
@@ -29,109 +29,109 @@ const char* Light::getElementName(void) const
 void Light::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    write(lightType, file);
-    write(color, COLOR_SIZE, file);
+    write(_lightType, file);
+    write(_color, COLOR_SIZE, file);
 
-    if (lightType == SpotLight)
+    if (_lightType == SpotLight)
     {
-        write(constantAttenuation, file);
-        write(linearAttenuation, file);
-        write(quadraticAttenuation, file);
-        write(falloffAngle, file);
-        write(falloffExponent, file);
+        write(_constantAttenuation, file);
+        write(_linearAttenuation, file);
+        write(_quadraticAttenuation, file);
+        write(_falloffAngle, file);
+        write(_falloffExponent, file);
     }
-    else if (lightType == PointLight)
+    else if (_lightType == PointLight)
     {
-        write(constantAttenuation, file);
-        write(linearAttenuation, file);
-        write(quadraticAttenuation, file);
+        write(_constantAttenuation, file);
+        write(_linearAttenuation, file);
+        write(_quadraticAttenuation, file);
     }
 
 }
 void Light::writeText(FILE* file)
 {
     fprintElementStart(file);
-    fprintfElement(file, "lightType", lightType);
-    fprintfElement(file, "color", color, COLOR_SIZE);
+    fprintfElement(file, "lightType", _lightType);
+    fprintfElement(file, "color", _color, COLOR_SIZE);
 
-    if (lightType == SpotLight)
+    if (_lightType == SpotLight)
     {
-        fprintfElement(file, "constantAttenuation", constantAttenuation);
-        fprintfElement(file, "linearAttenuation", linearAttenuation);
-        fprintfElement(file, "quadraticAttenuation", quadraticAttenuation);
-        fprintfElement(file, "falloffAngle", falloffAngle);
-        fprintfElement(file, "falloffExponent", falloffExponent);
+        fprintfElement(file, "constantAttenuation", _constantAttenuation);
+        fprintfElement(file, "linearAttenuation", _linearAttenuation);
+        fprintfElement(file, "quadraticAttenuation", _quadraticAttenuation);
+        fprintfElement(file, "falloffAngle", _falloffAngle);
+        fprintfElement(file, "falloffExponent", _falloffExponent);
     }
-    else if (lightType == PointLight)
+    else if (_lightType == PointLight)
     {
-        fprintfElement(file, "constantAttenuation", constantAttenuation);
-        fprintfElement(file, "linearAttenuation", linearAttenuation);
-        fprintfElement(file, "quadraticAttenuation", quadraticAttenuation);
+        fprintfElement(file, "constantAttenuation", _constantAttenuation);
+        fprintfElement(file, "linearAttenuation", _linearAttenuation);
+        fprintfElement(file, "quadraticAttenuation", _quadraticAttenuation);
     }
     fprintElementEnd(file);
 }
 
 float Light::getRed() const
 {
-    return color[0];
+    return _color[0];
 }
 float Light::getGreen() const
 {
-    return color[1];
+    return _color[1];
 }
 float Light::getBlue() const
 {
-    return color[2];
+    return _color[2];
 }
 
 bool Light::isAmbient() const
 {
-    return lightType == AmbientLight;
+    return _lightType == AmbientLight;
 }
 
 void Light::setAmbientLight()
 {
-    lightType = AmbientLight;
+    _lightType = AmbientLight;
 }
 void Light::setDirectionalLight()
 {
-    lightType = DirectionalLight;
+    _lightType = DirectionalLight;
 }
 void Light::setPointLight()
 {
-    lightType = PointLight;
+    _lightType = PointLight;
 }
 void Light::setSpotLight()
 {
-    lightType = SpotLight;
+    _lightType = SpotLight;
 }
 
 void Light::setColor(float r, float g, float b)
 {
-    color[0] = r;
-    color[1] = g;
-    color[2] = b;
+    _color[0] = r;
+    _color[1] = g;
+    _color[2] = b;
 }
 
 void Light::setConstantAttenuation(float value)
 {
-    constantAttenuation = value;
+    _constantAttenuation = value;
 }
 void Light::setLinearAttenuation(float value)
 {
-    linearAttenuation = value;
+    _linearAttenuation = value;
 }
 void Light::setQuadraticAttenuation(float value)
 {
-    quadraticAttenuation = value;
+    _quadraticAttenuation = value;
 }
 void Light::setFalloffAngle(float value)
 {
-    falloffAngle = value;
+    _falloffAngle = value;
 }
 void Light::setFalloffExponent(float value)
 {
-    falloffExponent = value;
+    _falloffExponent = value;
 }
 
 }

+ 8 - 8
gameplay-encoder/src/Light.h

@@ -51,7 +51,7 @@ public:
     void setFalloffExponent(float value);
 
     enum LightType
-    {   
+    {
         DirectionalLight = 1,
         PointLight = 2,
         SpotLight = 3,
@@ -60,14 +60,14 @@ public:
 
 private:
 
-    unsigned char lightType;
-    float color[COLOR_SIZE];
+    unsigned char _lightType;
+    float _color[COLOR_SIZE];
 
-    float constantAttenuation;
-    float linearAttenuation;
-    float quadraticAttenuation;
-    float falloffAngle;
-    float falloffExponent;
+    float _constantAttenuation;
+    float _linearAttenuation;
+    float _quadraticAttenuation;
+    float _falloffAngle;
+    float _falloffExponent;
 };
 
 

+ 12 - 9
gameplay-encoder/src/LightInstance.cpp

@@ -4,7 +4,7 @@
 namespace gameplay
 {
 
-LightInstance::LightInstance(void) : ref(NULL)
+LightInstance::LightInstance(void) : _ref(NULL)
 {
 
 }
@@ -24,29 +24,32 @@ const char* LightInstance::getElementName(void) const
 
 void LightInstance::writeBinary(FILE* file)
 {
-    //assert(ref != NULL);
-    if (ref != NULL)
-        ref->writeBinary(file);
+    if (_ref != NULL)
+    {
+        _ref->writeBinary(file);
+    }
 }
 void LightInstance::writeText(FILE* file)
 {
-    if (ref != NULL)
-        ref->writeText(file);
+    if (_ref != NULL)
+    {
+        _ref->writeText(file);
+    }
 }
 
 Light* LightInstance::getLight() const
 {
-    return ref;
+    return _ref;
 }
 
 void LightInstance::setLight(Light* light)
 {
-    ref = light;
+    _ref = light;
 }
 
 bool LightInstance::isAmbient() const
 {
-    return ref != NULL && ref->isAmbient();
+    return _ref != NULL && _ref->isAmbient();
 }
 
 }

+ 1 - 1
gameplay-encoder/src/LightInstance.h

@@ -32,7 +32,7 @@ public:
     bool isAmbient() const;
 
 private:
-    Light* ref;
+    Light* _ref;
 };
 
 }

+ 5 - 5
gameplay-encoder/src/Material.cpp

@@ -4,7 +4,7 @@ namespace gameplay
 {
 
 Material::Material(void) :
-    effect(NULL)
+    _effect(NULL)
 {
 }
 
@@ -24,14 +24,14 @@ const char* Material::getElementName(void) const
 void Material::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    //write(parameters, file);
-    //write(effect, file);
+    //write(_parameters, file);
+    //write(_effect, file);
 }
 void Material::writeText(FILE* file)
 {
     fprintElementStart(file);
-    //fprintfElement(file, "parameters", parameters);
-    //fprintfElement(file, "effect", effect);
+    //fprintfElement(file, "parameters", _parameters);
+    //fprintfElement(file, "effect", _effect);
     fprintElementEnd(file);
 }
 

+ 3 - 2
gameplay-encoder/src/Material.h

@@ -27,8 +27,9 @@ public:
     virtual void writeBinary(FILE* file);
     virtual void writeText(FILE* file);
 
-    std::list<MaterialParameter> parameters;
-    Effect* effect;
+private:
+    std::list<MaterialParameter> _parameters;
+    Effect* _effect;
 };
 
 

+ 5 - 5
gameplay-encoder/src/MaterialParameter.cpp

@@ -4,7 +4,7 @@ namespace gameplay
 {
 
 MaterialParameter::MaterialParameter(void) :
-    type(0)
+    _type(0)
 {
 }
 
@@ -24,14 +24,14 @@ const char* MaterialParameter::getElementName(void) const
 void MaterialParameter::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    write(value, file);
-    write(type, file);
+    write(_value, file);
+    write(_type, file);
 }
 void MaterialParameter::writeText(FILE* file)
 {
     fprintElementStart(file);
-    fprintfElement(file, "%f ", "value", value);
-    fprintfElement(file, "type", type);
+    fprintfElement(file, "%f ", "value", _value);
+    fprintfElement(file, "type", _type);
     fprintElementEnd(file);
 }
 

+ 3 - 2
gameplay-encoder/src/MaterialParameter.h

@@ -25,8 +25,9 @@ public:
     virtual void writeBinary(FILE* file);
     virtual void writeText(FILE* file);
 
-    std::vector<float> value;
-    unsigned int type;
+private:
+    std::vector<float> _value;
+    unsigned int _type;
 };
 
 

+ 7 - 3
gameplay-encoder/src/Matrix.cpp

@@ -9,9 +9,9 @@ Matrix::Matrix(void)
     setIdentity(m);
 }
 
-Matrix::Matrix(float m0, float m1, float m2, float m3, 
-               float m4, float m5, float m6, float m7, 
-               float m8, float m9, float m10, float m11, 
+Matrix::Matrix(float m0, float m1, float m2, float m3,
+               float m4, float m5, float m6, float m7,
+               float m8, float m9, float m10, float m11,
                float m12, float m13, float m14, float m15)
 {
     m[0] = m0;
@@ -233,7 +233,9 @@ bool Matrix::decompose(Vector3* scale, Quaternion* rotation, Vector3* translatio
 
     // nothing left to do
     if (scale == NULL && rotation == NULL)
+    {
         return true;
+    }
 
     // Extract the scale.
     // This is simply the length of each axis (row/column) in the matrix.
@@ -250,7 +252,9 @@ bool Matrix::decompose(Vector3* scale, Quaternion* rotation, Vector3* translatio
     // In this case, we simply negate a single axis of the scale.
     float det = determinant();
     if (det < 0)
+    {
         scaleZ = -scaleZ;
+    }
 
     if (scale)
     {

+ 5 - 5
gameplay-encoder/src/Matrix.h

@@ -19,7 +19,7 @@ namespace gameplay
 /**
  * The identify matrix.
  */
-static const float MATRIX4F_IDENTITY[16] = 
+static const float MATRIX4F_IDENTITY[16] =
 {
     1.0f, 0.0f, 0.0f, 0.0f,
     0.0f, 1.0f, 0.0f, 0.0f,
@@ -39,9 +39,9 @@ public:
     /**
      * Constructor.
      */
-    Matrix(float m0, float m1, float m2, float m3, 
-           float m4, float m5, float m6, float m7, 
-           float m8, float m9, float m10, float m11, 
+    Matrix(float m0, float m1, float m2, float m3,
+           float m4, float m5, float m6, float m7,
+           float m8, float m9, float m10, float m11,
            float m12, float m13, float m14, float m15);
 
     /**
@@ -71,7 +71,7 @@ public:
     static void setIdentity(float* matrix);
 
     /**
-     * Multiplies two matrices and stores the results in dst. 
+     * Multiplies two matrices and stores the results in dst.
      * m1 and m2 may be the same as dst.
      */
     static void multiply(const float* m1, const float* m2, float* dst);

+ 6 - 4
gameplay-encoder/src/Mesh.cpp

@@ -26,8 +26,8 @@ void Mesh::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
     // vertex formats
-    write(vertexFormats.size(), file);
-    for (std::vector<VertexElement>::iterator i = vertexFormats.begin(); i != vertexFormats.end(); i++)
+    write(_vertexFormats.size(), file);
+    for (std::vector<VertexElement>::iterator i = _vertexFormats.begin(); i != _vertexFormats.end(); i++)
     {
         i->writeBinary(file);
     }
@@ -74,7 +74,7 @@ void Mesh::writeText(FILE* file)
     // for each VertexFormat
     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);
         }
@@ -124,7 +124,7 @@ void Mesh::addMeshPart(Vertex* vertex)
 
 void Mesh::addVetexAttribute(unsigned int usage, unsigned int count)
 {
-    vertexFormats.push_back(VertexElement(usage, count));
+    _vertexFormats.push_back(VertexElement(usage, count));
 }
 
 size_t Mesh::getVertexCount() const
@@ -194,7 +194,9 @@ void Mesh::computeBounds()
     {
         float d = Vector3::distanceSquared(bounds.center, i->position);
         if (d > bounds.radius)
+        {
             bounds.radius = d;
+        }
     }
 
     // Convert squared distance to distance for radius

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

@@ -65,7 +65,8 @@ private:
 
     void computeBounds();
 
-    std::vector<VertexElement> vertexFormats;
+private:
+    std::vector<VertexElement> _vertexFormats;
 
 };
 

+ 20 - 16
gameplay-encoder/src/MeshPart.cpp

@@ -4,8 +4,8 @@ namespace gameplay
 {
 
 MeshPart::MeshPart(void) :
-    primitiveType(TRIANGLES),
-    indexFormat(INDEX8)
+    _primitiveType(TRIANGLES),
+    _indexFormat(INDEX8)
 {
 }
 
@@ -25,13 +25,13 @@ void MeshPart::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
 
-    write(primitiveType, file);
-    write(indexFormat, file);
+    write(_primitiveType, file);
+    write(_indexFormat, file);
 
     // write the number of bytes
     write(indicesByteSize(), file);
     // 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);
     }
@@ -39,31 +39,31 @@ void MeshPart::writeBinary(FILE* file)
 void MeshPart::writeText(FILE* file)
 {
     fprintElementStart(file);
-    fprintfElement(file, "primitiveType", primitiveType);
-    fprintfElement(file, "indexFormat", indexFormat);
-    fprintfElement(file, "%d ", "indices", indices);
+    fprintfElement(file, "primitiveType", _primitiveType);
+    fprintfElement(file, "indexFormat", _indexFormat);
+    fprintfElement(file, "%d ", "indices", _indices);
     fprintElementEnd(file);
 }
 
 void MeshPart::addIndex(unsigned int index)
 {
     updateIndexFormat(index);
-    indices.push_back(index);
+    _indices.push_back(index);
 }
 
 size_t MeshPart::getIndicesCount() const
 {
-    return indices.size();
+    return _indices.size();
 }
 
 unsigned int MeshPart::indicesByteSize() const
 {
-    return indices.size() * indexFormatSize();
+    return _indices.size() * indexFormatSize();
 }
 
 unsigned int MeshPart::indexFormatSize() const
 {
-    switch (indexFormat)
+    switch (_indexFormat)
     {
     case INDEX32:
         return 4;
@@ -77,7 +77,7 @@ unsigned int MeshPart::indexFormatSize() const
 
 void MeshPart::writeBinaryIndex(unsigned int index, FILE* file)
 {
-    switch (indexFormat)
+    switch (_indexFormat)
     {
     case INDEX32:
         write(index, file);
@@ -95,9 +95,13 @@ void MeshPart::writeBinaryIndex(unsigned int index, FILE* file)
 void MeshPart::updateIndexFormat(unsigned int newIndex)
 {
     if (newIndex >= 65536)
-        indexFormat = INDEX32;
-    else if (newIndex >= 256 && indexFormat != INDEX32)
-        indexFormat = INDEX16;
+    {
+        _indexFormat = INDEX32;
+    }
+    else if (newIndex >= 256 && _indexFormat != INDEX32)
+    {
+        _indexFormat = INDEX16;
+    }
 }
 
 }

+ 3 - 3
gameplay-encoder/src/MeshPart.h

@@ -80,9 +80,9 @@ private:
     void writeBinaryIndex(unsigned int index, FILE* file);
 
 private:
-    unsigned int primitiveType;
-    unsigned int indexFormat;
-    std::vector<unsigned int> indices;
+    unsigned int _primitiveType;
+    unsigned int _indexFormat;
+    std::vector<unsigned int> _indices;
 };
 
 

+ 18 - 58
gameplay-encoder/src/MeshSkin.cpp

@@ -6,11 +6,9 @@ namespace gameplay
 {
 
 MeshSkin::MeshSkin(void) :
-    influences(NULL),
-    vertexInfluenceCount(0),
-    animation(NULL)
+    _vertexInfluenceCount(0)
 {
-    setIdentityMatrix(bindShape);
+    setIdentityMatrix(_bindShape);
 }
 
 MeshSkin::~MeshSkin(void)
@@ -30,48 +28,29 @@ const char* MeshSkin::getElementName(void) const
 void MeshSkin::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    // bindShape
-    write(bindShape, 16, file);
-    // root joint
-    write(influences->getId(), file);
-    /*
-    if (influences != NULL)
-    {
-        influences->writeBinaryXref(file);
-    }
-    else
-    {
-        write((unsigned int)0, file);
-    }
-    */
-    // joints
-    write(joints.size(), file);
-    for (std::list<Node*>::const_iterator i = joints.begin(); i != joints.end(); i++)
+    write(_bindShape, 16, file);
+    write(_joints.size(), file);
+    for (std::list<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); i++)
     {
         (*i)->writeBinaryXref(file);
     }
-    // bindPoses
-    write(bindPoses, file);
+    write(_bindPoses, file);
 }
 
 void MeshSkin::writeText(FILE* file)
 {
     fprintElementStart(file);
     fprintf(file, "<bindShape>");
-    fprintfMatrix4f(file, bindShape);
+    fprintfMatrix4f(file, _bindShape);
     fprintf(file, "</bindShape>");
-    if (influences != NULL)
-    {
-        fprintf(file, "<ref xref=\"#%s\"/>", influences->getId().c_str());
-    }
     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, "</joints>\n");
-    fprintf(file, "<bindPoses count=\"%u\">", bindPoses.size());
-    for (std::list<float>::const_iterator i = bindPoses.begin(); i != bindPoses.end(); i++)
+    fprintf(file, "<bindPoses count=\"%u\">", _bindPoses.size());
+    for (std::list<float>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); i++)
     {
         fprintf(file, "%f ", *i);
     }
@@ -83,50 +62,45 @@ void MeshSkin::setBindShape(const float data[])
 {
     for (int i = 0; i < 16; i++)
     {
-        bindShape[i] = data[i];
+        _bindShape[i] = data[i];
     }
 }
 
 void MeshSkin::setVertexInfluenceCount(unsigned int count)
 {
-    vertexInfluenceCount = count;
-}
-
-void MeshSkin::setNode(Node* node)
-{
-    influences = node;
+    _vertexInfluenceCount = count;
 }
 
 void MeshSkin::setJointNames(const std::list<std::string>& list)
 {
-    jointNames = list;
+    _jointNames = list;
 }
 
 const std::list<std::string>& MeshSkin::getJointNames()
 {
-    return jointNames;
+    return _jointNames;
 }
 
 void MeshSkin::setJoints(const std::list<Node*>& list)
 {
-    joints = list;
+    _joints = list;
 }
 
 void MeshSkin::setBindPoses(std::vector<Matrix>& list)
 {
     for (std::vector<Matrix>::iterator i = list.begin(); i != list.end(); i++)
-    {   
+    {
         float* a = i->m;
         for (int j = 0; j < 16; j++)
         {
-            bindPoses.push_back(a[j]);
+            _bindPoses.push_back(a[j]);
         }
     }
 }
 
 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))
         {
@@ -136,18 +110,4 @@ bool MeshSkin::hasJoint(const char* id)
     return false;
 }
 
-Animation* MeshSkin::getAnimation()
-{
-    if (!animation)
-    {
-        animation = new Animation();
-    }
-    return animation;
-}
-
-void MeshSkin::setAnimationId(const char* id)
-{
-    getAnimation()->setId(id);
-}
-
 }

+ 6 - 24
gameplay-encoder/src/MeshSkin.h

@@ -36,8 +36,6 @@ public:
 
     void setVertexInfluenceCount(unsigned int count);
 
-    void setNode(Node* node);
-
     void setJointNames(const std::list<std::string>& list);
 
     const std::list<std::string>& getJointNames();
@@ -50,36 +48,20 @@ public:
      * Returns true if the MeshSkin contains a joint with the given ID.
      * 
      * @param id The ID of the joint to search for.
+     * 
      * @return True if the joint belongs to this skin, false otherwise.
      */
     bool hasJoint(const char* id);
 
-    /**
-     * Returns the animation that contains the animation channels that target this skin's joints.
-     * 
-     * @return The animation for this skin.
-     */
-    Animation* getAnimation();
-
-    /**
-     * Sets the id of the skin's animation.
-     * 
-     * @param id The new ID.
-     */
-    void setAnimationId(const char* id);
-
 private:
 
-    Node* influences;
-    float bindShape[16];
-    std::list<Node*> joints;
-    std::list<float> bindPoses;
-
-    std::list<std::string> jointNames;
+    float _bindShape[16];
+    std::list<Node*> _joints;
+    std::list<float> _bindPoses;
 
-    unsigned int vertexInfluenceCount;
+    std::list<std::string> _jointNames;
 
-    Animation* animation;
+    unsigned int _vertexInfluenceCount;
 };
 
 }

+ 19 - 15
gameplay-encoder/src/Model.cpp

@@ -4,8 +4,8 @@ namespace gameplay
 {
 
 Model::Model(void) :
-    ref(NULL),
-    meshSkin(NULL)
+    _ref(NULL),
+    _meshSkin(NULL)
 {
 }
 
@@ -26,52 +26,56 @@ void Model::writeBinary(FILE* file)
     Object::writeBinary(file);
 
     // xref:Mesh
-    if (ref != NULL)
-        ref->writeBinaryXref(file);
+    if (_ref != NULL)
+    {
+        _ref->writeBinaryXref(file);
+    }
     else
+    {
         write((unsigned int)0, file);
-    // meshSkin
+    }
+    // _meshSkin
     // Write one unsigned char to indicate if this model has a skin
-    if (meshSkin != NULL)
+    if (_meshSkin != NULL)
     {
         write((bool)true, file); // has a skin
-        meshSkin->writeBinary(file);
+        _meshSkin->writeBinary(file);
     }
     else
     {
         write((bool)false, file); // doesn't have a skin
     }
     // materials[]
-    writeBinaryObjects(materials, file);
+    writeBinaryObjects(_materials, file);
 
 }
 void Model::writeText(FILE* file)
 {
     fprintElementStart(file);
-    if (ref != NULL)
+    if (_ref != NULL)
     {
-        fprintfElement(file, "ref", ref->getId());
+        fprintfElement(file, "ref", _ref->getId());
     }
-    if (meshSkin != NULL)
+    if (_meshSkin != NULL)
     {
-        meshSkin->writeText(file);
+        _meshSkin->writeText(file);
     }
     fprintElementEnd(file);
 }
 
 MeshSkin* Model::getSkin()
 {
-    return meshSkin;
+    return _meshSkin;
 }
 
 void Model::setMesh(Mesh* mesh)
 {
-    ref = mesh;
+    _ref = mesh;
 }
 
 void Model::setSkin(MeshSkin* skin)
 {
-    meshSkin = skin;
+    _meshSkin = skin;
 }
 
 }

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

@@ -33,10 +33,11 @@ public:
     void setMesh(Mesh* mesh);
     MeshSkin* getSkin();
     void setSkin(MeshSkin* skin);
+
 private:
-    Mesh* ref;
-    MeshSkin* meshSkin;
-    std::list<Material*> materials;
+    Mesh* _ref;
+    MeshSkin* _meshSkin;
+    std::list<Material*> _materials;
 };
 
 }

+ 38 - 34
gameplay-encoder/src/Node.cpp

@@ -8,11 +8,11 @@ namespace gameplay
 
 Node::Node(void) :
     _childCount(0),
-    _nextSibling(NULL), _previousSibling(NULL), 
+    _nextSibling(NULL), _previousSibling(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);
+    setIdentityMatrix(_transform);
 }
 
 Node::~Node(void)
@@ -34,10 +34,10 @@ void Node::writeBinary(FILE* file)
     Object::writeBinary(file);
 
     // node type
-    unsigned int type = joint ? JOINT : NODE;
+    unsigned int type = _joint ? JOINT : NODE;
     write(type, file);
 
-    write(transform, 16, file);
+    write(_transform, 16, file);
     // children
     write(getChildCount(), file); // write number of children
     for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
@@ -46,27 +46,27 @@ void Node::writeBinary(FILE* file)
     }
 
     // camera
-    if (camera != NULL)
+    if (_camera != NULL)
     {
-        camera->writeBinary(file);
+        _camera->writeBinary(file);
     }
     else
     {
         write((unsigned char)0, file);
     }
     // light
-    if (light != NULL && !light->isAmbient())
+    if (_light != NULL && !_light->isAmbient())
     {
-        light->writeBinary(file);
+        _light->writeBinary(file);
     }
     else
     {
         write((unsigned char)0, file);
     }
     // mesh
-    if (model != NULL)
+    if (_model != NULL)
     {
-        model->writeBinary(file);
+        _model->writeBinary(file);
     }
     else
     {
@@ -77,14 +77,14 @@ void Node::writeText(FILE* file)
 {
     if (isJoint())
     {
-        fprintf(file, "<%s id=\"%s\" type=\"%s\">\n", getElementName(), id.c_str(), "JOINT");
+        fprintf(file, "<%s id=\"%s\" type=\"%s\">\n", getElementName(), getId().c_str(), "JOINT");
     }
     else
     {
         fprintElementStart(file);
     }
     fprintf(file, "<transform>");
-    fprintfMatrix4f(file, transform);
+    fprintfMatrix4f(file, _transform);
     fprintf(file, "</transform>\n");
 
     // children
@@ -93,19 +93,19 @@ void Node::writeText(FILE* file)
         node->writeText(file);
     }
     // camera
-    if (camera != NULL)
+    if (_camera != NULL)
     {
-        camera->writeText(file);
+        _camera->writeText(file);
     }
     // light
-    if (light != NULL && !light->isAmbient())
+    if (_light != NULL && !_light->isAmbient())
     {
-        light->writeText(file);
+        _light->writeText(file);
     }
     // mesh
-    if (model != NULL)
+    if (_model != NULL)
     {
-        model->writeText(file);
+        _model->writeText(file);
     }
     fprintElementEnd(file);
 }
@@ -159,9 +159,13 @@ void Node::removeChild(Node* child)
 
     // Was this child our first or last child?
     if (child == _firstChild)
+    {
         _firstChild = child->_nextSibling;
+    }
     if (child == _lastChild)
+    {
         _lastChild = child->_previousSibling;
+    }
 
     // Remove parent and sibling info from the child, now that it is no longer parented
     child->_parent = NULL;
@@ -217,58 +221,58 @@ Node* Node::getParent() const
 
 void Node::setCameraInstance(CameraInstance* cameraInstance)
 {
-    camera = cameraInstance;
+    _camera = cameraInstance;
 }
 void Node::setLightInstance(LightInstance* lightInstance)
 {
-    light = lightInstance;
+    _light = lightInstance;
 }
 void Node::setModel(Model* model)
 {
-    this->model = model;
+    _model = model;
 }
 
 void Node::setTransformMatrix(float matrix[])
 {
     for (int i = 0; i < 16; i++)
     {
-        transform[i] = matrix[i];
+        _transform[i] = matrix[i];
     }
 }
 
 void Node::setIsJoint(bool value)
 {
-    joint = value;
+    _joint = value;
 }
 
 bool Node::isJoint()
 {
-    return joint;
+    return _joint;
 }
 
 Camera* Node::getCamera() const
 {
-    if (camera)
+    if (_camera)
     {
-        return camera->getCamera();
+        return _camera->getCamera();
     }
     return NULL;
 }
 
 Light* Node::getLight() const
 {
-    if (light)
+    if (_light)
     {
-        return light->getLight();
+        return _light->getLight();
     }
     return NULL;
 }
 
 Model* Node::getModel() const
 {
-    if (model)
+    if (_model)
     {
-        return model;
+        return _model;
     }
     return NULL;
 }
@@ -292,12 +296,12 @@ Node* Node::getFirstCameraNode() const
 
 bool Node::hasCamera() const
 {
-    return camera != NULL;
+    return _camera != NULL;
 }
 
 bool Node::hasLight() const
 {
-    return light != NULL;
+    return _light != NULL;
 }
 
-} 
+}

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

@@ -138,6 +138,7 @@ public:
      * Sets if this node is a joint node.
      */
     void setIsJoint(bool value);
+
     /**
      * Returns true if this is a joint node.
      */
@@ -156,7 +157,7 @@ public:
     bool hasLight() const;
     
 private:
-    float transform[16];
+    float _transform[16];
 
     int _childCount;
     Node* _nextSibling;
@@ -165,11 +166,11 @@ private:
     Node* _lastChild;
     Node* _parent;
 
-    CameraInstance* camera;
-    LightInstance* light;
-    Model* model;
+    CameraInstance* _camera;
+    LightInstance* _light;
+    Model* _model;
 
-    bool joint;
+    bool _joint;
 };
 
 

+ 16 - 8
gameplay-encoder/src/Object.cpp

@@ -3,7 +3,7 @@
 namespace gameplay
 {
 
-Object::Object(void) : fposition(0)
+Object::Object(void) : _fposition(0)
 {
 }
 
@@ -23,27 +23,35 @@ void Object::writeBinary(FILE* file)
 
 const std::string& Object::getId() const
 {
-    return id;
+    return _id;
 }
 
 void Object::setId(const char* idStr)
 {
     if (idStr)
-        id = idStr;
+    {
+        _id = idStr;
+    }
 }
 
 void Object::setId(const std::string& newId)
 {
     if (newId.length() > 0)
-        id = newId;
+    {
+        _id = newId;
+    }
 }
 
 void Object::fprintElementStart(FILE* file)
 {
-    if (id.length() > 0)
-        fprintf(file, "<%s id=\"%s\">\n", getElementName(), id.c_str());
+    if (_id.length() > 0)
+    {
+        fprintf(file, "<%s id=\"%s\">\n", getElementName(), _id.c_str());
+    }
     else
+    {
         fprintf(file, "<%s>\n", getElementName());
+    }
 }
 
 void Object::fprintElementEnd(FILE* file)
@@ -53,12 +61,12 @@ void Object::fprintElementEnd(FILE* file)
 
 unsigned int Object::getFilePosition()
 {
-    return (unsigned int)fposition;
+    return (unsigned int)_fposition;
 }
 
 void Object::saveFilePosition(FILE* file)
 {
-    fposition = ftell(file);
+    _fposition = ftell(file);
 }
 
 void Object::writeBinaryXref(FILE* file)

+ 17 - 8
gameplay-encoder/src/Object.h

@@ -11,7 +11,9 @@
 
 namespace gameplay
 {
-
+/**
+ * Object is the abstract base class of all the objects that can be written in the GamePlay Binary file.
+ */
 class Object
 {
 public:
@@ -21,8 +23,9 @@ public:
     {
         SCENE_ID = 1,
         NODE_ID = 2,
-        ANIMATION_ID = 3,
-        ANIMATIONCHANNEL_ID = 4,
+        ANIMATIONS_ID = 3,
+        ANIMATION_ID = 4,
+        ANIMATIONCHANNEL_ID = 5,
         NODEINSTANCE_ID = 8,
         CAMERAINSTANCE_ID = 9,
         LIGHTINSTANCE_ID = 10,
@@ -47,19 +50,23 @@ public:
      * Destructor.
      */
     virtual ~Object(void);
+
     /**
      * Returns the Object TypeID.
      */
     virtual unsigned int getTypeId(void) const;
+
     /**
      * Returns the string element name of the object.
      * Used for printing the gameplayfile as text.
      */
     virtual const char* getElementName(void) const = 0;
+
     /**
      * Writes this object to the file stream as binary.
      */
     virtual void writeBinary(FILE* file);
+
     /**
      * Writes this object to the file stream as text.
      */
@@ -69,23 +76,28 @@ public:
      * Returns this objects id string.
      */
     const std::string& getId() const;
+
     /**
      * Sets this object's id string.
      */
     void setId(const char* id);
+
     /**
      * Sets this object's id string.
      */
     void setId(const std::string& id);
+
     /**
      * Prints an XML start element with the name of this object to the text file stream.
      * Also prints the id as an attribute if the id length is greater than zero.
      */
     void fprintElementStart(FILE* file);
+
     /**
      * Prints an XML end element with the name of this object to the text file stream.
      */
     void fprintElementEnd(FILE* file);
+
     /**
      * Writes the xref of this object to the binary file stream.
      */
@@ -135,12 +147,9 @@ private:
      */
     void saveFilePosition(FILE* file);
 
-protected:
-
-    std::string id;
-
 private:
-    long fposition;
+    std::string _id;
+    long _fposition;
 };
 
 }

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

@@ -173,6 +173,7 @@ public:
      * quaternion is already unit-length.
      *
      * @param dst A quaternion to store the inverse in.
+     * 
      * @return true if the inverse can be computed, false otherwise.
      */
     bool inverse(Quaternion* dst) const;
@@ -245,6 +246,7 @@ public:
      * Converts this Quaternion4f to axis-angle notation. The axis is normalized.
      *
      * @param e The Vector3f which stores the axis.
+     * 
      * @return The angle (in radians).
      */
     float toAxisAngle(Vector3* e) const;

+ 17 - 17
gameplay-encoder/src/Reference.cpp

@@ -4,17 +4,17 @@ namespace gameplay
 {
 
 Reference::Reference(void) :
-    type(0),
-    offset(0),
-    ref(NULL)
+    _type(0),
+    _offset(0),
+    _ref(NULL)
 {
 }
 
 Reference::Reference(std::string _xref, Object* _ref) :
-    xref(_xref),
-    type(_ref->getTypeId()),
-    offset(0),
-    ref(_ref)
+    _xref(_xref),
+    _type(_ref->getTypeId()),
+    _offset(0),
+    _ref(_ref)
 {
 }
 
@@ -30,22 +30,22 @@ const char* Reference::getElementName(void) const
 void Reference::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    write(xref, file);
-    write(type, file);
-    write(offset, file);
+    write(_xref, file);
+    write(_type, file);
+    write(_offset, file);
 }
 void Reference::writeText(FILE* file)
 {
     fprintElementStart(file);
-    fprintfElement(file, "xref", xref);
-    fprintfElement(file, "type", type);
-    fprintfElement(file, "offset", offset);
+    fprintfElement(file, "xref", _xref);
+    fprintfElement(file, "type", _type);
+    fprintfElement(file, "offset", _offset);
     fprintElementEnd(file);
 }
 
 bool Reference::updateOffset(FILE* file)
 {
-    long newOffset = ref->getFilePosition();
+    long newOffset = _ref->getFilePosition();
     return updateOffset(file, newOffset);
 }
 
@@ -57,7 +57,7 @@ bool Reference::updateOffset(FILE* file, long newOffset)
         long savedOffset = ftell(file);
 
         // update the offset data for this
-        offset = newOffset;
+        _offset = newOffset;
         // seek this Reference object in the file
         fseek(file, getFilePosition(), SEEK_SET);
 
@@ -69,7 +69,7 @@ bool Reference::updateOffset(FILE* file, long newOffset)
         //skipUint(file);
 
         // write over the old offset
-        write(offset, file);
+        write(_offset, file);
 
         // restore the offset
         fseek(file, savedOffset, SEEK_SET);
@@ -80,7 +80,7 @@ bool Reference::updateOffset(FILE* file, long newOffset)
 
 Object* Reference::getObj()
 {
-    return ref;
+    return _ref;
 }
 
 }

+ 6 - 4
gameplay-encoder/src/Reference.h

@@ -28,6 +28,7 @@ public:
     /**
      * Updates the offset of this Reference object if it has already need written to file.
      * @param file The file stream.
+     * 
      * @return True if the offset was updates, false otherwise.
      */
     bool updateOffset(FILE* file);
@@ -36,6 +37,7 @@ public:
      * Updates the offset of this Reference object if it has already need written to file.
      * @param file The file stream.
      * @param newOffset The new file offset.
+     * 
      * @return True if the offset in the binary file was updated. False if this ref hasn't been written to file yet.
      */
     bool updateOffset(FILE* file, long newOffset);
@@ -43,11 +45,11 @@ public:
     Object* getObj();
 
 private:
-    std::string xref;
-    unsigned int type;
-    unsigned int offset;
+    std::string _xref;
+    unsigned int _type;
+    unsigned int _offset;
 
-    Object* ref;
+    Object* _ref;
 };
 
 }

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

@@ -13,13 +13,13 @@ ReferenceTable::~ReferenceTable(void)
 
 void ReferenceTable::add(std::string xref, Object* obj)
 {
-    table[xref] = Reference(xref, obj);
+    _table[xref] = Reference(xref, obj);
 }
 
 Object* ReferenceTable::get(const std::string& xref)
 {
-    std::map<std::string, Reference>::iterator it = table.find(xref);
-    if (it != table.end())
+    std::map<std::string, Reference>::iterator it = _table.find(xref);
+    if (it != _table.end())
     {
         Reference ref = it->second;
         return ref.getObj();
@@ -29,8 +29,8 @@ Object* ReferenceTable::get(const std::string& xref)
 
 void ReferenceTable::writeBinary(FILE* file)
 {
-    write(table.size(), file);
-    for ( std::map<std::string, Reference>::iterator i=table.begin() ; i != table.end(); i++ )
+    write(_table.size(), file);
+    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); i++ )
     {
         i->second.writeBinary(file);
     }
@@ -39,7 +39,7 @@ void ReferenceTable::writeBinary(FILE* file)
 void ReferenceTable::writeText(FILE* file)
 {
     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);
     }
@@ -48,7 +48,7 @@ void ReferenceTable::writeText(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;
         ref.updateOffset(file);
@@ -57,12 +57,12 @@ void ReferenceTable::updateOffsets(FILE* file)
 
 std::map<std::string, Reference>::iterator ReferenceTable::begin()
 {
-    return table.begin();
+    return _table.begin();
 }
 
 std::map<std::string, Reference>::iterator ReferenceTable::end()
 {
-    return table.end();
+    return _table.end();
 }
 
 }

+ 14 - 1
gameplay-encoder/src/ReferenceTable.h

@@ -27,19 +27,32 @@ public:
      */
     virtual ~ReferenceTable(void);
 
+    /**
+     * Adds an object to the reference table.
+     * 
+     * @param xref The xref for the object.
+     * @param obj The object to be added.
+     */
     void add(std::string xref, Object* obj);
+
     Object* get(const std::string& xref);
 
     void writeBinary(FILE* file);
     void writeText(FILE* file);
 
+    /**
+     * Updates the file positon offsets of the Reference objects in the GamePlay binary file.
+     * This needs to be called after all of the objects have been written.
+     * 
+     * @param file The file pointer.
+     */
     void updateOffsets(FILE* file);
 
     std::map<std::string, Reference>::iterator begin();
     std::map<std::string, Reference>::iterator end();
 
 private:
-    std::map<std::string, Reference> table;
+    std::map<std::string, Reference> _table;
 };
 
 }

+ 19 - 19
gameplay-encoder/src/Scene.cpp

@@ -5,11 +5,11 @@
 namespace gameplay
 {
 
-Scene::Scene(void) : cameraNode(NULL)
+Scene::Scene(void) : _cameraNode(NULL)
 {
-    ambientColor[0] = 0.0f;
-    ambientColor[1] = 0.0f;
-    ambientColor[2] = 0.0f;
+    _ambientColor[0] = 0.0f;
+    _ambientColor[1] = 0.0f;
+    _ambientColor[2] = 0.0f;
 }
 
 Scene::~Scene(void)
@@ -29,45 +29,45 @@ const char* Scene::getElementName(void) const
 void Scene::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
-    writeBinaryObjects(nodes, file);
-    if (cameraNode)
+    writeBinaryObjects(_nodes, file);
+    if (_cameraNode)
     {
-        cameraNode->writeBinaryXref(file);
+        _cameraNode->writeBinaryXref(file);
     }
     else
     {
         writeZero(file);
     }
-    write(ambientColor, Light::COLOR_SIZE, file);
+    write(_ambientColor, Light::COLOR_SIZE, file);
 }
 void Scene::writeText(FILE* 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);
     }
-    if (cameraNode)
+    if (_cameraNode)
     {
-        fprintfElement(file, "activeCamera", cameraNode->getId());
+        fprintfElement(file, "activeCamera", _cameraNode->getId());
     }
-    fprintfElement(file, "ambientColor", ambientColor, Light::COLOR_SIZE);
+    fprintfElement(file, "ambientColor", _ambientColor, Light::COLOR_SIZE);
     fprintElementEnd(file);
 }
 
 void Scene::add(Node* node)
 {
-    nodes.push_back(node);
+    _nodes.push_back(node);
 }
 
 void Scene::setActiveCameraNode(Node* node)
 {
-    cameraNode = node;
+    _cameraNode = node;
 }
 
 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();
         if (n)
@@ -81,14 +81,14 @@ Node* Scene::getFirstCameraNode() const
 void Scene::calcAmbientColor()
 {
     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);
     }
     
-    ambientColor[0] = std::min(values[0], 1.0f);
-    ambientColor[1] = std::min(values[1], 1.0f);
-    ambientColor[2] = std::min(values[2], 1.0f);
+    _ambientColor[0] = std::min(values[0], 1.0f);
+    _ambientColor[1] = std::min(values[1], 1.0f);
+    _ambientColor[2] = std::min(values[2], 1.0f);
 }
 
 void Scene::calcAmbientColor(const Node* node, float* values) const

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

@@ -61,9 +61,10 @@ private:
      */
     void calcAmbientColor(const Node* node, float* values) const;
 
-    std::list<Node*> nodes;
-    Node* cameraNode;
-    float ambientColor[Light::COLOR_SIZE];
+private:
+    std::list<Node*> _nodes;
+    Node* _cameraNode;
+    float _ambientColor[Light::COLOR_SIZE];
 };
 
 }

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

@@ -14,6 +14,37 @@ inline char lowercase(char c)
     return c;
 }
 
+bool startsWith(const char* str, const char* prefix, bool ignoreCase)
+{
+    size_t length = strlen(str);
+    size_t prefixLength = strlen(prefix);
+
+    if (prefixLength > length)
+    {
+        return false;
+    }
+
+    const char* p = str;
+    while (*p != '\0' && *prefix != '\0')
+    {
+        if (ignoreCase)
+        {
+            if (lowercase(*p) != lowercase(*prefix))
+            {
+                return false;
+            }
+        }
+        else if (*p != *prefix)
+        {
+            return false;
+        }
+        
+        ++p;
+        ++prefix;
+    }
+    return true;
+}
+
 bool endsWith(const char* str, const char* suffix, bool ignoreCase)
 {
     size_t length = strlen(str);
@@ -27,7 +58,7 @@ bool endsWith(const char* str, const char* suffix, bool ignoreCase)
     size_t offset = length - suffixLength;
 
     const char* p = str + offset;
-    while (*p != '\0')
+    while (*p != '\0' && *suffix != '\0')
     {
         if (ignoreCase)
         {

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

@@ -6,6 +6,7 @@
 namespace gameplay
 {
 
+bool startsWith(const char* str, const char* prefix, bool ignoreCase = true);
 bool endsWith(const char* str, const char* suffix, bool ignoreCase = true);
 
 /**

+ 14 - 2
gameplay-encoder/src/TTFFontEncoder.cpp

@@ -89,16 +89,20 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     // Find the width of the image.
     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);
         if (error)
+        {
             fprintf(stderr, "FT_Load_Char error : %d \n", error);
+        }
         
         int bitmapRows = slot->bitmap.rows;
         actualfontHeight = (actualfontHeight < bitmapRows) ? bitmapRows : actualfontHeight;
         
         if (slot->bitmap.rows > slot->bitmap_top)
-          bitmapRows += (slot->bitmap.rows - slot->bitmap_top);
+        {
+            bitmapRows += (slot->bitmap.rows - slot->bitmap_top);
+        }
         rowSize = (rowSize < bitmapRows) ? bitmapRows : rowSize;
     }
 
@@ -133,7 +137,9 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
             // Load glyph image into the slot (erase the previous one).
             error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
             if (error)
+            {
                 fprintf(stderr, "FT_Load_Char error : %d \n", error);
+            }
 
             // Glyph image.
             int glyphWidth = slot->bitmap.pitch;
@@ -163,7 +169,9 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
             penY = row * rowSize;
 
             if (ascii == (END_INDEX-1))
+            {
                 textureSizeFound = true;
+            }
 
             i++;
         }
@@ -174,7 +182,9 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     for (;;)
     {
         if ((penY + rowSize) >= pow(2.0, powerOf2))
+        {
             powerOf2++;
+        }
         else
         {
             imageHeight = (int)pow(2.0, powerOf2);
@@ -194,7 +204,9 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
         // Load glyph image into the slot (erase the previous one).
         error = FT_Load_Char(face, ascii, FT_LOAD_RENDER);
         if (error)
+        {
             fprintf(stderr, "FT_Load_Char error : %d \n", error);
+        }
 
         // Glyph image.
         unsigned char* glyphBuffer =  slot->bitmap.buffer;

+ 1 - 1
gameplay-encoder/src/TTFFontEncoder.h

@@ -14,7 +14,7 @@
 
 // Structure of Glyph.
 class Glyph
-{   
+{
 public:
     unsigned int index;
     unsigned int width;

+ 7 - 0
gameplay-encoder/src/Vector2.h

@@ -115,6 +115,7 @@ public:
      *
      * @param v1 The first vector.
      * @param v2 The second vector.
+     * 
      * @return The angle between the two vectors, in radians.
      */
     static float angle(const Vector2& v1, const Vector2& v2);
@@ -157,6 +158,7 @@ public:
      * Returns the distance between this vector and v.
      *
      * @param v The other vector.
+     * 
      * @return The distance between this vector and v.
      * @see distanceSquared
      */
@@ -171,6 +173,7 @@ public:
      * this method instead of distance.
      *
      * @param v The other vector.
+     * 
      * @return The squared distance between this vector and v.
      * @see distance
      */
@@ -180,6 +183,7 @@ public:
      * Returns the dot product of this vector and the specified vector.
      *
      * @param v The vector to compute the dot product with.
+     * 
      * @return The dot product.
      */
     float dot(const Vector2& v);
@@ -189,6 +193,7 @@ public:
      *
      * @param v1 The first vector.
      * @param v2 The second vector.
+     * 
      * @return The dot product between the vectors.
      */
     static float dot(const Vector2& v1, const Vector2& v2);
@@ -311,7 +316,9 @@ public:
     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

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

@@ -136,6 +136,7 @@ public:
      *
      * @param v1 The first vector.
      * @param v2 The second vector.
+     * 
      * @return The angle between the two vectors, in radians.
      */
     static float angle(const Vector3& v1, const Vector3& v2);
@@ -195,6 +196,7 @@ public:
      * Returns the distance between this vector and v.
      *
      * @param v The other vector.
+     * 
      * @return The distance between this vector and v.
      * @see distanceSquared
      */
@@ -209,6 +211,7 @@ public:
      * this method instead of distance.
      *
      * @param v The other vector.
+     * 
      * @return The squared distance between this vector and v.
      * @see distance
      */
@@ -218,6 +221,7 @@ public:
      * Returns the dot product of this vector and the specified vector.
      *
      * @param v The vector to compute the dot product with.
+     * 
      * @return The dot product.
      */
     float dot(const Vector3& v);
@@ -227,6 +231,7 @@ public:
      *
      * @param v1 The first vector.
      * @param v2 The second vector.
+     * 
      * @return The dot product between the vectors.
      */
     static float dot(const Vector3& v1, const Vector3& v2);

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

@@ -145,6 +145,7 @@ public:
      *
      * @param v1 The first vector.
      * @param v2 The second vector.
+     * 
      * @return The angle between the two vectors, in radians.
      */
     static float angle(const Vector4& v1, const Vector4& v2);
@@ -187,6 +188,7 @@ public:
      * Returns the distance between this vector and v.
      *
      * @param v The other vector.
+     * 
      * @return The distance between this vector and v.
      * @see distanceSquared
      */
@@ -201,6 +203,7 @@ public:
      * this method instead of distance.
      *
      * @param v The other vector.
+     * 
      * @return The squared distance between this vector and v.
      * @see distance
      */
@@ -210,6 +213,7 @@ public:
      * Returns the dot product of this vector and the specified vector.
      *
      * @param v The vector to compute the dot product with.
+     * 
      * @return The dot product.
      */
     float dot(const Vector4& v);
@@ -219,6 +223,7 @@ public:
      *
      * @param v1 The first vector.
      * @param v2 The second vector.
+     * 
      * @return The dot product between the vectors.
      */
     static float dot(const Vector4& v1, const Vector4& v2);

+ 1 - 1
gameplay-encoder/src/Vertex.h

@@ -69,7 +69,7 @@ public:
 
     inline bool operator==(const Vertex& v) const
     {
-        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal && texCoord==v.texCoord && 
+        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal && texCoord==v.texCoord &&
             blendWeights==v.blendWeights && blendIndices==v.blendIndices;
     }
 

+ 21 - 169
gameplay-encoder/src/main.cpp

@@ -1,120 +1,24 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <iostream>
 #include <string>
-#include <sys/stat.h>
-#ifdef WIN32
-    #define PATH_MAX    _MAX_PATH
-    #define realpath(A,B)    _fullpath(B,A,PATH_MAX)
-#endif
 
 #include "DAESceneEncoder.h"
 #include "TTFFontEncoder.h"
-#include "StringUtil.h"
 #include "GPBDecoder.h"
+#include "EncoderArguments.h"
 
-using namespace std;
 using namespace gameplay;
 
-enum FileFormat
-{
-    FILEFORMAT_UNKNOWN,
-    FILEFORMAT_DAE,
-    FILEFORMAT_TTF,
-    FILEFORMAT_GPB
-};
-
-
-/**
- * Gets the file format from the file path based on extension.
- */
-FileFormat getFileFormat(const std::string& filename)
-{
-    // Extract the extension
-    std::string ext = "";
-    size_t pos = filename.find_last_of(".");
-    if (pos != std::string::npos)
-        ext = filename.substr(pos + 1);
-    
-    // Match every supported extension with its format constant
-    if (ext.compare("dae") == 0 || ext.compare("DAE") == 0)
-    {
-        return FILEFORMAT_DAE;
-    }
-    if (ext.compare("ttf") == 0 || ext.compare("TTF") == 0)
-    {
-        return FILEFORMAT_TTF;
-    }
-    if (ext.compare("gpb") == 0 || ext.compare("GPB") == 0)
-    {
-        return FILEFORMAT_GPB;
-    }
-
-    return FILEFORMAT_UNKNOWN;
-}
-
-
-/**
- * Tests if a file exists on the file system.
- */
-bool fileExists(const std::string& filename)
-{
-    struct stat buf;
-    if (stat(filename.c_str(), &buf) != -1)
-    {
-        return true;
-    }
-    return false;
-}
-
-
-/**
- * Replaces all instance of oldChar with newChar in str.
- */
-void replace_char(char* str, char oldChar, char newChar)
-{
-    for (; *str != '\0'; str++)
-    {
-        if (*str == oldChar)
-            *str = newChar;
-    }
-}
-
 std::string getFileName(const std::string& filepath)
 {
     size_t index1 = filepath.find_last_of('\\');
     size_t index2 = filepath.find_last_of('/');
     size_t index = (index1 != -1 && index1 > index2 ? index1 : index2);
     size_t length = filepath.length();
-    string filename = filepath.substr(index + 1, length);
+    std::string filename = filepath.substr(index + 1, length);
     length = filename.length();
-    string output = filename.substr(0, (length-4));
+    std::string output = filename.substr(0, (length-4));
     return output;
-    
-}
-
-
-std::string getRealpath(const std::string& filepath)
-{
-    char path[PATH_MAX + 1]; /* not sure about the "+ 1" */
-    realpath(filepath.c_str(), path);
-    replace_char(path, '\\', '/');
-    return std::string(path);
-}
-
-
-void usage()
-{
-    fprintf(stderr,"Usage: gameplay-encoder [options] <filepath>\n");
-    fprintf(stderr,".dae file options:\n");
-    fprintf(stderr," -i<id>\tFilter by node ID\n");
-    fprintf(stderr," -t\tWrite text/xml\n");
-    fprintf(stderr,".ttf file options:\n");
-    fprintf(stderr,"-s<size of font> -p \n");
-    exit(8);
 }
 
-
 /**
  * Main application entry point.
  *
@@ -129,102 +33,50 @@ void usage()
  */
 int main(int argc, const char** argv)
 {
-    std::string filepath;
-    const char* id = NULL;
-    unsigned int size = 0;
-    bool fontpreview = false;
-    bool text = false;
-
-    if (argc <= 1)
-    {
-        usage();
-    }
+    EncoderArguments arguments(argc, argv);
 
-    if ( endsWith(argv[1], ".dae") || endsWith(argv[1], ".gpb"))
+    if (arguments.parseErrorOccured())
     {
-        filepath = argv[1];
-    }
-    else
-    {
-        if (argc < 3)
-        {
-            usage();
-        }
-        else
-        {   
-            filepath = argv[argc-1];
-        }
+        arguments.printUsage();
+        return 0;
     }
 
     // Check if the file exists.
-    if (!fileExists(filepath))
+    if (!arguments.fileExists())
     {
-        fprintf(stderr, "Error: File not found: %s\n", filepath.c_str());
+        fprintf(stderr, "Error: File not found: %s\n", arguments.getFilePathPointer());
         return -1;
     }
-    // File exists
-    fprintf(stderr, "Encoding file: %s\n", filepath.c_str());
-    
-    // Get the file format
-    FileFormat fileFormat = getFileFormat(filepath);
-
-    // Parse arguments
-    while ((argc > 1) && (argv[1][0] == '-'))
-    {
-        switch (argv[1][1])
-        {
-            case 'i':
-            case 'o':
-                id = &argv[1][2];
-                break;
 
-            case 's':
-                size = atoi(&argv[1][2]);
-                break;
-            
-            case 'p':
-                fontpreview = true;
-                break;
-            case 't':
-                text = true;
-                break;
-
-            default:
-                usage();
-        }
-        ++argv;
-        --argc;
-    }
-    
+    // File exists
+    fprintf(stderr, "Encoding file: %s\n", arguments.getFilePathPointer());
 
-    switch (fileFormat)
+    switch (arguments.getFileFormat())
     {
-    case FILEFORMAT_DAE:
+    case EncoderArguments::FILEFORMAT_DAE:
         {
-            std::string realpath = getRealpath(filepath);
+            std::string realpath = arguments.getFilePath();
             DAESceneEncoder daeEncoder;
-            daeEncoder.write(realpath, id, text);
+            daeEncoder.write(realpath, arguments);
             break;
         }
-    case FILEFORMAT_TTF:
+    case EncoderArguments::FILEFORMAT_TTF:
         {
-            std::string realpath = getRealpath(filepath);
+            std::string realpath = arguments.getFilePath();
             std::string id = getFileName(realpath);
-            writeFont(realpath.c_str(), size, id.c_str(), fontpreview);
+            writeFont(realpath.c_str(), arguments.getFontSize(), id.c_str(), arguments.fontPreviewEnabled());
             break;
         }
-
-    case FILEFORMAT_GPB:
+    case EncoderArguments::FILEFORMAT_GPB:
         {
-            std::string realpath = getRealpath(filepath);
+            std::string realpath = arguments.getFilePath();
             GPBDecoder decoder;
             decoder.readBinary(realpath);
             break;
         }
-               
    default:
         {
-            fprintf(stderr, "Error: Unsupported file format: %s\n", filepath.c_str());
+            fprintf(stderr, "Error: Unsupported file format: %s\n", arguments.getFilePathPointer());
             return -1;
         }
     }

+ 101 - 28
gameplay-resources/res/shaders/bumped-specular.fsh

@@ -1,41 +1,114 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightColor;                        // RGB color of the light
-uniform vec3 u_ambientColor;                    // Ambient color
-uniform float u_specularExponent;                // Specular exponent or shininess property.
-uniform sampler2D u_diffuseTexture;                // Diffuse texture
-uniform sampler2D u_normalMapTexture;            // Normal map texture
+uniform vec3 u_lightColor;                  // Light color.
+uniform vec3 u_ambientColor;                // Ambient color.
+uniform float u_specularExponent;           // Specular exponent or shininess property.
+uniform sampler2D u_diffuseTexture;         // Diffuse texture.
+uniform sampler2D u_normalMapTexture;       // Normal map texture.
 
 // Inputs
-varying vec2 v_texCoord;                        // Texture Coordinate (u,v)
-varying vec3 v_lightDirectionTangentSpace;        // Direction of the light in tangent space
-varying vec3 v_cameraDirectionTangentSpace;     // Direction the camera is looking at in tangent space
+varying vec2 v_texCoord;                    // Texture Coordinate.
+varying vec3 v_cameraDirection;     	    // Direction the camera is looking at in tangent space.
 
-void main()
+// Common colors
+vec4 _baseColor;                            // Base color
+vec3 _ambientColor;                         // Ambient Color
+vec3 _diffuseColor;                         // Diffuse Color
+vec3 _specularColor;                        // Specular color
+
+void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
 {
-    // Fetch diffuse color from texture
-    vec4 diffuseColor = texture2D(u_diffuseTexture, v_texCoord);
+    // Ambient
+	_ambientColor += _baseColor.rgb * u_ambientColor;
+
+	// Diffuse
+	float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+	_diffuseColor += u_lightColor * _baseColor.rgb * diffuseIntensity;
+
+	// Specular
+	vec3 halfVector = normalize(cameraDirection + lightDirection);
+	float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
+    specularIntensity = max(0.0, specularIntensity);
+    _specularColor += u_lightColor * _baseColor.rgb * specularIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec3 v_pointLightDirectionCurrent;  // Light direction w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;      // Attenuation of point light.
+
+void applyLight()
+{
+    // Normalize the vectors.
+	// Fetch normals from the normal map.
+	vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 cameraDirection = normalize(v_cameraDirection);
     
-    // Normalize vectors
-    vec3 cameraDirection = normalize(v_cameraDirectionTangentSpace);
-    vec3 lightDirection = normalize(v_lightDirectionTangentSpace);
-    // Fetch normals from the normal map
-    vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 pointLightDirectionCurrent = normalize(v_pointLightDirectionCurrent);
     
-    // Ambient
-    vec3 lightColor = u_ambientColor;
+    // Fetch point light attenuation.
+    lighting(normalVector, cameraDirection, pointLightDirectionCurrent, v_pointLightAttenuation);
+}
 
-    // Diffuse
-    float diffuseIntensity = max(0.0, dot(normalVector, lightDirection));
-    lightColor += (u_lightColor * diffuseIntensity);
+#elif defined(SPOT_LIGHT)
+
+uniform float u_spotLightInnerCosAngle;     // The bright spot [0.5 - 1.0]
+uniform float u_spotLightOuterCosAngle;     // The soft outer part [0.0 - 0.5]
+varying vec3 v_spotLightDirection;          // Direction of spot light in tangent space.
+varying vec3 v_spotLightDirectionCurrent;   // Direction of the spot light w.r.t current vertex in tangent space.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return saturate( ( s - lower ) / ( upper - lower ) );
+}
 
-    // Specular
-    vec3 halfVector = normalize(cameraDirection + lightDirection);
-    float specularIntensity = pow(max(0.0, dot(normalVector, halfVector)), u_specularExponent);
+void applyLight()
+{
+    // Normalize the vectors.
+	// Fetch normals from the normal map.
+	vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 spotLightDirection =normalize(v_spotLightDirection);
+    vec3 spotLightDirectionCurrent = normalize(v_spotLightDirectionCurrent);
     
-    // Light the pixel.
-    gl_FragColor = diffuseColor;
-    gl_FragColor.rgb *= lightColor;
-    gl_FragColor.rgb += vec3(diffuseColor.rgb * specularIntensity);
+    // "-lightDirection" because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+	float spotCurrentCosAngle = max(0.0, dot(spotLightDirection, -spotLightDirectionCurrent));
+	
+    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
+    float spotLightAttenuation = lerpstep(u_spotLightOuterCosAngle, u_spotLightInnerCosAngle, spotCurrentCosAngle);
+
+    lighting(normalVector, cameraDirection, spotLightDirectionCurrent, spotLightAttenuation);
+}
+
+#else
+
+varying vec3 v_directionalLightDirection;    // Direction of light in tangent space.
+
+void applyLight()
+{
+    // Normalize vectors.
+	// Fetch normals from the normal map
+	vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 lightDirection = normalize(v_directionalLightDirection);
+
+    lighting(normalVector, cameraDirection, lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+    // Fetch diffuse color from texture.
+	_baseColor = texture2D(u_diffuseTexture, v_texCoord);
+
+    // Apply light
+	applyLight();
+
+	// Light the pixel
+    gl_FragColor.a = _baseColor.a;
+	gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
 }

+ 79 - 17
gameplay-resources/res/shaders/bumped-specular.vsh

@@ -1,21 +1,83 @@
 // Uniforms
-uniform    vec3 u_lightDirection;                        // Direction of the light
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;        // Matrix to transform a normal to view space.
-uniform mat4 u_worldMatrix;                            // Matrix to tranform a position to world space.
-uniform vec3 u_cameraPosition;                        // Position of the camera.
+uniform mat4 u_worldViewProjectionMatrix;       // Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix; // Matrix to transform a normal to view space.
+uniform mat4 u_worldMatrix;                     // Matrix to tranform a position to world space.
+uniform mat4 u_worldViewMatrix;					// Matrix to tranform a position to view space.
+uniform vec3 u_cameraPosition;                  // Position of the camera.
 
 // Inputs
-attribute vec4 a_position;                            // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                            // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                            // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                            // Vertex Binormal (actually Bi-tangent) (x, y, z)
+attribute vec4 a_position;                      // Vertex Position (x, y, z, w)
+attribute vec3 a_normal;                        // Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;                      // Vertex Texture Coordinate (u, v)
+attribute vec3 a_tangent;                       // Vertex Tangent (x, y, z)
+attribute vec3 a_binormal;                      // Vertex Binormal (actually Bi-tangent) (x, y, z)
 
 // Outputs
-varying vec2 v_texCoord;                            // Texture Coordinate (u,v)
-varying vec3 v_lightDirectionTangentSpace;            // Direction of the light in tangent space.
-varying vec3 v_cameraDirectionTangentSpace;         // Direction the camera is looking at in tangent space.
+varying vec2 v_texCoord;                        // Texture Coordinate (u,v)
+varying vec3 v_cameraDirection;                 // Direction the camera is looking at in tangent space.
+
+#if defined(POINT_LIGHT)
+
+uniform vec3 u_pointLightPosition;			    // Position
+uniform float u_pointLightRadius;               // Radius 
+varying vec3 v_pointLightDirectionCurrent;      // Direction of point light w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;          // Attenuation of point light.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    vec3 pointLightDirectionCurrent = normalize(tangentSpaceTransformMatrix * lightDirection);
+
+    // Attenuation
+    v_pointLightAttenuation = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+
+    // Output normalized light direction.
+    v_pointLightDirectionCurrent =  normalize(pointLightDirectionCurrent);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform vec3 u_spotLightPosition;               // Position
+uniform vec3 u_spotLightDirection;              // Direction
+varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
+varying vec3 v_spotLightDirectionCurrent;       // Direction of the spot light w.r.t current vertex in tangent space.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+
+    // Transform spot light direction to tangent space.
+    v_spotLightDirection = normalize(tangentSpaceTransformMatrix * u_spotLightDirection);
+
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    lightDirection = tangentSpaceTransformMatrix * lightDirection;
+
+    // Output normalized light direction.
+    v_spotLightDirectionCurrent = normalize(lightDirection);
+}
+
+#else
+
+uniform vec3 u_lightDirection;           // Direction
+varying vec3 v_directionalLightDirection;           // Direction of light in tangent space.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    // Transform light direction to tangent space.
+    v_directionalLightDirection = tangentSpaceTransformMatrix * u_lightDirection;
+}
+
+#endif
 
 void main()
 {
@@ -31,12 +93,12 @@ void main()
     // Create a transform to convert a vector to tangent space.
     mat3 tangentSpaceTransformMatrix = mat3(tangentVector, binormalVector, normalVector);
 
-    // Transform light direction to tangent space.
-    v_lightDirectionTangentSpace = tangentSpaceTransformMatrix * u_lightDirection;
-
     // Compute camera direction and transform it to tangent space.
     vec4 positionWorldSpace = u_worldMatrix * a_position;
-    v_cameraDirectionTangentSpace = tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldSpace.xyz);
+    v_cameraDirection = normalize(tangentSpaceTransformMatrix * (u_cameraPosition - positionWorldSpace.xyz));
+
+    // Apply light.
+    applyLight(tangentSpaceTransformMatrix);
 
     // Pass on the texture coordinates to Fragment shader.
     v_texCoord = a_texCoord;

+ 90 - 20
gameplay-resources/res/shaders/bumped.fsh

@@ -1,32 +1,102 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightColor;                    // RGB color of the light
-uniform vec3 u_ambientColor;                // Ambient color
-uniform sampler2D u_diffuseTexture;            // Texture
-uniform sampler2D u_normalMapTexture;        // Normalmap
+uniform vec3 u_lightColor;                  // Light color.
+uniform vec3 u_ambientColor;                // Ambient color.
+uniform sampler2D u_diffuseTexture;         // Diffuse texture.
+uniform sampler2D u_normalMapTexture;       // Normal map texture.
 
 // Inputs
-varying vec3 v_lightDirectionTangentSpace;    // light direction
-varying vec2 v_texCoord;                    // Texture coordinate.
+varying vec2 v_texCoord;                    // Texture Coordinate.
 
-void main()
+// Common colors
+vec4 _baseColor;                            // Base color
+vec3 _ambientColor;                         // Ambient Color
+vec3 _diffuseColor;                         // Diffuse Color
+
+void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 {
-    // Fetch normals from the normal map
-    vec3 normalVector = texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0;
-    normalVector = normalize(normalVector);
+    // Ambient
+	_ambientColor += _baseColor.rgb * u_ambientColor;
+
+	// Diffuse
+	float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+	_diffuseColor += u_lightColor * _baseColor.rgb * diffuseIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec3 v_pointLightDirectionCurrent;      // Light direction w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;          // Attenuation of point light.
+
+void applyLight()
+{
+    // Normalize the vectors.
+	// Fetch normals from the normal map.
+	vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
     
-    // Fetch diffuse color from texture
-    gl_FragColor = texture2D(u_diffuseTexture, v_texCoord);
+    vec3 pointLightDirectionCurrent = normalize(v_pointLightDirectionCurrent);
     
-    // Ambient
-    vec3 lightColor = u_ambientColor;
+    // Fetch point light attenuation.
+    lighting(normalVector, pointLightDirectionCurrent, v_pointLightAttenuation);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform float u_spotLightInnerCosAngle;     // The bright spot [0.5 - 1.0]
+uniform float u_spotLightOuterCosAngle;     // The soft outer part [0.0 - 0.5]
+varying vec3 v_spotLightDirection;          // Direction of spot light in tangent space.
+varying vec3 v_spotLightDirectionCurrent;   // Direction of the spot light w.r.t current vertex in tangent space.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return saturate( ( s - lower ) / ( upper - lower ) );
+}
+
+void applyLight()
+{
+    // Normalize the vectors.
+	// Fetch normals from the normal map.
+	vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 spotLightDirection =normalize(v_spotLightDirection);
+    vec3 spotLightDirectionCurrent = normalize(v_spotLightDirectionCurrent);
+    
+    // "-lightDirection" because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+	float spotCurrentCosAngle = max(0.0, dot(spotLightDirection, -spotLightDirectionCurrent));
+	
+    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
+    float spotLightAttenuation = lerpstep(u_spotLightOuterCosAngle, u_spotLightInnerCosAngle, spotCurrentCosAngle);
+
+    lighting(normalVector, spotLightDirectionCurrent, spotLightAttenuation);
+}
+
+#else
+
+varying vec3 v_directionalLightDirection;    // Direction of light in tangent space.
+
+void applyLight()
+{
+    // Normalize vectors.
+	// Fetch normals from the normal map
+	vec3 normalVector = normalize(texture2D(u_normalMapTexture, v_texCoord).rgb * 2.0 - 1.0);
+    vec3 lightDirection = normalize(v_directionalLightDirection);
+
+    lighting(normalVector, lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+    // Fetch diffuse color from texture.
+	_baseColor = texture2D(u_diffuseTexture, v_texCoord);
 
-    // Diffuse
-    vec3 lightDirection = normalize(v_lightDirectionTangentSpace);
-    float diffuseIntensity = clamp(dot(normalVector, lightDirection), 0.0, 1.0);
-    lightColor += (u_lightColor * diffuseIntensity);
+    // Apply light
+	applyLight();
 
-    // Light the fragment.
-    gl_FragColor.rgb *= lightColor;
+	// Light the pixel
+    gl_FragColor.a = _baseColor.a;
+	gl_FragColor.rgb = _ambientColor + _diffuseColor;
 }

+ 82 - 19
gameplay-resources/res/shaders/bumped.vsh

@@ -1,36 +1,99 @@
 // Uniforms
-uniform vec3 u_lightDirection;                        // Direction of the light
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;        // Matrix to transform a normal to view space.
+uniform mat4 u_worldViewProjectionMatrix;       // Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix; // Matrix to transform a normal to view space.
 
 // Inputs
-attribute vec4 a_position;                            // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                            // Vertex Texture Coordinate (u, v)
-attribute vec3 a_tangent;                            // Vertex Tangent (x, y, z)
-attribute vec3 a_binormal;                            // Vertex Binormal (actually Bi-tangent) (x, y, z)
+attribute vec4 a_position;                      // Vertex Position (x, y, z, w)
+attribute vec3 a_normal;                        // Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;                      // Vertex Texture Coordinate (u, v)
+attribute vec3 a_tangent;                       // Vertex Tangent (x, y, z)
+attribute vec3 a_binormal;                      // Vertex Binormal (actually Bi-tangent) (x, y, z)
 
 // Outputs
-varying vec3 v_lightDirectionTangentSpace;            // Direction of light in tangent space.
-varying vec2 v_texCoord;                            // Texture coordinate (u, v).
+varying vec2 v_texCoord;                        // Texture Coordinate (u,v)
+
+#if defined(POINT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;					// Matrix to tranform a position to view space.
+uniform vec3 u_pointLightPosition;			    // Position
+uniform float u_pointLightRadius;               // Radius 
+varying vec3 v_pointLightDirectionCurrent;      // Direction of point light w.r.t current vertex in tangent space.
+varying float v_pointLightAttenuation;          // Attenuation of point light.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+    
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    vec3 pointLightDirectionCurrent = normalize(tangentSpaceTransformMatrix * lightDirection);
+
+    // Attenuation
+    v_pointLightAttenuation = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+
+    // Output normalized light direction.
+    v_pointLightDirectionCurrent =  normalize(pointLightDirectionCurrent);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;					// Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;               // Position
+uniform vec3 u_spotLightDirection;              // Direction
+varying vec3 v_spotLightDirection;              // Direction of spot light in tangent space.
+varying vec3 v_spotLightDirectionCurrent;       // Direction of the spot light w.r.t current vertex in tangent space.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * a_position;
+
+    // Transform spot light direction to tangent space.
+    v_spotLightDirection = normalize(tangentSpaceTransformMatrix * u_spotLightDirection);
+
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+    
+    // Transform current light direction to tangent space.
+    lightDirection = tangentSpaceTransformMatrix * lightDirection;
+
+    // Output normalized light direction.
+    v_spotLightDirectionCurrent = normalize(lightDirection);
+}
+
+#else
+
+uniform vec3 u_lightDirection;           // Direction
+varying vec3 v_directionalLightDirection;           // Direction of light in tangent space.
+
+void applyLight(mat3 tangentSpaceTransformMatrix)
+{
+    // Transform light direction to tangent space.
+    v_directionalLightDirection = tangentSpaceTransformMatrix * u_lightDirection;
+}
+
+#endif
 
 void main()
 {
     // Transform position to clip space.
     gl_Position = u_worldViewProjectionMatrix * a_position;
 
-    // Transform normal, tangent and binormal to view space.
+    // Transform the normal, tangent and binormals to  view space.
     mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    vec3 tangent  = inverseTransposeWorldViewMatrix * a_tangent;
-    vec3 normal = inverseTransposeWorldViewMatrix * a_normal;
-    vec3 binormal = inverseTransposeWorldViewMatrix * a_binormal;
+    vec3 tangentVector  = inverseTransposeWorldViewMatrix * a_tangent;
+    vec3 normalVector = inverseTransposeWorldViewMatrix * a_normal;
+    vec3 binormalVector = inverseTransposeWorldViewMatrix * a_binormal;
 
     // Create a transform to convert a vector to tangent space.
-    mat3 tangentSpaceTransformMatrix = mat3(tangent, binormal, normal);
-    
-    // Transform light direction to tangent space.
-    v_lightDirectionTangentSpace = tangentSpaceTransformMatrix * u_lightDirection;
+    mat3 tangentSpaceTransformMatrix = mat3(tangentVector, binormalVector, normalVector);
+
+    // Apply light.
+    applyLight(tangentSpaceTransformMatrix);
 
     // Pass on the texture coordinates to Fragment shader.
     v_texCoord = a_texCoord;
-}
+}

+ 96 - 22
gameplay-resources/res/shaders/colored-specular.fsh

@@ -1,36 +1,110 @@
 precision highp float;
 
 // Uniforms
-uniform    vec3 u_lightDirection;        // Direction of the light
-uniform vec3 u_lightColor;            // RGB color of the light
-uniform vec3 u_ambientColor;        // Ambient color
-uniform vec4 u_diffuseColor;        // Diffuse color
-uniform float u_specularExponent;    // Specular exponent or shininess property.
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;			        // Ambient color
+uniform float u_specularExponent;		        // Specular exponent or shininess property.
+uniform vec4 u_diffuseColor;                     // Diffuse color
 
 // Inputs
-varying vec3 v_normalVector;        // Normal vector in view space.
-varying vec3 v_cameraDirection;        // Camera direction.
+varying vec3 v_normalVector;			        // NormalVector in view space.
+varying vec3 v_cameraDirection; 		        // Camera direction
 
-void main()
+// Common colors
+vec4 _baseColor;                                // Base color
+vec3 _ambientColor;                             // Ambient Color
+vec3 _diffuseColor;                             // Diffuse Color
+vec3 _specularColor;                            // Specular color
+
+void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
+{
+    // Ambient
+	_ambientColor += _baseColor.rgb * u_ambientColor;
+
+	// Diffuse
+	float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+	_diffuseColor += u_lightColor * _baseColor.rgb * diffuseIntensity;
+
+	// Specular
+	vec3 halfVector = normalize(cameraDirection + lightDirection);
+	float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
+    specularIntensity = max(0.0, specularIntensity);
+    _specularColor += u_lightColor * _baseColor.rgb * specularIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec4 v_pointLightDirectionCurrent;      // Light direction w.r.t current vertex.
+
+void applyLight()
 {
     // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
     vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(u_lightDirection);
-    vec3 normalVector = normalize(v_normalVector);
     
-    // Ambient
-    vec3 lightColor = u_ambientColor;
+    vec3 pointLightDirectionCurrent = normalize(v_pointLightDirectionCurrent.xyz);
+    
+    // Fetch point light attenuation.
+    float pointLightAttenuation = v_pointLightDirectionCurrent.w;
+    lighting(normalVector, cameraDirection, pointLightDirectionCurrent, pointLightAttenuation);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform vec3 u_spotLightDirection;          // Direction of the spot light.
+uniform float u_spotLightInnerCosAngle;     // The bright spot [0.5 - 1.0]
+uniform float u_spotLightOuterCosAngle;     // The soft outer part [0.0 - 0.5]
+varying vec3 v_spotLightDirectionCurrent;   // Light direction w.r.t current vertex.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return saturate( ( s - lower ) / ( upper - lower ) );
+}
 
-    // Diffuse
-    float diffuseIntensity = max(0.0, dot(normalVector, lightDirection));
-    lightColor += (u_lightColor * diffuseIntensity);
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 spotLightDirection =normalize(u_spotLightDirection); 
+    vec3 spotLightDirectionCurrent = normalize(v_spotLightDirectionCurrent);
+
+    // "-lightDirection" is used because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+	float spotCurrentCosAngle = max(0.0, dot(spotLightDirection, -spotLightDirectionCurrent));
+	
+    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
+    float spotLightAttenuation = lerpstep(u_spotLightOuterCosAngle, u_spotLightInnerCosAngle, spotCurrentCosAngle);
+
+    lighting(normalVector, cameraDirection, spotLightDirectionCurrent, spotLightAttenuation);
+}
+
+#else
+
+uniform vec3 u_lightDirection;       // Light direction
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 lightDirection = normalize(u_lightDirection);
+
+    lighting(normalVector, cameraDirection, lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+	// Fetch diffuse color from texture.
+	_baseColor = u_diffuseColor;
 
-    // Specular
-    vec3 halfVector = normalize(cameraDirection + lightDirection);
-    float specularIntensity = pow(max(0.0, dot(normalVector, halfVector)), u_specularExponent);
+    // Apply light
+	applyLight();
 
-    // Light the pixel.
-    gl_FragColor = u_diffuseColor;
-    gl_FragColor.rgb *= lightColor;
-    gl_FragColor.rgb += (u_diffuseColor.rgb * specularIntensity);
+	// Light the pixel
+    gl_FragColor.a = _baseColor.a;
+	gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
 }

+ 175 - 15
gameplay-resources/res/shaders/colored-specular.vsh

@@ -1,27 +1,187 @@
 // Uniforms
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;        // Matrix to transform a normal to view space.
-uniform mat4 u_worldMatrix;                            // Matrix to tranform a position to world space.
-uniform vec3 u_cameraPosition;                        // Position of the camera.
+uniform mat4 u_worldViewProjectionMatrix;			// Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;		// Matrix to transform a normal to view space.
+uniform mat4 u_worldMatrix;							// Matrix to tranform a position to world space.
+uniform vec3 u_cameraPosition;						// Position of the camera.
 
 // Inputs
-attribute vec4 a_position;                            // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
+attribute vec4 a_position;							// Vertex Position (x, y, z, w)
+attribute vec3 a_normal;							// Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;							// Vertex Texture Coordinate (u, v)
 
 // Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space.
-varying vec3 v_cameraDirection;                     // Camera direction
+varying vec3 v_normalVector;						// NormalVector in view space.
+varying vec3 v_cameraDirection; 					// Camera direction
+
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+vec3 _skinnedNormal;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinNormal(float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+
+    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
+
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getNormal()
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+#endif
+
+
+#if defined(POINT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_pointLightPosition;			        // Position
+uniform float u_pointLightRadius;                   // Radius 
+varying vec4 v_pointLightDirectionCurrent;          // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+    
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+	
+    vec4 pointLightDirectionCurrent;
+    pointLightDirectionCurrent.xyz = normalize(lightDirection);
+    
+    // Attenuation
+    pointLightDirectionCurrent.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+
+    // Output normalized light direction.
+    v_pointLightDirectionCurrent =  normalize(pointLightDirectionCurrent);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;                   // Position
+varying vec3 v_spotLightDirectionCurrent;           // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Output normalized light direction.
+    v_spotLightDirectionCurrent = normalize(lightDirection);
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+}
+
+#endif
 
 void main()
 {
+	vec4 position = getPosition();
+    vec3 normal = getNormal();
+
     // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
+	gl_Position = u_worldViewProjectionMatrix * position;
 
-    // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    v_normalVector = inverseTransposeWorldViewMatrix * a_normal;
+	// Transform normal to view space.
+	mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
+	v_normalVector = inverseTransposeWorldViewMatrix * normal;
 
     // Compute the camera direction.
-    vec4 positionWorldSpace = u_worldMatrix * a_position;
-    v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
-}
+	vec4 positionWorldSpace = u_worldMatrix * position;
+	v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
+
+    // Apply light.
+    applyLight(position);
+}

+ 87 - 13
gameplay-resources/res/shaders/colored.fsh

@@ -1,24 +1,98 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightDirection;        // Direction of the light
-uniform vec3 u_lightColor;            // RGB color of the light
-uniform vec3 u_ambientColor;        // Ambient color
-uniform vec4 u_diffuseColor;        // Diffuse color
+uniform vec3 u_lightColor;                  // Light color
+uniform vec3 u_ambientColor;			    // Ambient color
+uniform vec4 u_diffuseColor;                // Diffuse color
 
 // Inputs
-varying vec3 v_normalVector;        // NormalVector in view space (Normalized).
+varying vec3 v_normalVector;			    // NormalVector in view space.
 
-void main()
+// Common colors
+vec4 _baseColor;                            // Base color
+vec3 _ambientColor;                         // Ambient Color
+vec3 _diffuseColor;                         // Diffuse Color
+
+void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 {
     // Ambient
-    vec3 lightColor = u_ambientColor;
+	_ambientColor += _baseColor.rgb * u_ambientColor;
+
+	// Diffuse
+	float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+	_diffuseColor += u_lightColor * _baseColor.rgb * diffuseIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec4 v_pointLightDirectionCurrent;      // Light direction w.r.t current vertex.
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    
+    vec3 pointLightDirectionCurrent = normalize(v_pointLightDirectionCurrent.xyz);
+    
+    // Fetch point light attenuation.
+    float pointLightAttenuation = v_pointLightDirectionCurrent.w;
+    lighting(normalVector, pointLightDirectionCurrent, pointLightAttenuation);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform vec3 u_spotLightDirection;          // Direction of the spot light.
+uniform float u_spotLightInnerCosAngle;     // The bright spot [0.5 - 1.0]
+uniform float u_spotLightOuterCosAngle;     // The soft outer part [0.0 - 0.5]
+varying vec3 v_spotLightDirectionCurrent;   // Light direction w.r.t current vertex.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return saturate( ( s - lower ) / ( upper - lower ) );
+}
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 spotLightDirection =normalize(u_spotLightDirection); 
+    vec3 spotLightDirectionCurrent = normalize(v_spotLightDirectionCurrent);
+
+    // "-lightDirection" is used because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+	float spotCurrentCosAngle = max(0.0, dot(spotLightDirection, -spotLightDirectionCurrent));
+	
+    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
+    float spotLightAttenuation = lerpstep(u_spotLightOuterCosAngle, u_spotLightInnerCosAngle, spotCurrentCosAngle);
+
+    lighting(normalVector, spotLightDirectionCurrent, spotLightAttenuation);
+}
+
+#else
+
+uniform vec3 u_lightDirection;       // Light direction
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 lightDirection = normalize(u_lightDirection);
+
+    lighting(normalVector, lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+	// Fetch diffuse color from texture.
+	_baseColor = u_diffuseColor;
 
-    // Diffuse
-    float diffuseIntensity = max(dot(v_normalVector, u_lightDirection), 0.0);
-    lightColor += (u_lightColor * diffuseIntensity);
+    // Apply light
+	applyLight();
 
-    // Light the pixel.
-    gl_FragColor = u_diffuseColor;
-    gl_FragColor.rgb *= lightColor;
+	// Light the pixel
+    gl_FragColor.a = _baseColor.a;
+	gl_FragColor.rgb = _ambientColor + _diffuseColor;
 }

+ 168 - 10
gameplay-resources/res/shaders/colored.vsh

@@ -1,20 +1,178 @@
 // Uniforms
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;     // Matrix to transform a normal to view space.
+uniform mat4 u_worldViewProjectionMatrix;			// Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;		// Matrix to transform a normal to view space.
 
 // Inputs
-attribute vec4 a_position;                            // Vertex Position (x, y, z, w).
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z).
+attribute vec4 a_position;							// Vertex Position (x, y, z, w)
+attribute vec3 a_normal;							// Vertex Normal (x, y, z)
 
 // Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space (Normalized).
+varying vec3 v_normalVector;						// NormalVector in view space.
+
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+vec3 _skinnedNormal;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinNormal(float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+
+    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
+
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getNormal()
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+#endif
+
+#if defined(POINT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_pointLightPosition;			        // Position
+uniform float u_pointLightRadius;                   // Radius 
+varying vec4 v_pointLightDirectionCurrent;          // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+    
+    // Compute the light direction.
+	vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+	
+    vec4 pointLightDirectionCurrent;
+    pointLightDirectionCurrent.xyz = normalize(lightDirection);
+    
+    // Attenuation.
+    pointLightDirectionCurrent.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+
+    // Output normalized light direction.
+    v_pointLightDirectionCurrent =  normalize(pointLightDirectionCurrent);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;                   // Position
+varying vec3 v_spotLightDirectionCurrent;           // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+
+    // Compute the light direction.
+	vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Output normalized light direction.
+    v_spotLightDirectionCurrent = normalize(lightDirection);
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+}
+
+#endif
 
 void main()
 {
+	vec4 position = getPosition();
+    vec3 normal = getNormal();
+        
     // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
+	gl_Position = u_worldViewProjectionMatrix * position;
 
-    // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    v_normalVector = normalize(inverseTransposeWorldViewMatrix * a_normal);
-}
+	// Transform normal to view space.
+	mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
+	v_normalVector = inverseTransposeWorldViewMatrix * normal;
+
+    // Apply light.
+    applyLight(position);
+}

+ 97 - 26
gameplay-resources/res/shaders/diffuse-specular.fsh

@@ -1,40 +1,111 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightDirection;            // Direction of the light
-uniform vec3 u_lightColor;                // RGB color of the light
-uniform vec3 u_ambientColor;            // Ambient color
-uniform float u_specularExponent;        // Specular exponent or shininess property.
-uniform sampler2D u_diffuseTexture;        // Diffuse texture.
+uniform vec3 u_lightColor;                      // Light color
+uniform vec3 u_ambientColor;			        // Ambient color
+uniform float u_specularExponent;		        // Specular exponent or shininess property.
+uniform sampler2D u_diffuseTexture;		        // Diffuse texture.
 
 // Inputs
-varying vec3 v_normalVector;            // NormalVector in view space.
-varying vec2 v_texCoord;                // Texture coordinate (u, v).
-varying vec3 v_cameraDirection;         // Camera direction
+varying vec3 v_normalVector;			        // NormalVector in view space.
+varying vec2 v_texCoord;				        // Texture coordinate (u, v).
+varying vec3 v_cameraDirection; 		        // Camera direction
 
-void main()
+// Common colors
+vec4 _baseColor;                                // Base color
+vec3 _ambientColor;                             // Ambient Color
+vec3 _diffuseColor;                             // Diffuse Color
+vec3 _specularColor;                            // Specular color
+
+void lighting(vec3 normalVector, vec3 cameraDirection, vec3 lightDirection, float attenuation)
+{
+    // Ambient
+	_ambientColor += _baseColor.rgb * u_ambientColor;
+
+	// Diffuse
+	float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+	_diffuseColor += u_lightColor * _baseColor.rgb * diffuseIntensity;
+
+	// Specular
+	vec3 halfVector = normalize(cameraDirection + lightDirection);
+	float specularIntensity = attenuation * max(0.0, pow(dot(normalVector, halfVector), u_specularExponent));
+    specularIntensity = max(0.0, specularIntensity);
+    _specularColor += u_lightColor * _baseColor.rgb * specularIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec4 v_pointLightDirectionCurrent;      // Light direction w.r.t current vertex.
+
+void applyLight()
 {
-    // Fetch diffuse color from texture.
-    vec4 diffuseColor = texture2D(u_diffuseTexture, v_texCoord);
-    
     // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
     vec3 cameraDirection = normalize(v_cameraDirection);
-    vec3 lightDirection = normalize(u_lightDirection);
-    vec3 normalVector = normalize(v_normalVector);
     
-    // Ambient
-    vec3 lightColor = u_ambientColor;
+    vec3 pointLightDirectionCurrent = normalize(v_pointLightDirectionCurrent.xyz);
+    
+    // Fetch point light attenuation.
+    float pointLightAttenuation = v_pointLightDirectionCurrent.w;
+    lighting(normalVector, cameraDirection, pointLightDirectionCurrent, pointLightAttenuation);
+}
 
-    // Diffuse
-    float diffuseIntensity = max(0.0, dot(normalVector, lightDirection));
-    lightColor += (u_lightColor * diffuseIntensity);
+#elif defined(SPOT_LIGHT)
 
-    // Specular
-    vec3 halfVector = normalize(cameraDirection + lightDirection);
-    float specularIntensity = pow(max(0.0, dot(normalVector, halfVector)), u_specularExponent);
+uniform vec3 u_spotLightDirection;          // Direction of the spot light.
+uniform float u_spotLightInnerCosAngle;     // The bright spot [0.5 - 1.0]
+uniform float u_spotLightOuterCosAngle;     // The soft outer part [0.0 - 0.5]
+varying vec3 v_spotLightDirectionCurrent;   // Light direction w.r.t current vertex.
 
-    // Light the pixel
-    gl_FragColor = diffuseColor;
-    gl_FragColor.rgb *= lightColor;
-    gl_FragColor.rgb += vec3(diffuseColor.rgb * specularIntensity);
+float lerpstep( float lower, float upper, float s)
+{
+    return saturate( ( s - lower ) / ( upper - lower ) );
 }
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 spotLightDirection =normalize(u_spotLightDirection); 
+    vec3 spotLightDirectionCurrent = normalize(v_spotLightDirectionCurrent);
+
+    // "-lightDirection" is used because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+	float spotCurrentCosAngle = max(0.0, dot(spotLightDirection, -spotLightDirectionCurrent));
+	
+    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
+    float spotLightAttenuation = lerpstep(u_spotLightOuterCosAngle, u_spotLightInnerCosAngle, spotCurrentCosAngle);
+
+    lighting(normalVector, cameraDirection, spotLightDirectionCurrent, spotLightAttenuation);
+}
+
+#else
+
+uniform vec3 u_lightDirection;       // Light direction
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 cameraDirection = normalize(v_cameraDirection);
+    vec3 lightDirection = normalize(u_lightDirection);
+
+    lighting(normalVector, cameraDirection, lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+	// Fetch diffuse color from texture.
+	_baseColor = texture2D(u_diffuseTexture, v_texCoord);
+
+    // Apply light
+	applyLight();
+
+	// Light the pixel
+    gl_FragColor.a = _baseColor.a;
+	gl_FragColor.rgb = _ambientColor + _diffuseColor + _specularColor;
+}

+ 176 - 17
gameplay-resources/res/shaders/diffuse-specular.vsh

@@ -1,32 +1,191 @@
 // Uniforms
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;        // Matrix to transform a normal to view space.
-uniform mat4 u_worldMatrix;                            // Matrix to tranform a position to world space.
-uniform vec3 u_cameraPosition;                        // Position of the camera.
+uniform mat4 u_worldViewProjectionMatrix;			// Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;		// Matrix to transform a normal to view space.
+uniform mat4 u_worldMatrix;							// Matrix to tranform a position to world space.
+uniform vec3 u_cameraPosition;						// Position of the camera.
 
 // Inputs
-attribute vec4 a_position;                            // Vertex Position (x, y, z, w)
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z)
-attribute vec2 a_texCoord;                            // Vertex Texture Coordinate (u, v)
+attribute vec4 a_position;							// Vertex Position (x, y, z, w)
+attribute vec3 a_normal;							// Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;							// Vertex Texture Coordinate (u, v)
 
 // Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space.
-varying vec2 v_texCoord;                            // Texture coordinate (u, v).
-varying vec3 v_cameraDirection;                     // Camera direction
+varying vec3 v_normalVector;						// NormalVector in view space.
+varying vec2 v_texCoord;							// Texture coordinate (u, v).
+varying vec3 v_cameraDirection; 					// Camera direction
+
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+vec3 _skinnedNormal;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinNormal(float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+
+    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
+
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getNormal()
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+#endif
+
+
+#if defined(POINT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_pointLightPosition;			        // Position
+uniform float u_pointLightRadius;                   // Radius 
+varying vec4 v_pointLightDirectionCurrent;          // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+    
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+	
+    vec4 pointLightDirectionCurrent;
+    pointLightDirectionCurrent.xyz = normalize(lightDirection);
+    
+    // Attenuation
+    pointLightDirectionCurrent.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+
+    // Output normalized light direction.
+    v_pointLightDirectionCurrent =  normalize(pointLightDirectionCurrent);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;                   // Position
+varying vec3 v_spotLightDirectionCurrent;           // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Output normalized light direction.
+    v_spotLightDirectionCurrent = normalize(lightDirection);
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+}
+
+#endif
 
 void main()
 {
+	vec4 position = getPosition();
+    vec3 normal = getNormal();
+
     // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
+	gl_Position = u_worldViewProjectionMatrix * position;
 
-    // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    v_normalVector = inverseTransposeWorldViewMatrix * a_normal;
+	// Transform normal to view space.
+	mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
+	v_normalVector = inverseTransposeWorldViewMatrix * normal;
 
     // Compute the camera direction.
-    vec4 positionWorldSpace = u_worldMatrix * a_position;
-    v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
+	vec4 positionWorldSpace = u_worldMatrix * position;
+	v_cameraDirection = u_cameraPosition - positionWorldSpace.xyz;
+
+    // Apply light.
+    applyLight(position);
 
     // Pass on the texture coordinates to Fragment shader.
-    v_texCoord = a_texCoord;
+	v_texCoord = a_texCoord;
 }

+ 88 - 14
gameplay-resources/res/shaders/diffuse.fsh

@@ -1,25 +1,99 @@
 precision highp float;
 
 // Uniforms
-uniform vec3 u_lightDirection;              // Direction of the light
-uniform vec3 u_lightColor;                  // RGB color of the light
-uniform vec3 u_ambientColor;                // Ambient color
-uniform sampler2D u_diffuseTexture;         // Diffuse texture
+uniform vec3 u_lightColor;                  // Light color
+uniform vec3 u_ambientColor;			    // Ambient color
+uniform sampler2D u_diffuseTexture;		    // Diffuse texture.
 
 // Inputs
-varying vec3 v_normalVector;                // NormalVector in view space (Normalized).
-varying vec2 v_texCoord;                    // Texture coordinate (u, v).
+varying vec3 v_normalVector;			    // NormalVector in view space.
+varying vec2 v_texCoord;				    // Texture coordinate (u, v).
 
-void main()
+// Common colors
+vec4 _baseColor;                            // Base color
+vec3 _ambientColor;                         // Ambient Color
+vec3 _diffuseColor;                         // Diffuse Color
+
+void lighting(vec3 normalVector, vec3 lightDirection, float attenuation)
 {
     // Ambient
-    vec3 lightColor = u_ambientColor;
+	_ambientColor += _baseColor.rgb * u_ambientColor;
+
+	// Diffuse
+	float diffuseIntensity = attenuation * max(0.0, dot(normalVector, lightDirection));
+    diffuseIntensity = max(0.0, diffuseIntensity);
+	_diffuseColor += u_lightColor * _baseColor.rgb * diffuseIntensity;
+}
+
+#if defined(POINT_LIGHT)
+
+varying vec4 v_pointLightDirectionCurrent;  // Light direction w.r.t current vertex.
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    
+    vec3 pointLightDirectionCurrent = normalize(v_pointLightDirectionCurrent.xyz);
+    
+    // Fetch point light attenuation.
+    float pointLightAttenuation = v_pointLightDirectionCurrent.w;
+    lighting(normalVector, pointLightDirectionCurrent, pointLightAttenuation);
+}
 
-    // Diffuse
-    float diffuseIntensity = max(dot(v_normalVector, u_lightDirection), 0.0);
-    lightColor += (u_lightColor * diffuseIntensity);
+#elif defined(SPOT_LIGHT)
 
-    // Light the pixel.
-    gl_FragColor = texture2D(u_diffuseTexture, v_texCoord);
-    gl_FragColor.rgb *= lightColor;
+uniform vec3 u_spotLightDirection;          // Direction of the spot light.
+uniform float u_spotLightInnerCosAngle;     // The bright spot [0.5 - 1.0]
+uniform float u_spotLightOuterCosAngle;     // The soft outer part [0.0 - 0.5]
+varying vec3 v_spotLightDirectionCurrent;   // Light direction w.r.t current vertex.
+
+float lerpstep( float lower, float upper, float s)
+{
+    return saturate( ( s - lower ) / ( upper - lower ) );
 }
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 spotLightDirection =normalize(u_spotLightDirection); 
+    vec3 spotLightDirectionCurrent = normalize(v_spotLightDirectionCurrent);
+
+    // "-lightDirection" is used because light direction points in opposite direction to
+    // to spot direction.
+    // Calculate spot light effect.
+	float spotCurrentCosAngle = max(0.0, dot(spotLightDirection, -spotLightDirectionCurrent));
+	
+    // Intensity of spot depends on the part of the cone the light direction points to (inner or outer).
+    float spotLightAttenuation = lerpstep(u_spotLightOuterCosAngle, u_spotLightInnerCosAngle, spotCurrentCosAngle);
+
+    lighting(normalVector, spotLightDirectionCurrent, spotLightAttenuation);
+}
+
+#else
+
+uniform vec3 u_lightDirection;       // Light direction
+
+void applyLight()
+{
+    // Normalize the vectors.
+	vec3 normalVector = normalize(v_normalVector);
+    vec3 lightDirection = normalize(u_lightDirection);
+
+    lighting(normalVector, lightDirection, 1.0);
+}
+#endif
+
+void main()
+{
+	// Fetch diffuse color from texture.
+	_baseColor = texture2D(u_diffuseTexture, v_texCoord);
+
+    // Apply light
+	applyLight();
+
+	// Light the pixel
+    gl_FragColor.a = _baseColor.a;
+	gl_FragColor.rgb = _ambientColor + _diffuseColor;
+}

+ 173 - 14
gameplay-resources/res/shaders/diffuse.vsh

@@ -1,25 +1,184 @@
 // Uniforms
-uniform mat4 u_worldViewProjectionMatrix;            // Matrix to transform a position to clip space.
-uniform mat4 u_inverseTransposeWorldViewMatrix;        // Matrix to transform a normal to view space.
+uniform mat4 u_worldViewProjectionMatrix;			// Matrix to transform a position to clip space.
+uniform mat4 u_inverseTransposeWorldViewMatrix;		// Matrix to transform a normal to view space.
 
 // Inputs
-attribute vec4 a_position;                            // Vertex Position (x, y, z, w).
-attribute vec3 a_normal;                            // Vertex Normal (x, y, z).
-attribute vec2 a_texCoord;                            // Vertex Texture Coordinate (u, v).
+attribute vec4 a_position;							// Vertex Position (x, y, z, w)
+attribute vec3 a_normal;							// Vertex Normal (x, y, z)
+attribute vec2 a_texCoord;							// Vertex Texture Coordinate (u, v)
 
 // Outputs
-varying vec3 v_normalVector;                        // NormalVector in view space (Normalized).
-varying vec2 v_texCoord;                            // Texture coordinate (u, v).
+varying vec3 v_normalVector;						// NormalVector in view space.
+varying vec2 v_texCoord;							// Texture coordinate (u, v).
+varying vec3 v_cameraDirection; 					// Camera direction
+
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+vec3 _skinnedNormal;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+void skinNormal(float blendWeight, int matrixIndex)
+{
+    vec3 tmp;
+
+    tmp.x = dot(a_normal, u_matrixPalette[matrixIndex].xyz);
+    tmp.y = dot(a_normal, u_matrixPalette[matrixIndex + 1].xyz);
+    tmp.z = dot(a_normal, u_matrixPalette[matrixIndex + 2].xyz);
+
+    _skinnedNormal += blendWeight * tmp;
+}
+
+vec3 getNormal()
+{
+    _skinnedNormal = vec3(0.0);
+
+    // Transform normal to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinNormal(blendWeight, matrixIndex);
+
+    return _skinnedNormal;
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+vec3 getNormal()
+{
+    return a_normal;
+}
+
+#endif
+
+#if defined(POINT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_pointLightPosition;			        // Position
+uniform float u_pointLightRadius;                   // Radius
+varying vec4 v_pointLightDirectionCurrent;          // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+    
+    // Compute the light direction.
+	vec3 lightDirection = u_pointLightPosition - positionWorldViewSpace.xyz;
+	
+    vec4 pointLightDirectionCurrent;
+    pointLightDirectionCurrent.xyz = normalize(lightDirection);
+    
+    // Attenuation
+    pointLightDirectionCurrent.w = 1 - dot (lightDirection * u_pointLightRadius, lightDirection * u_pointLightRadius);
+
+    // Output normalized light direction.
+    v_pointLightDirectionCurrent =  normalize(pointLightDirectionCurrent);
+}
+
+#elif defined(SPOT_LIGHT)
+
+uniform mat4 u_worldViewMatrix;						// Matrix to tranform a position to view space.
+uniform vec3 u_spotLightPosition;                   // Position
+varying vec3 v_spotLightDirectionCurrent;           // Light direction w.r.t current vertex.
+
+void applyLight(vec4 position)
+{
+    // World space position.
+    vec4 positionWorldViewSpace = u_worldViewMatrix * position;
+
+    // Compute the light direction with light position and the vertex position.
+	vec3 lightDirection = u_spotLightPosition - positionWorldViewSpace.xyz;
+
+    // Output normalized light direction.
+    v_spotLightDirectionCurrent = normalize(lightDirection);
+}
+
+#else
+
+void applyLight(vec4 position)
+{
+}
+
+#endif
 
 void main()
 {
+	vec4 position = getPosition();
+    vec3 normal = getNormal();
+    
     // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
+	gl_Position = u_worldViewProjectionMatrix * position;
 
-    // Transform normal to view space.
-    mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
-    v_normalVector = normalize(inverseTransposeWorldViewMatrix * a_normal);
+	// Transform normal to view space.
+	mat3 inverseTransposeWorldViewMatrix = mat3(u_inverseTransposeWorldViewMatrix);
+	v_normalVector = inverseTransposeWorldViewMatrix * normal;
 
-    // Pass on texture coordinate to fragment shader.
-    v_texCoord = a_texCoord;
-}
+    // Apply light.
+    applyLight(position);
+
+    // Pass on the texture coordinates to Fragment shader.
+	v_texCoord = a_texCoord;
+}

+ 3 - 3
gameplay-resources/res/shaders/textured.fsh

@@ -1,11 +1,11 @@
 precision highp float;
 
 // Uniforms
-uniform sampler2D u_diffuseTexture;         // Diffuse texture
-uniform vec4 u_diffuseColor;                // Diffuse color/tint
+uniform sampler2D u_diffuseTexture;     // Diffuse texture
+uniform vec4 u_diffuseColor;            // Diffuse color/tint
 
 // Inputs
-varying vec2 v_texCoord;                    // Texture coordinate (u, v).
+varying vec2 v_texCoord;                // Texture coordinate (u, v).
 
 void main()
 {

+ 65 - 5
gameplay-resources/res/shaders/textured.vsh

@@ -1,17 +1,77 @@
 // Uniforms
-uniform mat4 u_worldViewProjectionMatrix;    // Matrix to transform a position to clip space.
+uniform mat4 u_worldViewProjectionMatrix;       // Matrix to transform a position to clip space.
 
 // Inputs
-attribute vec4 a_position;                    // Vertex Position (x, y, z, w).
-attribute vec2 a_texCoord;                    // Vertex Texture Coordinate (u, v).
+attribute vec4 a_position;                      // Vertex Position (x, y, z, w).
+attribute vec2 a_texCoord;                      // Vertex Texture Coordinate (u, v).
 
 // Outputs
-varying vec2 v_texCoord;                    // Texture coordinate (u, v).
+varying vec2 v_texCoord;                        // Texture coordinate (u, v).
+
+#if defined(SKINNING)
+
+attribute vec4 a_blendWeights;
+attribute vec4 a_blendIndices;
+
+// 32 4x3 matrices as an array of floats
+uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
+
+// Common vectors.
+vec4 _skinnedPosition;
+
+void skinPosition(float blendWeight, int matrixIndex)
+{
+    vec4 tmp;
+
+    tmp.x = dot(a_position, u_matrixPalette[matrixIndex]);
+    tmp.y = dot(a_position, u_matrixPalette[matrixIndex + 1]);
+    tmp.z = dot(a_position, u_matrixPalette[matrixIndex + 2]);
+    tmp.w = a_position.w;
+
+    _skinnedPosition += blendWeight * tmp;
+}
+
+vec4 getPosition()
+{
+    _skinnedPosition = vec4(0.0);
+
+    // Transform position to view space using 
+    // matrix palette with four matrices used to transform a vertex.
+
+    float blendWeight = a_blendWeights[0];
+    int matrixIndex = int (a_blendIndices[0]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[1];
+    matrixIndex = int(a_blendIndices[1]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[2];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    blendWeight = a_blendWeights[3];
+    matrixIndex = int(a_blendIndices[2]) * 3;
+    skinPosition(blendWeight, matrixIndex);
+
+    return _skinnedPosition;    
+}
+
+#else
+
+vec4 getPosition()
+{
+    return a_position;    
+}
+
+#endif
 
 void main()
 {
+    vec4 position = getPosition();
+
     // Transform position to clip space.
-    gl_Position = u_worldViewProjectionMatrix * a_position;
+    gl_Position = u_worldViewProjectionMatrix * position;
 
     // Pass on texture coordinate to fragment shader.
     v_texCoord = a_texCoord;

+ 12 - 3
gameplay/gameplay.vcxproj

@@ -23,7 +23,6 @@
     <ClCompile Include="src\BoundingBox.cpp" />
     <ClCompile Include="src\BoundingSphere.cpp" />
     <ClCompile Include="src\Camera.cpp" />
-    <ClCompile Include="src\Color.cpp" />
     <ClCompile Include="src\Curve.cpp" />
     <ClCompile Include="src\Effect.cpp" />
     <ClCompile Include="src\FileSystem.cpp" />
@@ -34,6 +33,7 @@
     <ClCompile Include="src\Joint.cpp" />
     <ClCompile Include="src\Light.cpp" />
     <ClCompile Include="src\Material.cpp" />
+    <ClCompile Include="src\Pass.cpp" />
     <ClCompile Include="src\MaterialParameter.cpp" />
     <ClCompile Include="src\Matrix.cpp" />
     <ClCompile Include="src\Mesh.cpp" />
@@ -53,8 +53,10 @@
     <ClCompile Include="src\Ray.cpp" />
     <ClCompile Include="src\Rectangle.cpp" />
     <ClCompile Include="src\Ref.cpp" />
+    <ClCompile Include="src\RenderState.cpp" />
     <ClCompile Include="src\Scene.cpp" />
     <ClCompile Include="src\SpriteBatch.cpp" />
+    <ClCompile Include="src\Technique.cpp" />
     <ClCompile Include="src\Texture.cpp" />
     <ClCompile Include="src\Transform.cpp" />
     <ClCompile Include="src\Vector2.cpp" />
@@ -78,7 +80,6 @@
     <ClInclude Include="src\BoundingBox.h" />
     <ClInclude Include="src\BoundingSphere.h" />
     <ClInclude Include="src\Camera.h" />
-    <ClInclude Include="src\Color.h" />
     <ClInclude Include="src\Curve.h" />
     <ClInclude Include="src\Effect.h" />
     <ClInclude Include="src\FileSystem.h" />
@@ -93,6 +94,7 @@
     <ClInclude Include="src\Joint.h" />
     <ClInclude Include="src\Light.h" />
     <ClInclude Include="src\Material.h" />
+    <ClInclude Include="src\Pass.h" />
     <ClInclude Include="src\MaterialParameter.h" />
     <ClInclude Include="src\Matrix.h" />
     <ClInclude Include="src\Mesh.h" />
@@ -102,9 +104,15 @@
     <ClInclude Include="src\Node.h" />
     <ClInclude Include="src\Package.h" />
     <ClInclude Include="src\ParticleEmitter.h" />
+    <ClInclude Include="src\PhysicsConstraint.h" />
     <ClInclude Include="src\PhysicsController.h" />
+    <ClInclude Include="src\PhysicsFixedConstraint.h" />
+    <ClInclude Include="src\PhysicsGenericConstraint.h" />
+    <ClInclude Include="src\PhysicsHingeConstraint.h" />
     <ClInclude Include="src\PhysicsMotionState.h" />
     <ClInclude Include="src\PhysicsRigidBody.h" />
+    <ClInclude Include="src\PhysicsSocketConstraint.h" />
+    <ClInclude Include="src\PhysicsSpringConstraint.h" />
     <ClInclude Include="src\Plane.h" />
     <ClInclude Include="src\Platform.h" />
     <ClInclude Include="src\Properties.h" />
@@ -112,11 +120,12 @@
     <ClInclude Include="src\Ray.h" />
     <ClInclude Include="src\Rectangle.h" />
     <ClInclude Include="src\Ref.h" />
+    <ClInclude Include="src\RenderState.h" />
     <ClInclude Include="src\Scene.h" />
     <ClInclude Include="src\SpriteBatch.h" />
+    <ClInclude Include="src\Technique.h" />
     <ClInclude Include="src\Texture.h" />
     <ClInclude Include="src\Transform.h" />
-    <ClInclude Include="src\Tree.h" />
     <ClInclude Include="src\Vector2.h" />
     <ClInclude Include="src\Vector3.h" />
     <ClInclude Include="src\Vector4.h" />

+ 41 - 14
gameplay/gameplay.vcxproj.filters

@@ -27,9 +27,6 @@
     <ClCompile Include="src\Camera.cpp">
       <Filter>src</Filter>
     </ClCompile>
-    <ClCompile Include="src\Color.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
     <ClCompile Include="src\Curve.cpp">
       <Filter>src</Filter>
     </ClCompile>
@@ -54,9 +51,6 @@
     <ClCompile Include="src\Light.cpp">
       <Filter>src</Filter>
     </ClCompile>
-    <ClCompile Include="src\Material.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
     <ClCompile Include="src\Matrix.cpp">
       <Filter>src</Filter>
     </ClCompile>
@@ -156,6 +150,18 @@
     <ClCompile Include="src\Properties.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="src\Material.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Technique.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Pass.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\RenderState.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
     <ClCompile Include="src\PhysicsController.cpp">
       <Filter>src</Filter>
     </ClCompile>
@@ -191,9 +197,6 @@
     <ClInclude Include="src\Camera.h">
       <Filter>src</Filter>
     </ClInclude>
-    <ClInclude Include="src\Color.h">
-      <Filter>src</Filter>
-    </ClInclude>
     <ClInclude Include="src\Curve.h">
       <Filter>src</Filter>
     </ClInclude>
@@ -230,9 +233,6 @@
     <ClInclude Include="src\Light.h">
       <Filter>src</Filter>
     </ClInclude>
-    <ClInclude Include="src\Material.h">
-      <Filter>src</Filter>
-    </ClInclude>
     <ClInclude Include="src\Matrix.h">
       <Filter>src</Filter>
     </ClInclude>
@@ -326,7 +326,16 @@
     <ClInclude Include="src\Properties.h">
       <Filter>src</Filter>
     </ClInclude>
-    <ClInclude Include="src\Tree.h">
+    <ClInclude Include="src\Material.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Technique.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Pass.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\RenderState.h">
       <Filter>src</Filter>
     </ClInclude>
     <ClInclude Include="src\PhysicsController.h">
@@ -338,5 +347,23 @@
     <ClInclude Include="src\PhysicsRigidBody.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\PhysicsFixedConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsGenericConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsHingeConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsSocketConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsSpringConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
-</Project>
+</Project>

+ 5 - 1
gameplay/src/Animation.cpp

@@ -100,7 +100,7 @@ void Animation::createClips(const char* animationFile)
         int begin = pClip->getInt("begin");
         int end = pClip->getInt("end");
 
-        AnimationClip* clip = createClip(pClip->getID(), ((float) begin / frameCount) * _duration, ((float) end / frameCount) * _duration);
+        AnimationClip* clip = createClip(pClip->getId(), ((float) begin / frameCount) * _duration, ((float) end / frameCount) * _duration);
 
         const char* repeat = pClip->getString("repeatCount");
         if (repeat)
@@ -188,7 +188,9 @@ void Animation::stop(const char* id)
         // Find animation clip.. and play.
         AnimationClip* clip = findClip(id);
         if (clip != NULL)
+        {
             clip->stop();
+        }
     }
 }
 
@@ -271,7 +273,9 @@ AnimationClip* Animation::findClip(const char* id) const
     for (unsigned int i = 0; i < clipCount; i++)
     {
         if (_clips.at(i)->_id.compare(id) == 0)
+        {
             return _clips.at(i);
+        }
     }
     return NULL;
 }

+ 1 - 0
gameplay/src/Animation.h

@@ -99,6 +99,7 @@ private:
         friend class Animation;
 
     private:
+
         Channel(AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration);
         Channel(const Channel& copy);
         ~Channel();

+ 3 - 1
gameplay/src/AnimationClip.cpp

@@ -47,7 +47,7 @@ AnimationClip::~AnimationClip()
         SAFE_DELETE(_beginListeners);
     }
 
-    if (_beginListeners)
+    if (_endListeners)
     {
         std::vector<Listener*>::iterator eIter = _endListeners->begin();
         while (eIter != _endListeners->end())
@@ -216,7 +216,9 @@ bool AnimationClip::update(unsigned long elapsedTime)
 
     // When ended. Probably should move to it's own method so we can call it when the clip is ended early.
     if (!_isPlaying)
+    {
         onEnd();
+    }
 
     return !_isPlaying;
 }

+ 1 - 2
gameplay/src/AnimationClip.h

@@ -10,7 +10,6 @@
 #include "Curve.h"
 #include "Animation.h"
 
-
 namespace gameplay
 {
 
@@ -30,7 +29,7 @@ public:
     /**
      * Defines a constant for indefinitely repeating an AnimationClip.
      */
-    static const int REPEAT_INDEFINITE = 0; 
+    static const unsigned int REPEAT_INDEFINITE = 0;
 
     /**
      * Defines an animation event listener.

+ 2 - 0
gameplay/src/AnimationController.cpp

@@ -100,7 +100,9 @@ Animation* AnimationController::getAnimation(const char* id) const
     for (unsigned int i = 0; i < animationCount; i++)
     {
         if (_animations.at(i)->_id.compare(id) == 0)
+        {
             return _animations.at(i);
+        }
     }
     return NULL;
 }

+ 3 - 1
gameplay/src/AnimationTarget.cpp

@@ -27,8 +27,8 @@ AnimationTarget::~AnimationTarget()
             SAFE_RELEASE((*animationIter));
             animationIter++;
         }
+        SAFE_DELETE(_animations);
     }
-    SAFE_DELETE(_animations);
 }
 
 void AnimationTarget::addAnimation(Animation* animation)
@@ -67,7 +67,9 @@ Animation* AnimationTarget::getAnimation(const char* id) const
         while(animationIter != _animations->end())
         {
             if ((*animationIter)->_id.compare(id) == 0)
+            {
                 return *animationIter;
+            }
 
             animationIter++;
         }

+ 3 - 20
gameplay/src/AudioBuffer.cpp

@@ -44,10 +44,6 @@ AudioBuffer* AudioBuffer::create(const char* path)
     }
 
     ALuint alBuffer;
-    ALenum format;
-    ALsizei size;
-    ALvoid* data = NULL;
-    ALsizei freq;
     ALboolean loop = AL_TRUE;
     ALCenum al_error;
 
@@ -65,24 +61,11 @@ AudioBuffer* AudioBuffer::create(const char* path)
     fullPath += "/";
     fullPath += path;
     
-    // Load wav file.
-    alutLoadWAVFile((ALbyte*)fullPath.c_str(), &format, &data, &size, &freq, &loop);
-    if (data == NULL)
+    // Load sound file.
+    alBuffer = alutCreateBufferFromFile(fullPath.c_str());
+    if (alBuffer == AL_NONE)
     {
         LOG_ERROR_VARG("AudioBuffer error (%d) loading file: %s", fullPath.c_str());
-    }
-
-    // Buffer the data.
-    alBufferData(alBuffer, format, data, size, freq);
-
-    // Unload the wav data.
-    alutUnloadWAV(format, data, size, freq);
-
-    al_error = alGetError();
-    if (al_error != AL_NO_ERROR)
-    {
-        LOG_ERROR_VARG("AudioBuffer error (%d) buffering data: %s", al_error, fullPath.c_str());
-        alDeleteBuffers(1, &alBuffer);
         return NULL;
     }
 

+ 5 - 26
gameplay/src/AudioController.cpp

@@ -14,7 +14,6 @@ namespace gameplay
 std::list<AudioSource*> AudioController::_playingSources;
 
 AudioController::AudioController()
-    : _device(NULL), _context(NULL)
 {
 }
 
@@ -24,39 +23,19 @@ AudioController::~AudioController()
 
 void AudioController::initialize()
 {    
-    // Open the audio device.
-    _device = alcOpenDevice(NULL);
-    if (!_device)
-        LOG_ERROR_VARG("AudioController::initialize() error. Unable to open device. ALc Error: %d", alcGetError(_device));
+	alutInit(0, 0);
 
-    // Create the audio context.
-    _context = alcCreateContext(_device, NULL);
-    ALCenum alcError = alcGetError(_device);
-    if (_context == NULL)
-        LOG_ERROR_VARG("AudioController::initialize() error. Unable to create context. ALc Error: %d", alcError);
-
-    // Make the context current.
-    alcMakeContextCurrent(_context);
-    alcError = alcGetError(_device);
-    if ( alcError != ALC_NO_ERROR)
+	ALenum errorID = alutGetError();
+    if ( errorID != ALUT_ERROR_NO_ERROR)
     {
-        LOG_ERROR_VARG("AudioController::initialize() error. Unable to make context current. ALc Error: %d", alcError);
-        // no sense in going forward if we couldn't create a device or context
+        LOG_ERROR_VARG("AudioController::initialize() error. Unable to initialize alut: %s\n", alutGetErrorString(errorID));
         return;  
     }
 }
 
 void AudioController::finalize()
 {
-    _context = alcGetCurrentContext();
-    _device = alcGetContextsDevice(_context);
-    alcMakeContextCurrent(NULL);
-    alcDestroyContext(_context);
-
-    if (_device)
-    {
-       alcCloseDevice(_device);
-    }
+	alutExit();
 }
 
 void AudioController::pause()

+ 1 - 2
gameplay/src/AudioController.h

@@ -58,8 +58,7 @@ private:
      */
     void update(long elapsedTime);
 
-    ALCdevice*_device;                                  // Audio device.
-    ALCcontext* _context;                               // Audio context.
+
     static std::list<AudioSource*> _playingSources;     // List of currently running sources.
 };
 

+ 1 - 1
gameplay/src/AudioSource.cpp

@@ -28,7 +28,7 @@ AudioSource::~AudioSource()
         _alSource = 0;
     }
 
-    SAFE_DELETE(_buffer);
+    SAFE_RELEASE(_buffer);
 }
 
 AudioSource* AudioSource::create(const char* path)

+ 2 - 9
gameplay/src/Base.h

@@ -96,8 +96,8 @@ extern void printError(const char* format, ...);
 #define MATH_LOG10E                 0.4342944819032518f
 #define MATH_LOG2E                  1.442695040888963387f
 #define MATH_PI                     3.14159265358979323846f
-#define MATH_PIOOVER2               1.57079632679489661923f
-#define MATH_PIOOVER4               M_PI_4
+#define MATH_PIOVER2                1.57079632679489661923f
+#define MATH_PIOVER4                M_PI_4
 #define MATH_PIX2                   6.28318530717958647693f
 #define MATH_EPSILON                0.000001f
 #define MATH_DEG_TO_RAD(x)          ((x) * 0.0174532925f)
@@ -151,13 +151,6 @@ extern void printError(const char* format, ...);
 #define VERTEX_ATTRIBUTE_BLENDINDICES_NAME          "a_blendIndices"
 #define VERTEX_ATTRIBUTE_TEXCOORD_PREFIX            "a_texCoord"
 
-// Uniforms
-#define UNIFORM_WORLD_MATRIX                        "u_worldMatrix"
-#define UNIFORM_VIEW_MATRIX                         "u_viewMatrix"
-#define UNIFORM_WORLD_VIEW_PROJECTION_MATRIX        "u_worldViewProjectionMatrix"
-#define UNIFORM_INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX "u_inverseTransposeWorldViewMatrix"
-#define UNIFORM_CAMERA_POSITION                     "u_cameraPosition"
-
 // Hardware Resources
 namespace gameplay
 {

+ 9 - 9
gameplay/src/BoundingBox.cpp

@@ -80,10 +80,10 @@ bool BoundingBox::intersects(const BoundingBox& box) const
 bool BoundingBox::intersects(const Frustum& frustum) const
 {
     // The box must either intersect or be in the positive half-space of all six planes of the frustum.
-    return (intersects(frustum.getNear()) != PLANE_INTERSECTS_BACK && intersects(frustum.getFar())
-        != PLANE_INTERSECTS_BACK && intersects(frustum.getLeft()) != PLANE_INTERSECTS_BACK && intersects(
-        frustum.getRight()) != PLANE_INTERSECTS_BACK && intersects(frustum.getBottom()) != PLANE_INTERSECTS_BACK
-        && intersects(frustum.getTop()) != PLANE_INTERSECTS_BACK);
+    return (intersects(frustum.getNear()) != Plane::INTERSECTS_BACK && intersects(frustum.getFar())
+        != Plane::INTERSECTS_BACK && intersects(frustum.getLeft()) != Plane::INTERSECTS_BACK && intersects(
+        frustum.getRight()) != Plane::INTERSECTS_BACK && intersects(frustum.getBottom()) != Plane::INTERSECTS_BACK
+        && intersects(frustum.getTop()) != Plane::INTERSECTS_BACK);
 }
 
 float BoundingBox::intersects(const Plane& plane) const
@@ -101,10 +101,10 @@ float BoundingBox::intersects(const Plane& plane) const
     if (fabsf(distance) <= (fabsf(extentX * planeNormal.x) + fabsf(extentY * planeNormal.y) + fabsf(
         extentZ * planeNormal.z)))
     {
-        return PLANE_INTERSECTS_INTERSECTING;
+        return Plane::INTERSECTS_INTERSECTING;
     }
 
-    return (float)(distance > 0.0f) ? PLANE_INTERSECTS_FRONT : PLANE_INTERSECTS_BACK;
+    return (float)(distance > 0.0f) ? Plane::INTERSECTS_FRONT : Plane::INTERSECTS_BACK;
 }
 
 float BoundingBox::intersects(const Ray& ray) const
@@ -136,7 +136,7 @@ float BoundingBox::intersects(const Ray& ray) const
     // Check if the ray misses the box.
     if (dnear > dfar || dfar < 0.0f)
     {
-        return RAY_INTERSECTS_NONE;
+        return Ray::INTERSECTS_NONE;
     }
 
     // Y direction.
@@ -164,7 +164,7 @@ float BoundingBox::intersects(const Ray& ray) const
     // Check if the ray misses the box.
     if (dnear > dfar || dfar < 0.0f)
     {
-        return RAY_INTERSECTS_NONE;
+        return Ray::INTERSECTS_NONE;
     }
 
     // Z direction.
@@ -193,7 +193,7 @@ float BoundingBox::intersects(const Ray& ray) const
     // Check if the ray misses the box.
     if (dnear > dfar || dfar < 0.0f)
     {
-        return RAY_INTERSECTS_NONE;
+        return Ray::INTERSECTS_NONE;
     }
     // The ray intersects the box (and since the direction of a Ray is normalized, dnear is the distance to the ray).
     return dnear;

+ 4 - 4
gameplay/src/BoundingBox.h

@@ -111,9 +111,9 @@ public:
      *
      * @param plane The plane to test intersection with.
      * 
-     * @return PLANE_INTERSECTS_BACK INTERSECTS_BACK if this bounding box is in the negative half-space of
-     *  the plane, PLANE_INTERSECTS_FRONT INTERSECTS_FRONT if it is in the positive half-space of the plane;
-     *  and PLANE_INTERSECTS_INTERSECTING INTERSECTS_INTERSECTING if it intersects the plane.
+     * @return Plane::INTERSECTS_BACK INTERSECTS_BACK if this bounding box is in the negative half-space of
+     *  the plane, Plane::INTERSECTS_FRONT INTERSECTS_FRONT if it is in the positive half-space of the plane;
+     *  and Plane::INTERSECTS_INTERSECTING INTERSECTS_INTERSECTING if it intersects the plane.
      */
     float intersects(const Plane& plane) const;
 
@@ -123,7 +123,7 @@ public:
      * @param ray The ray to test intersection with.
      * 
      * @return The distance from the origin of the ray to this bounding box or
-     *  RAY_INTERSECTS_NONE INTERSECTS_NONE if the ray does not intersect this bounding box.
+     *  INTERSECTS_NONE INTERSECTS_NONE if the ray does not intersect this bounding box.
      */
     float intersects(const Ray& ray) const;
 

+ 10 - 10
gameplay/src/BoundingSphere.cpp

@@ -95,12 +95,12 @@ bool BoundingSphere::intersects(const BoundingBox& box) const
 bool BoundingSphere::intersects(const Frustum& frustum) const
 {
     // The sphere must either intersect or be in the positive half-space of all six planes of the frustum.
-    return (intersects(frustum.getNear()) != PLANE_INTERSECTS_BACK &&
-            intersects(frustum.getFar()) != PLANE_INTERSECTS_BACK &&
-            intersects(frustum.getLeft()) != PLANE_INTERSECTS_BACK &&
-            intersects(frustum.getRight()) != PLANE_INTERSECTS_BACK &&
-            intersects(frustum.getBottom()) != PLANE_INTERSECTS_BACK &&
-            intersects(frustum.getTop()) != PLANE_INTERSECTS_BACK );
+    return (intersects(frustum.getNear()) != Plane::INTERSECTS_BACK &&
+            intersects(frustum.getFar()) != Plane::INTERSECTS_BACK &&
+            intersects(frustum.getLeft()) != Plane::INTERSECTS_BACK &&
+            intersects(frustum.getRight()) != Plane::INTERSECTS_BACK &&
+            intersects(frustum.getBottom()) != Plane::INTERSECTS_BACK &&
+            intersects(frustum.getTop()) != Plane::INTERSECTS_BACK );
 }
 
 float BoundingSphere::intersects(const Plane& plane) const
@@ -109,15 +109,15 @@ float BoundingSphere::intersects(const Plane& plane) const
 
     if (fabsf(distance) <= radius)
     {
-        return PLANE_INTERSECTS_INTERSECTING;
+        return Plane::INTERSECTS_INTERSECTING;
     }
     else if (distance > 0.0f)
     {
-        return PLANE_INTERSECTS_FRONT;
+        return Plane::INTERSECTS_FRONT;
     }
     else
     {
-        return PLANE_INTERSECTS_BACK;
+        return Plane::INTERSECTS_BACK;
     }
 }
 
@@ -142,7 +142,7 @@ float BoundingSphere::intersects(const Ray& ray) const
     // If the discriminant is negative, then there is no intersection.
     if (discriminant < 0.0f)
     {
-        return RAY_INTERSECTS_NONE;
+        return Ray::INTERSECTS_NONE;
     }
     else
     {

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff