Просмотр исходного кода

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

Conflicts:
	gameplay/gameplay.vcxproj.filters
	gameplay/src/FileSystem.cpp
	gameplay/src/PlatformMacOS.mm
Chris Culy 14 лет назад
Родитель
Сommit
12e7c20453
42 измененных файлов с 2979 добавлено и 584 удалено
  1. 1 0
      gameplay-encoder/gameplay-encoder.vcxproj
  2. 3 0
      gameplay-encoder/gameplay-encoder.vcxproj.filters
  3. 84 0
      gameplay-encoder/gameplay-encoder.xcodeproj/xcshareddata/xcschemes/gameplay-encoder.xcscheme
  4. 81 37
      gameplay-encoder/src/Quaternion.cpp
  5. 95 39
      gameplay-encoder/src/Quaternion.h
  6. 19 0
      gameplay-encoder/src/Quaternion.inl
  7. 2 2
      gameplay-template/src/TemplateGame.cpp
  8. 1 1
      gameplay-template/src/TemplateGame.h
  9. 8 0
      gameplay.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  10. 1 0
      gameplay/gameplay.vcxproj
  11. 565 182
      gameplay/gameplay.vcxproj.filters
  12. 564 45
      gameplay/gameplay.xcodeproj/project.pbxproj
  13. 57 0
      gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-MacOSX.xcscheme
  14. 57 0
      gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-iOS.xcscheme
  15. 9 156
      gameplay/src/AnimationClip.cpp
  16. 1 1
      gameplay/src/AnimationClip.h
  17. 12 1
      gameplay/src/AnimationController.cpp
  18. 2 1
      gameplay/src/AnimationController.h
  19. 1 1
      gameplay/src/AnimationTarget.cpp
  20. 4 3
      gameplay/src/AnimationTarget.h
  21. 7 9
      gameplay/src/AnimationValue.cpp
  22. 2 3
      gameplay/src/AnimationValue.h
  23. 34 13
      gameplay/src/Base.h
  24. 3 3
      gameplay/src/BoundingBox.cpp
  25. 3 10
      gameplay/src/Curve.cpp
  26. 78 0
      gameplay/src/FileSystem.cpp
  27. 10 0
      gameplay/src/FileSystem.h
  28. 9 0
      gameplay/src/Game.cpp
  29. 24 0
      gameplay/src/Game.h
  30. 145 18
      gameplay/src/MaterialParameter.cpp
  31. 5 1
      gameplay/src/MaterialParameter.h
  32. 39 0
      gameplay/src/Mouse.h
  33. 2 3
      gameplay/src/PlatformMacOS.mm
  34. 105 2
      gameplay/src/PlatformQNX.cpp
  35. 27 3
      gameplay/src/PlatformWin32.cpp
  36. 532 0
      gameplay/src/PlatformiOS.mm
  37. 42 28
      gameplay/src/Quaternion.cpp
  38. 30 2
      gameplay/src/Quaternion.h
  39. 261 16
      gameplay/src/Transform.cpp
  40. 29 3
      gameplay/src/Transform.h
  41. 23 0
      gameplay/src/gameplay-main-ios.mm
  42. 2 1
      gameplay/src/gameplay.h

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

@@ -98,6 +98,7 @@
     <ClInclude Include="src\VertexElement.h" />
   </ItemGroup>
   <ItemGroup>
+    <None Include="src\Quaternion.inl" />
     <None Include="src\Vector2.inl" />
     <None Include="src\Vector3.inl" />
     <None Include="src\Vector4.inl" />

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

@@ -263,6 +263,9 @@
     <None Include="src\Vector4.inl">
       <Filter>src</Filter>
     </None>
+    <None Include="src\Quaternion.inl">
+      <Filter>src</Filter>
+    </None>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="src">

+ 84 - 0
gameplay-encoder/gameplay-encoder.xcodeproj/xcshareddata/xcschemes/gameplay-encoder.xcscheme

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "42475CE5147208A000610A6A"
+               BuildableName = "gameplay-encoder"
+               BlueprintName = "gameplay-encoder"
+               ReferencedContainer = "container:gameplay-encoder.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "42475CE5147208A000610A6A"
+            BuildableName = "gameplay-encoder"
+            BlueprintName = "gameplay-encoder"
+            ReferencedContainer = "container:gameplay-encoder.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "42475CE5147208A000610A6A"
+            BuildableName = "gameplay-encoder"
+            BlueprintName = "gameplay-encoder"
+            ReferencedContainer = "container:gameplay-encoder.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "42475CE5147208A000610A6A"
+            BuildableName = "gameplay-encoder"
+            BlueprintName = "gameplay-encoder"
+            ReferencedContainer = "container:gameplay-encoder.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 81 - 37
gameplay-encoder/src/Quaternion.cpp

@@ -19,6 +19,10 @@ Quaternion::Quaternion(float* array)
     set(array);
 }
 
+Quaternion::Quaternion(const Vector3& axis, float angle)
+{
+    set(axis, angle);
+}
 
 Quaternion::Quaternion(const Quaternion& copy)
 {
@@ -31,14 +35,14 @@ Quaternion::~Quaternion()
 
 const Quaternion& Quaternion::identity()
 {
-    static Quaternion* value = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
-    return *value;
+    static Quaternion value(0.0f, 0.0f, 0.0f, 1.0f);
+    return value;
 }
 
 const Quaternion& Quaternion::zero()
 {
-    static Quaternion* value = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f);
-    return *value;
+    static Quaternion value(0.0f, 0.0f, 0.0f, 0.0f);
+    return value;
 }
 
 bool Quaternion::isIdentity() const
@@ -51,13 +55,6 @@ bool Quaternion::isZero() const
     return x == 0.0f && y == 0.0f && z == 0.0f && z == 0.0f;
 }
 
-void Quaternion::createFromRotationMatrix(const Matrix& m, Quaternion* dst)
-{
-    assert(dst);
-
-    m.decompose(NULL, dst, NULL);
-}
-
 void Quaternion::createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst)
 {
     assert(dst);
@@ -154,12 +151,12 @@ void Quaternion::normalize(Quaternion* dst) const
 
     float n = x * x + y * y + z * z + w * w;
 
-    // already normalized
+    // Already normalized.
     if (n == 1.0f)
         return;
 
     n = sqrt(n);
-    // too close to zero
+    // Too close to zero.
     if (n < 0.000001f)
         return;
 
@@ -188,6 +185,11 @@ void Quaternion::set(float* array)
     w = array[3];
 }
 
+void Quaternion::set(const Vector3& axis, float angle)
+{
+    Quaternion::createFromAxisAngle(axis, angle, this);
+}
+
 void Quaternion::set(const Quaternion& q)
 {
     this->x = q.x;
@@ -223,6 +225,17 @@ void Quaternion::lerp(const Quaternion& q1, const Quaternion& q2, float t, Quate
     assert(dst);
     assert(!(t < 0.0f || t > 1.0f));
 
+    if (t == 0.0f)
+    {
+        memcpy(dst, &q1, sizeof(float) * 4);
+        return;
+    }
+    else if (t == 1.0f)
+    {
+        memcpy(dst, &q2, sizeof(float) * 4);
+        return;
+    }
+
     float t1 = 1.0f - t;
 
     dst->x = t1 * q1.x + t * q2.x;
@@ -232,21 +245,65 @@ void Quaternion::lerp(const Quaternion& q1, const Quaternion& q2, float t, Quate
 }
 
 void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
+{
+    slerp(q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w, t, &dst->x, &dst->y, &dst->z, &dst->w);
+}
+
+void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
+{
+    assert(dst);
+    assert(!(t < 0.0f || t > 1.0f));
+
+    Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
+    Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
+
+    slerpForSquad(q1, q2, t, &dstQ);
+    slerpForSquad(s1, s2, t, &dstS);
+    slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
+}
+
+void Quaternion::slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw)
 {
     // Fast slerp implementation by kwhatmough:
     // It contains no division operations, no trig, no inverse trig
     // and no sqrt. Not only does this code tolerate small constraint
     // errors in the input quaternions, it actually corrects for them.
-    assert(dst);
+    assert(dstx && dsty && dstz && dstw);
     assert(!(t < 0.0f || t > 1.0f));
 
+    if (t == 0.0f)
+    {
+        *dstx = q1x;
+        *dsty = q1y;
+        *dstz = q1z;
+        *dstw = q1w;
+        return;
+    }
+    else if (t == 1.0f)
+    {
+        *dstx = q2x;
+        *dsty = q2y;
+        *dstz = q2z;
+        *dstw = q2w;
+        return;
+    }
+
+    if (q1x == q2x && q1y == q2y && q1z == q2z && q1w == q2w)
+    {
+        *dstx = q1x;
+        *dsty = q1y;
+        *dstz = q1z;
+        *dstw = q1w;
+        return;
+    }
+
     float halfY, alpha, beta;
     float u, f1, f2a, f2b;
     float ratio1, ratio2;
     float halfSecHalfTheta, versHalfTheta;
     float sqNotU, sqU;
 
-    float cosTheta = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;
+    float cosTheta = q1w * q2w + q1x * q2x + q1y * q2y + q1z * q2z;
 
     // As usual in all slerp implementations, we fold theta.
     alpha = cosTheta >= 0 ? 1.0f : -1.0f;
@@ -287,34 +344,21 @@ void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quat
     beta = f1 + f2b;
 
     // Apply final coefficients to a and b as usual.
-    float w = alpha * q1.w + beta * q2.w;
-    float x = alpha * q1.x + beta * q2.x;
-    float y = alpha * q1.y + beta * q2.y;
-    float z = alpha * q1.z + beta * q2.z;
+    float w = alpha * q1w + beta * q2w;
+    float x = alpha * q1x + beta * q2x;
+    float y = alpha * q1y + beta * q2y;
+    float z = alpha * q1z + beta * q2z;
 
     // This final adjustment to the quaternion's length corrects for
-    // any small constraint error in the inputs q1 and q2. But as you
+    // any small constraint error in the inputs q1 and q2 But as you
     // can see, it comes at the cost of 9 additional multiplication
     // operations. If this error-correcting feature is not required,
     // the following code may be removed.
     f1 = 1.5f - 0.5f * (w * w + x * x + y * y + z * z);
-    dst->w = w * f1;
-    dst->x = x * f1;
-    dst->y = y * f1;
-    dst->z = z * f1;
-}
-
-void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
-{
-    assert(dst);
-    assert(!(t < 0.0f || t > 1.0f));
-
-    Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
-    Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
-
-    slerpForSquad(q1, q2, t, &dstQ);
-    slerpForSquad(s1, s2, t, &dstS);
-    slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
+    *dstw = w * f1;
+    *dstx = x * f1;
+    *dsty = y * f1;
+    *dstz = z * f1;
 }
 
 void Quaternion::slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)

+ 95 - 39
gameplay-encoder/src/Quaternion.h

@@ -20,41 +20,46 @@ class Matrix;
  * lerp (linear interpolation): the interpolation curve gives a straight line in quaternion space. It is simple and fast to compute. The only problem is that it does not provide constant angular velocity. Note that a constant velocity is not necessarily a requirement for a curve;
  * slerp (spherical linear interpolation): the interpolation curve forms a great arc on the quaternion unit sphere. Slerp provides constant angular velocity;
  * squad (spherical spline interpolation): interpolating between a series of rotations using slerp leads to the following problems:
- * the curve is not smooth at the control points;
- * the angular velocity is not constant;
- * the angular velocity is not continuous at the control points.
+ * - the curve is not smooth at the control points;
+ * - the angular velocity is not constant;
+ * - the angular velocity is not continuous at the control points.
  *
  * Since squad is continuously differentiable, it remedies the first and third problems mentioned above.
  * The slerp method provided here is intended for interpolation of principal rotations. It treats +q and -q as the same principal rotation and is at liberty to use the negative of either input. The resulting path is always the shorter arc.
  *
  * The lerp method provided here interpolates strictly in quaternion space. Note that the resulting path may pass through the origin if interpolating between a quaternion and its exact negative.
  *
- * As an example, consider the following quaternions
+ * As an example, consider the following quaternions:
  *
  * q1 = (0.6, 0.8, 0.0, 0.0),
  * q2 = (0.0, 0.6, 0.8, 0.0),
  * q3 = (0.6, 0.0, 0.8, 0.0), and
  * q4 = (-0.8, 0.0, -0.6, 0.0).
  * For the point p = (1.0, 1.0, 1.0), the following figures show the trajectories of p using lerp, slerp, and squad.
- *
- * @image "http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/math/doc-files/LERP.PNG"
- * @image "http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/math/doc-files/SLERP.PNG"
- * @image "http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/math/doc-files/SQUAD.PNG"
  */
 class Quaternion
 {
+    friend class Curve;
+
 public:
 
-    /** The x-value of the quaternion's vector component. */
+    /**
+     * The x-value of the quaternion's vector component.
+     */
     float x;
-    /** The y-value of the quaternion's vector component. */
+    /**
+     * The y-value of the quaternion's vector component.
+     */
     float y;
-    /** The z-value of the quaternion's vector component. */
+    /**
+     * The z-value of the quaternion's vector component.
+     */
     float z;
-    /** The scalar component of the quaternion. */
+    /**
+     * The scalar component of the quaternion.
+     */
     float w;
 
-
     /**
      * Constructs a quaternion initialized to (0, 0, 0, 1).
      */
@@ -73,14 +78,22 @@ public:
     /**
      * Constructs a new quaternion from the values in the specified array.
      *
-     * @param array
+     * @param array The values for the new quaternion.
      */
     Quaternion(float* array);
 
+    /**
+     * Constructs a quaternion equal to the rotation from the specified axis and angle.
+     *
+     * @param axis A vector describing the axis of rotation.
+     * @param angle The angle of rotation (in radians).
+     */
+    Quaternion(const Vector3& axis, float angle);
+
     /**
      * Constructs a new quaternion that is a copy of the specified one.
      *
-     * @param copy The quaternion to copy
+     * @param copy The quaternion to copy.
      */
     Quaternion(const Quaternion& copy);
 
@@ -92,7 +105,7 @@ public:
     /**
      * Returns the identity quaternion.
      *
-     * @return The quaternion.
+     * @return The identity quaternion.
      */
     static const Quaternion& identity();
 
@@ -104,34 +117,25 @@ public:
     static const Quaternion& zero();
 
     /**
-     * Determines if this quaterion is equal to the identity quaternion.
+     * Determines if this quaternion is equal to the identity quaternion.
      *
-     * @return true if the identity, false otherwise.
+     * @return true if it is the identity quaternion, false otherwise.
      */
     bool isIdentity() const;
 
     /**
-     * Determines if this quaterion is all zeros.
+     * Determines if this quaternion is all zeros.
      *
-     * @return true if zeros, false otherwise.
+     * @return true if this quaternion is all zeros, false otherwise.
      */
     bool isZero() const;
 
-    /**
-     * Create a quaternion equal to the rotational part of the specified matrix
-     * and stores the result in dst.
-     *
-     * @param m The matrix.
-     * @param dst A quaternion to store the conjugate in.
-     */
-    static void createFromRotationMatrix(const Matrix& m, Quaternion* dst);
-
     /**
      * Creates this quaternion equal to the rotation from the specified axis and angle
-     * and store the result in dst.
+     * and stores the result in dst.
      *
      * @param axis A vector describing the axis of rotation.
-     * @param angle The angle of rotation, in radians.
+     * @param angle The angle of rotation (in radians).
      * @param dst A quaternion to store the conjugate in.
      */
     static void createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst);
@@ -226,6 +230,14 @@ public:
      */
     void set(float* array);
 
+    /**
+     * Sets the quaternion equal to the rotation from the specified axis and angle.
+     * 
+     * @param axis The axis of rotation.
+     * @param angle The angle of rotation (in radians).
+     */
+    void set(const Vector3& axis, float angle);
+
     /**
      * Sets the elements of this quaternion to a copy of the specified quaternion.
      *
@@ -256,10 +268,10 @@ public:
      * @param q1 The first quaternion.
      * @param q2 The second quaternion.
      * @param t The interpolation coefficient.
-     * @param dst A quaternion to store the result in
+     * @param dst A quaternion to store the result in.
      */
     static void lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
-
+    
     /**
      * Interpolates between two quaternions using spherical linear interpolation.
      *
@@ -273,10 +285,10 @@ public:
      * @param q1 The first quaternion.
      * @param q2 The second quaternion.
      * @param t The interpolation coefficient.
-     * @param dst A quaternion to store the result in
+     * @param dst A quaternion to store the result in.
      */
     static void slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
-
+    
     /**
      * Interpolates over a series of quaternions using spherical spline interpolation.
      *
@@ -289,20 +301,64 @@ public:
      *
      * @param q1 The first quaternion.
      * @param q2 The second quaternion.
-     * @param s1 The first control point
-     * @param s2 The second control point
+     * @param s1 The first control point.
+     * @param s2 The second control point.
      * @param t The interpolation coefficient.
-     * @param dst A quaternion to store the result in
+     * @param dst A quaternion to store the result in.
      */
     static void squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst);
 
+    /**
+     * Calculates the quaternion product of this quaternion with the given quaternion.
+     * 
+     * Note: this does not modify this quaternion.
+     * 
+     * @param q The quaternion to multiply.
+     * @return The quaternion product.
+     */
+    inline Quaternion operator*(const Quaternion& q) const;
+
+    /**
+     * Multiplies this quaternion with the given quaternion.
+     * 
+     * @param q The quaternion to multiply.
+     * @return This quaternion, after the multiplication occurs.
+     */
+    inline Quaternion& operator*=(const Quaternion& q);
 
 private:
 
-    static void slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
+    /**
+     * Interpolates between two quaternions using spherical linear interpolation.
+     *
+     * Spherical linear interpolation provides smooth transitions between different
+     * orientations and is often useful for animating models or cameras in 3D.
+     *
+     * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
+     * This method does not automatically normalize the input quaternions, so it is up to the
+     * caller to ensure they call normalize beforehand, if necessary.
+     *
+     * @param q1x The x component of the first quaternion.
+     * @param q1y The y component of the first quaternion.
+     * @param q1z The z component of the first quaternion.
+     * @param q1w The w component of the first quaternion.
+     * @param q2x The x component of the second quaternion.
+     * @param q2y The y component of the second quaternion.
+     * @param q2z The z component of the second quaternion.
+     * @param q2w The w component of the second quaternion.
+     * @param t The interpolation coefficient.
+     * @param dstx A pointer to store the x component of the slerp in.
+     * @param dsty A pointer to store the y component of the slerp in.
+     * @param dstz A pointer to store the z component of the slerp in.
+     * @param dstw A pointer to store the w component of the slerp in.
+     */
+    static void slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw);
 
+    static void slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
 };
 
 }
 
+#include "Quaternion.inl"
+
 #endif

+ 19 - 0
gameplay-encoder/src/Quaternion.inl

@@ -0,0 +1,19 @@
+#include "Quaternion.h"
+
+namespace gameplay
+{
+
+inline Quaternion Quaternion::operator*(const Quaternion& q) const
+{
+    Quaternion result(*this);
+    result.multiply(q);
+    return result;
+}
+
+inline Quaternion& Quaternion::operator*=(const Quaternion& q)
+{
+    multiply(q);
+    return *this;
+}
+
+}

+ 2 - 2
gameplay-template/src/TemplateGame.cpp

@@ -58,9 +58,9 @@ bool TemplateGame::drawScene(Node* node, void* cookie)
     return true;
 }
 
-void TemplateGame::touch(int x, int y, int touchEvent)
+void TemplateGame::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
-    switch (touchEvent)
+    switch (evt)
     {
     case Touch::TOUCH_PRESS:
         break;

+ 1 - 1
gameplay-template/src/TemplateGame.h

@@ -20,7 +20,7 @@ public:
     /**
      * Touch event handler.
      */
-    void touch(int x, int y, int touchEvent);
+    void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
 protected:
 

+ 8 - 0
gameplay.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
+	<true/>
+</dict>
+</plist>

+ 1 - 0
gameplay/gameplay.vcxproj

@@ -117,6 +117,7 @@
     <ClInclude Include="src\Light.h" />
     <ClInclude Include="src\Material.h" />
     <ClInclude Include="src\MeshBatch.h" />
+    <ClInclude Include="src\Mouse.h" />
     <ClInclude Include="src\Pass.h" />
     <ClInclude Include="src\MaterialParameter.h" />
     <ClInclude Include="src\Matrix.h" />

+ 565 - 182
gameplay/gameplay.vcxproj.filters

@@ -1,191 +1,574 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="src\Animation.cpp" />
-    <ClCompile Include="src\AnimationClip.cpp" />
-    <ClCompile Include="src\AnimationController.cpp" />
-    <ClCompile Include="src\AnimationTarget.cpp" />
-    <ClCompile Include="src\AnimationValue.cpp" />
-    <ClCompile Include="src\AudioBuffer.cpp" />
-    <ClCompile Include="src\AudioController.cpp" />
-    <ClCompile Include="src\AudioListener.cpp" />
-    <ClCompile Include="src\AudioSource.cpp" />
-    <ClCompile Include="src\BoundingBox.cpp" />
-    <ClCompile Include="src\BoundingSphere.cpp" />
-    <ClCompile Include="src\Camera.cpp" />
-    <ClCompile Include="src\Curve.cpp" />
-    <ClCompile Include="src\DebugNew.cpp" />
-    <ClCompile Include="src\DepthStencilTarget.cpp" />
-    <ClCompile Include="src\Effect.cpp" />
-    <ClCompile Include="src\FileSystem.cpp" />
-    <ClCompile Include="src\Font.cpp" />
-    <ClCompile Include="src\FrameBuffer.cpp" />
-    <ClCompile Include="src\Frustum.cpp" />
-    <ClCompile Include="src\Game.cpp" />
-    <ClCompile Include="src\gameplay-main-qnx.cpp" />
-    <ClCompile Include="src\gameplay-main-win32.cpp" />
-    <ClCompile Include="src\Image.cpp" />
-    <ClCompile Include="src\Joint.cpp" />
-    <ClCompile Include="src\Light.cpp" />
-    <ClCompile Include="src\Material.cpp" />
-    <ClCompile Include="src\MeshBatch.cpp" />
-    <ClCompile Include="src\Pass.cpp" />
-    <ClCompile Include="src\MaterialParameter.cpp" />
-    <ClCompile Include="src\Matrix.cpp" />
-    <ClCompile Include="src\Mesh.cpp" />
-    <ClCompile Include="src\MeshPart.cpp" />
-    <ClCompile Include="src\MeshSkin.cpp" />
-    <ClCompile Include="src\Model.cpp" />
-    <ClCompile Include="src\Node.cpp" />
-    <ClCompile Include="src\Package.cpp" />
-    <ClCompile Include="src\ParticleEmitter.cpp" />
-    <ClCompile Include="src\PhysicsConstraint.cpp" />
-    <ClCompile Include="src\PhysicsController.cpp" />
-    <ClCompile Include="src\PhysicsFixedConstraint.cpp" />
-    <ClCompile Include="src\PhysicsGenericConstraint.cpp" />
-    <ClCompile Include="src\PhysicsHingeConstraint.cpp" />
-    <ClCompile Include="src\PhysicsMotionState.cpp" />
-    <ClCompile Include="src\PhysicsRigidBody.cpp" />
-    <ClCompile Include="src\PhysicsSocketConstraint.cpp" />
-    <ClCompile Include="src\PhysicsSpringConstraint.cpp" />
-    <ClCompile Include="src\Plane.cpp" />
-    <ClCompile Include="src\PlatformQNX.cpp" />
-    <ClCompile Include="src\PlatformWin32.cpp" />
-    <ClCompile Include="src\Properties.cpp" />
-    <ClCompile Include="src\Quaternion.cpp" />
-    <ClCompile Include="src\Ray.cpp" />
-    <ClCompile Include="src\Rectangle.cpp" />
-    <ClCompile Include="src\Ref.cpp" />
-    <ClCompile Include="src\RenderState.cpp" />
-    <ClCompile Include="src\RenderTarget.cpp" />
-    <ClCompile Include="src\Scene.cpp" />
-    <ClCompile Include="src\SceneLoader.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" />
-    <ClCompile Include="src\Vector3.cpp" />
-    <ClCompile Include="src\Vector4.cpp" />
-    <ClCompile Include="src\VertexAttributeBinding.cpp" />
-    <ClCompile Include="src\VertexFormat.cpp" />
-    <ClCompile Include="src\Viewport.cpp" />
-    <ClCompile Include="src\gameplay-main-android.cpp" />
-    <ClCompile Include="src\PlatformAndroid.cpp" />
+    <Filter Include="src">
+      <UniqueIdentifier>{c4d4da1c-81e2-4944-901c-200e1c4d80e5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res">
+      <UniqueIdentifier>{4a30ac71-e135-47d3-9f56-baac7cffe64c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\shaders">
+      <UniqueIdentifier>{be0b36f1-49ed-4a06-9f1f-57c654a554fe}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="res\textures">
+      <UniqueIdentifier>{7c4ef2fb-63f2-4d5a-b31e-0dc78329abfd}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="src\Animation.h" />
-    <ClInclude Include="src\AnimationClip.h" />
-    <ClInclude Include="src\AnimationController.h" />
-    <ClInclude Include="src\AnimationTarget.h" />
-    <ClInclude Include="src\AnimationValue.h" />
-    <ClInclude Include="src\AudioBuffer.h" />
-    <ClInclude Include="src\AudioController.h" />
-    <ClInclude Include="src\AudioListener.h" />
-    <ClInclude Include="src\AudioSource.h" />
-    <ClInclude Include="src\Base.h" />
-    <ClInclude Include="src\BoundingBox.h" />
-    <ClInclude Include="src\BoundingSphere.h" />
-    <ClInclude Include="src\Camera.h" />
-    <ClInclude Include="src\Curve.h" />
-    <ClInclude Include="src\DebugNew.h" />
-    <ClInclude Include="src\DepthStencilTarget.h" />
-    <ClInclude Include="src\Effect.h" />
-    <ClInclude Include="src\FileSystem.h" />
-    <ClInclude Include="src\Font.h" />
-    <ClInclude Include="src\FrameBuffer.h" />
-    <ClInclude Include="src\Frustum.h" />
-    <ClInclude Include="src\Game.h" />
-    <ClInclude Include="src\gameplay.h" />
-    <ClInclude Include="src\Image.h" />
-    <ClInclude Include="src\Joint.h" />
-    <ClInclude Include="src\Keyboard.h" />
-    <ClInclude Include="src\Light.h" />
-    <ClInclude Include="src\Material.h" />
-    <ClInclude Include="src\MeshBatch.h" />
-    <ClInclude Include="src\Pass.h" />
-    <ClInclude Include="src\MaterialParameter.h" />
-    <ClInclude Include="src\Matrix.h" />
-    <ClInclude Include="src\Mesh.h" />
-    <ClInclude Include="src\MeshPart.h" />
-    <ClInclude Include="src\MeshSkin.h" />
-    <ClInclude Include="src\Model.h" />
-    <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" />
-    <ClInclude Include="src\Quaternion.h" />
-    <ClInclude Include="src\Ray.h" />
-    <ClInclude Include="src\Rectangle.h" />
-    <ClInclude Include="src\Ref.h" />
-    <ClInclude Include="src\RenderState.h" />
-    <ClInclude Include="src\RenderTarget.h" />
-    <ClInclude Include="src\Scene.h" />
-    <ClInclude Include="src\SceneLoader.h" />
-    <ClInclude Include="src\SpriteBatch.h" />
-    <ClInclude Include="src\Technique.h" />
-    <ClInclude Include="src\Texture.h" />
-    <ClInclude Include="src\Touch.h" />
-    <ClInclude Include="src\Transform.h" />
-    <ClInclude Include="src\Vector2.h" />
-    <ClInclude Include="src\Vector3.h" />
-    <ClInclude Include="src\Vector4.h" />
-    <ClInclude Include="src\VertexAttributeBinding.h" />
-    <ClInclude Include="src\VertexFormat.h" />
-    <ClInclude Include="src\Viewport.h" />
+    <ClCompile Include="src\Animation.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AnimationClip.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AnimationController.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AnimationValue.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\BoundingBox.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\BoundingSphere.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Camera.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Curve.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Effect.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\FileSystem.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Font.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Frustum.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Game.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Light.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Matrix.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Mesh.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\MeshPart.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\MeshSkin.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Model.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Node.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Package.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Plane.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PlatformQNX.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PlatformWin32.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Quaternion.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Ray.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Rectangle.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Ref.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Scene.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\SpriteBatch.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Texture.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Transform.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Vector2.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Vector3.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Vector4.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\VertexAttributeBinding.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\VertexFormat.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Viewport.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AudioController.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AudioListener.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AudioSource.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AudioBuffer.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\AnimationTarget.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\MaterialParameter.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Joint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\ParticleEmitter.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <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\gameplay-main-qnx.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\gameplay-main-win32.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\DebugNew.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsController.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsRigidBody.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsHingeConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsFixedConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsGenericConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsSocketConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsSpringConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsMotionState.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\SceneLoader.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Image.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\RenderTarget.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\FrameBuffer.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\DepthStencilTarget.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\MeshBatch.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\gameplay-main-android.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PlatformAndroid.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <None Include="res\shaders\bumped-specular.fsh" />
-    <None Include="res\shaders\bumped-specular.vsh" />
-    <None Include="res\shaders\bumped.fsh" />
-    <None Include="res\shaders\bumped.vsh" />
-    <None Include="res\shaders\colored-specular.fsh" />
-    <None Include="res\shaders\colored-specular.vsh" />
-    <None Include="res\shaders\colored.fsh" />
-    <None Include="res\shaders\colored.vsh" />
-    <None Include="res\shaders\diffuse-specular.fsh" />
-    <None Include="res\shaders\diffuse-specular.vsh" />
-    <None Include="res\shaders\diffuse.fsh" />
-    <None Include="res\shaders\diffuse.vsh" />
-    <None Include="res\shaders\parallax-specular.fsh" />
-    <None Include="res\shaders\parallax-specular.vsh" />
-    <None Include="res\shaders\parallax.fsh" />
-    <None Include="res\shaders\parallax.vsh" />
-    <None Include="res\shaders\solid.fsh" />
-    <None Include="res\shaders\solid.vsh" />
-    <None Include="res\shaders\textured.fsh" />
-    <None Include="res\shaders\textured.vsh" />
-    <None Include="res\textures\particle-default.png" />
-    <None Include="src\BoundingBox.inl" />
-    <None Include="src\BoundingSphere.inl" />
-    <None Include="src\Curve.inl" />
-    <None Include="src\Game.inl" />
-    <None Include="src\gameplay-main-macos.mm" />
-    <None Include="src\Image.inl" />
-    <None Include="src\Matrix.inl" />
-    <None Include="src\MeshBatch.inl" />
-    <None Include="src\Plane.inl" />
-    <None Include="src\PlatformMacOS.mm" />
-    <None Include="src\Quaternion.inl" />
-    <None Include="src\Ray.inl" />
-    <None Include="src\Vector2.inl" />
-    <None Include="src\Vector3.inl" />
-    <None Include="src\Vector4.inl" />
-    <None Include="src\PhysicsConstraint.inl" />
-    <None Include="src\PhysicsFixedConstraint.inl" />
-    <None Include="src\PhysicsGenericConstraint.inl" />
-    <None Include="src\PhysicsRigidBody.inl" />
-    <None Include="src\PhysicsSpringConstraint.inl" />
+    <ClInclude Include="src\Animation.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AnimationClip.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AnimationController.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AnimationTarget.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AnimationValue.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Base.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\BoundingBox.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\BoundingSphere.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Camera.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Curve.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Effect.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\FileSystem.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Font.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Frustum.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Game.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\gameplay.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Light.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Matrix.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Mesh.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\MeshPart.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\MeshSkin.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Model.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Node.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Package.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Plane.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Platform.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Quaternion.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Ray.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Rectangle.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Ref.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Scene.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\SpriteBatch.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Texture.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Transform.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Vector2.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Vector3.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Vector4.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\VertexAttributeBinding.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\VertexFormat.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Viewport.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AudioController.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AudioListener.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AudioSource.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\AudioBuffer.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\MaterialParameter.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Joint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\ParticleEmitter.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Properties.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <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\DebugNew.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsController.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsMotionState.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsRigidBody.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsSpringConstraint.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\SceneLoader.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Image.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\RenderTarget.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\FrameBuffer.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\DepthStencilTarget.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Keyboard.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Touch.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\MeshBatch.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Mouse.h">
+      <Filter>src</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\shaders\bumped-specular.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored-specular.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\colored-specular.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\diffuse.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\diffuse.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\diffuse-specular.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\diffuse-specular.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\parallax.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\parallax.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\parallax-specular.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\parallax-specular.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\solid.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\solid.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\textured.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\textured.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\bumped.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\bumped.vsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="res\shaders\bumped-specular.fsh">
+      <Filter>res\shaders</Filter>
+    </None>
+    <None Include="src\gameplay-main-macos.mm">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PlatformMacOS.mm">
+      <Filter>src</Filter>
+    </None>
+    <None Include="res\textures\particle-default.png">
+      <Filter>res\textures</Filter>
+    </None>
+    <None Include="src\Curve.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Game.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Image.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\MeshBatch.inl">
+      <Filter>src</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="src\PhysicsFixedConstraint.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\BoundingBox.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsGenericConstraint.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\BoundingSphere.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsSpringConstraint.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Matrix.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsRigidBody.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Plane.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Quaternion.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Ray.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Vector2.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Vector3.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\Vector4.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsConstraint.inl">
+      <Filter>src</Filter>
+    </None>
   </ItemGroup>
 </Project>

+ 564 - 45
gameplay/gameplay.xcodeproj/project.pbxproj

@@ -19,7 +19,6 @@
 		4283909A1489D6E800E2B2F5 /* SceneLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 428390981489D6E800E2B2F5 /* SceneLoader.h */; };
 		4299EFA9146AC94300FF4A73 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4299EFA8146AC94300FF4A73 /* OpenGL.framework */; };
 		4299EFAB146AC94B00FF4A73 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4299EFAA146AC94B00FF4A73 /* OpenAL.framework */; };
-		42CCD554146EC1DD00353661 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CCD553146EC1DD00353661 /* libz.dylib */; };
 		42CCD556146EC1EB00353661 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CCD555146EC1EB00353661 /* libpng.a */; };
 		42CD0DAB147D8EA80000361E /* libbullet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CD0DA6147D8EA80000361E /* libbullet.a */; };
 		42CD0DAC147D8EA80000361E /* libogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CD0DA7147D8EA80000361E /* libogg.a */; };
@@ -70,8 +69,6 @@
 		42CD0E6F147D8FF60000361E /* Game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDC147D8FF50000361E /* Game.cpp */; };
 		42CD0E70147D8FF60000361E /* Game.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DDD147D8FF50000361E /* Game.h */; };
 		42CD0E71147D8FF60000361E /* gameplay-main-macos.mm in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDE147D8FF50000361E /* gameplay-main-macos.mm */; };
-		42CD0E72147D8FF60000361E /* gameplay-main-qnx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDF147D8FF50000361E /* gameplay-main-qnx.cpp */; };
-		42CD0E73147D8FF60000361E /* gameplay-main-win32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DE0147D8FF50000361E /* gameplay-main-win32.cpp */; };
 		42CD0E74147D8FF60000361E /* gameplay.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE1147D8FF50000361E /* gameplay.h */; };
 		42CD0E77147D8FF60000361E /* Joint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DE4147D8FF50000361E /* Joint.cpp */; };
 		42CD0E78147D8FF60000361E /* Joint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE5147D8FF50000361E /* Joint.h */; };
@@ -121,8 +118,6 @@
 		42CD0EA4147D8FF60000361E /* Plane.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E17147D8FF50000361E /* Plane.h */; };
 		42CD0EA5147D8FF60000361E /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E19147D8FF50000361E /* Platform.h */; };
 		42CD0EA6147D8FF60000361E /* PlatformMacOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1A147D8FF50000361E /* PlatformMacOS.mm */; };
-		42CD0EA7147D8FF60000361E /* PlatformQNX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1B147D8FF50000361E /* PlatformQNX.cpp */; };
-		42CD0EA8147D8FF60000361E /* PlatformWin32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1C147D8FF50000361E /* PlatformWin32.cpp */; };
 		42CD0EA9147D8FF60000361E /* Properties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1D147D8FF50000361E /* Properties.cpp */; };
 		42CD0EAA147D8FF60000361E /* Properties.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E1E147D8FF50000361E /* Properties.h */; };
 		42CD0EAB147D8FF60000361E /* Quaternion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1F147D8FF50000361E /* Quaternion.cpp */; };
@@ -159,6 +154,156 @@
 		42CD0ECA147D8FF60000361E /* VertexFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E43147D8FF50000361E /* VertexFormat.h */; };
 		42CD0ECB147D8FF60000361E /* Viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E44147D8FF50000361E /* Viewport.cpp */; };
 		42CD0ECC147D8FF60000361E /* Viewport.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E45147D8FF50000361E /* Viewport.h */; };
+		5B04C52D14BFCFE100EB0071 /* Animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB1147D8FF50000361E /* Animation.cpp */; };
+		5B04C52E14BFCFE100EB0071 /* AnimationClip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB3147D8FF50000361E /* AnimationClip.cpp */; };
+		5B04C52F14BFCFE100EB0071 /* AnimationController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB5147D8FF50000361E /* AnimationController.cpp */; };
+		5B04C53014BFCFE100EB0071 /* AnimationTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB7147D8FF50000361E /* AnimationTarget.cpp */; };
+		5B04C53114BFCFE100EB0071 /* AnimationValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DB9147D8FF50000361E /* AnimationValue.cpp */; };
+		5B04C53214BFCFE100EB0071 /* AudioBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DBB147D8FF50000361E /* AudioBuffer.cpp */; };
+		5B04C53314BFCFE100EB0071 /* AudioController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DBD147D8FF50000361E /* AudioController.cpp */; };
+		5B04C53414BFCFE100EB0071 /* AudioListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DBF147D8FF50000361E /* AudioListener.cpp */; };
+		5B04C53514BFCFE100EB0071 /* AudioSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DC1147D8FF50000361E /* AudioSource.cpp */; };
+		5B04C53614BFCFE100EB0071 /* BoundingBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DC4147D8FF50000361E /* BoundingBox.cpp */; };
+		5B04C53714BFCFE100EB0071 /* BoundingSphere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DC7147D8FF50000361E /* BoundingSphere.cpp */; };
+		5B04C53814BFCFE100EB0071 /* Camera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DCA147D8FF50000361E /* Camera.cpp */; };
+		5B04C53914BFCFE100EB0071 /* Curve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DCC147D8FF50000361E /* Curve.cpp */; };
+		5B04C53A14BFCFE100EB0071 /* DebugNew.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DCE147D8FF50000361E /* DebugNew.cpp */; };
+		5B04C53B14BFCFE100EB0071 /* DepthStencilTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DD0147D8FF50000361E /* DepthStencilTarget.cpp */; };
+		5B04C53C14BFCFE100EB0071 /* Effect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DD2147D8FF50000361E /* Effect.cpp */; };
+		5B04C53D14BFCFE100EB0071 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DD4147D8FF50000361E /* FileSystem.cpp */; };
+		5B04C53E14BFCFE100EB0071 /* Font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DD6147D8FF50000361E /* Font.cpp */; };
+		5B04C53F14BFCFE100EB0071 /* FrameBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DD8147D8FF50000361E /* FrameBuffer.cpp */; };
+		5B04C54014BFCFE100EB0071 /* Frustum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDA147D8FF50000361E /* Frustum.cpp */; };
+		5B04C54114BFCFE100EB0071 /* Game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DDC147D8FF50000361E /* Game.cpp */; };
+		5B04C54514BFCFE100EB0071 /* Joint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DE4147D8FF50000361E /* Joint.cpp */; };
+		5B04C54614BFCFE100EB0071 /* Light.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DE6147D8FF50000361E /* Light.cpp */; };
+		5B04C54714BFCFE100EB0071 /* Material.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DE8147D8FF50000361E /* Material.cpp */; };
+		5B04C54814BFCFE100EB0071 /* MaterialParameter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DEA147D8FF50000361E /* MaterialParameter.cpp */; };
+		5B04C54914BFCFE100EB0071 /* Matrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DEC147D8FF50000361E /* Matrix.cpp */; };
+		5B04C54A14BFCFE100EB0071 /* Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DEF147D8FF50000361E /* Mesh.cpp */; };
+		5B04C54B14BFCFE100EB0071 /* MeshPart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF1147D8FF50000361E /* MeshPart.cpp */; };
+		5B04C54C14BFCFE100EB0071 /* MeshSkin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF3147D8FF50000361E /* MeshSkin.cpp */; };
+		5B04C54D14BFCFE100EB0071 /* Model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF5147D8FF50000361E /* Model.cpp */; };
+		5B04C54E14BFCFE100EB0071 /* Node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF7147D8FF50000361E /* Node.cpp */; };
+		5B04C54F14BFCFE100EB0071 /* Package.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DF9147D8FF50000361E /* Package.cpp */; };
+		5B04C55014BFCFE100EB0071 /* ParticleEmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFB147D8FF50000361E /* ParticleEmitter.cpp */; };
+		5B04C55114BFCFE100EB0071 /* Pass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFD147D8FF50000361E /* Pass.cpp */; };
+		5B04C55214BFCFE100EB0071 /* PhysicsConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0DFF147D8FF50000361E /* PhysicsConstraint.cpp */; };
+		5B04C55314BFCFE100EB0071 /* PhysicsController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E02147D8FF50000361E /* PhysicsController.cpp */; };
+		5B04C55414BFCFE100EB0071 /* PhysicsFixedConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E04147D8FF50000361E /* PhysicsFixedConstraint.cpp */; };
+		5B04C55514BFCFE100EB0071 /* PhysicsGenericConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E07147D8FF50000361E /* PhysicsGenericConstraint.cpp */; };
+		5B04C55614BFCFE100EB0071 /* PhysicsHingeConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E0A147D8FF50000361E /* PhysicsHingeConstraint.cpp */; };
+		5B04C55714BFCFE100EB0071 /* PhysicsMotionState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E0C147D8FF50000361E /* PhysicsMotionState.cpp */; };
+		5B04C55814BFCFE100EB0071 /* PhysicsRigidBody.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E0E147D8FF50000361E /* PhysicsRigidBody.cpp */; };
+		5B04C55914BFCFE100EB0071 /* PhysicsSocketConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E11147D8FF50000361E /* PhysicsSocketConstraint.cpp */; };
+		5B04C55A14BFCFE100EB0071 /* PhysicsSpringConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E13147D8FF50000361E /* PhysicsSpringConstraint.cpp */; };
+		5B04C55B14BFCFE100EB0071 /* Plane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E16147D8FF50000361E /* Plane.cpp */; };
+		5B04C55F14BFCFE100EB0071 /* Properties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1D147D8FF50000361E /* Properties.cpp */; };
+		5B04C56014BFCFE100EB0071 /* Quaternion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E1F147D8FF50000361E /* Quaternion.cpp */; };
+		5B04C56114BFCFE100EB0071 /* Ray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E22147D8FF50000361E /* Ray.cpp */; };
+		5B04C56214BFCFE100EB0071 /* Rectangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E25147D8FF50000361E /* Rectangle.cpp */; };
+		5B04C56314BFCFE100EB0071 /* Ref.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E27147D8FF50000361E /* Ref.cpp */; };
+		5B04C56414BFCFE100EB0071 /* RenderState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E29147D8FF50000361E /* RenderState.cpp */; };
+		5B04C56514BFCFE100EB0071 /* RenderTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E2B147D8FF50000361E /* RenderTarget.cpp */; };
+		5B04C56614BFCFE100EB0071 /* Scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E2D147D8FF50000361E /* Scene.cpp */; };
+		5B04C56714BFCFE100EB0071 /* SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E2F147D8FF50000361E /* SpriteBatch.cpp */; };
+		5B04C56814BFCFE100EB0071 /* Technique.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E31147D8FF50000361E /* Technique.cpp */; };
+		5B04C56914BFCFE100EB0071 /* Texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E33147D8FF50000361E /* Texture.cpp */; };
+		5B04C56A14BFCFE100EB0071 /* Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E35147D8FF50000361E /* Transform.cpp */; };
+		5B04C56B14BFCFE100EB0071 /* Vector2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E37147D8FF50000361E /* Vector2.cpp */; };
+		5B04C56C14BFCFE100EB0071 /* Vector3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E3A147D8FF50000361E /* Vector3.cpp */; };
+		5B04C56D14BFCFE100EB0071 /* Vector4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E3D147D8FF50000361E /* Vector4.cpp */; };
+		5B04C56E14BFCFE100EB0071 /* VertexAttributeBinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E40147D8FF50000361E /* VertexAttributeBinding.cpp */; };
+		5B04C56F14BFCFE100EB0071 /* VertexFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E42147D8FF50000361E /* VertexFormat.cpp */; };
+		5B04C57014BFCFE100EB0071 /* Viewport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42CD0E44147D8FF50000361E /* Viewport.cpp */; };
+		5B04C57114BFCFE100EB0071 /* SceneLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 428390971489D6E800E2B2F5 /* SceneLoader.cpp */; };
+		5B04C57214BFCFE100EB0071 /* Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4208DEE614A4079F00D3C511 /* Image.cpp */; };
+		5B04C57314BFCFE100EB0071 /* MeshBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4201818D14A41B18008C3F56 /* MeshBatch.cpp */; };
+		5B04C57514BFCFE100EB0071 /* libbullet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CD0DA6147D8EA80000361E /* libbullet.a */; };
+		5B04C57614BFCFE100EB0071 /* libogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CD0DA7147D8EA80000361E /* libogg.a */; };
+		5B04C57714BFCFE100EB0071 /* libvorbis.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CD0DA8147D8EA80000361E /* libvorbis.a */; };
+		5B04C57814BFCFE100EB0071 /* libvorbisenc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CD0DA9147D8EA80000361E /* libvorbisenc.a */; };
+		5B04C57914BFCFE100EB0071 /* libvorbisfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CD0DAA147D8EA80000361E /* libvorbisfile.a */; };
+		5B04C57A14BFCFE100EB0071 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CCD555146EC1EB00353661 /* libpng.a */; };
+		5B04C58114BFCFE100EB0071 /* Animation.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DB2147D8FF50000361E /* Animation.h */; };
+		5B04C58214BFCFE100EB0071 /* AnimationClip.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DB4147D8FF50000361E /* AnimationClip.h */; };
+		5B04C58314BFCFE100EB0071 /* AnimationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DB6147D8FF50000361E /* AnimationController.h */; };
+		5B04C58414BFCFE100EB0071 /* AnimationTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DB8147D8FF50000361E /* AnimationTarget.h */; };
+		5B04C58514BFCFE100EB0071 /* AnimationValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DBA147D8FF50000361E /* AnimationValue.h */; };
+		5B04C58614BFCFE100EB0071 /* AudioBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DBC147D8FF50000361E /* AudioBuffer.h */; };
+		5B04C58714BFCFE100EB0071 /* AudioController.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DBE147D8FF50000361E /* AudioController.h */; };
+		5B04C58814BFCFE100EB0071 /* AudioListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DC0147D8FF50000361E /* AudioListener.h */; };
+		5B04C58914BFCFE100EB0071 /* AudioSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DC2147D8FF50000361E /* AudioSource.h */; };
+		5B04C58A14BFCFE100EB0071 /* Base.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DC3147D8FF50000361E /* Base.h */; };
+		5B04C58B14BFCFE100EB0071 /* BoundingBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DC5147D8FF50000361E /* BoundingBox.h */; };
+		5B04C58C14BFCFE100EB0071 /* BoundingSphere.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DC8147D8FF50000361E /* BoundingSphere.h */; };
+		5B04C58D14BFCFE100EB0071 /* Camera.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DCB147D8FF50000361E /* Camera.h */; };
+		5B04C58E14BFCFE100EB0071 /* Curve.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DCD147D8FF50000361E /* Curve.h */; };
+		5B04C58F14BFCFE100EB0071 /* DebugNew.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DCF147D8FF50000361E /* DebugNew.h */; };
+		5B04C59014BFCFE100EB0071 /* DepthStencilTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DD1147D8FF50000361E /* DepthStencilTarget.h */; };
+		5B04C59114BFCFE100EB0071 /* Effect.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DD3147D8FF50000361E /* Effect.h */; };
+		5B04C59214BFCFE100EB0071 /* FileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DD5147D8FF50000361E /* FileSystem.h */; };
+		5B04C59314BFCFE100EB0071 /* Font.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DD7147D8FF50000361E /* Font.h */; };
+		5B04C59414BFCFE100EB0071 /* FrameBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DD9147D8FF50000361E /* FrameBuffer.h */; };
+		5B04C59514BFCFE100EB0071 /* Frustum.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DDB147D8FF50000361E /* Frustum.h */; };
+		5B04C59614BFCFE100EB0071 /* Game.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DDD147D8FF50000361E /* Game.h */; };
+		5B04C59714BFCFE100EB0071 /* gameplay.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE1147D8FF50000361E /* gameplay.h */; };
+		5B04C59814BFCFE100EB0071 /* Joint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE5147D8FF50000361E /* Joint.h */; };
+		5B04C59914BFCFE100EB0071 /* Light.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE7147D8FF50000361E /* Light.h */; };
+		5B04C59A14BFCFE100EB0071 /* Material.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DE9147D8FF50000361E /* Material.h */; };
+		5B04C59B14BFCFE100EB0071 /* MaterialParameter.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DEB147D8FF50000361E /* MaterialParameter.h */; };
+		5B04C59C14BFCFE100EB0071 /* Matrix.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DED147D8FF50000361E /* Matrix.h */; };
+		5B04C59D14BFCFE100EB0071 /* Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF0147D8FF50000361E /* Mesh.h */; };
+		5B04C59E14BFCFE100EB0071 /* MeshPart.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF2147D8FF50000361E /* MeshPart.h */; };
+		5B04C59F14BFCFE100EB0071 /* MeshSkin.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF4147D8FF50000361E /* MeshSkin.h */; };
+		5B04C5A014BFCFE100EB0071 /* Model.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF6147D8FF50000361E /* Model.h */; };
+		5B04C5A114BFCFE100EB0071 /* Node.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DF8147D8FF50000361E /* Node.h */; };
+		5B04C5A214BFCFE100EB0071 /* Package.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFA147D8FF50000361E /* Package.h */; };
+		5B04C5A314BFCFE100EB0071 /* ParticleEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFC147D8FF50000361E /* ParticleEmitter.h */; };
+		5B04C5A414BFCFE100EB0071 /* Pass.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0DFE147D8FF50000361E /* Pass.h */; };
+		5B04C5A514BFCFE100EB0071 /* PhysicsConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E00147D8FF50000361E /* PhysicsConstraint.h */; };
+		5B04C5A614BFCFE100EB0071 /* PhysicsController.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E03147D8FF50000361E /* PhysicsController.h */; };
+		5B04C5A714BFCFE100EB0071 /* PhysicsFixedConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E05147D8FF50000361E /* PhysicsFixedConstraint.h */; };
+		5B04C5A814BFCFE100EB0071 /* PhysicsGenericConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E08147D8FF50000361E /* PhysicsGenericConstraint.h */; };
+		5B04C5A914BFCFE100EB0071 /* PhysicsHingeConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E0B147D8FF50000361E /* PhysicsHingeConstraint.h */; };
+		5B04C5AA14BFCFE100EB0071 /* PhysicsMotionState.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E0D147D8FF50000361E /* PhysicsMotionState.h */; };
+		5B04C5AB14BFCFE100EB0071 /* PhysicsRigidBody.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E0F147D8FF50000361E /* PhysicsRigidBody.h */; };
+		5B04C5AC14BFCFE100EB0071 /* PhysicsSocketConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E12147D8FF50000361E /* PhysicsSocketConstraint.h */; };
+		5B04C5AD14BFCFE100EB0071 /* PhysicsSpringConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E14147D8FF50000361E /* PhysicsSpringConstraint.h */; };
+		5B04C5AE14BFCFE100EB0071 /* Plane.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E17147D8FF50000361E /* Plane.h */; };
+		5B04C5AF14BFCFE100EB0071 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E19147D8FF50000361E /* Platform.h */; };
+		5B04C5B014BFCFE100EB0071 /* Properties.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E1E147D8FF50000361E /* Properties.h */; };
+		5B04C5B114BFCFE100EB0071 /* Quaternion.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E20147D8FF50000361E /* Quaternion.h */; };
+		5B04C5B214BFCFE100EB0071 /* Ray.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E23147D8FF50000361E /* Ray.h */; };
+		5B04C5B314BFCFE100EB0071 /* Rectangle.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E26147D8FF50000361E /* Rectangle.h */; };
+		5B04C5B414BFCFE100EB0071 /* Ref.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E28147D8FF50000361E /* Ref.h */; };
+		5B04C5B514BFCFE100EB0071 /* RenderState.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E2A147D8FF50000361E /* RenderState.h */; };
+		5B04C5B614BFCFE100EB0071 /* RenderTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E2C147D8FF50000361E /* RenderTarget.h */; };
+		5B04C5B714BFCFE100EB0071 /* Scene.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E2E147D8FF50000361E /* Scene.h */; };
+		5B04C5B814BFCFE100EB0071 /* SpriteBatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E30147D8FF50000361E /* SpriteBatch.h */; };
+		5B04C5B914BFCFE100EB0071 /* Technique.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E32147D8FF50000361E /* Technique.h */; };
+		5B04C5BA14BFCFE100EB0071 /* Texture.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E34147D8FF50000361E /* Texture.h */; };
+		5B04C5BB14BFCFE100EB0071 /* Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E36147D8FF50000361E /* Transform.h */; };
+		5B04C5BC14BFCFE100EB0071 /* Vector2.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E38147D8FF50000361E /* Vector2.h */; };
+		5B04C5BD14BFCFE100EB0071 /* Vector3.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E3B147D8FF50000361E /* Vector3.h */; };
+		5B04C5BE14BFCFE100EB0071 /* Vector4.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E3E147D8FF50000361E /* Vector4.h */; };
+		5B04C5BF14BFCFE100EB0071 /* VertexAttributeBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E41147D8FF50000361E /* VertexAttributeBinding.h */; };
+		5B04C5C014BFCFE100EB0071 /* VertexFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E43147D8FF50000361E /* VertexFormat.h */; };
+		5B04C5C114BFCFE100EB0071 /* Viewport.h in Headers */ = {isa = PBXBuildFile; fileRef = 42CD0E45147D8FF50000361E /* Viewport.h */; };
+		5B04C5C214BFCFE100EB0071 /* SceneLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 428390981489D6E800E2B2F5 /* SceneLoader.h */; };
+		5B04C5C314BFCFE100EB0071 /* Image.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEE714A4079F00D3C511 /* Image.h */; };
+		5B04C5C414BFCFE100EB0071 /* Keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEEB14A407B900D3C511 /* Keyboard.h */; };
+		5B04C5C514BFCFE100EB0071 /* Touch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4208DEED14A407D500D3C511 /* Touch.h */; };
+		5B04C5C614BFCFE100EB0071 /* MeshBatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 4201818E14A41B18008C3F56 /* MeshBatch.h */; };
+		5B04C5CD14BFD48500EB0071 /* gameplay-main-ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B04C5CB14BFD48500EB0071 /* gameplay-main-ios.mm */; };
+		5B04C5CE14BFD48500EB0071 /* PlatformiOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B04C5CC14BFD48500EB0071 /* PlatformiOS.mm */; };
+		5B04C5F614BFE50100EB0071 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B04C5F514BFE50100EB0071 /* UIKit.framework */; };
+		5B04C5F814BFE50B00EB0071 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B04C5F714BFE50B00EB0071 /* QuartzCore.framework */; };
+		5B04C5FA14BFE51100EB0071 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B04C5F914BFE51000EB0071 /* OpenGLES.framework */; };
+		5B04C5FC14BFE51600EB0071 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B04C5FB14BFE51600EB0071 /* OpenAL.framework */; };
+		5B5ADCE314C22DF900AC6109 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B5ADCE214C22DF900AC6109 /* libz.dylib */; };
+		5B5ADCE514C22E1F00AC6109 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B5ADCE414C22E1F00AC6109 /* libz.dylib */; };
+		5B5ADD2F14C2439700AC6109 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B5ADD2E14C2439700AC6109 /* Foundation.framework */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
@@ -179,7 +324,6 @@
 		4299EFA8146AC94300FF4A73 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = SDKs/MacOSX10.7.sdk/System/Library/Frameworks/OpenGL.framework; sourceTree = DEVELOPER_DIR; };
 		4299EFAA146AC94B00FF4A73 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = SDKs/MacOSX10.7.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; };
 		42C932AF14919FD10098216A /* Game.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Game.inl; path = src/Game.inl; sourceTree = SOURCE_ROOT; };
-		42CCD553146EC1DD00353661 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = SDKs/MacOSX10.7.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
 		42CCD555146EC1EB00353661 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/macos/libpng.a"; sourceTree = "<group>"; };
 		42CD0DA6147D8EA80000361E /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "../external-deps/bullet/lib/macos/libbullet.a"; sourceTree = "<group>"; };
 		42CD0DA7147D8EA80000361E /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "../external-deps/oggvorbis/lib/macos/libogg.a"; sourceTree = "<group>"; };
@@ -333,6 +477,23 @@
 		42CD0E43147D8FF50000361E /* VertexFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VertexFormat.h; path = src/VertexFormat.h; sourceTree = SOURCE_ROOT; };
 		42CD0E44147D8FF50000361E /* Viewport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Viewport.cpp; path = src/Viewport.cpp; sourceTree = SOURCE_ROOT; };
 		42CD0E45147D8FF50000361E /* Viewport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Viewport.h; path = src/Viewport.h; sourceTree = SOURCE_ROOT; };
+		5B04C5CA14BFCFE100EB0071 /* libgameplay.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libgameplay.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		5B04C5CB14BFD48500EB0071 /* gameplay-main-ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "gameplay-main-ios.mm"; path = "src/gameplay-main-ios.mm"; sourceTree = SOURCE_ROOT; };
+		5B04C5CC14BFD48500EB0071 /* PlatformiOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatformiOS.mm; path = src/PlatformiOS.mm; sourceTree = SOURCE_ROOT; };
+		5B04C5F514BFE50100EB0071 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+		5B04C5F714BFE50B00EB0071 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
+		5B04C5F914BFE51000EB0071 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; };
+		5B04C5FB14BFE51600EB0071 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; };
+		5B43D17914C3497B008A5D9D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
+		5B5ADCE214C22DF900AC6109 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = SDKs/MacOSX10.7.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
+		5B5ADCE414C22E1F00AC6109 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; };
+		5B5ADD2E14C2439700AC6109 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+		5B5DB92D14C25B7B007755DB /* libbullet.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbullet.a; path = "../external-deps/bullet/lib/ios/i386/libbullet.a"; sourceTree = "<group>"; };
+		5B5DB92F14C25B94007755DB /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "../external-deps/libpng/lib/ios/armv7/libpng.a"; sourceTree = "<group>"; };
+		5B5DB93114C25BA5007755DB /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libogg.a"; sourceTree = "<group>"; };
+		5B5DB93214C25BA5007755DB /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbis.a"; sourceTree = "<group>"; };
+		5B5DB93314C25BA5007755DB /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbisenc.a"; sourceTree = "<group>"; };
+		5B5DB93414C25BA5007755DB /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "../external-deps/oggvorbis/lib/ios/armv7/libvorbisfile.a"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -340,13 +501,13 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				5B5ADCE314C22DF900AC6109 /* libz.dylib in Frameworks */,
 				42CD0DAB147D8EA80000361E /* libbullet.a in Frameworks */,
 				42CD0DAC147D8EA80000361E /* libogg.a in Frameworks */,
 				42CD0DAD147D8EA80000361E /* libvorbis.a in Frameworks */,
 				42CD0DAE147D8EA80000361E /* libvorbisenc.a in Frameworks */,
 				42CD0DAF147D8EA80000361E /* libvorbisfile.a in Frameworks */,
 				42CCD556146EC1EB00353661 /* libpng.a in Frameworks */,
-				42CCD554146EC1DD00353661 /* libz.dylib in Frameworks */,
 				4234D99E14686C52003031B3 /* Cocoa.framework in Frameworks */,
 				4220A6E8146B122B00CAEB3A /* QuartzCore.framework in Frameworks */,
 				4299EFA9146AC94300FF4A73 /* OpenGL.framework in Frameworks */,
@@ -354,6 +515,25 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		5B04C57414BFCFE100EB0071 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5B5ADD2F14C2439700AC6109 /* Foundation.framework in Frameworks */,
+				5B5ADCE514C22E1F00AC6109 /* libz.dylib in Frameworks */,
+				5B04C5FC14BFE51600EB0071 /* OpenAL.framework in Frameworks */,
+				5B04C5FA14BFE51100EB0071 /* OpenGLES.framework in Frameworks */,
+				5B04C5F814BFE50B00EB0071 /* QuartzCore.framework in Frameworks */,
+				5B04C5F614BFE50100EB0071 /* UIKit.framework in Frameworks */,
+				5B04C57514BFCFE100EB0071 /* libbullet.a in Frameworks */,
+				5B04C57614BFCFE100EB0071 /* libogg.a in Frameworks */,
+				5B04C57714BFCFE100EB0071 /* libvorbis.a in Frameworks */,
+				5B04C57814BFCFE100EB0071 /* libvorbisenc.a in Frameworks */,
+				5B04C57914BFCFE100EB0071 /* libvorbisfile.a in Frameworks */,
+				5B04C57A14BFCFE100EB0071 /* libpng.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
@@ -371,11 +551,86 @@
 			isa = PBXGroup;
 			children = (
 				4234D99A14686C52003031B3 /* libgameplay.a */,
+				5B04C5CA14BFCFE100EB0071 /* libgameplay.a */,
 			);
 			name = Products;
 			sourceTree = "<group>";
 		};
 		4234D9A314686C52003031B3 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				5B43D19714C35347008A5D9D /* gameplay */,
+				5B43D19614C35344008A5D9D /* platform */,
+			);
+			name = src;
+			path = gameplay;
+			sourceTree = "<group>";
+		};
+		427D4F42147DC8DE0076760E /* Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				42CD0DA6147D8EA80000361E /* libbullet.a */,
+				42CD0DA7147D8EA80000361E /* libogg.a */,
+				42CD0DA8147D8EA80000361E /* libvorbis.a */,
+				42CD0DA9147D8EA80000361E /* libvorbisenc.a */,
+				42CD0DAA147D8EA80000361E /* libvorbisfile.a */,
+				42CCD555146EC1EB00353661 /* libpng.a */,
+				5B5ADCE114C22DC700AC6109 /* Mac OS X */,
+				5B5ADCE014C22DBE00AC6109 /* iOS */,
+			);
+			name = Libraries;
+			sourceTree = "<group>";
+		};
+		42CCD4AF146D811D00353661 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				5B04C5FE14BFE52F00EB0071 /* Mac OS X */,
+				5B04C5FD14BFE52300EB0071 /* iOS */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		5B04C5FD14BFE52300EB0071 /* iOS */ = {
+			isa = PBXGroup;
+			children = (
+				5B43D17914C3497B008A5D9D /* CoreGraphics.framework */,
+				5B5ADD2E14C2439700AC6109 /* Foundation.framework */,
+				5B04C5FB14BFE51600EB0071 /* OpenAL.framework */,
+				5B04C5F914BFE51000EB0071 /* OpenGLES.framework */,
+				5B04C5F714BFE50B00EB0071 /* QuartzCore.framework */,
+				5B04C5F514BFE50100EB0071 /* UIKit.framework */,
+			);
+			name = iOS;
+			sourceTree = "<group>";
+		};
+		5B04C5FE14BFE52F00EB0071 /* Mac OS X */ = {
+			isa = PBXGroup;
+			children = (
+				4234D99D14686C52003031B3 /* Cocoa.framework */,
+				4220A6E7146B122B00CAEB3A /* QuartzCore.framework */,
+				4299EFA8146AC94300FF4A73 /* OpenGL.framework */,
+				4299EFAA146AC94B00FF4A73 /* OpenAL.framework */,
+			);
+			name = "Mac OS X";
+			sourceTree = "<group>";
+		};
+		5B43D19614C35344008A5D9D /* platform */ = {
+			isa = PBXGroup;
+			children = (
+				42CD0DE0147D8FF50000361E /* gameplay-main-win32.cpp */,
+				42CD0DDE147D8FF50000361E /* gameplay-main-macos.mm */,
+				5B04C5CB14BFD48500EB0071 /* gameplay-main-ios.mm */,
+				42CD0DDF147D8FF50000361E /* gameplay-main-qnx.cpp */,
+				42CD0E19147D8FF50000361E /* Platform.h */,
+				42CD0E1C147D8FF50000361E /* PlatformWin32.cpp */,
+				42CD0E1A147D8FF50000361E /* PlatformMacOS.mm */,
+				5B04C5CC14BFD48500EB0071 /* PlatformiOS.mm */,
+				42CD0E1B147D8FF50000361E /* PlatformQNX.cpp */,
+			);
+			name = platform;
+			sourceTree = "<group>";
+		};
+		5B43D19714C35347008A5D9D /* gameplay */ = {
 			isa = PBXGroup;
 			children = (
 				42CD0DB1147D8FF50000361E /* Animation.cpp */,
@@ -425,9 +680,6 @@
 				42CD0DDC147D8FF50000361E /* Game.cpp */,
 				42CD0DDD147D8FF50000361E /* Game.h */,
 				42C932AF14919FD10098216A /* Game.inl */,
-				42CD0DDE147D8FF50000361E /* gameplay-main-macos.mm */,
-				42CD0DDF147D8FF50000361E /* gameplay-main-qnx.cpp */,
-				42CD0DE0147D8FF50000361E /* gameplay-main-win32.cpp */,
 				42CD0DE1147D8FF50000361E /* gameplay.h */,
 				4208DEE614A4079F00D3C511 /* Image.cpp */,
 				4208DEE714A4079F00D3C511 /* Image.h */,
@@ -489,10 +741,6 @@
 				42CD0E16147D8FF50000361E /* Plane.cpp */,
 				42CD0E17147D8FF50000361E /* Plane.h */,
 				42CD0E18147D8FF50000361E /* Plane.inl */,
-				42CD0E19147D8FF50000361E /* Platform.h */,
-				42CD0E1A147D8FF50000361E /* PlatformMacOS.mm */,
-				42CD0E1B147D8FF50000361E /* PlatformQNX.cpp */,
-				42CD0E1C147D8FF50000361E /* PlatformWin32.cpp */,
 				42CD0E1D147D8FF50000361E /* Properties.cpp */,
 				42CD0E1E147D8FF50000361E /* Properties.h */,
 				42CD0E1F147D8FF50000361E /* Quaternion.cpp */,
@@ -538,33 +786,29 @@
 				42CD0E44147D8FF50000361E /* Viewport.cpp */,
 				42CD0E45147D8FF50000361E /* Viewport.h */,
 			);
-			name = src;
-			path = gameplay;
+			name = gameplay;
 			sourceTree = "<group>";
 		};
-		427D4F42147DC8DE0076760E /* Libraries */ = {
+		5B5ADCE014C22DBE00AC6109 /* iOS */ = {
 			isa = PBXGroup;
 			children = (
-				42CD0DA6147D8EA80000361E /* libbullet.a */,
-				42CD0DA7147D8EA80000361E /* libogg.a */,
-				42CD0DA8147D8EA80000361E /* libvorbis.a */,
-				42CD0DA9147D8EA80000361E /* libvorbisenc.a */,
-				42CD0DAA147D8EA80000361E /* libvorbisfile.a */,
-				42CCD555146EC1EB00353661 /* libpng.a */,
-				42CCD553146EC1DD00353661 /* libz.dylib */,
+				5B5DB93114C25BA5007755DB /* libogg.a */,
+				5B5DB93214C25BA5007755DB /* libvorbis.a */,
+				5B5DB93314C25BA5007755DB /* libvorbisenc.a */,
+				5B5DB93414C25BA5007755DB /* libvorbisfile.a */,
+				5B5DB92F14C25B94007755DB /* libpng.a */,
+				5B5DB92D14C25B7B007755DB /* libbullet.a */,
+				5B5ADCE414C22E1F00AC6109 /* libz.dylib */,
 			);
-			name = Libraries;
+			name = iOS;
 			sourceTree = "<group>";
 		};
-		42CCD4AF146D811D00353661 /* Frameworks */ = {
+		5B5ADCE114C22DC700AC6109 /* Mac OS X */ = {
 			isa = PBXGroup;
 			children = (
-				4234D99D14686C52003031B3 /* Cocoa.framework */,
-				4220A6E7146B122B00CAEB3A /* QuartzCore.framework */,
-				4299EFA8146AC94300FF4A73 /* OpenGL.framework */,
-				4299EFAA146AC94B00FF4A73 /* OpenAL.framework */,
+				5B5ADCE214C22DF900AC6109 /* libz.dylib */,
 			);
-			name = Frameworks;
+			name = "Mac OS X";
 			sourceTree = "<group>";
 		};
 /* End PBXGroup section */
@@ -647,12 +891,89 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		5B04C58014BFCFE100EB0071 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5B04C58114BFCFE100EB0071 /* Animation.h in Headers */,
+				5B04C58214BFCFE100EB0071 /* AnimationClip.h in Headers */,
+				5B04C58314BFCFE100EB0071 /* AnimationController.h in Headers */,
+				5B04C58414BFCFE100EB0071 /* AnimationTarget.h in Headers */,
+				5B04C58514BFCFE100EB0071 /* AnimationValue.h in Headers */,
+				5B04C58614BFCFE100EB0071 /* AudioBuffer.h in Headers */,
+				5B04C58714BFCFE100EB0071 /* AudioController.h in Headers */,
+				5B04C58814BFCFE100EB0071 /* AudioListener.h in Headers */,
+				5B04C58914BFCFE100EB0071 /* AudioSource.h in Headers */,
+				5B04C58A14BFCFE100EB0071 /* Base.h in Headers */,
+				5B04C58B14BFCFE100EB0071 /* BoundingBox.h in Headers */,
+				5B04C58C14BFCFE100EB0071 /* BoundingSphere.h in Headers */,
+				5B04C58D14BFCFE100EB0071 /* Camera.h in Headers */,
+				5B04C58E14BFCFE100EB0071 /* Curve.h in Headers */,
+				5B04C58F14BFCFE100EB0071 /* DebugNew.h in Headers */,
+				5B04C59014BFCFE100EB0071 /* DepthStencilTarget.h in Headers */,
+				5B04C59114BFCFE100EB0071 /* Effect.h in Headers */,
+				5B04C59214BFCFE100EB0071 /* FileSystem.h in Headers */,
+				5B04C59314BFCFE100EB0071 /* Font.h in Headers */,
+				5B04C59414BFCFE100EB0071 /* FrameBuffer.h in Headers */,
+				5B04C59514BFCFE100EB0071 /* Frustum.h in Headers */,
+				5B04C59614BFCFE100EB0071 /* Game.h in Headers */,
+				5B04C59714BFCFE100EB0071 /* gameplay.h in Headers */,
+				5B04C59814BFCFE100EB0071 /* Joint.h in Headers */,
+				5B04C59914BFCFE100EB0071 /* Light.h in Headers */,
+				5B04C59A14BFCFE100EB0071 /* Material.h in Headers */,
+				5B04C59B14BFCFE100EB0071 /* MaterialParameter.h in Headers */,
+				5B04C59C14BFCFE100EB0071 /* Matrix.h in Headers */,
+				5B04C59D14BFCFE100EB0071 /* Mesh.h in Headers */,
+				5B04C59E14BFCFE100EB0071 /* MeshPart.h in Headers */,
+				5B04C59F14BFCFE100EB0071 /* MeshSkin.h in Headers */,
+				5B04C5A014BFCFE100EB0071 /* Model.h in Headers */,
+				5B04C5A114BFCFE100EB0071 /* Node.h in Headers */,
+				5B04C5A214BFCFE100EB0071 /* Package.h in Headers */,
+				5B04C5A314BFCFE100EB0071 /* ParticleEmitter.h in Headers */,
+				5B04C5A414BFCFE100EB0071 /* Pass.h in Headers */,
+				5B04C5A514BFCFE100EB0071 /* PhysicsConstraint.h in Headers */,
+				5B04C5A614BFCFE100EB0071 /* PhysicsController.h in Headers */,
+				5B04C5A714BFCFE100EB0071 /* PhysicsFixedConstraint.h in Headers */,
+				5B04C5A814BFCFE100EB0071 /* PhysicsGenericConstraint.h in Headers */,
+				5B04C5A914BFCFE100EB0071 /* PhysicsHingeConstraint.h in Headers */,
+				5B04C5AA14BFCFE100EB0071 /* PhysicsMotionState.h in Headers */,
+				5B04C5AB14BFCFE100EB0071 /* PhysicsRigidBody.h in Headers */,
+				5B04C5AC14BFCFE100EB0071 /* PhysicsSocketConstraint.h in Headers */,
+				5B04C5AD14BFCFE100EB0071 /* PhysicsSpringConstraint.h in Headers */,
+				5B04C5AE14BFCFE100EB0071 /* Plane.h in Headers */,
+				5B04C5AF14BFCFE100EB0071 /* Platform.h in Headers */,
+				5B04C5B014BFCFE100EB0071 /* Properties.h in Headers */,
+				5B04C5B114BFCFE100EB0071 /* Quaternion.h in Headers */,
+				5B04C5B214BFCFE100EB0071 /* Ray.h in Headers */,
+				5B04C5B314BFCFE100EB0071 /* Rectangle.h in Headers */,
+				5B04C5B414BFCFE100EB0071 /* Ref.h in Headers */,
+				5B04C5B514BFCFE100EB0071 /* RenderState.h in Headers */,
+				5B04C5B614BFCFE100EB0071 /* RenderTarget.h in Headers */,
+				5B04C5B714BFCFE100EB0071 /* Scene.h in Headers */,
+				5B04C5B814BFCFE100EB0071 /* SpriteBatch.h in Headers */,
+				5B04C5B914BFCFE100EB0071 /* Technique.h in Headers */,
+				5B04C5BA14BFCFE100EB0071 /* Texture.h in Headers */,
+				5B04C5BB14BFCFE100EB0071 /* Transform.h in Headers */,
+				5B04C5BC14BFCFE100EB0071 /* Vector2.h in Headers */,
+				5B04C5BD14BFCFE100EB0071 /* Vector3.h in Headers */,
+				5B04C5BE14BFCFE100EB0071 /* Vector4.h in Headers */,
+				5B04C5BF14BFCFE100EB0071 /* VertexAttributeBinding.h in Headers */,
+				5B04C5C014BFCFE100EB0071 /* VertexFormat.h in Headers */,
+				5B04C5C114BFCFE100EB0071 /* Viewport.h in Headers */,
+				5B04C5C214BFCFE100EB0071 /* SceneLoader.h in Headers */,
+				5B04C5C314BFCFE100EB0071 /* Image.h in Headers */,
+				5B04C5C414BFCFE100EB0071 /* Keyboard.h in Headers */,
+				5B04C5C514BFCFE100EB0071 /* Touch.h in Headers */,
+				5B04C5C614BFCFE100EB0071 /* MeshBatch.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
-		4234D99914686C52003031B3 /* gameplay */ = {
+		4234D99914686C52003031B3 /* gameplay-macos */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = 4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay" */;
+			buildConfigurationList = 4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay-macos" */;
 			buildPhases = (
 				4234D99614686C52003031B3 /* Sources */,
 				4234D99714686C52003031B3 /* Frameworks */,
@@ -662,11 +983,28 @@
 			);
 			dependencies = (
 			);
-			name = gameplay;
+			name = "gameplay-macos";
 			productName = gameplay;
 			productReference = 4234D99A14686C52003031B3 /* libgameplay.a */;
 			productType = "com.apple.product-type.library.static";
 		};
+		5B04C52B14BFCFE100EB0071 /* gameplay-ios */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 5B04C5C714BFCFE100EB0071 /* Build configuration list for PBXNativeTarget "gameplay-ios" */;
+			buildPhases = (
+				5B04C52C14BFCFE100EB0071 /* Sources */,
+				5B04C57414BFCFE100EB0071 /* Frameworks */,
+				5B04C58014BFCFE100EB0071 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "gameplay-ios";
+			productName = gameplay;
+			productReference = 5B04C5CA14BFCFE100EB0071 /* libgameplay.a */;
+			productType = "com.apple.product-type.library.static";
+		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
@@ -687,7 +1025,8 @@
 			projectDirPath = "";
 			projectRoot = "";
 			targets = (
-				4234D99914686C52003031B3 /* gameplay */,
+				4234D99914686C52003031B3 /* gameplay-macos */,
+				5B04C52B14BFCFE100EB0071 /* gameplay-ios */,
 			);
 		};
 /* End PBXProject section */
@@ -719,8 +1058,6 @@
 				42CD0E6D147D8FF60000361E /* Frustum.cpp in Sources */,
 				42CD0E6F147D8FF60000361E /* Game.cpp in Sources */,
 				42CD0E71147D8FF60000361E /* gameplay-main-macos.mm in Sources */,
-				42CD0E72147D8FF60000361E /* gameplay-main-qnx.cpp in Sources */,
-				42CD0E73147D8FF60000361E /* gameplay-main-win32.cpp in Sources */,
 				42CD0E77147D8FF60000361E /* Joint.cpp in Sources */,
 				42CD0E79147D8FF60000361E /* Light.cpp in Sources */,
 				42CD0E7B147D8FF60000361E /* Material.cpp in Sources */,
@@ -745,8 +1082,6 @@
 				42CD0EA1147D8FF60000361E /* PhysicsSpringConstraint.cpp in Sources */,
 				42CD0EA3147D8FF60000361E /* Plane.cpp in Sources */,
 				42CD0EA6147D8FF60000361E /* PlatformMacOS.mm in Sources */,
-				42CD0EA7147D8FF60000361E /* PlatformQNX.cpp in Sources */,
-				42CD0EA8147D8FF60000361E /* PlatformWin32.cpp in Sources */,
 				42CD0EA9147D8FF60000361E /* Properties.cpp in Sources */,
 				42CD0EAB147D8FF60000361E /* Quaternion.cpp in Sources */,
 				42CD0EAD147D8FF60000361E /* Ray.cpp in Sources */,
@@ -771,18 +1106,96 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		5B04C52C14BFCFE100EB0071 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5B04C52D14BFCFE100EB0071 /* Animation.cpp in Sources */,
+				5B04C52E14BFCFE100EB0071 /* AnimationClip.cpp in Sources */,
+				5B04C52F14BFCFE100EB0071 /* AnimationController.cpp in Sources */,
+				5B04C53014BFCFE100EB0071 /* AnimationTarget.cpp in Sources */,
+				5B04C53114BFCFE100EB0071 /* AnimationValue.cpp in Sources */,
+				5B04C53214BFCFE100EB0071 /* AudioBuffer.cpp in Sources */,
+				5B04C53314BFCFE100EB0071 /* AudioController.cpp in Sources */,
+				5B04C53414BFCFE100EB0071 /* AudioListener.cpp in Sources */,
+				5B04C53514BFCFE100EB0071 /* AudioSource.cpp in Sources */,
+				5B04C53614BFCFE100EB0071 /* BoundingBox.cpp in Sources */,
+				5B04C53714BFCFE100EB0071 /* BoundingSphere.cpp in Sources */,
+				5B04C53814BFCFE100EB0071 /* Camera.cpp in Sources */,
+				5B04C53914BFCFE100EB0071 /* Curve.cpp in Sources */,
+				5B04C53A14BFCFE100EB0071 /* DebugNew.cpp in Sources */,
+				5B04C53B14BFCFE100EB0071 /* DepthStencilTarget.cpp in Sources */,
+				5B04C53C14BFCFE100EB0071 /* Effect.cpp in Sources */,
+				5B04C53D14BFCFE100EB0071 /* FileSystem.cpp in Sources */,
+				5B04C53E14BFCFE100EB0071 /* Font.cpp in Sources */,
+				5B04C53F14BFCFE100EB0071 /* FrameBuffer.cpp in Sources */,
+				5B04C54014BFCFE100EB0071 /* Frustum.cpp in Sources */,
+				5B04C54114BFCFE100EB0071 /* Game.cpp in Sources */,
+				5B04C54514BFCFE100EB0071 /* Joint.cpp in Sources */,
+				5B04C54614BFCFE100EB0071 /* Light.cpp in Sources */,
+				5B04C54714BFCFE100EB0071 /* Material.cpp in Sources */,
+				5B04C54814BFCFE100EB0071 /* MaterialParameter.cpp in Sources */,
+				5B04C54914BFCFE100EB0071 /* Matrix.cpp in Sources */,
+				5B04C54A14BFCFE100EB0071 /* Mesh.cpp in Sources */,
+				5B04C54B14BFCFE100EB0071 /* MeshPart.cpp in Sources */,
+				5B04C54C14BFCFE100EB0071 /* MeshSkin.cpp in Sources */,
+				5B04C54D14BFCFE100EB0071 /* Model.cpp in Sources */,
+				5B04C54E14BFCFE100EB0071 /* Node.cpp in Sources */,
+				5B04C54F14BFCFE100EB0071 /* Package.cpp in Sources */,
+				5B04C55014BFCFE100EB0071 /* ParticleEmitter.cpp in Sources */,
+				5B04C55114BFCFE100EB0071 /* Pass.cpp in Sources */,
+				5B04C55214BFCFE100EB0071 /* PhysicsConstraint.cpp in Sources */,
+				5B04C55314BFCFE100EB0071 /* PhysicsController.cpp in Sources */,
+				5B04C55414BFCFE100EB0071 /* PhysicsFixedConstraint.cpp in Sources */,
+				5B04C55514BFCFE100EB0071 /* PhysicsGenericConstraint.cpp in Sources */,
+				5B04C55614BFCFE100EB0071 /* PhysicsHingeConstraint.cpp in Sources */,
+				5B04C55714BFCFE100EB0071 /* PhysicsMotionState.cpp in Sources */,
+				5B04C55814BFCFE100EB0071 /* PhysicsRigidBody.cpp in Sources */,
+				5B04C55914BFCFE100EB0071 /* PhysicsSocketConstraint.cpp in Sources */,
+				5B04C55A14BFCFE100EB0071 /* PhysicsSpringConstraint.cpp in Sources */,
+				5B04C55B14BFCFE100EB0071 /* Plane.cpp in Sources */,
+				5B04C55F14BFCFE100EB0071 /* Properties.cpp in Sources */,
+				5B04C56014BFCFE100EB0071 /* Quaternion.cpp in Sources */,
+				5B04C56114BFCFE100EB0071 /* Ray.cpp in Sources */,
+				5B04C56214BFCFE100EB0071 /* Rectangle.cpp in Sources */,
+				5B04C56314BFCFE100EB0071 /* Ref.cpp in Sources */,
+				5B04C56414BFCFE100EB0071 /* RenderState.cpp in Sources */,
+				5B04C56514BFCFE100EB0071 /* RenderTarget.cpp in Sources */,
+				5B04C56614BFCFE100EB0071 /* Scene.cpp in Sources */,
+				5B04C56714BFCFE100EB0071 /* SpriteBatch.cpp in Sources */,
+				5B04C56814BFCFE100EB0071 /* Technique.cpp in Sources */,
+				5B04C56914BFCFE100EB0071 /* Texture.cpp in Sources */,
+				5B04C56A14BFCFE100EB0071 /* Transform.cpp in Sources */,
+				5B04C56B14BFCFE100EB0071 /* Vector2.cpp in Sources */,
+				5B04C56C14BFCFE100EB0071 /* Vector3.cpp in Sources */,
+				5B04C56D14BFCFE100EB0071 /* Vector4.cpp in Sources */,
+				5B04C56E14BFCFE100EB0071 /* VertexAttributeBinding.cpp in Sources */,
+				5B04C56F14BFCFE100EB0071 /* VertexFormat.cpp in Sources */,
+				5B04C57014BFCFE100EB0071 /* Viewport.cpp in Sources */,
+				5B04C57114BFCFE100EB0071 /* SceneLoader.cpp in Sources */,
+				5B04C57214BFCFE100EB0071 /* Image.cpp in Sources */,
+				5B04C57314BFCFE100EB0071 /* MeshBatch.cpp in Sources */,
+				5B04C5CD14BFD48500EB0071 /* gameplay-main-ios.mm in Sources */,
+				5B04C5CE14BFD48500EB0071 /* PlatformiOS.mm in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin XCBuildConfiguration section */
 		4234D99114686BB6003031B3 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				SUPPORTED_PLATFORMS = "iphonesimulator macosx iphoneos";
+				VALID_ARCHS = "armv7 armv6 i386 x86_64";
 			};
 			name = Debug;
 		};
 		4234D99214686BB6003031B3 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				SUPPORTED_PLATFORMS = "iphonesimulator macosx iphoneos";
+				VALID_ARCHS = "armv7 armv6 i386 x86_64";
 			};
 			name = Release;
 		};
@@ -790,7 +1203,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				COPY_PHASE_STRIP = NO;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				GCC_C_LANGUAGE_STANDARD = gnu99;
@@ -823,12 +1236,14 @@
 					"\"$(SRCROOT)/../external-deps/oggvorbis/lib/macos\"",
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
-				ONLY_ACTIVE_ARCH = YES;
+				ONLY_ACTIVE_ARCH = NO;
 				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
-				PRODUCT_NAME = "$(TARGET_NAME)";
+				PRODUCT_NAME = gameplay;
 				SDKROOT = macosx;
 				SHARED_PRECOMPS_DIR = "";
+				SUPPORTED_PLATFORMS = macosx;
 				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = "i386 x86_64";
 			};
 			name = Debug;
 		};
@@ -836,7 +1251,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				COPY_PHASE_STRIP = YES;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -864,10 +1279,105 @@
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.7;
 				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
-				PRODUCT_NAME = "$(TARGET_NAME)";
+				PRODUCT_NAME = gameplay;
 				SDKROOT = macosx;
 				SHARED_PRECOMPS_DIR = "";
+				SUPPORTED_PLATFORMS = macosx;
+				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = "i386 x86_64";
+			};
+			name = Release;
+		};
+		5B04C5C814BFCFE100EB0071 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CODE_SIGN_IDENTITY = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = NO;
+				GCC_PREFIX_HEADER = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_CHECK_SWITCH_STATEMENTS = NO;
+				GCC_WARN_MISSING_PARENTHESES = NO;
+				GCC_WARN_UNUSED_VARIABLE = NO;
+				HEADER_SEARCH_PATHS = (
+					"../external-deps/libpng/include",
+					"../external-deps/bullet/include",
+					"../external-deps/oggvorbis/include",
+				);
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/../external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
+					"\"$(SRCROOT)/../external-deps/bullet/lib/ios/$(CURRENT_ARCH)\"",
+					"\"$(SRCROOT)/../external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
+				);
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = "-ObjC";
+				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
+				PRODUCT_NAME = gameplay;
+				PROVISIONING_PROFILE = "";
+				SDKROOT = iphoneos;
+				SHARED_PRECOMPS_DIR = "";
+				SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = "armv7 armv6";
+			};
+			name = Debug;
+		};
+		5B04C5C914BFCFE100EB0071 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				CODE_SIGN_IDENTITY = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_PRECOMPILE_PREFIX_HEADER = NO;
+				GCC_PREFIX_HEADER = "";
+				GCC_PREPROCESSOR_DEFINITIONS = "";
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_CHECK_SWITCH_STATEMENTS = NO;
+				GCC_WARN_MISSING_PARENTHESES = NO;
+				GCC_WARN_UNUSED_VARIABLE = NO;
+				HEADER_SEARCH_PATHS = (
+					"../external-deps/libpng/include",
+					"../external-deps/bullet/include",
+					"../external-deps/oggvorbis/include",
+				);
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/../external-deps/libpng/lib/ios/$(CURRENT_ARCH)\"",
+					"\"$(SRCROOT)/../external-deps/bullet/lib/ios/$(CURRENT_ARCH)\"",
+					"\"$(SRCROOT)/../external-deps/oggvorbis/lib/ios/$(CURRENT_ARCH)\"",
+				);
+				MACOSX_DEPLOYMENT_TARGET = 10.7;
+				OTHER_LDFLAGS = "-ObjC";
+				PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
+				PRODUCT_NAME = gameplay;
+				PROVISIONING_PROFILE = "";
+				SDKROOT = iphoneos;
+				SHARED_PRECOMPS_DIR = "";
+				SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
 				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = "armv7 armv6";
 			};
 			name = Release;
 		};
@@ -883,7 +1393,7 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay" */ = {
+		4234D9AB14686C52003031B3 /* Build configuration list for PBXNativeTarget "gameplay-macos" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
 				4234D9A914686C52003031B3 /* Debug */,
@@ -892,6 +1402,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		5B04C5C714BFCFE100EB0071 /* Build configuration list for PBXNativeTarget "gameplay-ios" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				5B04C5C814BFCFE100EB0071 /* Debug */,
+				5B04C5C914BFCFE100EB0071 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 4234D98C14686BB6003031B3 /* Project object */;

+ 57 - 0
gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-MacOSX.xcscheme

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "4234D99914686C52003031B3"
+               BuildableName = "libgameplay.a"
+               BlueprintName = "gameplay-macos"
+               ReferencedContainer = "container:gameplay.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 57 - 0
gameplay/gameplay.xcodeproj/xcshareddata/xcschemes/gameplay-iOS.xcscheme

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "5B04C52B14BFCFE100EB0071"
+               BuildableName = "libgameplay.a"
+               BlueprintName = "gameplay-ios"
+               ReferencedContainer = "container:gameplay.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 9 - 156
gameplay/src/AnimationClip.cpp

@@ -198,7 +198,7 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
     _endListeners->push_back(listener);
 }
 
-bool AnimationClip::update(unsigned long elapsedTime)
+bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
 {
     float speed = _speed;
     if (!_isPlaying)
@@ -295,146 +295,16 @@ bool AnimationClip::update(unsigned long elapsedTime)
         target = channel->_target;
         value = _values[i];
 
-        // Get the current value.
-        target->getAnimationPropertyValue(channel->_propertyId, value);
+        // If the target's _animationPropertyBitFlag is clear, we can assume that this is the first
+        // animation channel to act on the target and we can add the target to the list of
+        // active targets stored by the AnimationController.
+        if (target->_animationPropertyBitFlag == 0x00)
+            activeTargets->push_front(target);
 
-        bool isHighest = false;
-        // My channel priority has changed if my priority is greater than the active animation count.
-        if (!target->_highestPriority)
-        {
-            target->_highestPriority = channel;
-            value->_isFirstActing = true;
-        }
-
-        if (_blendWeight != 0.0f)
-        {
-            // Evaluate point on Curve.
-            channel->_curve->evaluate(percentComplete, value->_interpolatedValue);
-
-            if (!channel->_curve->_quaternionOffset)
-            {
-                if (value->_isFirstActing)
-                {
-                    unsigned int componentCount = value->_componentCount;
-                    for (unsigned int j = 0; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] = value->_interpolatedValue[j];
-                    }
-                }
-                else
-                {
-                    unsigned int componentCount = value->_componentCount;
-                    for (unsigned int j = 0; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] += value->_interpolatedValue[j];
-                    }
-                }
-            }
-            else
-            {   //We have Quaternions!!!
-                unsigned int quaternionOffset = *(channel->_curve->_quaternionOffset);
-                
-                if (value->_isFirstActing)
-                {
-                    unsigned int j = 0;
-                    for (; j < quaternionOffset; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] = value->_interpolatedValue[j];
-                    }
-
-                    // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
-                    Quaternion* interpolatedQuaternion = (Quaternion*) (value->_interpolatedValue + j);
-                    Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
-
-                    // If we have a blend weight, we apply it by slerping from the identity to our interpolated value at the given weight.
-                    if (_blendWeight != 1.0f)
-                        Quaternion::slerp(Quaternion::identity(), *interpolatedQuaternion, _blendWeight, interpolatedQuaternion);
-                    
-                    // Add in contribution.
-                    currentQuaternion->set(*interpolatedQuaternion);
-                    
-                    unsigned int componentCount = value->_componentCount;
-                    for (j += 4; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] = value->_interpolatedValue[j];
-                    }
-                }
-                else
-                {
-                    unsigned int j = 0;
-                    for (; j < quaternionOffset; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] += value->_interpolatedValue[j];
-                    }
-                    // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
-
-                    Quaternion* interpolatedQuaternion = (Quaternion*) (value->_interpolatedValue + j);
-                    Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
-
-                    // If we have a blend weight, we apply it by slerping from the identity to our interpolated value at the given weight.
-                    if (_blendWeight != 1.0f)
-                        Quaternion::slerp(Quaternion::identity(), *interpolatedQuaternion, _blendWeight, interpolatedQuaternion);
-                    
-                    // Add in contribution.
-                    currentQuaternion->multiply(*interpolatedQuaternion);
-                    
-                    unsigned int componentCount = value->_componentCount;
-                    for (j += 4; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] += value->_interpolatedValue[j];
-                    }
-                }
-            }
-        }
-        else if (value->_isFirstActing)
-        {
-            if (!channel->_curve->_quaternionOffset)
-            {
-                memset(value->_currentValue, 0.0f, value->_componentCount);
-            }
-            else
-            {
-                unsigned int quaternionOffset = *(channel->_curve->_quaternionOffset);
-                unsigned int j = 0;
-                for (; j < quaternionOffset; j++)
-                {
-                    value->_currentValue[j] = 0.0f;
-                }
-
-                // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
-                Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
-
-                // Set it to identity.
-                currentQuaternion->setIdentity();
-                
-                unsigned int componentCount = value->_componentCount;
-                for (j += 4; j < componentCount; j++)
-                {
-                    value->_currentValue[j] = 0.0f;
-                }
-            }
-        }
-        
+        // Evaluate the point on Curve
+        channel->_curve->evaluate(percentComplete, value->_value);
         // Set the animation value on the target property.
-        target->setAnimationPropertyValue(channel->_propertyId, value);
+        target->setAnimationPropertyValue(channel->_propertyId, value, _blendWeight);
     }
 
     // When ended. Probably should move to it's own method so we can call it when the clip is ended early.
@@ -485,23 +355,6 @@ void AnimationClip::onBegin()
 
 void AnimationClip::onEnd()
 {
-    AnimationValue* value;
-    Animation::Channel* channel = NULL;
-    AnimationTarget* target = NULL;
-    unsigned int channelCount = _animation->_channels.size();
-    for (unsigned int i = 0; i < channelCount; i++)
-    {
-        value = _values[i];
-
-        if (value->_isFirstActing)
-        {
-            channel = _animation->_channels[i];
-            target = channel->_target;
-            target->_highestPriority = NULL;
-            value->_isFirstActing = false;
-        }
-    }
-
     _blendWeight = 1.0f;
     _timeStarted = 0;
 }

+ 1 - 1
gameplay/src/AnimationClip.h

@@ -215,7 +215,7 @@ private:
     /**
      * Updates the animation with the elapsed time.
      */
-    bool update(unsigned long elapsedTime);
+    bool update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets);
 
     /**
      * Handles when the AnimationClip begins.

+ 12 - 1
gameplay/src/AnimationController.cpp

@@ -333,11 +333,12 @@ void AnimationController::update(long elapsedTime)
     if (_state != RUNNING)
         return;
 
+    // Loop through running clips and call update() on them.
     std::list<AnimationClip*>::iterator clipIter = _runningClips.begin();
     while (clipIter != _runningClips.end())
     {
         AnimationClip* clip = (*clipIter);
-        if (clip->update(elapsedTime))
+        if (clip->update(elapsedTime, &_activeTargets))
         {
             SAFE_RELEASE(clip);
             clipIter = _runningClips.erase(clipIter);
@@ -347,6 +348,16 @@ void AnimationController::update(long elapsedTime)
             clipIter++;
         }
     }
+
+    // Loop through active AnimationTarget's and reset their _animationPropertyBitFlag for the next frame.
+    std::list<AnimationTarget*>::iterator targetItr = _activeTargets.begin();
+    while (targetItr != _activeTargets.end())
+    {
+        AnimationTarget* target = (*targetItr);
+        target->_animationPropertyBitFlag = 0x00;
+        targetItr++;
+    }
+    _activeTargets.clear();
     
     if (_runningClips.empty())
         _state = IDLE;

+ 2 - 1
gameplay/src/AnimationController.h

@@ -205,7 +205,8 @@ private:
     void destroyAllAnimations();
     
     State _state;                               // The current state of the AnimationController.
-    std::list<AnimationClip*> _runningClips;    // A list of currently running AnimationClips.
+    std::list<AnimationClip*> _runningClips;    // A list of running AnimationClips.
+    std::list<AnimationTarget*> _activeTargets;   // A list of animating AnimationTargets.
     std::vector<Animation*> _animations;        // A list of animations registered with the AnimationController
 };
 

+ 1 - 1
gameplay/src/AnimationTarget.cpp

@@ -8,7 +8,7 @@ namespace gameplay
 {
 
 AnimationTarget::AnimationTarget()
-    : _targetType(SCALAR), _highestPriority(NULL), _animationChannels(NULL)
+    : _targetType(SCALAR), _animationPropertyBitFlag(0x00), _animationChannels(NULL)
 {
 }
 

+ 4 - 3
gameplay/src/AnimationTarget.h

@@ -45,7 +45,7 @@ public:
      * @param propertyId The ID of the property on the AnimationTarget to set the animation property value on.
      * @param value The container to set the animation property value in.
      */
-    virtual void setAnimationPropertyValue(int propertyId, AnimationValue* value) = 0;
+    virtual void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f) = 0;
 
 protected:
     
@@ -69,6 +69,8 @@ protected:
 
     TargetType _targetType;             // The type of target this is.
 
+    char _animationPropertyBitFlag;     // Bit flag used to indicate which properties on the AnimationTarget are currently animating.
+
 private:
 
     /**
@@ -86,9 +88,8 @@ private:
      */
     static int getPropertyId(TargetType type, const char* propertyIdStr);
 
-    Animation::Channel* _highestPriority;
     std::vector<Animation::Channel*>* _animationChannels;   // Collection of all animation channels that target the AnimationTarget
-
+    
 };
 }
 

+ 7 - 9
gameplay/src/AnimationValue.cpp

@@ -5,44 +5,42 @@ namespace gameplay
 {
 
 AnimationValue::AnimationValue(unsigned int componentCount)
-  : _isFirstActing(false), _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
+  : _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
 {
-    _currentValue = new float[_componentCount];
-    _interpolatedValue = new float[_componentCount];
+    _value = new float[_componentCount];
 }
 
 AnimationValue::~AnimationValue()
 {
-    SAFE_DELETE_ARRAY(_currentValue);
-    SAFE_DELETE_ARRAY(_interpolatedValue);
+    SAFE_DELETE_ARRAY(_value);
 }
 
 float AnimationValue::getFloat(unsigned int index) const
 {
     assert(index < _componentCount);
 
-    return _currentValue[index];
+    return _value[index];
 }
 
 void AnimationValue::setFloat(unsigned int index, float value)
 {
     assert(index < _componentCount);
 
-    _currentValue[index] = value;
+    _value[index] = value;
 }
 
 void AnimationValue::getFloat(float* value, unsigned int offset, unsigned int length) const
 {
     assert(value && offset < _componentCount && (offset + length) <= _componentCount);
 
-    memcpy(value + offset, _currentValue, length * sizeof(float));
+    memcpy(value + offset, _value, length * sizeof(float));
 }
 
 void AnimationValue::setFloat(float* value, unsigned int offset, unsigned int length)
 {
     assert(value && offset < _componentCount && (offset + length) <= _componentCount);
 
-    memcpy(_currentValue, value + offset, length * sizeof(float));
+    memcpy(_value, value + offset, length * sizeof(float));
 }
 
 }

+ 2 - 3
gameplay/src/AnimationValue.h

@@ -72,11 +72,10 @@ private:
      */
     ~AnimationValue();
 
-    bool _isFirstActing;            // Flag indicating if this value's channel is the first to act on the target.
     unsigned int _componentCount;   // The number of float values for the property.
     unsigned int _componentSize;    // The number of bytes of memory the property is.
-    float* _currentValue;           // The current value of the property.
-    float* _interpolatedValue;      // The last interpolated value of the property.
+    float* _value;                  // The current value of the property.
+
 };
 
 }

+ 34 - 13
gameplay/src/Base.h

@@ -174,15 +174,12 @@ extern void printError(const char* format, ...);
 #include <vorbis/vorbisfile.h>
 #endif
 
-// Screen/Window
-#define WINDOW_WIDTH        1024
-#define WINDOW_HEIGHT       600
-#define WINDOW_VSYNC        1
-#define WINDOW_FULLSCREEN   0
-
 // Image
 #include <png.h>
 
+#define WINDOW_VSYNC        1
+#define WINDOW_FULLSCREEN   0
+
 // Graphics (OpenGL)
 #if defined (__QNX__) || defined(__ANDROID__)
     #include <EGL/egl.h>
@@ -193,19 +190,43 @@ extern void printError(const char* format, ...);
     extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays;
     extern PFNGLISVERTEXARRAYOESPROC glIsVertexArray;
     #define glClearDepth glClearDepthf
-   #define OPENGL_ES
+    #define OPENGL_ES
+    #define WINDOW_WIDTH    1024
+    #define WINDOW_HEIGHT   600
 #elif WIN32
     #define WIN32_LEAN_AND_MEAN
     #include <GL/glew.h>
+    #define WINDOW_WIDTH    1024
+    #define WINDOW_HEIGHT   600
 #elif __APPLE__
-#include <OpenGL/gl.h>
-#include <OpenGL/glext.h>
-#define glBindVertexArray glBindVertexArrayAPPLE
-#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
-#define glGenVertexArrays glGenVertexArraysAPPLE
-#define glIsVertexArray glIsVertexArrayAPPLE
+    #include "TargetConditionals.h"
+    #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+        #include <OpenGLES/ES2/gl.h>
+        #include <OpenGLES/ES2/glext.h>
+        #define glBindVertexArray glBindVertexArrayOES
+        #define glDeleteVertexArrays glDeleteVertexArraysOES
+        #define glGenVertexArrays glGenVertexArraysOES
+        #define glIsVertexArray glIsVertexArrayOES
+        #define glClearDepth glClearDepthf
+        #define OPENGL_ES
+        #define WINDOW_WIDTH    480
+        #define WINDOW_HEIGHT   360
+    #elif TARGET_OS_MAC
+        #include <OpenGL/gl.h>
+        #include <OpenGL/glext.h>
+        #define glBindVertexArray glBindVertexArrayAPPLE
+        #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
+        #define glGenVertexArrays glGenVertexArraysAPPLE
+        #define glIsVertexArray glIsVertexArrayAPPLE
+        #define WINDOW_WIDTH    960
+        #define WINDOW_HEIGHT   640
+    #else
+        #error "Unsupported Apple Device"
+    #endif
 #endif
 
+
+
 // Graphics (GLSL)
 #define VERTEX_ATTRIBUTE_POSITION_NAME              "a_position"
 #define VERTEX_ATTRIBUTE_NORMAL_NAME                "a_normal"

+ 3 - 3
gameplay/src/BoundingBox.cpp

@@ -69,9 +69,9 @@ bool BoundingBox::intersects(const BoundingSphere& sphere) const
 
 bool BoundingBox::intersects(const BoundingBox& box) const
 {
-    return ((min.x >= box.min.x && min.x <= max.x) || (box.min.x >= min.x && box.min.x <= max.x)) &&
-            ((min.y >= box.min.y && min.y <= max.y) || (box.min.y >= min.y && box.min.y <= max.y)) &&
-            ((min.z >= box.min.z && min.z <= max.z) || (box.min.z >= min.z && box.min.z <= max.z));
+    return ((min.x >= box.min.x && min.x <= box.max.x) || (box.min.x >= min.x && box.min.x <= max.x)) &&
+            ((min.y >= box.min.y && min.y <= box.max.y) || (box.min.y >= min.y && box.min.y <= max.y)) &&
+            ((min.z >= box.min.z && min.z <= box.max.z) || (box.min.z >= min.z && box.min.z <= max.z));
 }
 
 bool BoundingBox::intersects(const Frustum& frustum) const

+ 3 - 10
gameplay/src/Curve.cpp

@@ -1109,19 +1109,12 @@ void Curve::interpolateLinear(float s, Point* from, Point* to, float* dst) const
 }
 
 void Curve::interpolateQuaternion(float s, float* from, float* to, float* dst) const
-{
-    Quaternion quatFrom(from);
-    Quaternion quatTo(to);
-
-    // Normalize the quaternions.
-    quatFrom.normalize();
-    quatTo.normalize();
-        
+{        
     // Evaluate.
     if (s >= 0)
-        Quaternion::slerp(quatFrom, quatTo, s, (Quaternion*)dst);
+        Quaternion::slerp(from[0], from[1], from[2], from[3], to[0], to[1], to[2], to[3], s, dst, dst + 1, dst + 2, dst + 3);
     else
-        Quaternion::slerp(quatTo, quatFrom, -s, (Quaternion*)dst);
+        Quaternion::slerp(to[0], to[1], to[2], to[3], from[0], from[1], from[2], from[3], s, dst, dst + 1, dst + 2, dst + 3);
 }
 
 int Curve::determineIndex(float time) const

+ 78 - 0
gameplay/src/FileSystem.cpp

@@ -1,6 +1,15 @@
 #include "Base.h"
 #include "FileSystem.h"
 
+#ifdef WIN32
+    #include <windows.h>
+    #include <tchar.h>
+    #include <stdio.h>
+#else
+    #include <dirent.h>
+    #include <sys/stat.h>
+#endif
+
 #ifdef __ANDROID__
 extern AAssetManager* __assetManager;
 #endif
@@ -70,6 +79,75 @@ const char* FileSystem::getResourcePath()
     return __resourcePath.c_str();
 }
 
+bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files)
+{
+    // TODO make this method work with absolute and relative paths.
+#ifdef WIN32
+    std::string path(FileSystem::getResourcePath());
+    if (dirPath && strlen(dirPath) > 0)
+    {
+        path.append(dirPath);
+    }
+    path.append("/*");
+    // Convert char to wchar
+    std::basic_string<TCHAR> wPath;
+    wPath.assign(path.begin(), path.end());
+
+    WIN32_FIND_DATA FindFileData;
+    HANDLE hFind = FindFirstFile(wPath.c_str(), &FindFileData);
+    if (hFind == INVALID_HANDLE_VALUE) 
+    {
+        return false;
+    }
+    do
+    {
+        // Add to the list if this is not a directory
+        if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
+        {
+            // Convert wchar to char
+            std::basic_string<TCHAR> wfilename(FindFileData.cFileName);
+            std::string filename;
+            filename.assign(wfilename.begin(), wfilename.end());
+            files.push_back(filename);
+        }
+    } while(FindNextFile(hFind, &FindFileData) != 0);
+
+    FindClose(hFind);
+    return true;
+#else
+    std::string path(FileSystem::getResourcePath());
+    if (dirPath && strlen(dirPath) > 0)
+	{
+		path.append(dirPath);
+	}
+    path.append("/.");
+    struct dirent* dp;
+    DIR* dir = opendir(path.c_str());
+    if (!dir)
+    {
+        return false;
+    }
+	while ((dp = readdir(dir)) != NULL)
+	{
+		std::string filepath(path);
+		filepath.append("/");
+		filepath.append(dp->d_name);
+
+		struct stat buf;
+		if (!stat(filepath.c_str(), &buf))
+		{
+            // Add to the list if this is not a directory
+			if (!S_ISDIR(buf.st_mode))
+			{
+				files.push_back(dp->d_name);
+			}
+		}
+	}
+	closedir(dir);
+    return true;
+#endif
+}
+
 FILE* FileSystem::openFile(const char* path, const char* mode)
 {
     std::string fullPath(__resourcePath);

+ 10 - 0
gameplay/src/FileSystem.h

@@ -33,6 +33,16 @@ public:
      */
     static const char* getResourcePath();
 
+    /**
+     * Lists the files in the specified directory and adds the files to the vector. Excludes directories.
+     * 
+     * @param dirPath Directory path relative to the path set in <code>setResourcePath(const char*)</code>.
+     * @param files The vector to append the files to.
+     * 
+     * @return True if successful, false if error.
+     */
+    static bool listFiles(const char* dirPath, std::vector<std::string>& files);
+
     /**
      * Opens the specified file.
      *

+ 9 - 0
gameplay/src/Game.cpp

@@ -251,4 +251,13 @@ void Game::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactI
 {
 }
 
+bool Game::mouseEvent(Mouse::MouseEvent evt, int x, int y)
+{
+    return false;
+}
+
+void Game::mouseWheelEvent(int x, int y, int delta)
+{
+}
+
 }

+ 24 - 0
gameplay/src/Game.h

@@ -3,6 +3,7 @@
 
 #include "Keyboard.h"
 #include "Touch.h"
+#include "Mouse.h"
 #include "AudioController.h"
 #include "AnimationController.h"
 #include "PhysicsController.h"
@@ -215,6 +216,29 @@ public:
      */
     virtual void touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex);
 
+    /**
+     * Mouse callback on mouse events. If the game does not consume the mouse move event or left mouse click event
+     * then it is interpreted as a touch event instead.
+     *
+     * @param evt The mouse event that occurred.
+     * @param x The x position of the mouse in pixels. Left edge is zero.
+     * @param y The y position of the mouse in pixels. Top edge is zero.
+     *
+     * @return True if the mouse event is consumed or false if it is not consumed.
+     *
+     * @see Mouse::MouseEvent
+     */
+    virtual bool mouseEvent(Mouse::MouseEvent evt, int x, int y);
+
+    /**
+     * Mouse callback on mouse wheel events.
+     *
+     * @param x The x position of the mouse in pixels. Left edge is zero.
+     * @param y The y position of the mouse in pixels. Top edge is zero.
+     * @param delta The number of mouse wheel ticks. Positive is up (forward), negative is down (backward).
+     */
+    virtual void mouseWheelEvent(int x, int y, int delta);
+
     /**
      * Sets muli-touch is to be enabled/disabled. Default is disabled.
      *

+ 145 - 18
gameplay/src/MaterialParameter.cpp

@@ -304,7 +304,7 @@ unsigned int MaterialParameter::getAnimationPropertyComponentCount(int propertyI
                     return 0;
                 case FLOAT:
                 case INT:
-                    return 1;
+                    return _count;
                 case VECTOR2:
                     return 2 * _count;
                 case VECTOR3:
@@ -329,10 +329,30 @@ void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue
             switch (_type)
             {
                 case FLOAT:
-                    value->setFloat(0, _value.floatValue);
+                    if (_count == 1)
+                    {
+                        value->setFloat(0, _value.floatValue);
+                    }
+                    else
+                    {
+                        for (unsigned int i = 0; i < _count; i++)
+                        {
+                            value->setFloat(i, _value.floatPtrValue[i]);
+                        }
+                    }
                     break;
                 case INT:
-                    value->setFloat(0, _value.intValue);
+                    if (_count == 1)
+                    {
+                        value->setFloat(0, _value.intValue);
+                    }
+                    else
+                    {
+                        for (unsigned int i = 0; i < _count; i++)
+                        {
+                            value->setFloat(i, _value.intPtrValue[i]);
+                        }
+                    }
                     break;
                 case VECTOR2:
                     for (unsigned int i = 0; i < _count; i++)
@@ -359,8 +379,12 @@ void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue
     }
 }
 
-void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue* value)
+void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight)
 {
+    assert(blendWeight >= 0.0f && blendWeight <= 1.0f);
+    if (blendWeight == 0.0f)
+        return;
+
     switch (propertyId)
     {
         case ANIMATE_UNIFORM:
@@ -368,29 +392,99 @@ void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue
             switch (_type)
             {
                 case FLOAT:
-                    _value.floatValue = value->getFloat(0);
+                {
+                    if (_count == 1)
+                    {
+                        if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
+                        {
+                            _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
+
+                            if (blendWeight != 1.0f)
+                                _value.floatValue = value->getFloat(0) * blendWeight;
+                            else
+                                _value.floatValue = value->getFloat(0);
+                        }
+                        else
+                        {
+                            if (blendWeight != 1.0f)
+                                _value.floatValue += value->getFloat(0) * blendWeight;
+                            else
+                                _value.floatValue += value->getFloat(0);
+                        }
+                    }
+                    else
+                    {
+                        applyAnimationValue(value, blendWeight, 1);
+                    }                    
                     break;
+                }
                 case INT:
-                    _value.intValue = value->getFloat(0);
-                    break;
-                case VECTOR2:
-                    for (unsigned int i = 0; i < _count; i++)
+                {
+                    if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
                     {
-                        value->getFloat(_value.floatPtrValue, i * 2, 2);
+                        _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
+
+                        if (_count == 1)
+                        {
+                            if (blendWeight != 1.0f)
+                                _value.intValue = value->getFloat(0) * blendWeight;
+                            else
+                                _value.intValue = value->getFloat(0);
+                        }
+                        else
+                        {
+                            if (blendWeight != 1.0f)
+                            {
+                                for (unsigned int i = 0; i < _count; i++)
+                                    _value.intPtrValue[i] = value->getFloat(i) * blendWeight;
+                            }
+                            else
+                            {
+                                for (unsigned int i = 0; i < _count; i++)
+                                    _value.intPtrValue[i] = value->getFloat(i);
+                            }
+                        }
                     }
-                    break;
-                case VECTOR3:
-                    for (unsigned int i = 0; i < _count; i++)
+                    else
                     {
-                        value->getFloat(_value.floatPtrValue, i * 3, 3);
+                        if (_count == 1)
+                        {
+                            if (blendWeight != 1.0f)
+                                _value.intValue += value->getFloat(0) * blendWeight;
+                            else
+                                _value.intValue += value->getFloat(0);
+                        }
+                        else
+                        {
+                            if (blendWeight != 1.0f)
+                            {
+                                for (unsigned int i = 0; i < _count; i++)
+                                    _value.intPtrValue[i] += value->getFloat(i) * blendWeight;
+                            }
+                            else
+                            {
+                                for (unsigned int i = 0; i < _count; i++)
+                                    _value.intPtrValue[i] += value->getFloat(i);
+                            }
+                        }
                     }
                     break;
+                }
+                case VECTOR2:
+                {
+                    applyAnimationValue(value, blendWeight, 2);
+                    break;
+                }
+                case VECTOR3:
+                {
+                    applyAnimationValue(value, blendWeight, 3);
+                    break;
+                }
                 case VECTOR4:
-                    for (unsigned int i = 0; i < _count; i++)
-                    {
-                        value->getFloat(_value.floatPtrValue, i * 4, 4);
-                    }
+                {
+                    applyAnimationValue(value, blendWeight, 4);
                     break;
+                }
 
                 // UNSUPPORTED: NONE, MATRIX, METHOD, SAMPLER 
             }
@@ -398,4 +492,37 @@ void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue
     }
 }
 
+void MaterialParameter::applyAnimationValue(AnimationValue* value, float blendWeight, int components)
+{
+    unsigned int count = _count * components;
+    if ((_animationPropertyBitFlag & ANIMATION_UNIFORM_BIT) != ANIMATION_UNIFORM_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_UNIFORM_BIT;
+
+        if (blendWeight != 1.0f)
+        {
+            for (unsigned int i = 0; i < count; i++)
+                _value.floatPtrValue[i] = value->getFloat(i) * blendWeight;
+        }
+        else
+        {
+            for (unsigned int i = 0; i < count; i++)
+                _value.floatPtrValue[i] = value->getFloat(i);
+        }
+    }
+    else
+    {
+        if (blendWeight != 1.0f)
+        {
+            for (unsigned int i = 0; i < count; i++)
+                _value.floatPtrValue[i] += (value->getFloat(i) * blendWeight);
+        }
+        else
+        {
+            for (unsigned int i = 0; i < count; i++)
+                _value.floatPtrValue[i] += value->getFloat(i);
+        }
+    }
+}
+
 }

+ 5 - 1
gameplay/src/MaterialParameter.h

@@ -164,7 +164,7 @@ public:
     /**
      * @see AnimationTarget#setAnimationProperty
      */
-    void setAnimationPropertyValue(int propertyId, AnimationValue* value);
+    void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f);
 
 private:
 
@@ -253,6 +253,10 @@ private:
         METHOD
     } _type;
 
+    static const char ANIMATION_UNIFORM_BIT = 0x01;
+
+    void applyAnimationValue(AnimationValue* value, float blendWeight, int components);
+
     unsigned int _count;
     bool _dynamic;
     std::string _name;

+ 39 - 0
gameplay/src/Mouse.h

@@ -0,0 +1,39 @@
+#ifndef MOUSE_H_
+#define MOUSE_H_
+
+namespace gameplay
+{
+
+/**
+ * Mouse event
+ */
+class Mouse
+{
+public:
+
+    /**
+     * The mouse event type.
+     */
+    enum MouseEvent
+    {
+        MOUSE_LEFT_BUTTON_PRESS,
+        MOUSE_LEFT_BUTTON_RELEASE,
+        MOUSE_MIDDLE_BUTTON_PRESS,
+        MOUSE_MIDDLE_BUTTON_RELEASE,
+        MOUSE_RIGHT_BUTTON_PRESS,
+        MOUSE_RIGHT_BUTTON_RELEASE,
+        MOUSE_MOVE
+    };
+
+
+private:
+
+    /**
+     * Constructor. Used internally.
+     */
+    Mouse();
+};
+
+}
+
+#endif

+ 2 - 3
gameplay/src/PlatformMacOS.mm

@@ -65,7 +65,6 @@ static View* __view = NULL;
     [[NSApplication sharedApplication] terminate:self];
 }
 
-
 - (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -529,7 +528,7 @@ Platform* Platform::create(Game* game)
 int Platform::enterMessagePump()
 {
     NSAutoreleasePool* pool = [NSAutoreleasePool new];
-    NSApplication* NSApp = [NSApplication sharedApplication];
+    NSApplication* app = [NSApplication sharedApplication];
     NSRect screenBounds = [[NSScreen mainScreen] frame];
     NSRect viewBounds = NSMakeRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
     
@@ -550,7 +549,7 @@ int Platform::enterMessagePump()
     [window setDelegate:__view];
     [__view release];
     
-    [NSApp run];
+    [app run];
     
     [pool release];
     return EXIT_SUCCESS;

+ 105 - 2
gameplay/src/PlatformQNX.cpp

@@ -666,6 +666,23 @@ long timespec2millis(struct timespec *a)
     return a->tv_sec*1000 + a->tv_nsec/1000000;
 }
 
+/**
+ * Fires a mouse event or a touch event on the game.
+ * If the mouse event is not consumed, a touch event is fired instead.
+ *
+ * @param mouseEvent The mouse event to fire.
+ * @param touchEvent The touch event to fire.
+ * @param x The x position of the touch in pixels.
+ * @param y The y position of the touch in pixels.
+ */
+void mouseOrTouchEvent(Mouse::MouseEvent mouseEvent, Touch::TouchEvent touchEvent, int x, int y)
+{
+    if (!Game::getInstance()->mouseEvent(mouseEvent, x, y))
+    {
+        Game::getInstance()->touchEvent(touchEvent, x, y, 0);
+    }
+}
+
 int Platform::enterMessagePump()
 {
     int rc;
@@ -710,7 +727,7 @@ int Platform::enterMessagePump()
                         if (!__multiTouch)
                         {
                             screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_POSITION, position);
-                           Game::getInstance()->touchEvent(Touch::TOUCH_PRESS, position[0], position[1], 0);
+                            Game::getInstance()->touchEvent(Touch::TOUCH_PRESS, position[0], position[1], 0);
                         }
                         else
                         {
@@ -725,7 +742,7 @@ int Platform::enterMessagePump()
                         if (!__multiTouch)
                         {
                             screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_POSITION, position);
-                           Game::getInstance()->touchEvent(Touch::TOUCH_RELEASE, position[0], position[1], 0);
+                            Game::getInstance()->touchEvent(Touch::TOUCH_RELEASE, position[0], position[1], 0);
                         }
                         else
                         {
@@ -751,6 +768,92 @@ int Platform::enterMessagePump()
                         break;
                     }
 
+                    case SCREEN_EVENT_POINTER:
+                    {
+                        static int mouse_pressed = 0;
+                        int buttons;
+                        int wheel;
+                        // A move event will be fired unless a button state changed.
+                        bool move = true;
+                        bool left_move = false;
+                        //This is a mouse move event, it is applicable to a device with a usb mouse or simulator
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons);
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, position);
+                        screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel);
+
+                        // Handle left mouse. Interpret as touch if the left mouse event is not consumed.
+                        if (buttons & SCREEN_LEFT_MOUSE_BUTTON)
+                        {
+                            if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON)
+                            {
+                                left_move = true;
+                            }
+                            else
+                            {
+                                move = false;
+                                mouse_pressed |= SCREEN_LEFT_MOUSE_BUTTON;
+                                mouseOrTouchEvent(Mouse::MOUSE_LEFT_BUTTON_PRESS, Touch::TOUCH_PRESS, position[0], position[1]);
+                            }
+                        }
+                        else if (mouse_pressed & SCREEN_LEFT_MOUSE_BUTTON)
+                        {
+                            move = false;
+                            mouse_pressed &= ~SCREEN_LEFT_MOUSE_BUTTON;
+                            mouseOrTouchEvent(Mouse::MOUSE_LEFT_BUTTON_RELEASE, Touch::TOUCH_RELEASE, position[0], position[1]);
+                        }
+
+                        // Handle right mouse
+                        if (buttons & SCREEN_RIGHT_MOUSE_BUTTON)
+                        {
+                            if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON == 0)
+                            {
+                                move = false;
+                                mouse_pressed |= SCREEN_RIGHT_MOUSE_BUTTON;
+                                Game::getInstance()->mouseEvent(Mouse::MOUSE_RIGHT_BUTTON_PRESS, position[0], position[1]);
+                            }
+                        }
+                        else if (mouse_pressed & SCREEN_RIGHT_MOUSE_BUTTON)
+                        {
+                            move = false;
+                            mouse_pressed &= ~SCREEN_RIGHT_MOUSE_BUTTON;
+                            Game::getInstance()->mouseEvent(Mouse::MOUSE_RIGHT_BUTTON_RELEASE, position[0], position[1]);
+                        }
+
+                        // Handle middle mouse
+                        if (buttons & SCREEN_MIDDLE_MOUSE_BUTTON)
+                        {
+                            if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON == 0)
+                            {
+                                move = false;
+                                mouse_pressed |= SCREEN_MIDDLE_MOUSE_BUTTON;
+                                Game::getInstance()->mouseEvent(Mouse::MOUSE_MIDDLE_BUTTON_PRESS, position[0], position[1]);
+                            }
+                        }
+                        else if (mouse_pressed & SCREEN_MIDDLE_MOUSE_BUTTON)
+                        {
+                            move = false;
+                            mouse_pressed &= ~SCREEN_MIDDLE_MOUSE_BUTTON;
+                            Game::getInstance()->mouseEvent(Mouse::MOUSE_MIDDLE_BUTTON_RELEASE, position[0], position[1]);
+                        }
+
+                        // Fire a move event if none of the buttons changed.
+                        if (left_move)
+                        {
+                            mouseOrTouchEvent(Mouse::MOUSE_MOVE, Touch::TOUCH_MOVE, position[0], position[1]);
+                        }
+                        else if (move)
+                        {
+                            Game::getInstance()->mouseEvent(Mouse::MOUSE_MOVE, position[0], position[1]);
+                        }
+
+                        // Handle mouse wheel events
+                        if (wheel)
+                        {
+                            Game::getInstance()->mouseWheelEvent(position[0], position[1], -wheel);
+                        }
+                        break;
+                    }
+
                     case SCREEN_EVENT_KEYBOARD:
                     {
                         screen_get_event_property_iv(__screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &flags);

+ 27 - 3
gameplay/src/PlatformWin32.cpp

@@ -267,26 +267,43 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         return 0;
 
     case WM_LBUTTONDOWN:
-        gameplay::Game::getInstance()->touchEvent(gameplay::Touch::TOUCH_PRESS, LOWORD(lParam), HIWORD(lParam), 0);
+        if (!gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_LEFT_BUTTON_PRESS, LOWORD(lParam), HIWORD(lParam)))
+        {
+            gameplay::Game::getInstance()->touchEvent(gameplay::Touch::TOUCH_PRESS, LOWORD(lParam), HIWORD(lParam), 0);
+        }
         lMouseDown = true;
         return 0;
 
     case WM_LBUTTONUP:
         lMouseDown = false;
-        gameplay::Game::getInstance()->touchEvent(gameplay::Touch::TOUCH_RELEASE, LOWORD(lParam), HIWORD(lParam), 0);
+        if (!gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_LEFT_BUTTON_RELEASE, LOWORD(lParam), HIWORD(lParam)))
+        {
+            gameplay::Game::getInstance()->touchEvent(gameplay::Touch::TOUCH_RELEASE, LOWORD(lParam), HIWORD(lParam), 0);
+        }
         return 0;
 
     case WM_RBUTTONDOWN:
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RIGHT_BUTTON_PRESS, LOWORD(lParam), HIWORD(lParam));
         rMouseDown = true;
         lx = LOWORD(lParam);
         ly = HIWORD(lParam);
         break;
 
     case WM_RBUTTONUP:
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_RIGHT_BUTTON_RELEASE, LOWORD(lParam), HIWORD(lParam));
         rMouseDown = false;
         break;
 
+    case WM_MBUTTONDOWN:
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_MIDDLE_BUTTON_PRESS, LOWORD(lParam), HIWORD(lParam));
+        break;
+
+    case WM_MBUTTONUP:
+        gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_MIDDLE_BUTTON_RELEASE, LOWORD(lParam), HIWORD(lParam));
+        break;
+
     case WM_MOUSEMOVE:
+    {
         if (!hasMouse)
         {
             hasMouse = true;
@@ -299,8 +316,10 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
             TrackMouseEvent(&tme);
         }
 
-        if (lMouseDown)
+        bool consumed = gameplay::Game::getInstance()->mouseEvent(gameplay::Mouse::MOUSE_MOVE, LOWORD(lParam), HIWORD(lParam));
+        if (lMouseDown && !consumed)
         {
+            // Mouse move events should be interpreted as touch move only if left mouse is held and the game did not consume the mouse event.
             gameplay::Game::getInstance()->touchEvent(gameplay::Touch::TOUCH_MOVE, LOWORD(lParam), HIWORD(lParam), 0);
             return 0;
         }
@@ -319,6 +338,7 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
             ly = HIWORD(lParam);
         }
         break;
+    }
 
     case WM_MOUSELEAVE:
         hasMouse = false;
@@ -326,6 +346,10 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         rMouseDown = false;
         break;
 
+    case WM_MOUSEWHEEL:
+        gameplay::Game::getInstance()->mouseWheelEvent(LOWORD(lParam), HIWORD(lParam), GET_WHEEL_DELTA_WPARAM(wParam) / 120);
+        break;
+
     case WM_KEYDOWN:
         if (wParam == VK_LSHIFT || wParam == VK_RSHIFT)
             shiftDown = true;

+ 532 - 0
gameplay/src/PlatformiOS.mm

@@ -0,0 +1,532 @@
+#ifdef __APPLE__
+
+#include "Base.h"
+#include "Platform.h"
+#include "FileSystem.h"
+#include "Game.h"
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/EAGLDrawable.h>
+#import <OpenGLES/ES2/gl.h>
+#import <OpenGLES/ES2/glext.h>
+#import <mach/mach_time.h>
+
+
+using namespace std;
+using namespace gameplay;
+
+static const float ACCELEROMETER_X_FACTOR = 90.0f / WINDOW_WIDTH;
+static const float ACCELEROMETER_Y_FACTOR = 90.0f / WINDOW_HEIGHT;
+
+@class View;
+
+static View* __view = NULL;
+static long __timeStart;
+static long __timeAbsolute;
+static bool __vsync = WINDOW_VSYNC;
+static float __pitch;
+static float __roll;
+static int __lx;
+static int __ly;
+static bool __hasMouse = false;
+static bool __leftMouseDown = false;
+static bool __rightMouseDown = false;
+static bool __shiftDown = false;
+
+
+long getMachTimeInMilliseconds()
+{
+    static const int64_t kOneMillion = 1000 * 1000;
+    static mach_timebase_info_data_t s_timebase_info;
+    
+    if (s_timebase_info.denom == 0) 
+        (void) mach_timebase_info(&s_timebase_info);
+    
+    // mach_absolute_time() returns billionth of seconds, so divide by one million to get milliseconds
+    return (long)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
+}
+
+
+@interface View : UIView 
+{
+    EAGLContext* context;	
+    CADisplayLink* displayLink;
+	GLuint defaultFramebuffer;
+    GLuint colorRenderbuffer;
+    GLuint depthRenderbuffer;
+    GLint framebufferWidth;
+    GLint framebufferHeight;    
+    NSInteger swapInterval;
+    BOOL updating;
+    Game* _game;
+}
+
+@property (readonly, nonatomic, getter=isUpdating) BOOL updating;
+@property (readonly, nonatomic, getter=getContext) EAGLContext* context;
+
+- (void)startUpdating;
+- (void)stopUpdating;
+- (void)update:(id)sender;
+- (void)createFramebuffer;
+- (void)deleteFramebuffer;
+
+@end
+
+
+@implementation View
+
+@synthesize updating;
+@synthesize context;
+
++ (Class) layerClass
+{
+    return [CAEAGLLayer class];
+}
+
+- (id) initWithFrame:(CGRect)frame
+{
+    if ((self = [super initWithFrame:frame]))
+	{
+        // Do a sanity check
+        // A system version of 3.1 or greater is required to use CADisplayLink. 
+		NSString *reqSysVer = @"3.1";
+		NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
+		if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
+        {
+            // Log the system version
+            NSLog(@"System Version: %@", currSysVer);
+        }
+        else
+        {
+            printError("Invalid OS Version: %s\n", (currSysVer == NULL?"NULL":[currSysVer cStringUsingEncoding:NSASCIIStringEncoding]));
+            [self release];
+            return nil;
+        }
+        
+        
+        // Configure the CAEAGLLayer and setup out the rendering context
+        CAEAGLLayer* layer = (CAEAGLLayer *)self.layer;
+        layer.opaque = TRUE;
+        layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+                                   [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, 
+                                    kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+		context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+        if (!context || ![EAGLContext setCurrentContext:context])
+		{
+			[self release];
+			return nil;
+		}
+        
+        // Initialize Internal Defaults
+        displayLink = nil;
+        defaultFramebuffer = 0;
+        colorRenderbuffer = 0;
+        depthRenderbuffer = 0;
+        framebufferWidth = 0;
+        framebufferHeight = 0;
+		swapInterval = 1;        
+        updating = FALSE;
+        
+        [self createFramebuffer];
+        
+        // Set the resource path and initalize the game
+        NSString* bundlePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/"];
+        FileSystem::setResourcePath([bundlePath fileSystemRepresentation]); 
+        
+        _game = Game::getInstance();
+        __timeStart = getMachTimeInMilliseconds();
+        _game->run(WINDOW_WIDTH, WINDOW_HEIGHT);    // TODO: Handle based on current orientation
+    }
+    return self;
+}
+
+- (void) dealloc
+{
+    _game->exit();
+    [self deleteFramebuffer];
+    
+	if ([EAGLContext currentContext] == context)
+        [EAGLContext setCurrentContext:nil];
+	[context release];
+    [super dealloc];
+}
+
+- (void)createFramebuffer
+{
+    // iOS Requires all content go to a rendering buffer then it is swapped into the windows rendering surface
+    assert(defaultFramebuffer == 0);
+    //NSLog(@"EAGLView: creating Framebuffer");
+    
+    // Create the default frame buffer, and render buffer
+    glGenFramebuffers(1, &defaultFramebuffer);
+    glGenRenderbuffers(1, &colorRenderbuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);    
+    glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
+    
+    // request storage, width, and height of the view that we will render in
+    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
+    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth);
+    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight);
+    
+    glGenRenderbuffers(1, &depthRenderbuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, framebufferWidth, framebufferHeight);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
+    
+    // Sanity check, ensure that the framebuffer is valid
+    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+        NSLog(@"ERROR: Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
+}
+
+- (void)deleteFramebuffer
+{
+    // Deleting the framebuffer and all the buffers it contains
+    if (context) 
+    {
+        [EAGLContext setCurrentContext:context];        
+        if (defaultFramebuffer) 
+        {
+            glDeleteFramebuffers(1, &defaultFramebuffer);
+            defaultFramebuffer = 0;
+        }        
+        if (colorRenderbuffer) 
+        {
+            glDeleteRenderbuffers(1, &colorRenderbuffer);
+            colorRenderbuffer = 0;
+        }
+        if (depthRenderbuffer) 
+        {
+            glDeleteRenderbuffers(1, &depthRenderbuffer);
+            depthRenderbuffer = 0;
+        }
+    }
+}
+
+- (void)setSwapInterval:(NSInteger)interval
+{
+	if (interval >= 1)
+	{
+		swapInterval = interval;		
+		if (updating)
+		{
+			[self stopUpdating];
+			[self startUpdating];
+		}
+	}
+}
+
+- (int)swapInterval 
+{
+    return swapInterval;
+}
+
+- (void)startUpdating
+{
+	if (!updating)
+	{
+        displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
+        [displayLink setFrameInterval:swapInterval];
+        [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+		updating = TRUE;
+	}
+}
+
+- (void)stopUpdating
+{
+	if (updating)
+	{
+		[displayLink invalidate];
+        displayLink = nil;
+		updating = FALSE;
+	}
+}
+
+- (void)update:(id)sender
+{   
+    if (context != nil)
+    {
+        [EAGLContext setCurrentContext:context];
+        if (!defaultFramebuffer)
+            [self createFramebuffer];
+        
+        glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
+        glViewport(0, 0, framebufferWidth, framebufferHeight);
+
+        if (_game && _game->getState() == Game::RUNNING)       
+            _game->frame();
+        
+        glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
+        [context presentRenderbuffer:GL_RENDERBUFFER];
+    }
+}
+
+- (void) layoutSubviews
+{
+    [self deleteFramebuffer];
+}
+
+- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event 
+{
+    unsigned int uniqueTouch = 0;
+    for(UITouch *t in touches) 
+    {
+        CGPoint touchLoc = [t locationInView:nil];
+        // TODO: Handle this based on orientation
+        Game::getInstance()->touchEvent(Touch::TOUCH_PRESS, touchLoc.y,  WINDOW_WIDTH - touchLoc.x, uniqueTouch);
+    }
+}
+
+- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent *)event 
+{
+    unsigned int uniqueTouch = 0;
+    for(UITouch* t in touches) 
+    {
+        CGPoint touchLoc = [t locationInView:nil];
+        // TODO: Handle this based on orientation
+        Game::getInstance()->touchEvent(Touch::TOUCH_RELEASE, touchLoc.y, WINDOW_WIDTH - touchLoc.x, uniqueTouch);
+    }
+}
+
+- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event 
+{
+    // No equivalent for this in GamePlay -- treat as touch end
+    [self touchesEnded:touches withEvent:event];
+}
+
+- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event 
+{
+    unsigned 
+    int uniqueTouch = 0;
+    for(UITouch* t in touches) 
+    {
+        CGPoint touchLoc = [t locationInView:nil];
+        // TODO: Handle this based on orientation
+        Game::getInstance()->touchEvent(Touch::TOUCH_MOVE, touchLoc.y,  WINDOW_WIDTH - touchLoc.x, uniqueTouch);
+    }
+}
+
+@end
+
+
+@interface ViewController : UIViewController
+- (void)startUpdating;
+- (void)stopUpdating;
+@end
+
+
+@implementation ViewController 
+
+- (id)init 
+{
+    if((self = [super init])) 
+    {
+    }
+    return self;
+}
+
+- (void)dealloc 
+{
+    __view = nil;
+    [super dealloc];
+}
+
+- (void)didReceiveMemoryWarning
+{
+    [super didReceiveMemoryWarning];    
+    // Release any cached data, images, etc that aren't in use.
+}
+
+#pragma mark - View lifecycle
+- (void)loadView
+{
+    self.view = [[[View alloc] init] autorelease];
+    if(__view == nil) 
+    {
+        __view = self.view;
+    }
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    // Return YES for supported orientation, currently support landscape only?
+    return UIInterfaceOrientationIsLandscape(interfaceOrientation);
+}
+
+- (void)startUpdating 
+{
+    [(View*)self.view startUpdating];
+}
+
+- (void)stopUpdating 
+{
+    [(View*)self.view stopUpdating];
+}
+
+@end
+
+
+@interface AppDelegate : UIApplication <UIApplicationDelegate, UIAccelerometerDelegate>
+{
+    UIWindow* window;
+    ViewController* viewController;
+}
+@end
+
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
+{
+    [UIApplication sharedApplication].statusBarHidden = YES;
+    UIAccelerometer*  accelerometer = [UIAccelerometer sharedAccelerometer];
+    accelerometer.updateInterval = 1 / 40.0;    // 40Hz
+    accelerometer.delegate = self;
+    
+    window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+    viewController = [[ViewController alloc] init];
+    [window setRootViewController:viewController];
+    [window makeKeyAndVisible];
+    return YES;
+}
+
+
+- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
+{
+    UIAccelerationValue x, y, z;
+    x = acceleration.x;
+    y = acceleration.y;
+    z = acceleration.z;
+    
+    // Do something with the values.
+}
+
+- (void)applicationWillResignActive:(UIApplication*)application
+{    
+	[viewController stopUpdating];
+}
+
+- (void)applicationDidEnterBackground:(UIApplication*)application 
+{
+	[viewController stopUpdating];
+}
+
+- (void)applicationWillEnterForeground:(UIApplication*)application 
+{	
+	[viewController startUpdating];
+}
+
+- (void)applicationDidBecomeActive:(UIApplication*)application 
+{
+	[viewController startUpdating];
+}
+
+- (void)applicationWillTerminate:(UIApplication*)application 
+{	
+	[viewController stopUpdating];
+}
+
+- (void)dealloc 
+{
+    [window setRootViewController:nil];
+    [viewController release];
+    [window release];
+	[super dealloc];
+}
+
+@end
+
+
+namespace gameplay
+{
+    extern void printError(const char* format, ...)
+    {
+        va_list argptr;
+        va_start(argptr, format);
+        vfprintf(stderr, format, argptr);
+        fprintf(stderr, "\n");
+        va_end(argptr);
+    }
+    
+    Platform::Platform(Game* game)
+        : _game(game)
+    {
+    }
+    
+    Platform::Platform(const Platform& copy)
+    {
+        // hidden
+    }
+    
+    Platform::~Platform()
+    {
+    }
+    
+    Platform* Platform::create(Game* game)
+    {
+        Platform* platform = new Platform(game);
+        return platform;
+    }
+    
+    int Platform::enterMessagePump()
+    {
+        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+        [AppDelegate load];
+        UIApplicationMain(0, nil, NSStringFromClass([AppDelegate class]), NSStringFromClass([AppDelegate class]));
+        [pool release];
+        return EXIT_SUCCESS;
+    }
+    
+    long Platform::getAbsoluteTime()
+    {
+        __timeAbsolute = getMachTimeInMilliseconds();
+        return __timeAbsolute;
+    }
+    
+    void Platform::setAbsoluteTime(long time)
+    {
+        __timeAbsolute = time;
+    }
+    
+    bool Platform::isVsync()
+    {
+        return __vsync;
+    }
+    
+    void Platform::setVsync(bool enable)
+    {
+        __vsync = enable;
+    }
+    
+    int Platform::getOrientationAngle()
+    {
+        return 0;
+    }
+    
+    void Platform::getAccelerometerValues(float* pitch, float* roll)
+    {
+        *pitch = __pitch;
+        *roll = __roll;
+    }
+    
+    void Platform::setMultiTouch(bool enabled) 
+    {
+        __view.multipleTouchEnabled = enabled;
+    }
+    
+    bool Platform::isMultiTouch() 
+    {
+        return __view.multipleTouchEnabled;
+    }
+    
+    void Platform::swapBuffers()
+    {
+        if (__view)
+            [[__view getContext] presentRenderbuffer:GL_RENDERBUFFER];
+    }
+    
+}
+
+#endif

+ 42 - 28
gameplay/src/Quaternion.cpp

@@ -262,28 +262,55 @@ void Quaternion::lerp(const Quaternion& q1, const Quaternion& q2, float t, Quate
 }
 
 void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
+{
+    slerp(q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w, t, &dst->x, &dst->y, &dst->z, &dst->w);
+}
+
+void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
+{
+    assert(dst);
+    assert(!(t < 0.0f || t > 1.0f));
+
+    Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
+    Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
+
+    slerpForSquad(q1, q2, t, &dstQ);
+    slerpForSquad(s1, s2, t, &dstS);
+    slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
+}
+
+void Quaternion::slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw)
 {
     // Fast slerp implementation by kwhatmough:
     // It contains no division operations, no trig, no inverse trig
     // and no sqrt. Not only does this code tolerate small constraint
     // errors in the input quaternions, it actually corrects for them.
-    assert(dst);
+    assert(dstx && dsty && dstz && dstw);
     assert(!(t < 0.0f || t > 1.0f));
 
     if (t == 0.0f)
     {
-        memcpy(dst, &q1, sizeof(float) * 4);
+        *dstx = q1x;
+        *dsty = q1y;
+        *dstz = q1z;
+        *dstw = q1w;
         return;
     }
     else if (t == 1.0f)
     {
-        memcpy(dst, &q2, sizeof(float) * 4);
+        *dstx = q2x;
+        *dsty = q2y;
+        *dstz = q2z;
+        *dstw = q2w;
         return;
     }
 
-    if (q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w)
+    if (q1x == q2x && q1y == q2y && q1z == q2z && q1w == q2w)
     {
-        memcpy(dst, &q1, sizeof(float) * 4);
+        *dstx = q1x;
+        *dsty = q1y;
+        *dstz = q1z;
+        *dstw = q1w;
         return;
     }
 
@@ -293,7 +320,7 @@ void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quat
     float halfSecHalfTheta, versHalfTheta;
     float sqNotU, sqU;
 
-    float cosTheta = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;
+    float cosTheta = q1w * q2w + q1x * q2x + q1y * q2y + q1z * q2z;
 
     // As usual in all slerp implementations, we fold theta.
     alpha = cosTheta >= 0 ? 1.0f : -1.0f;
@@ -334,34 +361,21 @@ void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quat
     beta = f1 + f2b;
 
     // Apply final coefficients to a and b as usual.
-    float w = alpha * q1.w + beta * q2.w;
-    float x = alpha * q1.x + beta * q2.x;
-    float y = alpha * q1.y + beta * q2.y;
-    float z = alpha * q1.z + beta * q2.z;
+    float w = alpha * q1w + beta * q2w;
+    float x = alpha * q1x + beta * q2x;
+    float y = alpha * q1y + beta * q2y;
+    float z = alpha * q1z + beta * q2z;
 
     // This final adjustment to the quaternion's length corrects for
-    // any small constraint error in the inputs q1 and q2. But as you
+    // any small constraint error in the inputs q1 and q2 But as you
     // can see, it comes at the cost of 9 additional multiplication
     // operations. If this error-correcting feature is not required,
     // the following code may be removed.
     f1 = 1.5f - 0.5f * (w * w + x * x + y * y + z * z);
-    dst->w = w * f1;
-    dst->x = x * f1;
-    dst->y = y * f1;
-    dst->z = z * f1;
-}
-
-void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
-{
-    assert(dst);
-    assert(!(t < 0.0f || t > 1.0f));
-
-    Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
-    Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
-
-    slerpForSquad(q1, q2, t, &dstQ);
-    slerpForSquad(s1, s2, t, &dstS);
-    slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
+    *dstw = w * f1;
+    *dstx = x * f1;
+    *dsty = y * f1;
+    *dstz = z * f1;
 }
 
 void Quaternion::slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)

+ 30 - 2
gameplay/src/Quaternion.h

@@ -40,6 +40,8 @@ class Matrix;
  */
 class Quaternion
 {
+    friend class Curve;
+
 public:
 
     /**
@@ -293,7 +295,7 @@ public:
      * @param dst A quaternion to store the result in.
      */
     static void lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
-
+    
     /**
      * Interpolates between two quaternions using spherical linear interpolation.
      *
@@ -310,7 +312,7 @@ public:
      * @param dst A quaternion to store the result in.
      */
     static void slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
-
+    
     /**
      * Interpolates over a series of quaternions using spherical spline interpolation.
      *
@@ -350,6 +352,32 @@ public:
 
 private:
 
+    /**
+     * Interpolates between two quaternions using spherical linear interpolation.
+     *
+     * Spherical linear interpolation provides smooth transitions between different
+     * orientations and is often useful for animating models or cameras in 3D.
+     *
+     * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
+     * This method does not automatically normalize the input quaternions, so it is up to the
+     * caller to ensure they call normalize beforehand, if necessary.
+     *
+     * @param q1x The x component of the first quaternion.
+     * @param q1y The y component of the first quaternion.
+     * @param q1z The z component of the first quaternion.
+     * @param q1w The w component of the first quaternion.
+     * @param q2x The x component of the second quaternion.
+     * @param q2y The y component of the second quaternion.
+     * @param q2z The z component of the second quaternion.
+     * @param q2w The w component of the second quaternion.
+     * @param t The interpolation coefficient.
+     * @param dstx A pointer to store the x component of the slerp in.
+     * @param dsty A pointer to store the y component of the slerp in.
+     * @param dstz A pointer to store the z component of the slerp in.
+     * @param dstw A pointer to store the w component of the slerp in.
+     */
+    static void slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw);
+
     static void slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
 };
 

+ 261 - 16
gameplay/src/Transform.cpp

@@ -226,6 +226,13 @@ void Transform::getRightVector(Vector3* dst) const
     getMatrix().getRightVector(dst);
 }
 
+void Transform::rotate(float qx, float qy, float qz, float qw)
+{
+    Quaternion q(qx, qy, qz, qw);
+    _rotation.multiply(q);
+    dirty();
+}
+
 void Transform::rotate(const Quaternion& rotation)
 {
     _rotation.multiply(rotation);
@@ -640,49 +647,194 @@ void Transform::getAnimationPropertyValue(int propertyId, AnimationValue* value)
     }
 }
 
-void Transform::setAnimationPropertyValue(int propertyId, AnimationValue* value)
+void Transform::setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight)
 {
+    assert(blendWeight >= 0.0f && blendWeight <= 1.0f);
+    if (blendWeight == 0.0f)
+        return;
+
     switch (propertyId)
     {
         case ANIMATE_SCALE_UNIT:
-            setScale(value->getFloat(0));
+        {
+            float scale = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                scale *= blendWeight;
+
+            applyAnimationValueScaleX(scale);
+            applyAnimationValueScaleY(scale);
+            applyAnimationValueScaleZ(scale);
+            
             break;
+        }   
         case ANIMATE_SCALE:
-            setScale(value->getFloat(0), value->getFloat(1), value->getFloat(2));
+        {
+            float sx = value->getFloat(0);
+            float sy = value->getFloat(1);
+            float sz = value->getFloat(2);
+            if (blendWeight != 1.0f)
+            {
+                sx *= blendWeight;
+                sy *= blendWeight;
+                sz *= blendWeight;
+            }
+
+            applyAnimationValueScaleX(sx);
+            applyAnimationValueScaleY(sy);
+            applyAnimationValueScaleZ(sz);
+
             break;
+        }
         case ANIMATE_SCALE_X:
-            setScaleX(value->getFloat(0));
+        {
+            float sx = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                sx *= blendWeight;
+
+            applyAnimationValueScaleX(sx);
+
             break;
+        }
         case ANIMATE_SCALE_Y:
-            setScaleY(value->getFloat(0));
+        {
+            float sy = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                sy *= blendWeight;
+
+            applyAnimationValueScaleY(sy);
+
             break;
+        }
         case ANIMATE_SCALE_Z:
-            setScaleZ(value->getFloat(0));
+        {
+            float sz = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                sz *= blendWeight;
+
+            applyAnimationValueScaleZ(sz);
+
             break;
+        }
         case ANIMATE_ROTATE:
-            setRotation(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
+        {
+            Quaternion q(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
+
+            if (blendWeight != 1.0f)
+                Quaternion::slerp(Quaternion::identity(), q, blendWeight, &q);
+
+            applyAnimationValueRotation(&q);
+            
             break;
+        }
         case ANIMATE_TRANSLATE:
-            setTranslation(value->getFloat(0), value->getFloat(1), value->getFloat(2));
+        {
+            float tx = value->getFloat(0);
+            float ty = value->getFloat(1);
+            float tz = value->getFloat(2);
+
+            if (blendWeight != 1.0f)
+            {
+                tx *= blendWeight;
+                ty *= blendWeight;
+                tz *= blendWeight;
+            }
+
+            applyAnimationValueTranslationX(tx);
+            applyAnimationValueTranslationY(ty);
+            applyAnimationValueTranslationZ(tz);
+            
             break;
+        }
         case ANIMATE_TRANSLATE_X:
-            setTranslationX(value->getFloat(0));
+        {
+            float tx = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                tx *= blendWeight;
+
+            applyAnimationValueTranslationX(tx);
+
             break;
+        }
         case ANIMATE_TRANSLATE_Y:
-            setTranslationY(value->getFloat(0));
+        {
+            float ty = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                ty *= blendWeight;
+            
+            applyAnimationValueTranslationY(ty);
+
             break;
+        }
         case ANIMATE_TRANSLATE_Z:
-            setTranslationZ(value->getFloat(0));
+        {
+            float tz = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                tz *= blendWeight;
+
+            applyAnimationValueTranslationZ(tz);
+
             break;
+        }
         case ANIMATE_ROTATE_TRANSLATE:
-            setRotation(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
-            setTranslation(value->getFloat(4), value->getFloat(5), value->getFloat(6));
+        {
+            Quaternion q(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
+            float tx = value->getFloat(4);
+            float ty = value->getFloat(5);
+            float tz = value->getFloat(6);
+
+            if (blendWeight != 1.0f)
+            {
+                Quaternion::slerp(Quaternion::identity(), q, blendWeight, &q);
+                tx *= blendWeight;
+                ty *= blendWeight;
+                tz *= blendWeight;
+            }
+
+            applyAnimationValueRotation(&q);
+            applyAnimationValueTranslationX(tx);
+            applyAnimationValueTranslationY(ty);
+            applyAnimationValueTranslationZ(tz);
+            
             break;
+        }
         case ANIMATE_SCALE_ROTATE_TRANSLATE:
-            setScale(value->getFloat(0), value->getFloat(1), value->getFloat(2));
-            setRotation(value->getFloat(3), value->getFloat(4), value->getFloat(5), value->getFloat(6));
-            setTranslation(value->getFloat(7), value->getFloat(8), value->getFloat(9));
+        {
+            float sx = value->getFloat(0);
+            float sy = value->getFloat(1);
+            float sz = value->getFloat(2);
+            Quaternion q(value->getFloat(3), value->getFloat(4), value->getFloat(5), value->getFloat(6));
+            float tx = value->getFloat(7);
+            float ty = value->getFloat(8);
+            float tz = value->getFloat(9);
+
+            if (blendWeight != 1.0f)
+            {
+                sx *= blendWeight;
+                sy *= blendWeight;
+                sz *= blendWeight;
+                Quaternion::slerp(Quaternion::identity(), q, blendWeight, &q);
+                tx *= blendWeight;
+                ty *= blendWeight;
+                tz *= blendWeight;
+            }
+
+            applyAnimationValueScaleX(sx);
+            applyAnimationValueScaleY(sy);
+            applyAnimationValueScaleZ(sz);
+            applyAnimationValueRotation(&q);
+            applyAnimationValueTranslationX(tx);
+            applyAnimationValueTranslationY(ty);
+            applyAnimationValueTranslationZ(tz);
+            
             break;
+        }
         default:
             break;
     }
@@ -732,4 +884,97 @@ void Transform::transformChanged()
     }
 }
 
+void Transform::applyAnimationValueScaleX(float sx)
+{
+    if ((_animationPropertyBitFlag & ANIMATION_SCALE_X_BIT) != ANIMATION_SCALE_X_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_SCALE_X_BIT;
+        setScaleX(sx);
+    }
+    else
+    {
+        _scale.x += sx;
+        dirty();
+    }
+}
+
+void Transform::applyAnimationValueScaleY(float sy)
+{
+    if ((_animationPropertyBitFlag & ANIMATION_SCALE_Y_BIT) != ANIMATION_SCALE_Y_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_SCALE_Y_BIT;
+        setScaleY(sy);
+    }
+    else
+    {
+        _scale.y += sy;
+        dirty();
+    }
+}
+
+void Transform::applyAnimationValueScaleZ(float sz)
+{
+    if ((_animationPropertyBitFlag & ANIMATION_SCALE_Z_BIT) != ANIMATION_SCALE_Z_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_SCALE_Z_BIT;
+        setScaleZ(sz);
+    }
+    else
+    {
+        _scale.z += sz;
+        dirty();
+    }
+}
+
+void Transform::applyAnimationValueRotation(Quaternion* q)
+{
+    if ((_animationPropertyBitFlag & ANIMATION_ROTATION_BIT) != ANIMATION_ROTATION_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_ROTATION_BIT;
+        setRotation(*q);
+    }
+    else
+    {
+        rotate(*q);
+    }
+}
+
+void Transform::applyAnimationValueTranslationX(float tx)
+{
+    if ((_animationPropertyBitFlag & ANIMATION_TRANSLATION_X_BIT) != ANIMATION_TRANSLATION_X_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_TRANSLATION_X_BIT;
+        setTranslationX(tx);
+    }
+    else
+    {
+        translateX(tx);
+    }
+}
+
+void Transform::applyAnimationValueTranslationY(float ty)
+{
+    if ((_animationPropertyBitFlag & ANIMATION_TRANSLATION_Y_BIT) != ANIMATION_TRANSLATION_Y_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_TRANSLATION_Y_BIT;
+        setTranslationY(ty);
+    }
+    else
+    {
+        translateY(ty);
+    }
+}
+
+void Transform::applyAnimationValueTranslationZ(float tz)
+{
+    if ((_animationPropertyBitFlag & ANIMATION_TRANSLATION_Z_BIT) != ANIMATION_TRANSLATION_Z_BIT)
+    {
+        _animationPropertyBitFlag |= ANIMATION_TRANSLATION_Z_BIT;
+        setTranslationZ(tz);
+    }
+    else
+    {
+        translateZ(tz);
+    }
+}
 }

+ 29 - 3
gameplay/src/Transform.h

@@ -31,12 +31,12 @@ class Transform : public AnimationTarget
 public:
 
     /**
-     * Scale animation property. Data=sx,sy,sz
+     * Scale animation property. Data=scale
      */
     static const int ANIMATE_SCALE_UNIT = 0;
 
     /**
-     * Scale animation property. Data=scale
+     * Scale animation property. Data=sx,sy,sz
      */
     static const int ANIMATE_SCALE = 1;
 
@@ -324,6 +324,16 @@ public:
      */
     void getRightVector(Vector3* dst) const;
 
+    /**
+     * Rotates this transform's rotation component by the given rotation.
+     *
+     * @param qx The quaternion x value.
+     * @param qy The quaternion y value.
+     * @param qz The quaternion z value.
+     * @param qw The quaternion w value.
+     */
+    void rotate(float qx, float qy, float qz, float qw);
+
     /**
      * Rotates this transform's rotation component by the given rotation.
      *
@@ -715,7 +725,7 @@ public:
     /**
      * @see AnimationTarget#setAnimationProperty
      */
-    void setAnimationPropertyValue(int propertyId, AnimationValue* value);
+    void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f);
 
 protected:
 
@@ -735,6 +745,22 @@ protected:
     mutable bool _matrixDirty;
     std::list<TransformListener>* _listeners;
 
+private:
+    static const char ANIMATION_SCALE_X_BIT = 0x01; 
+    static const char ANIMATION_SCALE_Y_BIT = 0x02; 
+    static const char ANIMATION_SCALE_Z_BIT = 0x04; 
+    static const char ANIMATION_ROTATION_BIT = 0x08;  
+    static const char ANIMATION_TRANSLATION_X_BIT = 0x10; 
+    static const char ANIMATION_TRANSLATION_Y_BIT = 0x20; 
+    static const char ANIMATION_TRANSLATION_Z_BIT = 0x40; 
+
+    void applyAnimationValueScaleX(float sx);
+    void applyAnimationValueScaleY(float sy);
+    void applyAnimationValueScaleZ(float sz);
+    void applyAnimationValueRotation(Quaternion* q);
+    void applyAnimationValueTranslationX(float tx);
+    void applyAnimationValueTranslationY(float ty);
+    void applyAnimationValueTranslationZ(float tz);
 };
 
 }

+ 23 - 0
gameplay/src/gameplay-main-ios.mm

@@ -0,0 +1,23 @@
+#ifndef GAMEPLAYMAINIOS_H_
+#define GAMEPLAYMAINIOS_H_
+
+#ifdef __APPLE__
+
+#include "gameplay.h"
+
+using namespace gameplay;
+
+/**
+ * Main entry point.
+ */
+int main(int argc, char** argv)
+{
+    Game* game = Game::getInstance();
+    assert(game != NULL);
+    Platform* platform = Platform::create(game);
+    return platform->enterMessagePump();
+}
+
+#endif
+
+#endif

+ 2 - 1
gameplay/src/gameplay.h

@@ -4,6 +4,7 @@
 #include "Game.h"
 #include "Keyboard.h"
 #include "Touch.h"
+#include "Mouse.h"
 #include "FileSystem.h"
 #include "Package.h"
 
@@ -65,4 +66,4 @@
 #include "PhysicsHingeConstraint.h"
 #include "PhysicsSocketConstraint.h"
 #include "PhysicsSpringConstraint.h"
-#include "PhysicsRigidBody.h"
+#include "PhysicsRigidBody.h"