Пример #1
0
void InnerWalls::Create()
{
	PxRigidStatic* rgd = PHYSICS->createRigidStatic(m_pose);
	
	Board* b = const_cast<Board*>(P::board);

	// Determine Poses
	Transform p_pLaneWall, p_pLaneWallTp, p_pLaneWallExt, p_fWallLft, p_fWallRgt;

	p_pLaneWall		= Transform(b->Right()	+ Vec3(b->PlungerLaneWidth() + (m_width*4), 0, b->Bottom().z+m_geometrys[IW_ID_PLUNGE_LN_WALL].box().halfExtents.z));
	p_pLaneWallTp = Transform(b->Top() - Vec3(m_width * 2, 0, (b->PlungerLaneWidth() * 3) + (m_width * 6)));

	// Create Shapes
	PxShape* pL		   = rgd->createShape(m_geometrys[IW_ID_PLUNGE_LN_WALL].box(), *m_material); // Plunger Lane Wall
	PxShape* PlT	   = rgd->createShape(m_geometrys[IW_ID_PLUNGE_LN_WALL_TP].box(), *m_material); // Plunger Lane Wall Top

	// Set Local Poses
	pL->setLocalPose(p_pLaneWall);
	PlT->setLocalPose(p_pLaneWallTp);

	// Set Global Pose
	rgd->setGlobalPose(P::board->Pose() * Transform(0, m_height*2, 0));

	m_actor.staticActor = rgd;

	m_actor.staticActor->userData = &m_color;
}
Пример #2
0
PxRigidDynamic* Vehicle::createVehicleActor(const PxVehicleChassisData& chassisData,
	PxMaterial** wheelMaterials, PxConvexMesh** wheelConvexMeshes, const PxU32 numWheels,
	PxMaterial** chassisMaterials, PxConvexMesh** chassisConvexMeshes, const PxU32 numChassisMeshes, PxPhysics& physics, PxVec3 initPos)
{
	//We need a rigid body actor for the vehicle.
	//Don't forget to add the actor to the scene after setting up the associated vehicle.
	PxRigidDynamic* vehActor = physics.createRigidDynamic(PxTransform(initPos));
	vehActor->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true);

	//Wheel and chassis simulation filter data.
	PxFilterData wheelSimFilterData;
	wheelSimFilterData.word0 = COLLISION_FLAG_WHEEL;
	wheelSimFilterData.word1 = COLLISION_FLAG_WHEEL_AGAINST;
	PxFilterData chassisSimFilterData;
	chassisSimFilterData.word0 = COLLISION_FLAG_CHASSIS;
	chassisSimFilterData.word1 = COLLISION_FLAG_CHASSIS_AGAINST;

	//Wheel and chassis query filter data.
	//Optional: cars don't drive on other cars.
	PxFilterData wheelQryFilterData;
	wheelQryFilterData.word0 = FilterGroup::eWHEEL;
	setupNonDrivableSurface(wheelQryFilterData);
	PxFilterData chassisQryFilterData;
	chassisQryFilterData.word0 = FilterGroup::eVEHICLE;

	setupNonDrivableSurface(chassisQryFilterData);

	//Add all the wheel shapes to the actor.
	for (PxU32 i = 0; i < numWheels; i++)
	{
		PxConvexMeshGeometry geom(wheelConvexMeshes[i]);
		PxShape* wheelShape = vehActor->createShape(geom, *wheelMaterials[i]);
		wheelShape->setQueryFilterData(wheelQryFilterData);
		wheelShape->setSimulationFilterData(wheelSimFilterData);
		wheelShape->setLocalPose(PxTransform(PxIdentity));
	}

	//Add the chassis shapes to the actor.
	for (PxU32 i = 0; i < numChassisMeshes; i++)
	{
		PxShape* chassisShape = vehActor->createShape
			(PxConvexMeshGeometry(chassisConvexMeshes[i]), *chassisMaterials[i]);
		chassisShape->setQueryFilterData(chassisQryFilterData);
		chassisShape->setSimulationFilterData(chassisSimFilterData);
		chassisShape->setLocalPose(PxTransform(PxIdentity));
	}

	vehActor->setMass(chassisData.mMass);
	vehActor->setMassSpaceInertiaTensor(chassisData.mMOI);
	vehActor->setCMassLocalPose(PxTransform(chassisData.mCMOffset, PxQuat(PxIdentity)));

	return vehActor;
}
FDUint BuildingSystem::newPoint(Vector3 point, PhysicsSystem& physics) {
	FDUint i = pointAuthor->newPoint(point);
	pointMesh->setSourceVertexData(pointAuthor->getVertexData());

	PxMaterial* m = physics.genericMaterial;

	// Point actor is constructed on the fly because PhysX issues a warning
	// if you try to add a physical object to the scene with no initial
	// geometry.
	FDbool actorExistsAlready = pointActor != NULL;
	if (!actorExistsAlready) {
		pointActor =  physics.physics->createRigidStatic(
			Transform(PxVec3(0, 0, 0)));
	}
	PxShape* shape = pointActor->createShape(PxSphereGeometry(0.2f), *m);
	shape->setFlags(PxShapeFlag::eSCENE_QUERY_SHAPE);
	shape->setLocalPose(Transform(Vector3(point)));
	shape->userData = (void*)i;

	if (!actorExistsAlready) {
		physics.scene->addActor(*pointActor);
	}

	return i;
}
Пример #4
0
	PxShape* AttachShape_AssumesLocked(const PxGeometry& PGeom, const PxTransform& PLocalPose, const float ContactOffset, PxShapeFlags PShapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eSIMULATION_SHAPE) const
	{
		const PxMaterial* PMaterial = GetDefaultPhysMaterial(); 
		PxShape* PNewShape = bShapeSharing ? GPhysXSDK->createShape(PGeom, *PMaterial, /*isExclusive =*/ false, PShapeFlags) : PDestActor->createShape(PGeom, *PMaterial, PShapeFlags);

		if (PNewShape)
		{
			PNewShape->setLocalPose(PLocalPose);

			if (NewShapes)
			{
				NewShapes->Add(PNewShape);
			}

			PNewShape->setContactOffset(ContactOffset);

			const bool bSyncFlags = bShapeSharing || SceneType == PST_Sync;
			const FShapeFilterData& Filters = ShapeData.FilterData;
			const bool bComplexShape = PNewShape->getGeometryType() == PxGeometryType::eTRIANGLEMESH;

			PNewShape->setQueryFilterData(bComplexShape ? Filters.QueryComplexFilter : Filters.QuerySimpleFilter);
			PNewShape->setFlags( (bSyncFlags ? ShapeData.SyncShapeFlags : ShapeData.AsyncShapeFlags) | (bComplexShape ? ShapeData.ComplexShapeFlags : ShapeData.SimpleShapeFlags));
			PNewShape->setSimulationFilterData(Filters.SimFilter);
			FBodyInstance::ApplyMaterialToShape_AssumesLocked(PNewShape, SimpleMaterial, ComplexMaterials, bShapeSharing);

			if(bShapeSharing)
			{
				PDestActor->attachShape(*PNewShape);
				PNewShape->release();
			}
		}

		return PNewShape;
	}
	PhysXMeshCollider::PhysXMeshCollider(PxPhysics* physx, const Vector3& position, const Quaternion& rotation)
	{
		PxSphereGeometry geometry(0.01f); // Dummy

		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
		shape->setLocalPose(toPxTransform(position, rotation));
		shape->userData = this;

		mInternal = bs_new<FPhysXCollider>(shape);
	}
Пример #6
0
void UBodySetup::AddTriMeshToRigidActor(PxRigidActor* PDestActor, const FVector& Scale3D, const FVector& Scale3DAbs) const
{
	float ContactOffsetFactor, MaxContactOffset;
	GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset);
	PxMaterial* PDefaultMat = GetDefaultPhysMaterial();

	if(TriMesh || TriMeshNegX)
	{
		PxTransform PLocalPose;
		bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose);

		// Only case where TriMeshNegX should be null is BSP, which should not require negX version
		if (bUseNegX && TriMeshNegX == NULL)
		{
			UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: Want to use NegX but it doesn't exist! %s"), *GetPathName());
		}

		PxTriangleMesh* UseTriMesh = bUseNegX ? TriMeshNegX : TriMesh;
		if (UseTriMesh != NULL)
		{


			PxTriangleMeshGeometry PTriMeshGeom;
			PTriMeshGeom.triangleMesh = bUseNegX ? TriMeshNegX : TriMesh;
			PTriMeshGeom.scale.scale = U2PVector(Scale3DAbs);
			if (bDoubleSidedGeometry)
			{
				PTriMeshGeom.meshFlags |= PxMeshGeometryFlag::eDOUBLE_SIDED;
			}


			if (PTriMeshGeom.isValid())
			{
				ensure(PLocalPose.isValid());

				// Create without 'sim shape' flag, problematic if it's kinematic, and it gets set later anyway.
				PxShape* NewShape = PDestActor->createShape(PTriMeshGeom, *PDefaultMat, PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eVISUALIZATION);
				if (NewShape)
				{
					NewShape->setLocalPose(PLocalPose);
					NewShape->setContactOffset(MaxContactOffset);
				}
				else
				{
					UE_LOG(LogPhysics, Log, TEXT("Can't create new mesh shape in AddShapesToRigidActor"));
				}
			}
			else
			{
				UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: TriMesh invalid"));
			}
		}
	}
}
Пример #7
0
	PhysXBoxCollider::PhysXBoxCollider(PxPhysics* physx, const Vector3& position, const Quaternion& rotation, 
		const Vector3& extents)
		:mExtents(extents)
	{
		PxBoxGeometry geometry(extents.x, extents.y, extents.z);

		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
		shape->setLocalPose(toPxTransform(position, rotation));
		shape->userData = this;

		mInternal = bs_new<FPhysXCollider>(shape);
		applyGeometry();
	}
	PhysXSphereCollider::PhysXSphereCollider(PxPhysics* physx, const Vector3& position, const Quaternion& rotation,
		float radius)
		:mRadius(radius)
	{
		PxSphereGeometry geometry(radius);

		PxShape* shape = physx->createShape(geometry, *gPhysX().getDefaultMaterial(), true);
		shape->setLocalPose(toPxTransform(position, rotation));
		shape->userData = this;

		mInternal = bs_new<FPhysXCollider>(shape);
		applyGeometry();
	}
Пример #9
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);

}
Пример #10
0
void Border::Create()
{
	PxRigidStatic* rgd = PHYSICS->createRigidStatic(m_pose);
	
	Board* b = const_cast<Board*>(P::board);

	// Determine Poses
	Transform p_top, p_bottom_lft, p_bottom_rgt, p_left, p_right;
	p_top =			Transform(b->Top()	  - Vec3(0,0,m_width));
	p_bottom_lft =  Transform(Vec3(b->Left().x - m_geometrys[BDR_ID_BTM_LFT].box().halfExtents.x, 0, b->Bottom().z));
	p_bottom_rgt =  Transform(Vec3(b->Right().x + m_geometrys[BDR_ID_BTM_RGT].box().halfExtents.x + b->PlungerLaneWidth() + m_width*3, 0, b->Bottom().z));
	p_left	 =		Transform(b->Left()	  - Vec3(m_width, 0, 0));
	p_right  =		Transform(b->Right()  + Vec3(m_width, 0, -m_width));

	// Create Shapes
	PxShape* sT = rgd->createShape(m_geometrys[BDR_ID_TOP].box(), *m_material);
	PxShape* sBl = rgd->createShape(m_geometrys[BDR_ID_BTM_LFT].box(), *m_material);
	PxShape* sBr = rgd->createShape(m_geometrys[BDR_ID_BTM_RGT].box(), *m_material);
	PxShape* sL = rgd->createShape(m_geometrys[BDR_ID_LFT].box(), *m_material);
	PxShape* sR = rgd->createShape(m_geometrys[BDR_ID_RGT].box(), *m_material);

	// Set Local Poses
	sT->setLocalPose(p_top);
	sBl->setLocalPose(p_bottom_lft);
	sBr->setLocalPose(p_bottom_rgt);
	sL->setLocalPose(p_left);
	sR->setLocalPose(p_right);
	
	// Set Global Pose
	Transform t = const_cast<Board*>(P::board)->Get().staticActor->getGlobalPose();
	rgd->setGlobalPose(P::board->Pose() * Transform(0, m_height*2, 0));

	m_actor.staticActor = rgd;

	m_actor.staticActor->userData = &m_color;
}
Пример #11
0
PxShape* PxCloneShape(PxPhysics &physics, const PxShape& from, bool isExclusive)
{
	Ps::InlineArray<PxMaterial*, 64> materials;
	PxU16 materialCount = from.getNbMaterials();
	materials.resize(materialCount);
	from.getMaterials(materials.begin(), materialCount);

	PxShape* to = physics.createShape(from.getGeometry().any(), materials.begin(), materialCount, isExclusive, from.getFlags());

	to->setLocalPose(from.getLocalPose());
	to->setContactOffset(from.getContactOffset());
	to->setRestOffset(from.getRestOffset());
	to->setSimulationFilterData(from.getSimulationFilterData());
	to->setQueryFilterData(from.getQueryFilterData());
	return to;
}
PxRigidStatic*	PxCreateStatic(PxPhysics& sdk,
							   const PxTransform& transform,
							   const PxGeometry& geometry,
							   PxMaterial& material,
							   const PxTransform& shapeOffset)
{

	PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid.");
	PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateStatic: shapeOffset is not valid.");

	PxShape* shape = sdk.createShape(geometry, material, true);
	if(!shape)
		return NULL;

	shape->setLocalPose(shapeOffset);

	PxRigidStatic* s = PxCreateStatic(sdk, transform, *shape);
	shape->release();
	return s;
}
Пример #13
0
bool copyStaticProperties(PxRigidActor& to, const PxRigidActor& from,NxMirrorScene::MirrorFilter &mirrorFilter)
{
	physx::shdfnd::InlineArray<PxShape*, 64> shapes;
	shapes.resize(from.getNbShapes());

	PxU32 shapeCount = from.getNbShapes();
	from.getShapes(shapes.begin(), shapeCount);

	physx::shdfnd::InlineArray<PxMaterial*, 64> materials;
	for(PxU32 i = 0; i < shapeCount; i++)
	{
		PxShape* s = shapes[i];

		if ( mirrorFilter.shouldMirror(*s) )
		{
			PxU32 materialCount = s->getNbMaterials();
			materials.resize(materialCount);
			s->getMaterials(materials.begin(), materialCount);
			PxShape* shape = to.createShape(s->getGeometry().any(), materials.begin(), static_cast<physx::PxU16>(materialCount));
			shape->setLocalPose( s->getLocalPose());
			shape->setContactOffset(s->getContactOffset());
			shape->setRestOffset(s->getRestOffset());
			shape->setFlags(s->getFlags());
			shape->setSimulationFilterData(s->getSimulationFilterData());
			shape->setQueryFilterData(s->getQueryFilterData());
			mirrorFilter.reviseMirrorShape(*shape);
		}
	}

	to.setActorFlags(from.getActorFlags());
	to.setOwnerClient(from.getOwnerClient());
	to.setDominanceGroup(from.getDominanceGroup());

	if ( to.getNbShapes() )
	{
		mirrorFilter.reviseMirrorActor(to);
	}

	return to.getNbShapes() != 0;
}
Пример #14
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);
	}
}
PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk, 
								const PxTransform& transform, 
								const PxGeometry& geometry,
							    PxMaterial& material, 
								PxReal density,
								const PxTransform& shapeOffset)
{
	PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid.");
	PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateDynamic: shapeOffset is not valid.");

	if(!isDynamicGeometry(geometry.getType()) || density <= 0.0f)
	    return NULL;

	PxShape* shape = sdk.createShape(geometry, material, true);
	if(!shape)
		return NULL;

	shape->setLocalPose(shapeOffset);

	PxRigidDynamic* body = shape ? PxCreateDynamic(sdk, transform, *shape, density) : NULL;
	shape->release();
	return body;
}
Пример #16
0
// Creates an physics entity from an entity info structure and a starting transform
void PhysicsEngine::createEntity(PhysicsEntity* entity, PhysicsEntityInfo* info, PxTransform transform)
{
	transform.p.y += info->yPosOffset;
	// Set static/dynamic info for actor depending on its type
	PxRigidActor* actor;
	if (info->type == PhysicsType::DYNAMIC) 
	{
		DynamicInfo* dInfo = info->dynamicInfo;
		PxRigidDynamic* dynamicActor = physics->createRigidDynamic(transform);
		dynamicActor->setLinearDamping(dInfo->linearDamping);
		dynamicActor->setAngularDamping(dInfo->angularDamping);
		dynamicActor->setMaxAngularVelocity(dInfo->maxAngularVelocity);

		actor = dynamicActor;
	}
	else if (info->type == PhysicsType::STATIC)
	{
		PxRigidStatic* staticActor = physics->createRigidStatic(transform);
		actor = staticActor;
	}

	// All shapes in actor
	for (auto sInfo : info->shapeInfo)
	{
		// Create material and geometry for shape and add it to actor
		PxGeometry* geometry;
		PxMaterial* material;
		if (sInfo->geometry == Geometry::SPHERE)
		{
			SphereInfo* sphInfo = (SphereInfo*)sInfo;
			geometry = new PxSphereGeometry(sphInfo->radius);
		}
		else if (sInfo->geometry == Geometry::BOX)
		{
			BoxInfo* boxInfo = (BoxInfo*)sInfo;		
			geometry = new PxBoxGeometry(boxInfo->halfX, boxInfo->halfY, boxInfo->halfZ);
		}
		else if (sInfo->geometry == Geometry::CAPSULE)
		{
			CapsuleInfo* capInfo = (CapsuleInfo*)sInfo;
			geometry = new PxCapsuleGeometry(capInfo->radius, capInfo->halfHeight);
		}
		else if (sInfo->geometry == Geometry::CONVEX_MESH)
		{
			ConvexMeshInfo* cmInfo = (ConvexMeshInfo*)sInfo;

			PxConvexMesh* mesh = helper->createConvexMesh(cmInfo->verts.data(), cmInfo->verts.size());
			geometry = new PxConvexMeshGeometry(mesh);
		}
		// Not working until index drawing is set up
		else if (sInfo->geometry == Geometry::TRIANGLE_MESH)
		{
			TriangleMeshInfo* tmInfo = (TriangleMeshInfo*)sInfo;

			PxTriangleMesh* mesh = helper->createTriangleMesh(tmInfo->verts.data(), tmInfo->verts.size(), tmInfo->faces.data(), tmInfo->faces.size()/3);
			geometry = new PxTriangleMeshGeometry(mesh);
		}
		material = (sInfo->isDrivable) ? drivingSurfaces[0] : physics->createMaterial(sInfo->dynamicFriction, sInfo->staticFriction, sInfo->restitution);
		PxShape* shape = actor->createShape(*geometry, *material); // TODO support shape flags
		shape->setLocalPose(sInfo->transform);

		material->release();
		delete geometry;

		// Set up querry filter data for shape
		PxFilterData qryFilterData;
		qryFilterData.word3 = (sInfo->isDrivable) ? (PxU32)Surface::DRIVABLE : (PxU32)Surface::UNDRIVABLE;
		shape->setQueryFilterData(qryFilterData);

		// Set up simulation filter data for shape
		PxFilterData simFilterData;
		simFilterData.word0 = (PxU32)sInfo->filterFlag0;
		simFilterData.word1 = (PxU32)sInfo->filterFlag1;
		simFilterData.word2 = (PxU32)sInfo->filterFlag2;
		simFilterData.word3 = (PxU32)sInfo->filterFlag3;
		shape->setSimulationFilterData(simFilterData);

		if (info->type == PhysicsType::DYNAMIC) 
		{
			DynamicInfo* dInfo = info->dynamicInfo;
			PxRigidBodyExt::updateMassAndInertia(*(PxRigidBody*)actor, dInfo->density, &dInfo->cmOffset);

			PxRigidBody* body = (PxRigidBody*)actor;
		}
	}

	// Add actor to scene, set actor for entity, and set user data for actor. Creates one to one between entities and phyX
	scene->addActor(*actor);
	entity->setActor(actor);
	actor->userData = entity;
}
Пример #17
0
bool CTank::CreateTankActor( CPhysX * pPhysX )
{
	if( !LoadData( "InitShader.lua" ) )
		return false;

// 	CParamTank* pParamTank = new CParamTank;
// 
// 	if( !CLua::LoadParamTank( "", &pParamTank ) )
// 	{
// 
// 	}

	if( GameObject * pBody = GetDetail( BODY ) )
	{
		if ( pBody->CreateTriangleMesh( pPhysX ) )
		{			
			pBody->Update( 0.f );
			
			PxTriangleMesh* triangleMesh = pBody->GetTriangleMesh();
			D3DXVECTOR3     Position     = pBody->GetPosition();
			//D3DXComputeBoundingBox(Vertices,  g_pMesh->GetNumVertices(),  FVFVertexSize, &pMin, &pMax);
			//PxRigidDynamic* pRigDynAct   = pPhysX->GetPhysics()->createRigidDynamic( PxTransform( physx::PxVec3( Position.x, Position.y, Position.z ) ) );
// 			PxRigidDynamic* pRigDynAct   = PxCreateDynamic( *pPhysX->GetPhysics(), PxTransform( physx::PxVec3( Position.x, Position.y, Position.z ) ), PxBoxGeometry( 14.f, 4.6f, 6.f ), *pMaterial, 1.f );
// 
// 			if( pRigDynAct && pMaterial && triangleMesh )
// 			{
// 				//pRigDynAct->createShape( PxTriangleMeshGeometry( triangleMesh ), *pMaterial );
// 				
// 				pRigDynAct->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, false);
// 				pRigDynAct->setActorFlag( PxActorFlag::eVISUALIZATION, true );
// 				pRigDynAct->setAngularDamping( 0.5f );
// 				//pRigDynAct->setMass( 10000.f );
// 				PxRigidBodyExt::updateMassAndInertia( *pRigDynAct, 10.f );
// 				
// 				if( pMaterial )
// 					pPhysX->PushMaterial( pMaterial );
// 				
// 				pPhysX->AddActorScene( pRigDynAct );
// 				m_pActor = pRigDynAct;
// 
// 				return true;
// 			}

			const int    nWheels     = 12;
			PxF32        chassisMass = 1500.f;
			const PxF32  wheelMass   = 50.f;			
			PxF32		 fShift      = -0.85f;
			PxVec3 wheelCentreOffsets[ nWheels ];

			for( int i = 0; i < nWheels/2; ++i )
			{
				wheelCentreOffsets[ i*2   ] = PxVec3( -1.2f, -0.5f,  2.1f + i * fShift );
				wheelCentreOffsets[ i*2+1 ] = PxVec3(  1.2f, -0.5f,  2.1f + i * fShift );				
			}

			// размеры корпуса
			const PxVec3 chassisDims( 2.4f, 1.f, 6.f );// = computeChassisAABBDimensions(chassisConvexMesh);

			// Начало координат находится в центре шасси сетки
			// Установить центр масс будет ниже этой точки
			const PxVec3 chassisCMOffset = PxVec3( 0.f, -chassisDims.y * 0.5f - 0.65f, 0.f );

			PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate( nWheels );
			PxVehicleWheelsSimData& wheelsData = *wheelsSimData;
			PxVehicleDriveSimData4W driveData;
			
			PxVec3 chassisMOI( (chassisDims.y*chassisDims.y + chassisDims.z * chassisDims.z) * chassisMass / 12.f,
							   (chassisDims.x*chassisDims.x + chassisDims.z * chassisDims.z) * chassisMass / 12.f,
							   (chassisDims.x*chassisDims.x + chassisDims.y * chassisDims.y) * chassisMass / 12.f);

			// структура шасси
			PxVehicleChassisData chassisData;
			
			chassisData.mMass	  = chassisMass;		// Масса транспортного средства жесткой актер тела
			chassisData.mMOI	  = chassisMOI;			// Момент инерции автомобиля жесткая актер тела.
			chassisData.mCMOffset = chassisCMOffset;	// Центр масс смещение автомобиля жесткая актер тела.

			// Немного настройки здесь.Автомобиль будет иметь более отзывчивым поворот, если мы сведем
			// у-компоненты шасси момента инерции.
			chassisMOI.y *= 0.8f;

			const PxF32 massRear  = 0.5f * chassisMass * ( chassisDims.z - 3 * chassisCMOffset.z ) / chassisDims.z;
			const PxF32 massFront = massRear;

			//Extract the wheel radius and width from the wheel convex meshes
			PxF32 wheelWidths[ nWheels ] = {0.f};
			PxF32 wheelRadii[ nWheels ]  = {0.f};
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				 wheelWidths[ i ] = 0.5f;
				 wheelRadii [ i ] = 0.32f;
			}

			// Теперь вычислим колеса массы и инерции компонентов вокруг оси оси			
			PxF32 wheelMOIs[ nWheels ];
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				wheelMOIs[ i ] = 0.5f * wheelMass * wheelRadii[ i ] * wheelRadii[ i ];
			}

			// Давайте создадим структуру данных колеса теперь с радиусом, массы и МВД
			PxVehicleWheelData wheels[ nWheels ];
			for(PxU32 i = 0; i < nWheels; ++i )
			{
				wheels[ i ].mRadius				= wheelRadii[ i ];		// Радиус блок, который включает в себя колеса металл плюс резиновые шины
				wheels[ i ].mMass				= wheelMass;			// Масса колеса плюс шины
				wheels[ i ].mMOI				= wheelMOIs[ i ];		// Момент инерции колеса
				wheels[ i ].mWidth				= wheelWidths[ i ];		// Максимальная ширина блок, который включает в себя колеса плюс шин
				//wheels[ i ].mMaxHandBrakeTorque = 0.f;					// Отключение стояночного тормоза от передних колес и позволяют для задних колес
				//wheels[ i ].mMaxSteer			= 0.f;					// Включить рулевого управления для передних колес и отключить для передних колес
				//wheels[ i ].mDampingRate		= 1.f;				// Скорость затухания описывает скорость, с которой свободно вращающееся колесо теряет скорость вращения
			}

			//Let's set up the tire data structures now.
			//Put slicks on the front tires and wets on the rear tires.
			PxVehicleTireData tires[ nWheels ];

			for(PxU32 i = 0; i < nWheels; ++i )
			{				
				tires[ i ].mType = 1;			// тип сцепления шин с поверхностью
			}

			// Структура данных подвески
			PxVehicleSuspensionData susps[ nWheels ];

			for( PxU32 i = 0; i < nWheels; i++ )
			{
				susps[ i ].mMaxCompression	 = 0.03f;				// Максимальное сжатие пружинной подвески
				susps[ i ].mMaxDroop		 = 0.03f;				// Максимальное удлинение пружинной подвески
				susps[ i ].mSpringStrength	 = 20000.f;	// пружинная сила подвески блока
				susps[ i ].mSpringDamperRate = 500.f;
				susps[ i ].mSprungMass		 = chassisMass / nWheels;	// Масса транспортного средства, которая поддерживается пружинная подвеска, указанных в кг.
			}
			
			PxVec3 suspTravelDirections[ nWheels ];
			PxVec3 wheelCentreCMOffsets[ nWheels ];
			PxVec3 suspForceAppCMOffsets[ nWheels ];
			PxVec3 tireForceAppCMOffsets[ nWheels ];

			for( PxU32 i = 0 ; i < nWheels; ++i )
			{
				wheelCentreCMOffsets [ i ] = wheelCentreOffsets[ i ] - chassisCMOffset;
				suspForceAppCMOffsets[ i ] = PxVec3( wheelCentreCMOffsets[ i ].x, -0.3f, wheelCentreCMOffsets[ i ].z );
				tireForceAppCMOffsets[ i ] = PxVec3( wheelCentreCMOffsets[ i ].x, -0.3f, wheelCentreCMOffsets[ i ].z );
				suspTravelDirections [ i ] = PxVec3( 0, -1, 0 );	// направление подвески
			}

			// Теперь добавьте колеса, шины и подвеска данных
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				wheelsData.setWheelData( i, wheels[ i ] );								// установить данные колеса
				wheelsData.setTireData( i, tires[ i ] );								// Установите шину данных колеса
				wheelsData.setSuspensionData( i, susps[ i ] );							// Установите подвеску данные колеса
				wheelsData.setSuspTravelDirection( i, suspTravelDirections[ i ] );		// Установить направление движения подвески колес
				wheelsData.setWheelCentreOffset( i, wheelCentreCMOffsets[ i ] );		// Установить смещение от центра жесткой тело массой в центре колеса
				wheelsData.setSuspForceAppPointOffset( i, suspForceAppCMOffsets[ i ] );	// Установить приложение точкой подвески силу подвески колес
				wheelsData.setTireForceAppPointOffset( i, tireForceAppCMOffsets[ i ] );	// Установить приложение точку шин силу шинах колес
			}

			//Diff
			PxVehicleDifferential4WData diff;
			diff.mType = PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD;
			driveData.setDiffData( diff );

			//Engine
			PxVehicleEngineData engine;
			engine.mPeakTorque								= 300.f;	// максимальная скорость вращения двигателя
			engine.mMaxOmega								= 400.f;	// Максимальный крутящий момент доступен обратиться к двигателю
			engine.mDampingRateFullThrottle					= 0.15f;	// скорость затухания двигатель при полностью открытой дроссельной заслонке	
			engine.mDampingRateZeroThrottleClutchEngaged	= 8.f;		// скорость затухания двигатель при нулевой газ при включении сцепления
			engine.mDampingRateZeroThrottleClutchDisengaged	= 0.35f;	// Краткие скорость затухания двигатель при нулевой газ при выключенном сцеплении (на нейтральной передаче)

			driveData.setEngineData( engine );

			//Gears
			PxVehicleGearsData gears;
			gears.mSwitchTime = 0.5f;
			driveData.setGearsData( gears );

			// Прочность сцепления
			PxVehicleClutchData clutch;
			clutch.mStrength = PxVehicleGearsData::eMAX_NUM_GEAR_RATIOS;
			driveData.setClutchData( clutch );

			//Ackermann steer accuracy
			PxVehicleAckermannGeometryData ackermann;
			ackermann.mAccuracy		  = 0.1f;
			ackermann.mAxleSeparation = wheelCentreOffsets[ 0 ].z - wheelCentreOffsets[ nWheels - 1 ].z;	// Расстояние между центром передней оси и центром задней оси
			ackermann.mFrontWidth	  = wheelCentreOffsets[ 0 ].x - wheelCentreOffsets[ 1		    ].x;	// Расстояние между центральной точке два передних колеса
			ackermann.mRearWidth	  = wheelCentreOffsets[ nWheels - 2 ].x - wheelCentreOffsets[ nWheels - 1 ].x;	// Расстояние между центральной точке два задних колеса
			driveData.setAckermannGeometryData(ackermann);			
			
			PxTriangleMesh * pTriangleMesh = 0;
			D3DXVECTOR3      vPosition;

			if( GameObject * pRoller = GetDetail( WHEEL_LEFT_1ST ) )
			{
				if( pRoller->CreateTriangleMesh( pPhysX ) )
				{
					pRoller->Update( 0.f );					
					pTriangleMesh = pRoller->GetTriangleMesh();
					Position      = pRoller->GetPosition();
				}
			}

			// Нам нужно добавить колеса столкновения форм, их местный позы, материал для колес, и моделирование фильтра для колес
			PxTriangleMeshGeometry WheelGeom( pTriangleMesh );
			
			PxGeometry* wheelGeometries[ nWheels ] = {0};
			PxTransform wheelLocalPoses[ nWheels ];

			for( PxU32 i = 0; i < nWheels; ++i )
			{
				wheelGeometries[ i ] = &WheelGeom;
				wheelLocalPoses[ i ] = PxTransform::createIdentity();
			}
			
			PxMaterial* pMaterial = pPhysX->GetPhysics()->createMaterial( 0.5f, 0.5f, 0.1f );    //коэффициенты трения скольжения и покоя(Dynamic friction,Static friction), коэффициент упругости
			const PxMaterial& wheelMaterial	= *pMaterial;
			PxFilterData wheelCollFilterData;

			wheelCollFilterData.word0 = COLLISION_FLAG_WHEEL;
			wheelCollFilterData.word1 = COLLISION_FLAG_WHEEL_AGAINST;

			// Нам нужно добавить шасси столкновения форм, их местный позы, материала для шасси и моделирования фильтр для шасси.
			//PxBoxGeometry chassisConvexGeom( 1.5f, 0.3f, 4.f );
			PxBoxGeometry chassisConvexGeom( chassisDims.x/2, chassisDims.y/2, chassisDims.z/2 );

			const PxGeometry* chassisGeoms	    = &chassisConvexGeom;
			const PxTransform chassisLocalPoses = PxTransform::createIdentity();
			const PxMaterial& chassisMaterial	= *pMaterial;

			PxFilterData chassisCollFilterData;
			chassisCollFilterData.word0 = COLLISION_FLAG_CHASSIS;
			chassisCollFilterData.word1 = COLLISION_FLAG_CHASSIS_AGAINST;

			// Создание фильтра запроса данных для автомобилей, чтобы машины не пытайтесь ездить на себя.
			PxFilterData vehQryFilterData;			
			SampleVehicleSetupVehicleShapeQueryFilterData( &vehQryFilterData );

			PxRigidDynamic* vehActor = pPhysX->GetPhysics()->createRigidDynamic( PxTransform::createIdentity() );

			//Add all the wheel shapes to the actor.
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				PxShape* wheelShape=vehActor->createShape( *wheelGeometries[ i ], wheelMaterial );
				wheelShape->setQueryFilterData( vehQryFilterData );
				wheelShape->setSimulationFilterData( wheelCollFilterData );
				wheelShape->setLocalPose( wheelLocalPoses[ i ] );
				wheelShape->setFlag( PxShapeFlag::eSIMULATION_SHAPE, true );
			}

			//Add the chassis shapes to the actor			
			PxShape* chassisShape = vehActor->createShape( *chassisGeoms, chassisMaterial );
			chassisShape->setQueryFilterData( vehQryFilterData );
			chassisShape->setSimulationFilterData( chassisCollFilterData );
			chassisShape->setLocalPose( PxTransform( physx::PxVec3( 0, 0, 0 ) ) );
			

			vehActor->setMass( chassisData.mMass );
			vehActor->setMassSpaceInertiaTensor( chassisData.mMOI );
			vehActor->setCMassLocalPose( PxTransform( chassisData.mCMOffset, PxQuat::createIdentity() ) );
			vehActor->setGlobalPose( PxTransform( physx::PxVec3( 0, 8, 0 ), PxQuat::createIdentity() ) );

			PxVehicleDriveTank* pTank = PxVehicleDriveTank::allocate( nWheels );
 			
 			pTank->setup( pPhysX->GetPhysics(), vehActor, *wheelsSimData, driveData, nWheels );			
			pPhysX->AddActorScene( vehActor );
			m_pActor = vehActor;
			pPhysX->AddTank( pTank );

			//Free the sim data because we don't need that any more.
			wheelsSimData->free();
			//pTank->setDriveModel( PxVehicleDriveTank::eDRIVE_MODEL_SPECIAL );
			pTank->setToRestState();			
			pTank->mDriveDynData.setUseAutoGears( true );

			return true;
		}
	}

	return false;
}