Example #1
0
	void SetupShapesUserData(const VehicleDescriptor &vd)
	{
		PxRigidDynamic *a = vd.vehicle->mActor;
		if (!a)
			return;

		PxU32 numShapes = a->getNbShapes();
		r3d_assert(numShapes <= vd.numWheels + vd.numHullParts);
		
		for (PxU32 i = 0; i < numShapes; ++i)
		{
			PxShape *s = 0;
			a->getShapes(&s, 1, i);
			if (!s)
				continue;

			if (i < vd.numWheels)
			{
				s->userData = reinterpret_cast<void*>(vd.wheelBonesRemapIndices[i]);
			}
			else
			{
				s->userData = reinterpret_cast<void*>(vd.hullBonesRemapIndices[i - vd.numWheels]);
			}
		}
	}
/**
 @brief 
 @date 2013-12-03
*/
void CEvc::pickup()
{
	PxU32 width;
	PxU32 height;
	mApplication.getPlatform()->getWindowSize(width, height);
	mPicking->moveCursor(width/2,height/2);
	mPicking->lazyPick();
	PxActor *actor = mPicking->letGo();
	//PxRigidDynamic *rigidActor = static_cast<PxRigidDynamic*>(actor->is<PxRigidDynamic>());
	PxRigidDynamic *rigidActor = (PxRigidDynamic*)actor;
	if (rigidActor)
	{
		const PxVec3 pos = getCamera().getPos() + (getCamera().getViewDir()*10.f);
		const PxVec3 vel = getCamera().getViewDir() * 20.f;

		rigidActor->addForce( getCamera().getViewDir()*g_pDbgConfig->force );

		PxU32 nbShapes = rigidActor->getNbShapes();
		if(!nbShapes)
			return;

		PxShape** shapes = (PxShape**)SAMPLE_ALLOC(sizeof(PxShape*)*nbShapes);
		PxU32 nb = rigidActor->getShapes(shapes, nbShapes);
		PX_ASSERT(nb==nbShapes);
		for(PxU32 i=0;i<nbShapes;i++)
		{
			RenderBaseActor *renderActor = getRenderActor(rigidActor, shapes[i]);
			if (renderActor)
			{
				renderActor->setRenderMaterial(mManagedMaterials[ 1]);
			}
		}
		SAMPLE_FREE(shapes);
	}
}
Example #3
0
void getSimplePose( PxActor* actor, float* data ) //TODO rework
{
    PxShape* shp[1];
    PxRigidDynamic* rigid = (PxRigidDynamic*)actor;
    rigid->getShapes( shp, PxU32(1) );
    PxMat44 shape_pose = rigid->getGlobalPose(); //(PxShapeExt::getGlobalPose(*shp[0], *rigid));
    for( int i = 0; i < 4; i++ )
        for( int j = 0; j < 4; j++ )
            data[i*4 + j] = shape_pose[j][i];
}
void defaultCCTInteraction(const PxControllerShapeHit& hit)
{
	PxRigidDynamic* actor = hit.shape->getActor()->is<PxRigidDynamic>();
	if(actor)
	{
		if(actor->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)
			return;

		if(0)
		{
			const PxVec3 p = actor->getGlobalPose().p + hit.dir * 10.0f;

			PxShape* shape;
			actor->getShapes(&shape, 1);
			PxRaycastHit newHit;
			PxU32 n = PxShapeExt::raycast(*shape, *shape->getActor(), p, -hit.dir, 20.0f, PxHitFlag::ePOSITION, 1, &newHit, false);
			if(n)
			{
				// We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates
				// useless stress on the solver. It would be possible to enable/disable vertical pushes on
				// particular objects, if the gameplay requires it.
				const PxVec3 upVector = hit.controller->getUpDirection();
				const PxF32 dp = hit.dir.dot(upVector);
		//		shdfnd::printFormatted("%f\n", fabsf(dp));
				if(fabsf(dp)<1e-3f)
		//		if(hit.dir.y==0.0f)
				{
					const PxTransform globalPose = actor->getGlobalPose();
					const PxVec3 localPos = globalPose.transformInv(newHit.position);
					::addForceAtLocalPos(*actor, hit.dir*hit.length*1000.0f, localPos, PxForceMode::eACCELERATION);
				}
			}
		}

		// We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates
		// useless stress on the solver. It would be possible to enable/disable vertical pushes on
		// particular objects, if the gameplay requires it.
		const PxVec3 upVector = hit.controller->getUpDirection();
		const PxF32 dp = hit.dir.dot(upVector);
//		shdfnd::printFormatted("%f\n", fabsf(dp));
		if(fabsf(dp)<1e-3f)
//		if(hit.dir.y==0.0f)
		{
			const PxTransform globalPose = actor->getGlobalPose();
			const PxVec3 localPos = globalPose.transformInv(toVec3(hit.worldPos));
			::addForceAtLocalPos(*actor, hit.dir*hit.length*1000.0f, localPos, PxForceMode::eACCELERATION);
		}
	}
}
Example #5
0
PxRigidDynamic* CServer::createDynamicBox(const Vector3 &position, const Vector3 &dimensions, 
	                                      float mass, bool kinematic, bool trigger, int group, 
										  const IPhysics *component)
{
	assert(_scene);

	// Nota: PhysX coloca el sistema de coordenadas local en el centro de la caja, mientras
	// que la lógica asume que el origen del sistema de coordenadas está en el centro de la 
	// cara inferior. Para unificar necesitamos realizar una traslación en el eje Y.
	// Afortunadamente, el descriptor que se usa para crear el actor permite definir esta 
	// transformación local, por lo que la conversión entre sistemas de coordenadas es transparente. 

	// Crear un cubo dinámico
	PxTransform pose(Vector3ToPxVec3(position));
	PxBoxGeometry geom(Vector3ToPxVec3(dimensions));
	PxMaterial *material = _defaultMaterial;
	float density = mass / (dimensions.x * dimensions.y * dimensions.z);
	PxTransform localPose(PxVec3(0, dimensions.y, 0)); // Transformación de coordenadas lógicas a coodenadas de PhysX

	// Crear cubo dinámico o cinemático
	PxRigidDynamic *actor;
	if (kinematic)
		actor = PxCreateKinematic(*_physics, pose, geom, *material, density, localPose);
	else
		actor = PxCreateDynamic(*_physics, pose, geom, *material, density, localPose);
	
	// Transformarlo en trigger si es necesario
	if (trigger) {
		PxShape *shape;
		actor->getShapes(&shape, 1, 0);
		shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
		shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
	}

	// Anotar el componente lógico asociado a la entidad física
	actor->userData = (void *) component;

	// Establecer el grupo de colisión
	PxSetGroup(*actor, group);

	// Añadir el actor a la escena
	_scene->addActor(*actor);

	return actor;
}
Example #6
0
physx::PxRigidDynamic* CPhysicManager::createDynamicSphere(const Vector3 &position, const float &radius, float mass, bool kinematic, bool trigger, int group, const Logic::Component::IPhysic *component)
{
    assert(m_scene);

    PxTransform pose(Vector3ToPxVec3(position));
    PxSphereGeometry geom(radius);
    PxMaterial *material = m_defaultMaterial;
    float density = mass / ((4/3) * Common::Util::Math::PI * radius * radius * radius);

    PxRigidDynamic *actor = nullptr;
    if(kinematic) {
        actor = PxCreateKinematic(*m_physics,pose,geom,*material,density);
    } else {
        actor = PxCreateDynamic(*m_physics,pose,geom,*material,density);
    }

    if(trigger) {
        PxShape *shape;
        actor->getShapes(&shape,1,0);
        shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
        shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
    }

    actor->userData = (void*)component;

    PxSetGroup(*actor,group);

    setupFiltering(actor,FilterGroup::eSPACE_FILTER,FilterGroup::eSPACE_FILTER);

    PxD6Joint* joint = PxD6JointCreate(*m_physics, actor, PxTransform::createIdentity(), nullptr, actor->getGlobalPose());
    joint->setMotion(PxD6Axis::eX,PxD6Motion::eFREE);
    joint->setMotion(PxD6Axis::eY,PxD6Motion::eLOCKED);
    joint->setMotion(PxD6Axis::eZ,PxD6Motion::eFREE);
    joint->setMotion(PxD6Axis::eSWING1,PxD6Motion::eFREE);
    joint->setMotion(PxD6Axis::eSWING2,PxD6Motion::eLOCKED);
    joint->setMotion(PxD6Axis::eTWIST,PxD6Motion::eLOCKED);
    //TODO release

    //m_scene->addActor(*actor);

    return actor;
}
Example #7
0
Entity* CreateBall(float _fRadius, SimpleTree& _rParentNode)
{
	Entity* pBall = new Entity(EntityCategories::BALL);

	// The model
	Sphere* pSphere = new Sphere(Vector2(), _fRadius);
	pSphere->setColour(BALL_COLOUR);
	pSphere->setLevelOfDetail(10);
	pBall->addComponent(pSphere);
	pSphere->setEntity(pBall);

	// The physical body
	Body::Material material;
	material.density = 0.5f;
	material.friction = 0.5f;
	material.restitution = 0.5f;
	PhysXBody* pBody = static_cast<PhysXBody*>(PhysicsFactory::getInstance()->createBody(material, pSphere,
		BALL_POSITION, true));
	pBall->addComponent(pBody);
	pBody->setEntity(pBall);

	// Collision detection
	PxRigidDynamic* pRigidDynamic = pBody->getActor()->isRigidDynamic();
	PxFilterData filterData;
	filterData.word0 = EntityCategories::BALL;
	filterData.word1 = EntityCategories::WALL_BLOCK;
	PxShape* shapes;
	pRigidDynamic->getShapes(&shapes, 1);
	shapes->setSimulationFilterData(filterData);
	pRigidDynamic->setContactReportThreshold(DESTRUCTION_FORCE_THRESHOLD);

	// The scene
	SimpleTree* pNode = new SimpleTree;
	setTranslation(pNode->getTransformation(), BALL_POSITION);
	pNode->setModel(pSphere);
	pBody->setNode(pNode);
	_rParentNode.addChild(pNode);

	GazEngine::addEntity(pBall);
	return pBall;
}
Example #8
0
Entity* CreateWallBlock(const Matrix44& _rTransformation, float _fBlockSize, SimpleTree& _rParentNode)
{
	Entity* pWallBlock = new Entity(EntityCategories::WALL_BLOCK);

	// The model
	Cube* pCube = new Cube(Vector2(), _fBlockSize);
	pCube->setColour(Vector4(Math::getRandomFloat(0.0f, 1.0f), Math::getRandomFloat(0.0f, 1.0f),
		Math::getRandomFloat(0.0f, 1.0f), 1.0f));
	pWallBlock->addComponent(pCube);
	pCube->setEntity(pWallBlock);

	// The physical body
	Body::Material material;
	material.density = 0.5f;
	material.friction = 0.5f;
	material.restitution = 0.5f;
	PhysXBody* pBody = static_cast<PhysXBody*>(PhysicsFactory::getInstance()->createBody(material, pCube,
		getTranslation3(_rTransformation), true));
	pWallBlock->addComponent(pBody);
	pBody->setEntity(pWallBlock);

	// Collision detection
	PxRigidDynamic* pRigidDynamic = pBody->getActor()->isRigidDynamic();
	PxFilterData filterData;
	filterData.word0 = EntityCategories::WALL_BLOCK;
	filterData.word1 = EntityCategories::BALL | EntityCategories::WALL_BLOCK;
	PxShape* shapes;
	pRigidDynamic->getShapes(&shapes, 1);
	shapes->setSimulationFilterData(filterData);
	pRigidDynamic->setContactReportThreshold(DESTRUCTION_FORCE_THRESHOLD);

	// The scene
	SimpleTree* pNode = new SimpleTree;
	pNode->setTransformation(_rTransformation);
	pNode->setModel(pCube);
	pBody->setNode(pNode);
	_rParentNode.addChild(pNode);

	GazEngine::addEntity(pWallBlock);
	return pWallBlock;
}
Example #9
0
PxRigidDynamic* CPhysicManager::createDynamicBox(const Vector3 &position, const Vector3 &dimensions,
        float mass, bool kinematic, bool trigger, int group,
        const IPhysic *component)
{
    assert(m_scene);

    PxTransform pose(Vector3ToPxVec3(position));
    PxBoxGeometry geom(Vector3ToPxVec3(dimensions));
    PxMaterial *material = m_defaultMaterial;
    float density = mass / (dimensions.x * dimensions.y * dimensions.z);
    PxTransform localPose(PxVec3(0, dimensions.y, 0));

    PxRigidDynamic *actor = nullptr;
    if(kinematic) {
        actor = PxCreateKinematic(*m_physics,pose,geom,*material,density,localPose);
    } else {
        actor = PxCreateDynamic(*m_physics,pose,geom,*material,density,localPose);
    }

    if(trigger) {
        PxShape *shape;
        actor->getShapes(&shape,1,0);
        shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
        shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
    }

    actor->userData = (void*)component;

    PxSetGroup(*actor,group);

    setupFiltering(actor,FilterGroup::eSPACE_FILTER,FilterGroup::eSPACE_FILTER);

    //m_scene->addActor(*actor);

    return actor;
}
Example #10
0
void FBXActor::createCollisionShapes(PhysicsDemoScene *a_app)
{
	float density = 300;

	//pole
	PxBoxGeometry box = PxBoxGeometry(0.1f,4,0.1f);
	PxTransform transform(*((PxMat44*)(&m_world)));	//cast from glm to PhysX matrices

	PxRigidDynamic* dynamicActor = PxCreateDynamic(*a_app->g_Physics, transform, box, *a_app->g_PhysicsMaterial, density);

	dynamicActor->userData = this;	//set the user data to point at this FBXActor class

	//offset
	int nShapes = dynamicActor->getNbShapes();
	PxShape* shapes;
	dynamicActor->getShapes(&shapes, nShapes);

	PxTransform relativePose = PxTransform(PxVec3(0.0f,4.0f,0.0f));
	shapes->setLocalPose(relativePose);

	//head
	box = PxBoxGeometry(0.8f,0.5f,0.3f);
	relativePose = PxTransform(PxVec3(0.0f,2.0f,0.0f));
	PxShape* shape = dynamicActor->createShape(box, *a_app->g_PhysicsMaterial);
	if (shape)
	{
		shape->setLocalPose(relativePose);
	}

	PxRigidBodyExt::updateMassAndInertia(*dynamicActor, (PxReal)density);

	//add to scene
	a_app->g_PhysicsScene->addActor(*dynamicActor);
	a_app->g_PhysXActors.push_back(dynamicActor);

}
PxController* ControlledActor::init(const ControlledActorDesc& desc, PxControllerManager* manager)
{
	const float radius	= desc.mRadius;
	float height		= desc.mHeight;
	float crouchHeight	= desc.mCrouchHeight;

	PxControllerDesc* cDesc;
	PxBoxControllerDesc boxDesc;
	PxCapsuleControllerDesc capsuleDesc;

	if(desc.mType==PxControllerShapeType::eBOX)
	{
		height *= 0.5f;
		height += radius;
		crouchHeight *= 0.5f;
		crouchHeight += radius;
		boxDesc.halfHeight			= height;
		boxDesc.halfSideExtent		= radius;
		boxDesc.halfForwardExtent	= radius;
		cDesc = &boxDesc;
	}
	else 
	{
		PX_ASSERT(desc.mType==PxControllerShapeType::eCAPSULE);
		capsuleDesc.height = height;
		capsuleDesc.radius = radius;
		capsuleDesc.climbingMode = PxCapsuleClimbingMode::eCONSTRAINED;
		cDesc = &capsuleDesc;
	}

	cDesc->density				= desc.mProxyDensity;
	cDesc->scaleCoeff			= desc.mProxyScale;
	cDesc->material				= &mOwner.getDefaultMaterial();
	cDesc->position				= desc.mPosition;
	cDesc->slopeLimit			= desc.mSlopeLimit;
	cDesc->contactOffset		= desc.mContactOffset;
	cDesc->stepOffset			= desc.mStepOffset;
	cDesc->invisibleWallHeight	= desc.mInvisibleWallHeight;
	cDesc->maxJumpHeight		= desc.mMaxJumpHeight;
//	cDesc->nonWalkableMode		= PxControllerNonWalkableMode::ePREVENT_CLIMBING_AND_FORCE_SLIDING;
	cDesc->reportCallback		= desc.mReportCallback;
	cDesc->behaviorCallback		= desc.mBehaviorCallback;
	cDesc->volumeGrowth			= desc.mVolumeGrowth;

	mType						= desc.mType;
	mInitialPosition			= desc.mPosition;
	mStandingSize				= height;
	mCrouchingSize				= crouchHeight;
	mControllerRadius			= radius;

	PxController* ctrl = static_cast<PxBoxController*>(manager->createController(*cDesc));
	PX_ASSERT(ctrl);

	// remove controller shape from scene query for standup overlap test
	PxRigidDynamic* actor = ctrl->getActor();
	if(actor)
	{
		if(actor->getNbShapes())
		{
			PxShape* ctrlShape;
			actor->getShapes(&ctrlShape,1);
			ctrlShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);

			Renderer* renderer = mOwner.getRenderer();

			if(desc.mType==PxControllerShapeType::eBOX)
			{
				const PxVec3 standingExtents(radius, height, radius);
				const PxVec3 crouchingExtents(radius, crouchHeight, radius);

				mRenderActorStanding = SAMPLE_NEW(RenderBoxActor)(*renderer, standingExtents);
				mRenderActorCrouching = SAMPLE_NEW(RenderBoxActor)(*renderer, crouchingExtents);
			}
			else if(desc.mType==PxControllerShapeType::eCAPSULE)
			{
				mRenderActorStanding = SAMPLE_NEW(RenderCapsuleActor)(*renderer, radius, height*0.5f);
				mRenderActorCrouching = SAMPLE_NEW(RenderCapsuleActor)(*renderer, radius, crouchHeight*0.5f);
			}
		}
	}

	mController = ctrl;
	return ctrl;
}
Example #12
0
void SampleParticles::Raygun::update(float dtime)
{
	if(!isEnabled())
		return;
	
	PX_ASSERT(mSample && mForceSmokeCapsule && mForceWaterCapsule && mRenderActor);

	// access properties from sample
	PxScene& scene = mSample->getActiveScene();
	PxVec3 position = mSample->getCamera().getPos();
	PxTransform cameraPose = mSample->getCamera().getViewMatrix();
	PxMat33 cameraBase(cameraPose.q);
	PxVec3 cameraForward = -cameraBase[2];
	PxVec3 cameraUp = -cameraBase[1];
	
	// perform raycast here and update impact point
	PxRaycastHit hit;
	mIsImpacting = scene.raycastSingle(cameraPose.p, cameraForward, 500.0f, PxSceneQueryFlags(0xffffffff), hit);
	float impactParam = mIsImpacting ? (hit.impact - position).magnitude() : FLT_MAX;	

	PxTransform rayPose(position + cameraUp * 0.5f, cameraPose.q*PxQuat(PxHalfPi, PxVec3(0,1,0)));

	updateRayCapsule(mForceSmokeCapsule, rayPose, 1.0f);
	updateRayCapsule(mForceWaterCapsule, rayPose, 0.3f);
	mRenderActor->setTransform(rayPose);

	// if we had an impact
	if (impactParam < FLT_MAX)
	{
		PxVec3 impactPos = position + cameraForward*impactParam;
		// update emitter with new impact point and direction
		if(mSmokeEmitter.emitter)
			mSmokeEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));
		if(mDebrisEmitter.emitter)
			mDebrisEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));

		// spawn new RB debris
		if(mRbDebrisTimer < 0.0f && impactParam < FLT_MAX) 
		{
			mRbDebrisTimer = RAYGUN_RB_DEBRIS_RATE;

			PxVec3 randDir(getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f));
			PxVec3 vel = -7.0f * (cameraForward + RAYGUN_RB_DEBRIS_ANGLE_RANDOMNESS * randDir.getNormalized());
			PxVec3 dim(getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE));
			// give spawn position, initial velocity and dimensions, spawn convex
			// which will not act in scene queries
			PxConvexMesh* convexMesh = generateConvex(mSample->getPhysics(), mSample->getCooking(), RAYGUN_RB_DEBRIS_SCALE);
			mSample->runtimeAssert(convexMesh, "Error generating convex for debris.\n");
			PxRigidDynamic* debrisActor = PxCreateDynamic(
				mSample->getPhysics(), 
				PxTransform(impactPos - cameraForward * 0.5f), 
				PxConvexMeshGeometry(convexMesh), 
				mSample->getDefaultMaterial(), 1.f);  
			mSample->getActiveScene().addActor(*debrisActor);

			PX_ASSERT(debrisActor->getNbShapes() == 1);
			PxShape* debrisShape;
			debrisActor->getShapes(&debrisShape, 1);
			debrisShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
			debrisActor->setLinearVelocity(vel);
			debrisActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
			debrisActor->setAngularDamping(0.5f);
			
			// default material is green for debris
			RenderMaterial* debriMaterial = mSample->getMaterial(MATERIAL_HEIGHTFIELD);
			if(!debriMaterial) 
			{
				debriMaterial = mSample->mRenderMaterials[MATERIAL_GREEN];				
			}
			mSample->createRenderObjectsFromActor(debrisActor, debriMaterial);
			mDebrisLifetime[debrisShape] = RAYGUN_RB_DEBRIS_LIFETIME;
		}
	}

	// update debris lifetime, remove if life ends
	DebrisLifetimeMap::iterator it = mDebrisLifetime.begin();
	while(it != mDebrisLifetime.end()) 
	{
		(*it).second -= dtime;
		if((*it).second < 0.0f) 
		{
			PxShape* debrisShape = (*it).first;
			PX_ASSERT(debrisShape);

			// remove convex mesh
			PxConvexMeshGeometry geometry;
			bool isConvex = debrisShape->getConvexMeshGeometry(geometry);
			PX_ASSERT(isConvex);
			PX_UNUSED(isConvex);
			geometry.convexMesh->release();
			
			// remove render and physics actor
			PxRigidActor& actorToRemove = debrisShape->getActor();
			mSample->removeActor(&actorToRemove);			
			actorToRemove.release();
			
			// remove actor from lifetime map
			mDebrisLifetime.erase(it);
			it = mDebrisLifetime.begin();
			continue;
		}
		++it;
	}
}
PxCapsuleController* SampleCustomGravity::createCharacter(const PxExtendedVec3& position)
#endif
{
	const float height = 2.0f;		
//	const float height = 1e-6f;	// PT: TODO: make it work with 0?

#ifdef USE_BOX_CONTROLLER
	PxBoxControllerDesc cDesc;
	cDesc.halfHeight			= height;
	cDesc.halfSideExtent		= mControllerRadius;
	cDesc.halfForwardExtent		= mControllerRadius;
#else
	PxCapsuleControllerDesc cDesc;
	cDesc.height				= height;
	cDesc.radius				= mControllerRadius;
#endif
	cDesc.material				= &getDefaultMaterial();
	cDesc.position				= position;
	cDesc.slopeLimit			= SLOPE_LIMIT;
	cDesc.contactOffset			= CONTACT_OFFSET;
	cDesc.stepOffset			= STEP_OFFSET;
	cDesc.invisibleWallHeight	= INVISIBLE_WALLS_HEIGHT;
	cDesc.maxJumpHeight			= MAX_JUMP_HEIGHT;
	cDesc.callback				= this;

	mControllerInitialPosition = cDesc.position;

#ifdef USE_BOX_CONTROLLER
	PxBoxController* ctrl = static_cast<PxBoxController*>(mControllerManager->createController(getPhysics(), &getActiveScene(), cDesc));
#else
	PxCapsuleController* ctrl = static_cast<PxCapsuleController*>(mControllerManager->createController(getPhysics(), &getActiveScene(), cDesc));
#endif
	// remove controller shape from scene query for standup overlap test
	PxRigidDynamic* actor = ctrl->getActor();
	if(actor)
	{
		if(actor->getNbShapes())
		{
			PxShape* ctrlShape;
			actor->getShapes(&ctrlShape,1);
			ctrlShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);

#ifdef USE_BOX_CONTROLLER
			const PxVec3 standingExtents(mControllerRadius, height, mControllerRadius);
 			mRenderActor = SAMPLE_NEW(RenderBoxActor)(*getRenderer(), standingExtents);
#else
 			mRenderActor = SAMPLE_NEW(RenderCapsuleActor)(*getRenderer(), mControllerRadius, height*0.5f);
#endif
			if(mRenderActor)
				mRenderActors.push_back(mRenderActor);
		}
		else
			fatalError("character actor has no shape");
	}
	else
		fatalError("character could not create actor");

	// uncomment the next line to render the character
	//createRenderObjectsFromActor(ctrl->getActor());

	return ctrl;
}