Пример #1
0
PxRigidStatic* CPhysicManager::createStaticBox(const Vector3 &position, const Vector3 &dimensions, bool trigger,
        int group, const IPhysic *component)
{
    assert(m_scene);
    PxVec3 p = Vector3ToPxVec3(position);
    PxVec3 d = Vector3ToPxVec3(dimensions);

    PxTransform pose(p);
    PxBoxGeometry geom(d);
    PxTransform localPose(PxVec3(0,dimensions.y,0));

    PxRigidStatic *actor = PxCreateStatic(*m_physics,pose,geom,*m_defaultMaterial,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;
}
Пример #2
0
physx::PxRigidStatic* CPhysicManager::createStaticSphere(const Vector3 &position, const float &radius, bool trigger, int group, const Logic::Component::IPhysic *component)
{
    assert(m_scene);
    PxVec3 p = Vector3ToPxVec3(position);

    PxTransform pose(p);
    PxSphereGeometry geom(radius);

    PxRigidStatic *actor = PxCreateStatic(*m_physics,pose,geom,*m_defaultMaterial);

    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;
}
Пример #3
0
void SampleParticles::createDrain() 
{
	float lakeHeight = 5.5f;
	
	//Creates a drain plane for the particles. This is good practice to avoid unnecessary 
	//spreading of particles, which is bad for performance. The drain represents a lake in this case.
	{
		PxRigidStatic* actor = getPhysics().createRigidStatic(PxTransform(PxVec3(0.0f, lakeHeight - 1.0f, 0.0f), PxQuat(PxHalfPi, PxVec3(0,0,1))));
		runtimeAssert(actor, "PxPhysics::createRigidStatic returned NULL\n");
		PxShape* shape = actor->createShape(PxPlaneGeometry(), getDefaultMaterial());
		runtimeAssert(shape, "PxRigidStatic::createShape returned NULL\n");
		shape->setSimulationFilterData(collisionGroupDrain);
		shape->setFlags(PxShapeFlag::ePARTICLE_DRAIN | PxShapeFlag::eSIMULATION_SHAPE);
		getActiveScene().addActor(*actor);
		mPhysicsActors.push_back(actor);
	}
	
	//Creates the surface of the lake (the particles actually just collide with the underlaying drain).
	{
		PxBoxGeometry bg;
		bg.halfExtents = PxVec3(130.0f, lakeHeight + 1.0f, 130.0f);
		PxRigidStatic* actor = getPhysics().createRigidStatic(PxTransform(PxVec3(0.0f, 0.0f, 0.0f), PxQuat::createIdentity()));
		runtimeAssert(actor, "PxPhysics::createRigidStatic returned NULL\n");
		PxShape* shape = actor->createShape(bg, getDefaultMaterial());
		runtimeAssert(shape, "PxRigidStatic::createShape returned NULL\n");
		shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
		shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
		getActiveScene().addActor(*actor);
		mPhysicsActors.push_back(actor);
		createRenderObjectsFromActor(actor, getMaterial(MATERIAL_LAKE));
	}
}
void UDestructibleComponent::SetCollisionResponseForActor(const FCollisionResponse& ColResponse, PxRigidDynamic* Actor, int32 ChunkIdx)
{
	// Get collision channel and response
	PxFilterData PQueryFilterData, PSimFilterData;
	uint8 MoveChannel = GetCollisionObjectType();
	if(IsCollisionEnabled())
	{
		AActor* Owner = GetOwner();
		CreateShapeFilterData(MoveChannel, (Owner ? Owner->GetUniqueID() : 0), ColResponse.GetResponseContainer(), 0, ChunkIdxToBoneIdx(ChunkIdx), PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, BodyInstance.bNotifyRigidBodyCollision, false);		
		PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision;

		SCOPED_SCENE_WRITE_LOCK(Actor->getScene());

		TArray<PxShape*> Shapes;
		Shapes.AddUninitialized(Actor->getNbShapes());

		int ShapeCount = Actor->getShapes(Shapes.GetTypedData(), Shapes.Num());

		for (int32 i=0; i < ShapeCount; ++i)
		{
			PxShape* Shape = Shapes[i];

			Shape->setQueryFilterData(PQueryFilterData);
			Shape->setSimulationFilterData(PSimFilterData);
			Shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true); 
			Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); 
			Shape->setFlag(PxShapeFlag::eVISUALIZATION, true);
		}
	}
}
Пример #5
0
void PhysicsEngine::createPizzaPickup(physx::PxVec3 location, physx::PxF32 radius)
{
	PxBoxGeometry geometry(radius, radius, radius); 
	PxTransform transform(location, PxQuat::createIdentity());
	PxMaterial* material = physics->createMaterial(0.5f, 0.5f, 0.5f);

	PxRigidStatic* actor = PxCreateStatic(*physics, transform, geometry, *material);
	PxShape* shape;
	actor->getShapes(&shape, 1);
	shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
	shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
	shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);

	scene->addActor(*actor);
}
Пример #6
0
PxRigidDynamic* SampleParticles::Raygun::createRayCapsule(bool enableCollision, PxFilterData filterData)
{
	PxRigidDynamic* actor = mSample->getPhysics().createRigidDynamic(PxTransform::createIdentity());
	mSample->runtimeAssert(actor, "PxPhysics::createRigidDynamic returned NULL\n");
	PxShape* shape = actor->createShape(PxCapsuleGeometry(0.1f, 150.0f), mSample->getDefaultMaterial());
	mSample->runtimeAssert(shape, "PxRigidDynamic::createShape returned NULL\n");
	shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
	shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, enableCollision);
	shape->setSimulationFilterData(filterData);
	actor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);
	actor->setMass(1.0f);
	actor->setMassSpaceInertiaTensor(PxVec3(1.0f));
	mSample->getActiveScene().addActor(*actor);	
	return actor;
}
Пример #7
0
// add some physics objects into the scene
void AddPhyObjects()
{
	PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0, 1, 0, 0), *gMaterial);
	gScene->addActor(*groundPlane);

	PxShape* shape = gPhysics->createShape(PxBoxGeometry(1.0f, 1.0f, 1.0f), *gMaterial);
	PxTransform localTm(PxVec3(-3.0f, 5.0f, 0.f));
	PxRigidDynamic* body = gPhysics->createRigidDynamic(localTm);
	body->attachShape(*shape);
	PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
	gScene->addActor(*body);

	shape->release();

	shape = gPhysics->createShape(PxSphereGeometry(1.0f), *gMaterial);
	PxTransform localTmS(PxVec3(3.0f, 5.0f, 0.f));
	body = gPhysics->createRigidDynamic(localTmS);
	body->attachShape(*shape);
	PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
	gScene->addActor(*body);

	shape->release();

	PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, PxTransform(PxVec3(0, 20, 20)), PxSphereGeometry(1), *gMaterial, 10.0f);
	dynamic->setAngularDamping(0.5f);
	dynamic->setLinearVelocity(PxVec3(0, -5, -10));
	gScene->addActor(*dynamic);

	// add capsule into the scene
	shape = gPhysics->createShape(PxCapsuleGeometry(1.0f, 3.0f), *gMaterial);
	PxTransform localTmC(PxVec3(3.0f, 5.0f, -3.f));
	body = gPhysics->createRigidDynamic(localTmC);
	body->attachShape(*shape);
	PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
	gScene->addActor(*body);

	// add a static box as the trigger
	shape = gPhysics->createShape(PxBoxGeometry(1.0f, 1.0f, 1.0f), *gMaterial);
	PxTransform localTmTrigger(PxVec3(0.0f, 1.0f, -10.f));
	body = gPhysics->createRigidDynamic(localTmTrigger);
	shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
	shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
	body->attachShape(*shape);
	body->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
	gScene->addActor(*body);

	shape->release();
}
Пример #8
0
PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk, 
								  const PxTransform& transform, 
								  const PxGeometry& geometry, 
								  PxMaterial& material,
								  PxReal density,
								  const PxTransform& shapeOffset)
{
	PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid.");
	PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateKinematic: shapeOffset is not valid.");

	bool isDynGeom = isDynamicGeometry(geometry);
	if(isDynGeom && density <= 0.0f)
	    return NULL;

	PxShape* shape;
	PxRigidDynamic* actor = setShape(sdk.createRigidDynamic(transform), geometry, material, shapeOffset, shape);
	
	if(actor)
	{
		actor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);

		if(isDynGeom)
			PxRigidBodyExt::updateMassAndInertia(*actor, density);
		else		
		{
			shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
			actor->setMass(1);
			actor->setMassSpaceInertiaTensor(PxVec3(1,1,1));
		}
	}
	return actor;
}
Пример #9
0
void UDestructibleComponent::SetCollisionResponseForActor(PxRigidDynamic* Actor, int32 ChunkIdx, const FCollisionResponseContainer* ResponseOverride /*= NULL*/)
{
#if WITH_APEX
	if (ApexDestructibleActor == NULL)
	{
		return;
	}

	// Get collision channel and response
	PxFilterData PQueryFilterData, PSimFilterData;
	uint8 MoveChannel = GetCollisionObjectType();
	if(IsCollisionEnabled())
	{
		UDestructibleMesh* TheDestructibleMesh = GetDestructibleMesh();
		AActor* Owner = GetOwner();
		bool bLargeChunk = IsChunkLarge(ChunkIdx);
		const FCollisionResponseContainer& UseResponse = ResponseOverride == NULL ? (bLargeChunk ? LargeChunkCollisionResponse.GetResponseContainer() : SmallChunkCollisionResponse.GetResponseContainer()) : *ResponseOverride;

		physx::PxU32 SupportDepth = TheDestructibleMesh->ApexDestructibleAsset->getChunkDepth(ChunkIdx);

		const bool bEnableImpactDamage = IsImpactDamageEnabled(TheDestructibleMesh, SupportDepth);
		CreateShapeFilterData(MoveChannel, GetUniqueID(), UseResponse, 0, ChunkIdxToBoneIdx(ChunkIdx), PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, bEnableImpactDamage, false);
		
		PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision;

		SCOPED_SCENE_WRITE_LOCK(Actor->getScene());

		TArray<PxShape*> Shapes;
		Shapes.AddUninitialized(Actor->getNbShapes());

		int ShapeCount = Actor->getShapes(Shapes.GetData(), Shapes.Num());

		for (int32 i=0; i < ShapeCount; ++i)
		{
			PxShape* Shape = Shapes[i];

			Shape->setQueryFilterData(PQueryFilterData);
			Shape->setSimulationFilterData(PSimFilterData);
			Shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true); 
			Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); 
			Shape->setFlag(PxShapeFlag::eVISUALIZATION, true);
		}
	}
#endif
}
Пример #10
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;
}
Пример #11
0
void SampleNorthPole::setCCDActive(PxShape& shape)
{
	
	shape.setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS,true);

	PxFilterData fd = shape.getSimulationFilterData();
	fd.word3 |= CCD_FLAG;
	shape.setSimulationFilterData(fd);
	
}
Пример #12
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;
}
Пример #13
0
void Apex::LoadTriangleMesh(int numVerts, PxVec3* verts, ObjectInfo info)
{
	PxRigidStatic* meshActor = mPhysics->createRigidStatic(PxTransform::createIdentity());
	PxShape* meshShape;
	if(meshActor)
	{
		
		PxTriangleMeshDesc meshDesc;
		meshDesc.points.count           = numVerts;
		meshDesc.points.stride          = sizeof(PxVec3);
		meshDesc.points.data            = verts;

		//meshDesc.triangles.count        = numInds/3.;
		//meshDesc.triangles.stride       = 3*sizeof(int);
		//meshDesc.triangles.data         = inds;

		PxToolkit::MemoryOutputStream writeBuffer;
		bool status = mCooking->cookTriangleMesh(meshDesc, writeBuffer);
		if(!status)
			return;

		PxToolkit::MemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize());

		PxTriangleMeshGeometry triGeom;
		triGeom.triangleMesh = mPhysics->createTriangleMesh(readBuffer);
		triGeom.scale = PxMeshScale(PxVec3(info.sx,info.sy,info.sz),physx::PxQuat::createIdentity());
		
		meshShape = meshActor->createShape(triGeom, *defaultMaterial);
		meshShape->setLocalPose(PxTransform(PxVec3(info.x,info.y,info.z), PxQuat(info.ry, PxVec3(0.0f,1.0f,0.0f))));
		meshShape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, true);


		meshShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
		

		mScene[mCurrentScene]->addActor(*meshActor);
	}
}
Пример #14
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;
}
Пример #15
0
PxActor* addSimpleObject( PxScene* scene, 
                         PxPhysics* physics, 
                         PxTransform* transform, 
                         PxGeometry* geometry,
                         PxMaterial* material, 
                         bool isStatic, bool isKinematic )
{
    PxActor* actor;
    if( isStatic )
        actor = physics->createRigidStatic( *transform );
    else
    {
        actor = physics->createRigidDynamic( *transform );
        ((PxRigidDynamic*)(actor))->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, isKinematic);
    }

    PxShape* shape = ((PxRigidBody*)(actor))->createShape( *geometry, *material );

    if( isKinematic )
        shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);

    scene->addActor( *actor );
    return actor;
}
Пример #16
0
PxRigidActor* SampleSubmarine::loadTerrain(const char* name, const PxReal heightScale, const PxReal rowScale, const PxReal columnScale) 
{
	PxRigidActor* heightFieldActor = NULL;
	BmpLoader loader;
	if(loader.loadBmp(getSampleMediaFilename(name))) 
	{
		PxU16 nbColumns = PxU16(loader.mWidth), nbRows = PxU16(loader.mHeight);
		PxHeightFieldDesc heightFieldDesc;
		heightFieldDesc.nbColumns = nbColumns;
		heightFieldDesc.nbRows = nbRows;
		PxU32* samplesData = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*nbColumns * nbRows);
		heightFieldDesc.samples.data = samplesData;
		heightFieldDesc.samples.stride = sizeof(PxU32);
		PxU8* currentByte = (PxU8*)heightFieldDesc.samples.data;
		PxU8* loader_ptr = loader.mRGB;
		PxVec3Alloc* vertexesA = SAMPLE_NEW(PxVec3Alloc)[nbRows * nbColumns];
		PxF32* uvs = (PxF32*)SAMPLE_ALLOC(sizeof(PxF32) * nbRows * nbColumns * 2);
		PxVec3* vertexes = vertexesA;
		for (PxU32 row = 0; row < nbRows; row++) 
		{
			for (PxU32 column = 0; column < nbColumns; column++) 
			{
				PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte;
				currentSample->height = *loader_ptr;
				vertexes[row * nbColumns + column] = PxVec3(PxReal(row)*rowScale, 
					PxReal(currentSample->height * heightScale), 
					PxReal(column)*columnScale);

				uvs[(row * nbColumns + column)*2 + 0] = (float)column/7.0f;
				uvs[(row * nbColumns + column)*2 + 1] = (float)row/7.0f;

				currentSample->materialIndex0 = 0;
				currentSample->materialIndex1 = 0;
				currentSample->clearTessFlag();
				currentByte += heightFieldDesc.samples.stride;
				loader_ptr += 3 * sizeof(PxU8);
			}
		}
		PxHeightField* heightField = getPhysics().createHeightField(heightFieldDesc);
		if(!heightField) fatalError("createHeightField failed!");
		// create shape for heightfield		
		PxTransform pose(PxVec3(-((PxReal)nbRows*rowScale) / 2.0f, 
			0.0f, 
			-((PxReal)nbColumns*columnScale) / 2.0f), 
			PxQuat::createIdentity());
		heightFieldActor = getPhysics().createRigidStatic(pose);
		if(!heightFieldActor) fatalError("createRigidStatic failed!");
		PxShape* shape = heightFieldActor->createShape(PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), heightScale, rowScale, columnScale), getDefaultMaterial());
		if(!shape) fatalError("createShape failed!");
		// add actor to the scene
		getActiveScene().addActor(*heightFieldActor);
		// create indices
		PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*((nbColumns - 1) * (nbRows - 1) * 3 * 2));
		for(int i = 0; i < (nbColumns - 1); ++i) 
		{
			for(int j = 0; j < (nbRows - 1); ++j) 
			{
				// first triangle
				indices[6 * (i * (nbRows - 1) + j) + 0] = (i + 1) * nbRows + j; 
				indices[6 * (i * (nbRows - 1) + j) + 1] = i * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 2] = i * nbRows + j + 1;
				// second triangle
				indices[6 * (i * (nbRows - 1) + j) + 3] = (i + 1) * nbRows + j + 1;
				indices[6 * (i * (nbRows - 1) + j) + 4] = (i + 1) * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 5] = i * nbRows + j + 1;
			}
		}
		// add mesh to renderer
		RAWMesh data;
		data.mName = name;
		data.mTransform = PxTransform::createIdentity();
		data.mNbVerts = nbColumns * nbRows;
		data.mVerts = vertexes;
		data.mVertexNormals = NULL;
		data.mUVs = uvs;
		data.mMaterialID = MATERIAL_TERRAIN_MUD;
		data.mNbFaces = (nbColumns - 1) * (nbRows - 1) * 2;
		data.mIndices = indices;

		RenderMeshActor* hf_mesh = createRenderMeshFromRawMesh(data);
		if(!hf_mesh) fatalError("createRenderMeshFromRawMesh failed!");
		hf_mesh->setPhysicsShape(shape);
		shape->setFlag(PxShapeFlag::eVISUALIZATION, false);
		SAMPLE_FREE(indices);
		SAMPLE_FREE(uvs);
		DELETEARRAY(vertexesA);
		SAMPLE_FREE(samplesData);
	}

	return heightFieldActor;
}
Пример #17
0
void PhysX::CreateShapes(const PINT_OBJECT_CREATE& desc, PxRigidActor* actor)
{
	ASSERT(actor);
	ASSERT(mDefaultMaterial);
	const PINT_SHAPE_CREATE* CurrentShape = desc.mShapes;
	while(CurrentShape)
	{
		PxTransform LocalPose;
		LocalPose.p	= ToPxVec3(CurrentShape->mLocalPos);
		LocalPose.q	= ToPxQuat(CurrentShape->mLocalRot);

		PxMaterial* ShapeMaterial = mDefaultMaterial;
		if(CurrentShape->mMaterial)
		{
			ShapeMaterial = CreateMaterial(*CurrentShape->mMaterial);
			ASSERT(ShapeMaterial);
		}

		PxShape* shape = null;
		if(CurrentShape->mType==PINT_SHAPE_SPHERE)
		{
			const PINT_SPHERE_CREATE* SphereCreate = static_cast<const PINT_SPHERE_CREATE*>(CurrentShape);
			shape = actor->createShape(PxSphereGeometry(SphereCreate->mRadius), *ShapeMaterial, LocalPose);
			ASSERT(shape);
		}
		else if(CurrentShape->mType==PINT_SHAPE_BOX)
		{
			const PINT_BOX_CREATE* BoxCreate = static_cast<const PINT_BOX_CREATE*>(CurrentShape);
			shape = actor->createShape(PxBoxGeometry(ToPxVec3(BoxCreate->mExtents)), *ShapeMaterial, LocalPose);
			ASSERT(shape);
		}
		else if(CurrentShape->mType==PINT_SHAPE_CAPSULE)
		{
			const PINT_CAPSULE_CREATE* CapsuleCreate = static_cast<const PINT_CAPSULE_CREATE*>(CurrentShape);

/*			// ### PhysX is weird with capsules
			Matrix3x3 Rot;
			Rot.RotY(HALFPI);
			LocalPose.q *= ToPxQuat(Quat(Rot));
*/
			const PxQuat q = PxShortestRotation(PxVec3(1.0f, 0.0f, 0.0f), PxVec3(0.0f, 1.0f, 0.0f));
			LocalPose.q *= q;

			shape = actor->createShape(PxCapsuleGeometry(CapsuleCreate->mRadius, CapsuleCreate->mHalfHeight), *ShapeMaterial, LocalPose);
			ASSERT(shape);
		}
		else if(CurrentShape->mType==PINT_SHAPE_CONVEX)
		{
			const PINT_CONVEX_CREATE* ConvexCreate = static_cast<const PINT_CONVEX_CREATE*>(CurrentShape);

			ASSERT(mCooking);
//			PxConvexMesh* ConvexMesh = CreateConvexMesh(ConvexCreate->mVerts, ConvexCreate->mNbVerts, PxConvexFlag::eCOMPUTE_CONVEX|PxConvexFlag::eINFLATE_CONVEX, CurrentShape->mRenderer);
			PxConvexMesh* ConvexMesh = CreateConvexMesh(ConvexCreate->mVerts, ConvexCreate->mNbVerts, PxConvexFlag::eCOMPUTE_CONVEX, CurrentShape->mRenderer);
			ASSERT(ConvexMesh);

			shape = actor->createShape(PxConvexMeshGeometry(ConvexMesh), *ShapeMaterial, LocalPose);
			ASSERT(shape);
		}
		else if(CurrentShape->mType==PINT_SHAPE_MESH)
		{
			const PINT_MESH_CREATE* MeshCreate = static_cast<const PINT_MESH_CREATE*>(CurrentShape);

			ASSERT(mCooking);
			PxTriangleMesh* TriangleMesh = CreateTriangleMesh(MeshCreate->mSurface, CurrentShape->mRenderer);
			ASSERT(TriangleMesh);

			shape = actor->createShape(PxTriangleMeshGeometry(TriangleMesh), *ShapeMaterial, LocalPose);
			ASSERT(shape);
		}
		else ASSERT(0);

		if(shape)
		{
			SetupShape(mParams, CurrentShape, *shape, desc.mCollisionGroup, gDebugVizParams[0]);
			shape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, mParams.mUseCCD);
		}

		CurrentShape = CurrentShape->mNext;
	}
}
Пример #18
0
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;
}
Пример #19
0
void SampleParticles::loadTerrain(const char* path, PxReal xScale, PxReal yScale, PxReal zScale) 
{
	SampleFramework::SampleAsset* asset = getAsset(terrain_hf, SampleFramework::SampleAsset::ASSET_TEXTURE);
	mManagedAssets.push_back(asset);
	PX_ASSERT(asset->getType() == SampleFramework::SampleAsset::ASSET_TEXTURE);	
	SampleFramework::SampleTextureAsset* texAsset = static_cast<SampleFramework::SampleTextureAsset*>(asset);
	SampleRenderer::RendererTexture2D* heightfieldTexture = texAsset->getTexture();
	// NOTE: Assuming that heightfield texture has B8G8R8A8 format.
	if(heightfieldTexture) 
	{
		PxU16 nbColumns = PxU16(heightfieldTexture->getWidth());
		PxU16 nbRows = PxU16(heightfieldTexture->getHeight());
		PxHeightFieldDesc heightFieldDesc;
		heightFieldDesc.nbColumns = nbColumns;
		heightFieldDesc.nbRows = nbRows;
		PxU32* samplesData = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32) * nbColumns * nbRows);
		heightFieldDesc.samples.data = samplesData;
		heightFieldDesc.samples.stride = sizeof(PxU32);
		heightFieldDesc.convexEdgeThreshold = 0;
		PxU8* currentByte = (PxU8*)heightFieldDesc.samples.data;
		PxU32 texturePitch = 0;
		PxU8* loaderPtr = static_cast<PxU8*>(heightfieldTexture->lockLevel(0, texturePitch));
		PxVec3Alloc* verticesA = SAMPLE_NEW(PxVec3Alloc)[nbRows * nbColumns];
		PxVec3* vertices = verticesA;
		PxReal* UVs = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal) * nbRows * nbColumns * 2);
		for (PxU32 row = 0; row < nbRows; row++) 
		{
			for (PxU32 column = 0; column < nbColumns; column++) 
			{
				PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte;
				currentSample->height = *loaderPtr;
				vertices[row * nbColumns + column] = 
					PxVec3(PxReal(row) * xScale, 
					PxReal(currentSample->height * zScale), 
					PxReal(column) * yScale);
				
				UVs[2 * (row * nbColumns + column)] = (PxReal(row) / PxReal(nbRows)) * 7.0f;
				UVs[2 * (row * nbColumns + column) + 1] = (PxReal(column) / PxReal(nbColumns)) * 7.0f;
				currentSample->materialIndex0 = 0;
				currentSample->materialIndex1 = 0;
				currentSample->clearTessFlag();
				currentByte += heightFieldDesc.samples.stride;
				loaderPtr += 4 * sizeof(PxU8);
			}
		}
		PxHeightField* heightField = getPhysics().createHeightField(heightFieldDesc);
		// free allocated memory for heightfield samples description
		SAMPLE_FREE(samplesData);
		// create shape for heightfield		
		PxTransform pose(PxVec3(-((PxReal)nbRows*yScale) / 2.0f, 
								0.0f, 
								-((PxReal)nbColumns*xScale) / 2.0f), 
						PxQuat::createIdentity());
		PxRigidActor* hf = getPhysics().createRigidStatic(pose);
		runtimeAssert(hf, "PxPhysics::createRigidStatic returned NULL\n");
		PxShape* shape = hf->createShape(PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), zScale, xScale, yScale), getDefaultMaterial());
		runtimeAssert(shape, "PxRigidActor::createShape returned NULL\n");
		shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, false);
		shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
		// add actor to the scene
		getActiveScene().addActor(*hf);
		mPhysicsActors.push_back(hf);
		// create indices and UVs
		PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32) * (nbColumns - 1) * (nbRows - 1) * 3 * 2);
		for(int i = 0; i < (nbColumns - 1); ++i) 
		{
			for(int j = 0; j < (nbRows - 1); ++j) 
			{
				// first triangle
				indices[6 * (i * (nbRows - 1) + j) + 0] = (i + 1) * nbRows + j; 
				indices[6 * (i * (nbRows - 1) + j) + 1] = i * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 2] = i * nbRows + j + 1;
				// second triangle
				indices[6 * (i * (nbRows - 1) + j) + 3] = (i + 1) * nbRows + j + 1;
				indices[6 * (i * (nbRows - 1) + j) + 4] = (i + 1) * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 5] = i * nbRows + j + 1;
			}
		}
		// add mesh to renderer
		RAWMesh data;
		data.mName = "terrain";
		data.mTransform = PxTransform::createIdentity();
		data.mNbVerts = nbColumns * nbRows;
		data.mVerts = (PxVec3*)vertices;
		data.mVertexNormals = NULL;
		data.mUVs = UVs;
		data.mMaterialID = MATERIAL_HEIGHTFIELD;
		data.mNbFaces = (nbColumns - 1) * (nbRows - 1) * 2;
		data.mIndices = indices;
		RenderMeshActor* hf_mesh = createRenderMeshFromRawMesh(data);
		hf_mesh->setPhysicsShape(shape);
		SAMPLE_FREE(indices);
		SAMPLE_FREE(UVs);
		DELETEARRAY(verticesA);
	} 
	else 
	{ 
		char errMsg[256];
		physx::string::sprintf_s(errMsg, 256, "Couldn't load %s\n", path);
		fatalError(errMsg);
	}
}
Пример #20
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;
	}
}
Пример #21
0
void SampleSubmarine::createDynamicActors()
{
	// create mines
	static const PxU32 numMines = 20;
	static const PxVec3 mineFieldCenter = PxVec3(0, 64, 0);
	static const PxReal minMineDistance = 3.0f;
	static const PxI32 mineFieldRadius = 30;
	for(PxU32 i = 0; i < numMines; i++)
	{
		// raycast against floor (height field) to find the height to attach the mine
		PxRaycastHit rayHit;
		bool hit = false;
		do
		{
			PxVec3 offset = PxVec3(PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius)), 0, PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius)));
			PxVec3 raycastStart = mineFieldCenter + offset*minMineDistance;
			hit = getActiveScene().raycastSingle(raycastStart, PxVec3(0,-1,0), 100.0f, PxSceneQueryFlag::eIMPACT, rayHit);
		} 
		while(!hit || (rayHit.impact.y > 25.0f) || rayHit.shape->getActor().is<PxRigidDynamic>());
		createSeamine(rayHit.impact, getSampleRandom().rand(10.0f, 25.0f));
	}

	// create treasure
	{
		static const PxVec3 treasureDim = PxVec3(5, 3, 4)*0.5f;

		PxRaycastHit rayHit;
		PxVec3 raycastStart = PxVec3(-19, 64, -24);
		getActiveScene().raycastSingle(raycastStart, PxVec3(0,-1,0), 100.0f, PxSceneQueryFlag::eIMPACT, rayHit);

#ifdef RENDERER_PSP2
		gTreasureActor = createBox(rayHit.impact+treasureDim, treasureDim, NULL, mTreasureMaterial, 1)->is<PxRigidDynamic>();
#else
		gTreasureActor = createBox(rayHit.impact+treasureDim, treasureDim, NULL, mManagedMaterials[MATERIAL_BLUE], 1)->is<PxRigidDynamic>();
#endif
		if(!gTreasureActor) fatalError("createBox failed!");
		gTreasureActor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
		PxShape* treasureShape;
		gTreasureActor->getShapes(&treasureShape, 1);
		treasureShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
		treasureShape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
	}

	// create submarine
	createSubmarine(PxVec3(-110, 50, 110), 2.1f);
	
	char theCrabName[256];
	sprintf(theCrabName, "crab_%s.bin", getPlatformName());
	
	// If we have already had crab copy, just load it, or will create crab and export it
	char thePathBuffer[1024];
	const char* theCrabPath = getSampleOutputDirManager().getFilePath( theCrabName, thePathBuffer, false );
	FILE *fp = fopen( theCrabPath, "r" );
	if( fp )
	{
		printf("loading the crab from file status: ");
		gCrab = SAMPLE_NEW(Crab)(*this, theCrabPath, mManagedMaterials[MATERIAL_RED]);
		if (gCrab && !gCrab->getCrabBody())
		{
			delete gCrab;
			gCrab = NULL;
		}
		printf(gCrab ? "successful\n":"failed\n");						
		fclose (fp); 
	}

	if( !gCrab )
	{
		gCrab = SAMPLE_NEW(Crab)(*this, PxVec3(0, 50, 0), mManagedMaterials[MATERIAL_RED]);
		printf("crab file not found ... exporting crab file\n");
		gCrab->save(theCrabPath);
	}
	
	PX_ASSERT( gCrab );
	mCrabs.push_back(gCrab);

	static const PxU32 numCrabs = 3;
	for(PxU32 i = 0; i < numCrabs; i++)
	{
		Crab* crab = SAMPLE_NEW(Crab)(*this, PxVec3(getSampleRandom().rand(-20.0f,20.0f), 50, getSampleRandom().rand(-20.0f,20.0f)), mManagedMaterials[MATERIAL_RED]);
		mCrabs.push_back(crab);
	}
}
Пример #22
0
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;
}