瀏覽代碼

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

Adam Blake 13 年之前
父節點
當前提交
353b877fd3

+ 4 - 1
gameplay/src/AudioSource.cpp

@@ -465,7 +465,10 @@ void AudioSource::transformChanged(Transform* transform, long cookie)
 {
 #ifndef __ANDROID__
     if (_node)
-        alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&_node->getTranslationWorld());
+    {
+    	Vector3 translation = _node->getTranslationWorld();
+        alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&translation.x);
+    }
 #else
     if (_playerLocation)
     {

+ 148 - 1
gameplay/src/DebugNew.cpp

@@ -5,6 +5,15 @@
 #include <cstdio>
 #include <cstdarg>
 
+#ifdef WIN32
+#include <windows.h>
+#include <dbghelp.h>
+#pragma comment(lib,"dbghelp.lib")
+
+#define MAX_STACK_FRAMES 16
+bool __trackStackTrace = false;
+#endif
+
 struct MemoryAllocationRecord
 {
     unsigned long address;          // address returned to the caller after allocation
@@ -13,6 +22,10 @@ struct MemoryAllocationRecord
     int line;                       // source line of the allocation request
     MemoryAllocationRecord* next;
     MemoryAllocationRecord* prev;
+#ifdef WIN32
+    bool trackStackTrace;
+    unsigned int pc[MAX_STACK_FRAMES];
+#endif
 };
 
 MemoryAllocationRecord* __memoryAllocations = 0;
@@ -99,6 +112,54 @@ void* debugAlloc(std::size_t size, const char* file, int line)
     rec->next = __memoryAllocations;
     rec->prev = 0;
 
+    // Capture the stack frame (up to MAX_STACK_FRAMES) if we 
+    // are running on Windows and the user has enabled it.
+#if defined(WIN32)
+    rec->trackStackTrace = __trackStackTrace;
+    if (rec->trackStackTrace)
+    {
+        static bool initialized = false;
+        if (!initialized)
+        {
+            if (!SymInitialize(GetCurrentProcess(), NULL, true))
+                gameplay::printError("Stack trace tracking will not work.");
+            initialized = true;
+        }
+    
+        // Get the current context (state of EBP, EIP, ESP registers).
+        static CONTEXT context;
+        RtlCaptureContext(&context);
+    
+        static STACKFRAME64 stackFrame;
+        memset(&stackFrame, 0, sizeof(STACKFRAME64));
+
+        // Initialize the stack frame based on the machine architecture.
+#ifdef _M_IX86
+        static const DWORD machineType = IMAGE_FILE_MACHINE_I386;
+        stackFrame.AddrPC.Offset = context.Eip;
+        stackFrame.AddrPC.Mode = AddrModeFlat;
+        stackFrame.AddrFrame.Offset = context.Ebp;
+        stackFrame.AddrFrame.Mode = AddrModeFlat;
+        stackFrame.AddrStack.Offset = context.Esp;
+        stackFrame.AddrStack.Mode = AddrModeFlat;
+#else
+#error "Machine architecture not supported!"
+#endif
+
+        // Walk up the stack and store the program counters.
+        memset(rec->pc, 0, sizeof(rec->pc));
+        for (int i = 0; i < MAX_STACK_FRAMES; i++)
+        {
+            rec->pc[i] = stackFrame.AddrPC.Offset;
+            if (!StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame,
+                &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
+            {
+                break;
+            }
+        }
+    }
+#endif
+
     if (__memoryAllocations)
         __memoryAllocations->prev = rec;
     __memoryAllocations = rec;
@@ -137,6 +198,70 @@ void debugFree(void* p)
     free(mem);
 }
 
+#ifdef WIN32
+void printStackTrace(MemoryAllocationRecord* rec)
+{
+    const unsigned int bufferSize = 512;
+
+    // Resolve the program counter to the corresponding function names.
+    unsigned int pc;
+    for (int i = 0; i < MAX_STACK_FRAMES; i++)
+    {
+        // Check to see if we are at the end of the stack trace.
+        pc = rec->pc[i];
+        if (pc == 0)
+            break;
+
+        // Get the function name.
+        unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + bufferSize];
+        IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)buffer;
+        DWORD64 displacement;
+        memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + bufferSize);
+        symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+        symbol->MaxNameLength = bufferSize;
+        if (!SymGetSymFromAddr64(GetCurrentProcess(), pc, &displacement, symbol))
+        {
+            gameplay::printError("[memory] STACK TRACE: <unknown location>");
+        }
+        else
+        {
+            symbol->Name[bufferSize - 1] = '\0';
+
+            // Check if we need to go further up the stack.
+            if (strncmp(symbol->Name, "operator new", 12) == 0)
+            {
+                // In operator new or new[], keep going...
+            }
+            else
+            {
+                // Get the file and line number.
+                if (pc != 0)
+                {
+                    IMAGEHLP_LINE64 line;
+                    DWORD displacement;
+                    memset(&line, 0, sizeof(line));
+                    line.SizeOfStruct = sizeof(line);
+                    if (!SymGetLineFromAddr64(GetCurrentProcess(), pc, &displacement, &line))
+                    {
+                        gameplay::printError("[memory] STACK TRACE: %s - <unknown file>:<unknown line number>", symbol->Name);
+                    }
+                    else
+                    {
+                        const char* file = strrchr(line.FileName, '\\');
+                        if(!file) 
+                            file = line.FileName;
+                        else
+                            file++;
+                        
+                        gameplay::printError("[memory] STACK TRACE: %s - %s:%d", symbol->Name, file, line.LineNumber);
+                    }
+                }
+            }
+        }
+    }
+}
+#endif
+
 extern void printMemoryLeaks()
 {
     // Dump general heap memory leaks
@@ -150,10 +275,32 @@ extern void printMemoryLeaks()
         MemoryAllocationRecord* rec = __memoryAllocations;
         while (rec)
         {
-            gameplay::printError("[memory] LEAK: HEAP allocation leak of size %d leak from line %d in file '%s'.", rec->size, rec->line, rec->file);
+#ifdef WIN32
+            if (rec->trackStackTrace)
+            {
+                gameplay::printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d:", rec->address, rec->size);
+                printStackTrace(rec);
+            }
+            else
+                gameplay::printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.", rec->address, rec->size, rec->line, rec->file);
+#else
+            gameplay::printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.", rec->address, rec->size, rec->line, rec->file);
+#endif
             rec = rec->next;
         }
     }
 }
 
+#if defined(WIN32)
+void setTrackStackTrace(bool trackStackTrace)
+{
+    __trackStackTrace = trackStackTrace;
+}
+
+void toggleTrackStackTrace()
+{
+    __trackStackTrace = !__trackStackTrace;
+}
+#endif
+
 #endif

+ 14 - 0
gameplay/src/DebugNew.h

@@ -89,4 +89,18 @@ T* bullet_new(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
 #endif
 }
 
+#if defined(WIN32)
+/**
+ * Sets whether stack traces are tracked on memory allocations or not.
+ * 
+ * @param trackStackTrace Whether to track the stack trace on memory allocations.
+ */
+void setTrackStackTrace(bool trackStackTrace);
+
+/**
+ * Toggles stack trace tracking on memory allocations.
+ */
+void toggleTrackStackTrace();
+#endif
+
 #endif

+ 6 - 5
gameplay/src/Game.cpp

@@ -21,6 +21,7 @@ Game::Game()
 {
     assert(__gameInstance == NULL);
     __gameInstance = this;
+    _timeEvents = new std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >();
 }
 
 Game::Game(const Game& copy)
@@ -31,7 +32,7 @@ Game::~Game()
 {
     // Do not call any virtual functions from the destructor.
     // Finalization is done from outside this class.
-
+    delete _timeEvents;
 #ifdef GAMEPLAY_MEM_LEAK_DETECTION
     Ref::printLeaks();
     printMemoryLeaks();
@@ -280,7 +281,7 @@ void Game::schedule(long timeOffset, TimeListener* timeListener, void* cookie)
 {
     assert(timeListener);
     TimeEvent timeEvent(getGameTime() + timeOffset, timeListener, cookie);
-    _timeEvents.push(timeEvent);
+    _timeEvents->push(timeEvent);
 }
 
 bool Game::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
@@ -304,15 +305,15 @@ void Game::updateOnce()
 
 void Game::fireTimeEvents(long frameTime)
 {
-    while (_timeEvents.size() > 0)
+    while (_timeEvents->size() > 0)
     {
-        const TimeEvent* timeEvent = &_timeEvents.top();
+        const TimeEvent* timeEvent = &_timeEvents->top();
         if (timeEvent->time > frameTime)
         {
             break;
         }
         timeEvent->listener->timeEvent(frameTime - timeEvent->time, timeEvent->cookie);
-        _timeEvents.pop();
+        _timeEvents->pop();
     }
 }
 

+ 14 - 1
gameplay/src/Game.h

@@ -392,7 +392,9 @@ private:
     AudioController* _audioController;          // Controls audio sources that are playing in the game.
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
     AudioListener* _audioListener;              // The audio listener in 3D space.
-    std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> > _timeEvents; // Contains the scheduled time events.
+    std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >* _timeEvents; // Contains the scheduled time events.
+
+    // Note: Do not add STL object member variables on the stack; this will cause false memory leaks to be reported.
 
     friend class SplashDisplayer;
 };
@@ -425,6 +427,17 @@ private:
     long _startTime;
 };
 
+/**
+ * Displays a splash screen using the {@link Game#renderOnce} mechanism for at least the given amount
+ * of time. This function is intended to be called at the beginning of a block of code that is be 
+ * executed while the splash screen is displayed (i.e. Game#initialize). This function will block 
+ * at the end of the block of code in which it is called for the amount of time that has not yet elapsed.
+ * 
+ * @param instance See {@link Game#renderOnce}.
+ * @param method See {@link Game#renderOnce}.
+ * @param cookie See {@link Game#renderOnce}.
+ * @param time The minimum amount of time to display the splash screen (in milliseconds).
+ */
 #define displaySplash(instance, method, cookie, time) \
     SplashDisplayer __##instance##SplashDisplayer; \
     __##instance##SplashDisplayer.run(instance, method, cookie, time)

+ 1 - 1
gameplay/src/Node.cpp

@@ -745,7 +745,7 @@ void Node::cloneInto(Node* node, NodeCloneContext &context) const
     }
     if (Light* light = getLight())
     {
-        Light* lightClone = lightClone = light->clone(context);
+        Light* lightClone = light->clone(context);
         node->setLight(lightClone);
         lightClone->release();
     }

+ 29 - 26
gameplay/src/PhysicsCharacter.cpp

@@ -32,7 +32,7 @@ public:
 	{
 	}
 
-	virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
+	btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
 	{
 		if (convexResult.m_hitCollisionObject == _me)
 			return btScalar(1.0);
@@ -72,7 +72,7 @@ PhysicsCharacter::PhysicsCharacter(Node* node, const PhysicsCollisionShape::Defi
 	setMaxSlopeAngle(45.0f);
 
     // Set the collision flags on the ghost object to indicate it's a character
-    //_ghostObject->setCollisionFlags(_ghostObject->getCollisionFlags() | btCollisionObject::CF_CHARACTER_OBJECT);
+    _ghostObject->setCollisionFlags(_ghostObject->getCollisionFlags() | btCollisionObject::CF_CHARACTER_OBJECT);
 
     // Register ourselves as an action on the physics world so we are called back during physics ticks
     Game::getInstance()->getPhysicsController()->_world->addAction(this);
@@ -432,7 +432,7 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
     {
         // No velocity, so we aren't moving
         return;
-    }
+	}
 
     // Translate the target position by the velocity vector (already scaled by t)
     btVector3 targetPosition = _currentPosition + velocity;
@@ -455,7 +455,7 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
 	{
         updateTargetPositionFromCollision(targetPosition, _collisionNormal);
 	}
-
+ 
 	int maxIter = 10;
 
 	while (fraction > btScalar(0.01) && maxIter-- > 0)
@@ -465,24 +465,25 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
 		btVector3 sweepDirNegative(_currentPosition - targetPosition);
 
 		ClosestNotMeConvexResultCallback callback(_ghostObject, sweepDirNegative, btScalar(0.0));
-		callback.m_collisionFilterGroup = btBroadphaseProxy::CharacterFilter;
-		callback.m_collisionFilterMask = btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter;
+		callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
+		callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
+		//callback.m_collisionFilterGroup = btBroadphaseProxy::CharacterFilter;
+		//callback.m_collisionFilterMask = btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter;
 
-		_ghostObject->convexSweepTest(_collisionShape->getShape<btConvexShape>(), start, end, callback, 0.01f/*collisionWorld->getDispatchInfo().m_allowedCcdPenetration*/);
+		_ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, 0.0f);//collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
 
 		fraction -= callback.m_closestHitFraction;
 
 		if (callback.hasHit())
         {
-			// We hit something so can move only a fraction
-			//btScalar hitDistance = (callback.m_hitPointWorld - _currentPosition).length();
-
-            //targetPosition = _currentPosition;
-			//targetPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction * 0.1f);
-
-			//btVector3 normalDir = callback.m_hitNormalWorld;
-			//normalDir.normalize();
-			//targetPosition = callback.m_hitPointWorld + (normalDir * 0.2f);
+			/*Vector3 normal(callback.m_hitNormalWorld.x(), callback.m_hitNormalWorld.y(), callback.m_hitNormalWorld.z());
+			PhysicsCollisionObject* o = Game::getInstance()->getPhysicsController()->getCollisionObject(callback.m_hitCollisionObject);
+			if (o->getType() == PhysicsCollisionObject::RIGID_BODY && o->isDynamic())
+			{
+				PhysicsRigidBody* rb = static_cast<PhysicsRigidBody*>(o);
+				normal.normalize();
+				rb->applyImpulse(-normal);
+			}*/
 
 			updateTargetPositionFromCollision(targetPosition, callback.m_hitNormalWorld);
 			btVector3 currentDir = targetPosition - _currentPosition;
@@ -501,7 +502,6 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
         else
         {
             // Nothing in our way
-            //_currentPosition = targetPosition;
             break;
         }
     }
@@ -521,9 +521,8 @@ void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
     btVector3 targetPosition = _currentPosition + _fallVelocity;
 
     // Perform a convex sweep test between current and target position
-    btTransform start, end;
-    start.setIdentity();
-    end.setIdentity();
+	btTransform start = _ghostObject->getWorldTransform();
+	btTransform end = _ghostObject->getWorldTransform();
     start.setOrigin(_currentPosition);
     end.setOrigin(targetPosition);
 
@@ -534,7 +533,11 @@ void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
     ClosestNotMeConvexResultCallback callback(_ghostObject, btVector3(0, 1, 0), _cosSlopeAngle);
 	callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
 	callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
-	_ghostObject->convexSweepTest(_collisionShape->getShape<btConvexShape>(), start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+	//callback.m_collisionFilterGroup = btBroadphaseProxy::CharacterFilter;
+	//callback.m_collisionFilterMask = btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter;
+
+	_ghostObject->convexSweepTest(static_cast<btConvexShape*>(_collisionShape->getShape()), start, end, callback, 0.0f);//collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
 	if (callback.hasHit())
 	{
         // Collision detected, fix it
@@ -618,7 +621,9 @@ bool PhysicsCharacter::fixCollision(btCollisionWorld* world)
 	world->getDispatcher()->dispatchAllCollisionPairs(pairCache, world->getDispatchInfo(), world->getDispatcher());
 
     // Store our current world position
-    btVector3 currentPosition = _ghostObject->getWorldTransform().getOrigin();
+    Vector3 startPosition;
+	_node->getWorldMatrix().getTranslation(&startPosition);
+	btVector3 currentPosition = BV(startPosition);
 
     // Handle all collisions/overlappign pairs
 	btScalar maxPenetration = btScalar(0.0);
@@ -668,10 +673,8 @@ bool PhysicsCharacter::fixCollision(btCollisionWorld* world)
 		}
 	}
 
-    // Set the new world transformation to apply to fix the collision
-	btTransform newTransform = _ghostObject->getWorldTransform();
-	newTransform.setOrigin(currentPosition);
-	_ghostObject->setWorldTransform(newTransform);
+	// Set the new world transformation to apply to fix the collision
+	_node->translate(Vector3(currentPosition.x(), currentPosition.y(), currentPosition.z()) - startPosition);
 
 	return collision;
 }

+ 12 - 7
gameplay/src/PhysicsCollisionShape.cpp

@@ -10,6 +10,11 @@ PhysicsCollisionShape::PhysicsCollisionShape(Type type, btCollisionShape* shape)
 	memset(&_shapeData, 0, sizeof(_shapeData));
 }
 
+PhysicsCollisionShape::PhysicsCollisionShape(const PhysicsCollisionShape& copy)
+{
+	// hidden
+}
+
 PhysicsCollisionShape::~PhysicsCollisionShape()
 {
 	if (_shape)
@@ -80,8 +85,8 @@ PhysicsCollisionShape::Definition PhysicsCollisionShape::box(const Vector3& exte
 {
 	Definition d;
 	d.type = SHAPE_BOX;
-	d.data.boxExtents = extents;
-	d.data.boxCenter = center;
+	memcpy(d.data.box.extents, &extents.x, sizeof(float) * 3);
+	memcpy(d.data.box.center, &center.x, sizeof(float) * 3);
 	d.isExplicit = true;
 	d.centerAbsolute = absolute;
 	return d;
@@ -100,8 +105,8 @@ PhysicsCollisionShape::Definition PhysicsCollisionShape::sphere(float radius, co
 {
 	Definition d;
 	d.type = SHAPE_SPHERE;
-	d.data.sphereRadius = radius;
-	d.data.sphereCenter = center;
+	d.data.sphere.radius = radius;
+	memcpy(d.data.sphere.center, &center.x, sizeof(float) * 3);
 	d.isExplicit  = true;
 	d.centerAbsolute = absolute;
 	return d;
@@ -120,9 +125,9 @@ PhysicsCollisionShape::Definition PhysicsCollisionShape::capsule(float radius, f
 {
 	Definition d;
 	d.type = SHAPE_CAPSULE;
-	d.data.capsuleRadius = radius;
-	d.data.capsuleHeight = height;
-	d.data.capsuleCenter = center;
+	d.data.capsule.radius = radius;
+	d.data.capsule.height = height;
+	memcpy(d.data.capsule.center, &center.x, sizeof(float) * 3);
 	d.isExplicit = true;
 	d.centerAbsolute = absolute;
 	return d;

+ 15 - 16
gameplay/src/PhysicsCollisionShape.h

@@ -55,13 +55,17 @@ public:
 		PhysicsCollisionShape::Type type;
 
 		// Shape data.
+		struct BoxData { float center[3], extents[3]; };
+		struct SphereData { float center[3]; float radius; };
+		struct CapsuleData { float center[3]; float radius, height; };
+
 		union
 		{
-			struct { Vector3 boxExtents, boxCenter; };
-			struct { Vector3 sphereCenter; float sphereRadius; };
-			struct { Vector3 capsuleCenter; float capsuleRadius, capsuleHeight; };
-			struct { Image* heightfield; };
-			struct { Mesh* mesh; };
+			BoxData box;
+			SphereData sphere;
+			CapsuleData capsule;
+			Image* heightfield;
+			Mesh* mesh;
 		} data;
 
 		// Whether the shape definition is explicit, or if it is inherited from node bounds.
@@ -83,17 +87,7 @@ public:
 	 *
 	 * @return The bullet shape object.
 	 */
-	template <class T> T* getShape() const
-	{
-		return static_cast<T*>(_shape);
-	}
-
-	/**
-	 * Returns the internal bullet physics shape object.
-	 *
-	 * @return The bullet shape object.
-	 */
-	template <> btCollisionShape* getShape<btCollisionShape>() const
+	btCollisionShape* getShape() const
 	{
 		return _shape;
 	}
@@ -195,6 +189,11 @@ private:
 	 */
 	PhysicsCollisionShape(Type type, btCollisionShape* shape);
 
+	/** 
+	 * Hidden copy constructor.
+	 */
+	PhysicsCollisionShape(const PhysicsCollisionShape& copy);
+
 	/**
 	 * Destructor.
 	 */

+ 13 - 13
gameplay/src/PhysicsController.cpp

@@ -275,7 +275,7 @@ void PhysicsController::update(long elapsedTime)
     {
         Listener::EventType oldStatus = _status;
 
-        if (_status = Listener::DEACTIVATED)
+        if (_status == Listener::DEACTIVATED)
         {
             for (int i = 0; i < _world->getNumCollisionObjects(); i++)
             {
@@ -402,15 +402,15 @@ void PhysicsController::addCollisionObject(PhysicsCollisionObject* object)
     switch (object->getType())
     {
     case PhysicsCollisionObject::RIGID_BODY:
-		_world->addRigidBody(static_cast<btRigidBody*>(object->getCollisionObject()));//, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::AllFilter);
+		_world->addRigidBody(static_cast<btRigidBody*>(object->getCollisionObject()), btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::DefaultFilter | btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::AllFilter);
         break;
 
     case PhysicsCollisionObject::CHARACTER:
-		_world->addCollisionObject(object->getCollisionObject());//, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::AllFilter);//, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::CharacterFilter );// | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter*/ 0);
+		_world->addCollisionObject(object->getCollisionObject(), btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::DefaultFilter | btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::AllFilter);
         break;
 
     case PhysicsCollisionObject::GHOST_OBJECT:
-		_world->addCollisionObject(object->getCollisionObject());//, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::AllFilter);//, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::DefaultFilter | btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter);
+		_world->addCollisionObject(object->getCollisionObject(), btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::DefaultFilter | btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::AllFilter);
         break;
 
     default:
@@ -523,17 +523,17 @@ PhysicsCollisionShape* PhysicsController::createShape(Node* node, const PhysicsC
 			if (shape.isExplicit)
 			{
 				// Use the passed in box information
-				collisionShape = createBox(shape.data.boxExtents, Vector3::one());
+				collisionShape = createBox(Vector3(shape.data.box.extents), Vector3::one());
 
 				if (shape.centerAbsolute)
 				{
-					computeCenterOfMass(shape.data.boxCenter, scale, centerOfMassOffset);
+					computeCenterOfMass(Vector3(shape.data.box.center), scale, centerOfMassOffset);
 				}
 				else
 				{
 					BoundingBox box;
 					getBoundingBox(node, &box);
-					computeCenterOfMass(box.getCenter() + shape.data.boxCenter, scale, centerOfMassOffset);
+					computeCenterOfMass(box.getCenter() + Vector3(shape.data.box.center), scale, centerOfMassOffset);
 				}
 			}
 			else
@@ -553,17 +553,17 @@ PhysicsCollisionShape* PhysicsController::createShape(Node* node, const PhysicsC
 			if (shape.isExplicit)
 			{
 				// Use the passed in sphere information
-				collisionShape = createSphere(shape.data.sphereRadius, Vector3::one());
+				collisionShape = createSphere(shape.data.sphere.radius, Vector3::one());
 
 				if (shape.centerAbsolute)
 				{
-					computeCenterOfMass(shape.data.sphereCenter, scale, centerOfMassOffset);
+					computeCenterOfMass(Vector3(shape.data.sphere.center), scale, centerOfMassOffset);
 				}
 				else
 				{
 					BoundingSphere sphere;
 					getBoundingSphere(node, &sphere);
-					computeCenterOfMass(sphere.center + shape.data.sphereCenter, scale, centerOfMassOffset);
+					computeCenterOfMass(sphere.center + Vector3(shape.data.sphere.center), scale, centerOfMassOffset);
 				}
 			}
 			else
@@ -583,17 +583,17 @@ PhysicsCollisionShape* PhysicsController::createShape(Node* node, const PhysicsC
 			if (shape.isExplicit)
 			{
 				// Use the passed in capsule information
-				collisionShape = createCapsule(shape.data.capsuleRadius, shape.data.capsuleHeight, Vector3::one());
+				collisionShape = createCapsule(shape.data.capsule.radius, shape.data.capsule.height, Vector3::one());
 
 				if (shape.centerAbsolute)
 				{
-					computeCenterOfMass(shape.data.capsuleCenter, scale, centerOfMassOffset);
+					computeCenterOfMass(Vector3(shape.data.capsule.center), scale, centerOfMassOffset);
 				}
 				else
 				{
 					BoundingBox box;
 					getBoundingBox(node, &box);
-					computeCenterOfMass(box.getCenter() + shape.data.capsuleCenter, scale, centerOfMassOffset);
+					computeCenterOfMass(box.getCenter() + Vector3(shape.data.capsule.center), scale, centerOfMassOffset);
 				}
 			}
 			else

+ 1 - 1
gameplay/src/PhysicsGhostObject.cpp

@@ -17,7 +17,7 @@ PhysicsGhostObject::PhysicsGhostObject(Node* node, const PhysicsCollisionShape::
 
 	// Create the ghost object.
     _ghostObject = bullet_new<btPairCachingGhostObject>();
-	_ghostObject->setCollisionShape(_collisionShape->getShape<btCollisionShape>());
+	_ghostObject->setCollisionShape(_collisionShape->getShape());
 
     // Initialize a physics motion state object for syncing the transform.
 	_motionState = new PhysicsMotionState(_node, &centerOfMassOffset);

+ 3 - 3
gameplay/src/PhysicsRigidBody.cpp

@@ -25,10 +25,10 @@ PhysicsRigidBody::PhysicsRigidBody(Node* node, const PhysicsCollisionShape::Defi
     // inertia since Bullet doesn't currently support this.
     btVector3 localInertia(0.0, 0.0, 0.0);
 	if (parameters.mass != 0.0 && _collisionShape->getType() != PhysicsCollisionShape::SHAPE_MESH)
-		_collisionShape->getShape<btCollisionShape>()->calculateLocalInertia(parameters.mass, localInertia);
+		_collisionShape->getShape()->calculateLocalInertia(parameters.mass, localInertia);
 
     // Create the Bullet physics rigid body object.
-    btRigidBody::btRigidBodyConstructionInfo rbInfo(parameters.mass, _motionState, _collisionShape->getShape<btCollisionShape>(), localInertia);
+    btRigidBody::btRigidBodyConstructionInfo rbInfo(parameters.mass, _motionState, _collisionShape->getShape(), localInertia);
     rbInfo.m_friction = parameters.friction;
     rbInfo.m_restitution = parameters.restitution;
     rbInfo.m_linearDamping = parameters.linearDamping;
@@ -182,7 +182,7 @@ PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
     // Load the defined properties.
     properties->rewind();
     const char* name;
-    while (name = properties->getNextProperty())
+    while ((name = properties->getNextProperty()) != NULL)
     {
         if (strcmp(name, "type") == 0)
         {

+ 2 - 1
gameplay/src/PlatformQNX.cpp

@@ -4,6 +4,7 @@
 #include "Platform.h"
 #include "FileSystem.h"
 #include "Game.h"
+#include "Form.h"
 #include <unistd.h>
 #include <sys/keycodes.h>
 #include <screen/screen.h>
@@ -942,7 +943,7 @@ int Platform::enterMessagePump()
                         if ((flags & KEY_REPEAT) == 0)
                         {
                             keyEventInternal(evt, getKey(value));
-                            if (evt == gameplay::Keyboard::KEY_PRESS && flags & KEY_SYM_VALID)
+                            if (evt == gameplay::Keyboard::KEY_PRESS && (flags & KEY_SYM_VALID))
                             {
                                 int unicode = getUnicode(value);
                                 if (unicode)

+ 45 - 1
gameplay/src/Scene.cpp

@@ -356,6 +356,7 @@ void drawDebugLine(MeshBatch* batch, const Vector3& point1, const Vector3& point
 }
 
 #define DEBUG_BOX_COLOR Vector3(0, 1, 0)
+#define DEBUG_SPHERE_COLOR Vector3(0, 1, 0)
 
 void drawDebugBox(MeshBatch* batch, const BoundingBox& box, const Matrix& matrix)
 {
@@ -384,6 +385,49 @@ void drawDebugBox(MeshBatch* batch, const BoundingBox& box, const Matrix& matrix
 
 void drawDebugSphere(MeshBatch* batch, const BoundingSphere& sphere)
 {
+	// Draw three rings for the sphere (one for the x, y and z axes)
+	Vector3 pos1, pos2;
+	float step = MATH_PI * 0.2f;
+	float max = MATH_PIX2 + step;
+
+	// X ring
+	for (float r = 0.0f; r < max; r += step)
+	{
+		pos2.x = sphere.center.x;
+		pos2.y = sphere.center.y + std::cos(r) * sphere.radius;
+		pos2.z = sphere.center.z + std::sin(r) * sphere.radius;
+
+		if (r > 0)
+			drawDebugLine(batch, pos1, pos2, DEBUG_SPHERE_COLOR);
+
+		pos1 = pos2;
+	}
+
+	// Y ring
+	for (float r = 0.0f; r < max; r += step)
+	{
+		pos2.x = sphere.center.x + std::cos(r) * sphere.radius;
+		pos2.y = sphere.center.y;
+		pos2.z = sphere.center.z + std::sin(r) * sphere.radius;
+
+		if (r > 0)
+			drawDebugLine(batch, pos1, pos2, DEBUG_SPHERE_COLOR);
+
+		pos1 = pos2;
+	}
+
+	// Z ring
+	for (float r = 0.0f; r < max; r += step)
+	{
+		pos2.x = sphere.center.x + std::cos(r) * sphere.radius;
+		pos2.y = sphere.center.y + std::sin(r) * sphere.radius;
+		pos2.z = sphere.center.z;
+
+		if (r > 0)
+			drawDebugLine(batch, pos1, pos2, DEBUG_SPHERE_COLOR);
+
+		pos1 = pos2;
+	}
 }
 
 void drawDebugNode(MeshBatch* batch, Node* node, unsigned int debugFlags)
@@ -406,7 +450,7 @@ void drawDebugNode(MeshBatch* batch, Node* node, unsigned int debugFlags)
 		}
 	}
 
-	if ((debugFlags & Scene::DEBUG_SPHERES) && !node->getBoundingSphere().isEmpty())
+	if ((debugFlags & Scene::DEBUG_SPHERES) && model)
 	{
 		drawDebugSphere(batch, node->getBoundingSphere());
 	}

+ 5 - 5
gameplay/src/SceneLoader.cpp

@@ -164,7 +164,7 @@ void SceneLoader::applyNodeProperties(const Scene* scene, const Properties* scen
             for (unsigned int j = 0, pcount = sceneNode._properties.size(); j < pcount; ++j)
             {
                 SceneNodeProperty& snp = sceneNode._properties[j];
-                if ((typeFlags & snp._type) == snp._type)
+                if (typeFlags & snp._type)
                     applyNodeProperty(sceneNode, node, sceneProperties, snp);
             }
         }
@@ -481,7 +481,7 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
     // Go through the child namespaces of the scene.
     Properties* ns;
     const char* name = NULL;
-    while (ns = sceneProperties->getNextNamespace())
+    while ((ns = sceneProperties->getNextNamespace()) != NULL)
     {
         if (strcmp(ns->getNamespace(), "node") == 0)
         {
@@ -496,7 +496,7 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
             SceneNode& sceneNode = _sceneNodes[_sceneNodes.size()-1];
             sceneNode._nodeID = ns->getId();
 
-            while (name = ns->getNextProperty())
+            while ((name = ns->getNextProperty()) != NULL)
             {
                 if (strcmp(name, "url") == 0)
                 {
@@ -552,7 +552,7 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
         {
             // Load all the animations.
             Properties* animation;
-            while (animation = ns->getNextNamespace())
+            while ((animation = ns->getNextNamespace()) != NULL)
             {
                 if (strcmp(animation->getNamespace(), "animation") == 0)
                 {
@@ -753,7 +753,7 @@ void SceneLoader::loadPhysics(Properties* physics, Scene* scene)
 
     Properties* constraint;
     const char* name;
-    while (constraint = physics->getNextNamespace())
+    while ((constraint = physics->getNextNamespace()) != NULL)
     {
         if (strcmp(constraint->getNamespace(), "constraint") == 0)
         {

+ 1 - 1
gameplay/src/Theme.cpp

@@ -742,7 +742,7 @@ namespace gameplay
 
     Theme::Style::~Style()
     {
-        for (int i = 0; i < MAX_OVERLAYS; i++)
+        for (unsigned int i = 0; i < MAX_OVERLAYS; i++)
         {
             SAFE_RELEASE(_overlays[i]);
         }

+ 2 - 2
gameplay/src/Vector2.cpp

@@ -14,7 +14,7 @@ Vector2::Vector2(float x, float y)
     set(x, y);
 }
 
-Vector2::Vector2(float* array)
+Vector2::Vector2(const float* array)
 {
     set(array);
 }
@@ -235,7 +235,7 @@ void Vector2::set(float x, float y)
     this->y = y;
 }
 
-void Vector2::set(float* array)
+void Vector2::set(const float* array)
 {
     assert(array);
 

+ 2 - 2
gameplay/src/Vector2.h

@@ -41,7 +41,7 @@ public:
      *
      * @param array An array containing the elements of the vector in the order x, y.
      */
-    Vector2(float* array);
+    Vector2(const float* array);
 
     /**
      * Constructs a vector that describes the direction between the specified points.
@@ -282,7 +282,7 @@ public:
      *
      * @param array An array containing the elements of the vector in the order x, y.
      */
-    void set(float* array);
+    void set(const float* array);
 
     /**
      * Sets the elements of this vector to those in the specified vector.

+ 2 - 2
gameplay/src/Vector3.cpp

@@ -14,7 +14,7 @@ Vector3::Vector3(float x, float y, float z)
     set(x, y, z);
 }
 
-Vector3::Vector3(float* array)
+Vector3::Vector3(const float* array)
 {
     set(array);
 }
@@ -277,7 +277,7 @@ void Vector3::set(float x, float y, float z)
     this->z = z;
 }
 
-void Vector3::set(float* array)
+void Vector3::set(const float* array)
 {
     assert(array);
 

+ 2 - 2
gameplay/src/Vector3.h

@@ -54,7 +54,7 @@ public:
      *
      * @param array An array containing the elements of the vector in the order x, y, z.
      */
-    Vector3(float* array);
+    Vector3(const float* array);
 
     /**
      * Constructs a vector that describes the direction between the specified points.
@@ -315,7 +315,7 @@ public:
      *
      * @param array An array containing the elements of the vector in the order x, y, z.
      */
-    void set(float* array);
+    void set(const float* array);
 
     /**
      * Sets the elements of this vector to those in the specified vector.

+ 2 - 2
gameplay/src/Vector4.cpp

@@ -14,7 +14,7 @@ Vector4::Vector4(float x, float y, float z, float w)
     set(x, y, z, w);
 }
 
-Vector4::Vector4(float* src)
+Vector4::Vector4(const float* src)
 {
     set(src);
 }
@@ -284,7 +284,7 @@ void Vector4::set(float x, float y, float z, float w)
     this->w = w;
 }
 
-void Vector4::set(float* array)
+void Vector4::set(const float* array)
 {
     assert(array);
 

+ 2 - 2
gameplay/src/Vector4.h

@@ -53,7 +53,7 @@ public:
      *
      * @param array An array containing the elements of the vector in the order x, y, z, w.
      */
-    Vector4(float* array);
+    Vector4(const float* array);
 
     /**
      * Constructs a vector that describes the direction between the specified points.
@@ -307,7 +307,7 @@ public:
      *
      * @param array An array containing the elements of the vector in the order x, y, z, w.
      */
-    void set(float* array);
+    void set(const float* array);
 
     /**
      * Sets the elements of this vector to those in the specified vector.