/**
		 * Method is used to add new dynamic actor to physics scene.
		 * @param	entity is pointer to scene entity which will be added to physics simulation.
		 * @param	type is enumeration of shape type.
		 * @param	filterGroup is actor own id.
		 * @param	filterMask is mask to filter pairs that trigger a contact callback.
		 */
		void PhysicsManager::addDynamicActor(SceneEntity* entity, ShapeType type, PxU32 filterGroup, PxU32 filterMask)
		{
			PxRigidDynamic* actor = nullptr;
			
			PxVec3 position = PxVec3(entity->entityState.position[0],entity->entityState.position[1],entity->entityState.position[2]);	
			PxQuat orientation = PxQuat(entity->entityState.orientation[0],entity->entityState.orientation[1],entity->entityState.orientation[2],entity->entityState.orientation[3]);
			PxReal density = 1.0f;
			PxTransform transformation = PxTransform(position,orientation); 

			if(type == BOX)
			{
				float x = (entity->entityGeometry.geometryBox->max.x() - entity->entityGeometry.geometryBox->min.x())*entity->entityState.scale.x()*0.5f;
				float y = (entity->entityGeometry.geometryBox->max.y() - entity->entityGeometry.geometryBox->min.y())*entity->entityState.scale.y()*0.5f;
				float z = (entity->entityGeometry.geometryBox->max.z() - entity->entityGeometry.geometryBox->min.z())*entity->entityState.scale.z()*0.5f;
				
				PxVec3 dimensions(x,y,z);
				actor = PxCreateDynamic(*physicsSDK,transformation,PxBoxGeometry(dimensions),*materials[0].second,density);
				PxRigidBodyExt::updateMassAndInertia(*actor, density);
			}
			else if(type == SPHERE)
			{
				float radius = entity->entityGeometry.geometrySphere->sphereRadius;
				actor = PxCreateDynamic(*physicsSDK,transformation,PxSphereGeometry(radius),*materials[0].second,density);
			}
			else if(type == CAPSULE)
			{
				float radius = entity->entityGeometry.geometrySphere->sphereRadius;
				actor = PxCreateDynamic(*physicsSDK,transformation,PxCapsuleGeometry(radius/2, radius),*materials[0].second,density);
			}
			else if(type == CONVEX)
			{
				/*int vertsCount = entity->entityGeometry.geometryMesh->getVerticesAmount();
				AyumiUtils::Vertex<>* verts = entity->entityGeometry.geometryMesh->getVertices();
				PxVec3* convexVerts = new PxVec3[vertsCount];

				for(int i = 0; i < vertsCount; ++i)
					convexVerts[i] = PxVec3(verts[i].x,verts[i].y,verts[i].z);

				PxConvexMeshDesc convexDesc;
				convexDesc.points.count = entity->entityGeometry.geometryMesh->getVerticesAmount();
				convexDesc.points.stride = sizeof(PxVec3);
				convexDesc.points.data = convexVerts;
				convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;

				MemoryWriteBuffer buf;
				if(cooking->cookConvexMesh(convexDesc, buf))
				{
					PxConvexMesh* convexMesh = physicsSDK->createConvexMesh(MemoryReadBuffer(buf.data));
					actor = PxCreateDynamic(*physicsSDK,transformation,PxConvexMeshGeometry(convexMesh,PxMeshScale()),*materials[0].second,density);
				}
				else
				{
					Logger::getInstance()->saveLog(Log<string>("Convex Mesh creation error occurred!"));
					return;
				}*/
				//delete[] convexVerts;
			}
			else
			{
				Logger::getInstance()->saveLog(Log<string>("Dynamic Actor shape creation error occurred!"));
				return;
			}

			if(!actor)
				Logger::getInstance()->saveLog(Log<string>("Static Actor creation error occurred!"));
			
			PxRigidBodyExt::updateMassAndInertia(*actor, density);
			actor->setAngularDamping(0.75);
			actor->setLinearVelocity(PxVec3(0,0,0));
			actor->setName(entity->entityName.c_str());
			setupFiltering(actor,filterGroup,filterMask);
			scene->addActor(*actor);
			
			DynamicActor* d = new DynamicActor();
			d->entityLogic = entity;
			d->entityPhysics = actor;
			d->shapesAmount = actor->getNbShapes();
			d->shapes = new PxShape*[d->shapesAmount];
			dynamicActors.push_back(d);
		}
Example #2
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;
	}
}
void PxVehicleCopyDynamicsData(const PxVehicleCopyDynamicsMap& wheelMap, const PxVehicleWheels& src, PxVehicleWheels* trg)
{
	PX_CHECK_AND_RETURN(trg, "PxVehicleCopyDynamicsData requires that trg is a valid vehicle pointer");

	PX_CHECK_AND_RETURN(src.getVehicleType() == trg->getVehicleType(), "PxVehicleCopyDynamicsData requires that both src and trg are the same type of vehicle");

#ifdef PX_CHECKED
	{
		const PxU32 numWheelsSrc = src.mWheelsSimData.getNbWheels();
		const PxU32 numWheelsTrg = trg->mWheelsSimData.getNbWheels();
		PxU8 copiedWheelsSrc[PX_MAX_NB_WHEELS];
		PxMemZero(copiedWheelsSrc, sizeof(PxU8) * PX_MAX_NB_WHEELS);
		PxU8 setWheelsTrg[PX_MAX_NB_WHEELS];
		PxMemZero(setWheelsTrg, sizeof(PxU8) * PX_MAX_NB_WHEELS);
		for(PxU32 i = 0; i < PxMin(numWheelsSrc, numWheelsTrg); i++)
		{
			const PxU32 srcWheelId = wheelMap.sourceWheelIds[i];
			PX_CHECK_AND_RETURN(srcWheelId < numWheelsSrc, "PxVehicleCopyDynamicsData - wheelMap contains illegal source wheel id");
			PX_CHECK_AND_RETURN(0 == copiedWheelsSrc[srcWheelId], "PxVehicleCopyDynamicsData - wheelMap contains illegal source wheel id");
			copiedWheelsSrc[srcWheelId] = 1;

			const PxU32 trgWheelId = wheelMap.targetWheelIds[i];
			PX_CHECK_AND_RETURN(trgWheelId < numWheelsTrg, "PxVehicleCopyDynamicsData - wheelMap contains illegal target wheel id");
			PX_CHECK_AND_RETURN(0 == setWheelsTrg[trgWheelId], "PxVehicleCopyDynamicsData - wheelMap contains illegal target wheel id");
			setWheelsTrg[trgWheelId]=1;
		}
	}
#endif


	const PxU32 numWheelsSrc = src.mWheelsSimData.getNbWheels();
	const PxU32 numWheelsTrg = trg->mWheelsSimData.getNbWheels();

	//Set all dynamics data on the target to zero.
	//Be aware that setToRestState sets the rigid body to 
	//rest so set the momentum back after calling setToRestState.
	PxRigidDynamic* actorTrg = trg->getRigidDynamicActor();
	PxVec3 linVel = actorTrg->getLinearVelocity();
	PxVec3 angVel = actorTrg->getAngularVelocity();
	switch(src.getVehicleType())
	{
	case PxVehicleTypes::eDRIVE4W:
		((PxVehicleDrive4W*)trg)->setToRestState();
		break;
	case PxVehicleTypes::eDRIVENW:
		((PxVehicleDriveNW*)trg)->setToRestState();
		break;
	case PxVehicleTypes::eDRIVETANK:
		((PxVehicleDriveTank*)trg)->setToRestState();
		break;
	case PxVehicleTypes::eNODRIVE:
		((PxVehicleNoDrive*)trg)->setToRestState();
		break;
	default:
		break;
	}
	actorTrg->setLinearVelocity(linVel);
	actorTrg->setAngularVelocity(angVel);


	//Keep a track of the wheels on trg that have their dynamics data set as a copy from src.
	PxU8 setWheelsTrg[PX_MAX_NB_WHEELS];
	PxMemZero(setWheelsTrg, sizeof(PxU8) * PX_MAX_NB_WHEELS);

	//Keep a track of the average wheel rotation speed of all enabled wheels on src.
	PxU32 numEnabledWheelsSrc = 0;
	PxF32 accumulatedWheelRotationSpeedSrc = 0.0f;

	//Copy wheel dynamics data from src wheels to trg wheels.
	//Track the target wheels that have been given dynamics data from src wheels.
	//Compute the accumulated wheel rotation speed of all enabled src wheels.
	const PxU32 numMappedWheels = PxMin(numWheelsSrc, numWheelsTrg);
	for(PxU32 i = 0; i < numMappedWheels; i++)
	{
		const PxU32 srcWheelId = wheelMap.sourceWheelIds[i];
		const PxU32 trgWheelId = wheelMap.targetWheelIds[i];

		trg->mWheelsDynData.copy(src.mWheelsDynData, srcWheelId, trgWheelId);

		setWheelsTrg[trgWheelId] = 1;

		if(!src.mWheelsSimData.getIsWheelDisabled(srcWheelId))
		{
			numEnabledWheelsSrc++;
			accumulatedWheelRotationSpeedSrc += src.mWheelsDynData.getWheelRotationSpeed(srcWheelId);
		}
	}

	//Compute the average wheel rotation speed of src.
	PxF32 averageWheelRotationSpeedSrc = 0;
	if(numEnabledWheelsSrc > 0)
	{
		averageWheelRotationSpeedSrc = (accumulatedWheelRotationSpeedSrc/ (1.0f * numEnabledWheelsSrc));
	}

	//For wheels on trg that have not had their dynamics data copied from src just set
	//their wheel rotation speed to the average wheel rotation speed.
	for(PxU32 i = 0; i < numWheelsTrg; i++)
	{
		if(0 == setWheelsTrg[i] && !trg->mWheelsSimData.getIsWheelDisabled(i))
		{
			trg->mWheelsDynData.setWheelRotationSpeed(i, averageWheelRotationSpeedSrc);
		}
	}

	//Copy the engine rotation speed/gear states/autobox states/etc.
	switch(src.getVehicleType())
	{
	case PxVehicleTypes::eDRIVE4W:
	case PxVehicleTypes::eDRIVENW:
	case PxVehicleTypes::eDRIVETANK:
		{
			const PxVehicleDriveDynData& driveDynDataSrc = ((const PxVehicleDrive&)src).mDriveDynData;
			PxVehicleDriveDynData* driveDynDataTrg = &((PxVehicleDrive*)trg)->mDriveDynData;
			*driveDynDataTrg = driveDynDataSrc;
		}
		break;
	default:
		break;
	}
}