bool CPhysicsManager::ReleasePhysicActor (CPhysicActor* actor)
{
	assert(actor != NULL);
	assert(m_pScene != NULL);
	assert(m_pPhysicsSDK != NULL);

	bool isOk = false;
	NxActor* nxActor = actor->GetPhXActor();

	if( nxActor != 0)
	{
		NxArray<NxCCDSkeleton*> skeletons;
		for (NxU32 i = 0; i < nxActor->getNbShapes(); i++) 
		{
			NxShape* shape = nxActor->getShapes()[i];
			if (shape->getCCDSkeleton() != NULL) {
				skeletons.pushBack(shape->getCCDSkeleton());
			}
		}

		for (NxU32 i = 0; i < skeletons.size(); i++) 
		{
			m_pPhysicsSDK->releaseCCDSkeleton(*skeletons[i]);
		}
		m_pScene->releaseActor(*nxActor);
		nxActor = 0;
	}
	
	return true;
}
Example #2
0
//----------------------------------------------------------------------------
// ReleaseAllActors : Alliberem tots els actors de l'escena de PhysX 
//----------------------------------------------------------------------------
bool CPhysicsManager::ReleaseAllActors ( void ) //EUserDataFlag _eFlags )
{
	assert ( m_pScene != NULL );
	assert ( m_pPhysicsSDK != NULL );

	bool isOk = true;

	NxActor** l_ppActorList = m_pScene->getActors();
	NxU32 l_TotalActors		= m_pScene->getNbActors();

	while ( l_TotalActors -- )
	{
		NxActor* nxActor = *l_ppActorList;
		if ( nxActor != 0)
		{
			NxArray<NxCCDSkeleton*> skeletons;
			for (NxU32 i = 0; i < nxActor->getNbShapes(); i++) 
			{
				NxShape* shape = nxActor->getShapes()[i];
				if (shape->getCCDSkeleton() != NULL) {
					skeletons.pushBack(shape->getCCDSkeleton());
				}
			}

			for (NxU32 i = 0; i < skeletons.size(); i++) 
			{
				m_pPhysicsSDK->releaseCCDSkeleton(*skeletons[i]);
			}
			m_pScene->releaseActor(*nxActor);
			nxActor = 0;
		}
	}
	
	return isOk;
}
Example #3
0
//
//	EPhysXPhysEngine::BuildConvexMesh
//
NxConvexMesh *ESciVis::BuildConvexMesh( const IPxTriMesh input_mesh )
{
	//IPxTriMesh	mesh	=	input_mesh->Clone();
	//mesh->SetFormat( GE_MESH_POSITION );
	//mesh->MergeVertices();				//This command causes convex cook crash

	NxConvexMeshDesc	convex_mesh_desc;

	NxArray<NxVec3>	verts;
	
	for (uint i=0; i<input_mesh->GetVertexNum(); i++) {
		EVertex v;
		v = input_mesh->GetVertex(i);
		verts.push_back( NxVec3(v.position.x, v.position.y, v.position.z) );
	}

    convex_mesh_desc.numVertices		= input_mesh->GetVertexNum();
    convex_mesh_desc.pointStrideBytes	= sizeof(NxVec3);
    convex_mesh_desc.points				= &verts[0];
	convex_mesh_desc.flags				= NX_CF_COMPUTE_CONVEX;
	
	ASSERT( convex_mesh_desc.isValid() );

	MemoryWriteBuffer	buf;	
	bool r = nx_cook->NxCookConvexMesh(convex_mesh_desc, buf);
	
	if (!r) {
		RUNTIME_ERROR("mesh contains to many vertices");
	}

	return nx->createConvexMesh(MemoryReadBuffer(buf.data));
}
Example #4
0
// ----------------------------------------------------------------------------------------------------------
void MeshHash::query(const NxBounds3 &bounds, NxArray<int> &itemIndices, int maxIndices)
{
	int x1,y1,z1;
	int x2,y2,z2;
	int x,y,z;

	cellCoordOf(bounds.min, x1,y1,z1);
	cellCoordOf(bounds.max, x2,y2,z2);

	itemIndices.clear();

	for (x = x1; x <= x2; x++)
  {
		for (y = y1; y <= y2; y++)
	  {
			for (z = z1; z <= z2; z++)
		  {
				int h = hashFunction(x,y,z);
				MeshHashRoot &r = mHashIndex[h];
				if (r.timeStamp != mTime) continue;
				int i = r.first;
				while (i >= 0)
			  {
					MeshHashEntry &entry = mEntries[i];
					itemIndices.push_back(entry.itemIndex);
					if (maxIndices >= 0 && (int)itemIndices.size() >= maxIndices) return;
					i = entry.next;
				}
			}
		}
	}
}
void SetupAttachmentScene()
{
    sprintf(gTitleString, "Attachment Demo");

	// Create objects in scene
	groundPlane = CreateGroundPlane();
	NxActor* box1 = CreateBox(NxVec3(-7,12.25,0), NxVec3(2.5,1,1), 0);
	NxActor* box2 = CreateBox(NxVec3(0,12.25,0), NxVec3(2.5,1,1), 0);
	NxActor* box3 = CreateBox(NxVec3(7,12.25,0), NxVec3(2.5,1,1), 0);	

	NxActor* attachedBox = CreateBox(NxVec3(-7.2,4.5,1.6), NxVec3(1.25,1,1), 1);
	NxActor* attachedSphere = CreateSphere(NxVec3(-0.25,4.0,2.0), 1.3, 1);
	NxActor* attachedCapsule = CreateCapsule(NxVec3(9.0,5.5,2.0),2.0, 1, 1); 

	NxReal damping = 0.3;
	attachedBox->setAngularDamping(damping);
	attachedBox->setLinearDamping(damping);
	attachedSphere->setAngularDamping(damping);
	attachedSphere->setLinearDamping(damping);
	attachedCapsule->setAngularDamping(damping);
	attachedCapsule->setLinearDamping(damping);

	NxQuat q;
	q.fromAngleAxis(90,NxVec3(0,0,1));
	attachedCapsule->setGlobalOrientationQuat(q);

	// Cloth
	NxClothDesc clothDesc;
	clothDesc.globalPose.M.rotX(1.3);
	clothDesc.thickness = 0.3;	
	clothDesc.attachmentResponseCoefficient = 1;
	clothDesc.flags |= NX_CLF_BENDING;
	clothDesc.flags |= NX_CLF_BENDING_ORTHO;
	clothDesc.flags |= NX_CLF_DAMPING | NX_CLF_VISUALIZATION;

	if (gHardwareCloth)
		clothDesc.flags |= NX_CLF_HARDWARE;

	// Cloth attaching to sphere
	clothDesc.globalPose.t = NxVec3(0.75,5,2);
	MyCloth* regularCloth1 = new MyCloth(gScene, clothDesc, 2, 8, 0.4);
	regularCloth1->getNxCloth()->attachToCollidingShapes(NX_CLOTH_ATTACHMENT_TWOWAY);
	gCloths.push_back(regularCloth1);

	// Cloth attaching to box
	clothDesc.globalPose.t = NxVec3(-6.2,5,2);
	MyCloth* regularCloth2 = new MyCloth(gScene, clothDesc, 2, 8, 0.4);
	regularCloth2->getNxCloth()->attachToCollidingShapes(NX_CLOTH_ATTACHMENT_TWOWAY);
	gCloths.push_back(regularCloth2);

	// Cloth attaching to capsule
	clothDesc.globalPose.t = NxVec3(8.0,5,2);
	clothDesc.attachmentTearFactor = 2.0;
	MyCloth* regularCloth3 = new MyCloth(gScene, clothDesc, 2, 8, 0.4);
	regularCloth3->getNxCloth()->attachToShape(box3->getShapes()[0], NX_CLOTH_ATTACHMENT_TEARABLE);
	regularCloth3->getNxCloth()->attachToShape(attachedCapsule->getShapes()[0], NX_CLOTH_ATTACHMENT_TWOWAY);
	gCloths.push_back(regularCloth3);
}
Example #6
0
// Create a static trigger
static void CreateTrigger(const NxVec3& pos, NxF32 size = 2, const NxVec3* initial_velocity=NULL, bool kinematic = 	false)
{
	// Our trigger is a cube
	NxBodyDesc triggerBody;
	NxBoxShapeDesc dummyShape;
	NxBoxShapeDesc BoxDesc;
	BoxDesc.dimensions		= NxVec3(size, size, size);
	BoxDesc.shapeFlags		|= NX_TRIGGER_ENABLE;

	NxActorDesc ActorDesc;

	if(initial_velocity || kinematic) {
		if (initial_velocity) {
			triggerBody.linearVelocity = *initial_velocity;
		}
		if (kinematic) {
			triggerBody.flags |= NX_BF_KINEMATIC;
		}
		triggerBody.mass = 1;
		ActorDesc.body = &triggerBody;
		NxF32 sizeinc = 1.01f;
		dummyShape.dimensions.set(size*sizeinc, size*sizeinc, size*sizeinc);
		dummyShape.group = 1;
		ActorDesc.shapes.pushBack(&dummyShape);
	}

	ActorDesc.shapes.pushBack(&BoxDesc);
	ActorDesc.globalPose.t = pos;
	int thisNb = ++gNbTriggers;
	gNbTouchedBodies.pushBack(0);
	NX_ASSERT(gNbTouchedBodies.size() == gNbTriggers);
	gMyPhysX.getScene()->setGroupCollisionFlag(1,0, false);
	gMyPhysX.getScene()->setGroupCollisionFlag(1,1, false);
	gMyPhysX.getScene()->setGroupCollisionFlag(1,2, true);
	ActorDesc.userData = (void*)(-thisNb);
	if (!ActorDesc.isValid()) {
		printf("Invalid ActorDesc\n");
		return;
	}
	NxActor* actor = gMyPhysX.getScene()->createActor(ActorDesc);	// This is just a quick-and-dirty way to identify the trigger for rendering
	NX_ASSERT(actor != NULL);

	if (kinematic) {
		KinematicActor k;
		k.actor = actor;
		if (initial_velocity) {
			k.vel = *initial_velocity;
		} else {
			k.vel.set(0,0,0);
		}
		gKinematicActors.pushBack(k);
	}

	gMyPhysX.getScene()->setUserTriggerReport(&myTriggerCallback);
}
void ReleaseNx()
{
    if (gScene)
	{
		for (MyCloth** cloth = gCloths.begin(); cloth != gCloths.end(); cloth++)
			delete *cloth;
		gCloths.clear();
		gPhysicsSDK->releaseScene(*gScene);
	}
	if (gPhysicsSDK)  NxReleasePhysicsSDK(gPhysicsSDK);
    NX_DELETE_SINGLE(gAllocator);
}
Example #8
0
void TickCar()
{
	NxReal steeringAngle = gSteeringValue * gMaxSteeringAngle;

	NxArray<CarWheelContact>::iterator i = wheelContactPoints.begin();
	while(i != wheelContactPoints.end())
	{
		CarWheelContact& cwc = *i;

		WheelShapeUserData* wheelData = (WheelShapeUserData *)(cwc.wheel->userData);

		//apply to powered wheels only.
		if (wheelData->frontWheel)
	    {
			//steering:
			NxMat33 wheelOrientation = cwc.wheel->getLocalOrientation();
			wheelOrientation.setColumn(0,  NxVec3(NxMath::cos(steeringAngle), 0,  NxMath::sin(steeringAngle) ));
			wheelOrientation.setColumn(2,  NxVec3(NxMath::sin(steeringAngle), 0, -NxMath::cos(steeringAngle) ));
			cwc.wheel->setLocalOrientation(wheelOrientation);

			if (frontWheelIsPowered)
			{
				//get the world space orientation:
				wheelOrientation = cwc.wheel->getGlobalOrientation();
				NxVec3 steeringDirection;
				wheelOrientation.getColumn(0, steeringDirection);

				//the power direction of the front wheel is the wheel's axis as it is steered.
				if (gMotorForce)
				{
					cwc.car->addForceAtPos(steeringDirection * gMotorForce,cwc.contactPoint);
				}
			}
		}
		if (!wheelData->frontWheel && rearWheelIsPowered)
		{
			//get the orientation of this car:
			NxMat33 m = cwc.car->getGlobalOrientation();
			NxVec3 carForwardAxis;
			m.getColumn(0, carForwardAxis);
			//the power direction of the rear wheel is always the car's length axis.
			cwc.car->addForceAtPos(carForwardAxis * gMotorForce,cwc.contactPoint);
		}
		i++;
	}

	wheelContactPoints.clear();
}
Example #9
0
static void CreateCube(const NxVec3& pos, int size=2, const NxVec3* initial_velocity=NULL, bool kinematic = false, bool Static = false)
{
	// Create body
	NxBodyDesc BodyDesc;
	BodyDesc.angularDamping	= 0.5f;
	//	BodyDesc.maxAngularVelocity	= 10.0f;
	if(initial_velocity)	BodyDesc.linearVelocity = *initial_velocity;

	NxBoxShapeDesc BoxDesc;
	BoxDesc.dimensions		= NxVec3(float(size), float(size), float(size));

	NxActorDesc ActorDesc;
	//	ActorDesc.userData		= (void*)size;
	ActorDesc.shapes.pushBack(&BoxDesc);
	if (!Static)
		ActorDesc.body			= &BodyDesc;
	ActorDesc.density		= 10.0f;
	ActorDesc.globalPose.t  = pos;
	ActorDesc.userData = (void*)size;

	NxActor* actor = gMyPhysX.getScene()->createActor(ActorDesc);

	if (kinematic) {
		KinematicActor k;
		k.actor = actor;
		actor->raiseBodyFlag(NX_BF_KINEMATIC);
		if (initial_velocity) {
			k.vel = *initial_velocity;
		} else {
			k.vel.set(0,0,0);
		}
		gKinematicActors.pushBack(k);
	}

}
Example #10
0
	virtual void  onContactNotify(NxContactPair& pair, NxU32 events)
	{
		// Iterate through contact points
		NxContactStreamIterator i(pair.stream);
		//user can call getNumPairs() here
		while(i.goNextPair())
		{
			//user can also call getShape() and getNumPatches() here
			while(i.goNextPatch())
			{
				//user can also call getPatchNormal() and getNumPoints() here
				const NxVec3& contactNormal = i.getPatchNormal();
				while(i.goNextPoint())
				{
					//user can also call getPoint() and getSeparation() here
					if(i.getSeparation()<0.0f)
					{
						const NxVec3& contactPoint = i.getPoint();

						NxU32 faceIndex = i.getFeatureIndex0();
						if(faceIndex==0xffffffff)	faceIndex = i.getFeatureIndex1();
						if(faceIndex!=0xffffffff)
						{
							gTouchedTris.pushBack(faceIndex);
							//printf("Contack!\n");
						}
					}
				}
			}
		}
	}
Example #11
0
void SetupTearingScene()
{
    sprintf(gTitleString, "Tearing Demo");

	// Create the objects in the scene
	groundPlane = CreateGroundPlane();
	NxActor* bar = CreateBox(NxVec3(0,12,0), NxVec3(3,0.5,0.5), 0);
	NxActor* box = CreateBox(NxVec3(-2.3,4.0,0), NxVec3(0.5,0.5,0.5), 10); 

	// Cloth
	NxClothDesc clothDesc;
	clothDesc.globalPose.t = NxVec3(2.5,12,0);
	clothDesc.globalPose.M.rotX(-NxHalfPiF32);
	clothDesc.thickness = 0.1;
	clothDesc.tearFactor = 2;
	clothDesc.flags |= NX_CLF_BENDING;
	clothDesc.flags |= NX_CLF_COLLISION_TWOWAY;
	clothDesc.flags |= NX_CLF_TEARABLE | NX_CLF_VISUALIZATION; // Tearable cloth

	if (gHardwareCloth)
		clothDesc.flags |= NX_CLF_HARDWARE;

	MyCloth* regularCloth = new MyCloth(gScene, clothDesc, 5, 8, 0.1, "rug512.bmp", gTearLines);
	gCloths.push_back(regularCloth);

	regularCloth->getNxCloth()->attachToShape(*bar->getShapes(), 0);
	regularCloth->getNxCloth()->attachToShape(*box->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY);
}
Example #12
0
static void RenderTerrain()
{
	if(gTerrainData)
	{		
		renderTerrainTriangles(*gTerrainData, gTouchedTris.size(), &gTouchedTris[0]);	
		renderTerrain(*gTerrainData);
	}
}
Example #13
0
// ----------------------------------------------------------------------------------------------------------
void MeshHash::compressIndices(NxArray<int> &itemIndices)
{
	if (itemIndices.size() == 0) return;
	// sort results
	quickSort(itemIndices, 0, itemIndices.size()-1);
	// mark duplicates
	int i = 0;
	while (i < (int)itemIndices.size())
  {
		int j = i+1;
		while (j < (int)itemIndices.size() && itemIndices[i] == itemIndices[j])
	  {
			itemIndices[j] = -1; j++;
		}
		i = j;
	}
	// remove duplicates
	i = 0;
	while (i < (int)itemIndices.size())
  {
		if (itemIndices[i] < 0)
	  {
			itemIndices[i] = itemIndices[itemIndices.size()-1];
			itemIndices.pop_back();
		}
		else i++;
	}
}
Example #14
0
// ----------------------------------------------------------------------------------------------------------
void MeshHash::query(const NxVec3 &pos, NxArray<int> &itemIndices, int maxIndices)
{
	int x,y,z;
	cellCoordOf(pos, x,y,z);
	itemIndices.clear();

	int h = hashFunction(x,y,z);
	MeshHashRoot &r = mHashIndex[h];
	if (r.timeStamp != mTime) return;
	int i = r.first;
	while (i >= 0)
  {
		MeshHashEntry &entry = mEntries[i];
		itemIndices.push_back(entry.itemIndex);
		if (maxIndices >= 0 && (int)itemIndices.size() >= maxIndices) return;
		i = entry.next;
	}
}
Example #15
0
	virtual void  onContactNotify(NxContactPair& pair, NxU32 events)
	{
		
		NxU32 carIndex = 0;
		if (isCar(pair.actors[0]))
			carIndex = 0;
		else if (isCar(pair.actors[1]))
			carIndex = 1;
		else
			return;
		
		//ignore the 'both are cars' case for now.

		// Iterate through contact points
		NxContactStreamIterator i(pair.stream);
		//user can call getNumPairs() here
		while (i.goNextPair())
        {
			//user can also call getShape() and getNumPatches() here
			NxShape * s = i.getShape(carIndex);
			while (i.goNextPatch())
            {
				//user can also call getPatchNormal() and getNumPoints() here
				const NxVec3& contactNormal = i.getPatchNormal();
				while (i.goNextPoint())
                {
					//user can also call getPoint() and getSeparation() here
					const NxVec3& contactPoint = i.getPoint();

					NxVec3 contactNormalForce = pair.sumNormalForce;
					NxVec3 contactFrictionForce = pair.sumFrictionForce;

					//add forces:

					//assuming front wheel drive we need to apply a force at the wheels.
					if (s->is(NX_SHAPE_CAPSULE))		//assuming only the wheels of the car are capsules, otherwise we need more checks.
														//this branch can't be pulled out of loops because we have to do a full iteration through the stream
                    {
						CarWheelContact cwc;
						cwc.car = pair.actors[carIndex];
						cwc.wheel = s;
						cwc.contactPoint = contactPoint;
						cwc.contactNormalForce = contactNormalForce;
						cwc.contactFrictionForce = contactFrictionForce;
						wheelContactPoints.pushBack(cwc);
						//#error too bad this is illegal (reentry) and also technically busted because the accumulators get zeroed after this returns.
						//pair.actors[carIndex]->addForceAtPos(NxVec3(100,0,0),contactPoint);
                    }
                }
            }		
        }
	}
Example #16
0
void RenderCallback()
{
    if (gScene && !bPause)
	{
		StartPhysics();	
		GetPhysicsResults();
	}

    // Clear buffers
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	ProcessInputs();
	ProcessCameraKeys();
	SetupCamera();

 	RenderActors(bShadows);

    // Render all the cloths in the scene
	for (MyCloth **cloth = gCloths.begin(); cloth != gCloths.end(); cloth++)
	{
		glColor4f(1.0f, 0.0f, 0.0f,1.0f);
		(*cloth)->draw(bShadows);
	}

	if (bForceMode)
		DrawForce(gSelectedActor, gForceVec, NxVec3(1,1,0));
	else
		DrawForce(gSelectedActor, gForceVec, NxVec3(0,1,1));
	gForceVec = NxVec3(0,0,0);

	// Render HUD
	hud.Render();

    glFlush();
    glutSwapBuffers();
}
Example #17
0
void render()
{
	static Timer t;
	if(gScene && !gPauseSimulation)  //start the simulation
	{
		gTouchedTris.clear();
		gScene->simulate(t.elapsed_time());
		//printf("%f\n",t.elapsed_time());
		t.reset();
		gScene->flushStream();
		/*ASYNC: in here we can do computations which depend only on the old
	      state of the scene "actors". Writing to the scene is not allowed.
		  Write calls in here are skipped.
		*/
		gScene->fetchResults(NX_RIGID_BODY_FINISHED,true);
	}
	// Clear buffers
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glColor4f(0.0,1.0,1.0,1.0);
	DrawSkyBox(5000.0f);
	//drawPlane(2000.0);
	 //Render all actors
	int nbActors = gScene->getNbActors();
	NxActor** actors = gScene->getActors();
	while(nbActors--)
	{
		NxActor* actor = *actors++;
		if(!actor->userData) continue;

		// Render actor
		glPushMatrix();
		float glMat[16];
		actor->getGlobalPose().getColumnMajor44(glMat);
		glMultMatrixf(glMat);
		NxVec3 color = static_cast<UserData*>(actor->userData)->color;
		glColor4f(color.x,color.y,color.z,1.0f);
		glutSolidCube((static_cast<UserData*>(actor->userData)->size)*2.0f);
		glPopMatrix();
	}
	RenderTerrain();
}
void SetHelpString(const char *demoKeyString)
{
	char tempString[512];
	sprintf(gHelpString, "\nGeneral:\n");
#ifdef __PPCGEKKO__
	sprintf(gHelpString, "    +,-: choose scene\n");
	strcat(gHelpString, "    arrows: move/strafe\n");
	strcat(gHelpString, "    b: shoot sphere\n");
	strcat(gHelpString, "    HOME: toggle help\n");
	strcat(gHelpString, "    1: Reset scene\n");
	if(gSampleIndex == 6) strcat(gHelpString, "    2: toggle debug rendering\n");
#else	
	sprintf(tempString, "    1-%d: choose scene\n", gSamples.size());
	strcat(gHelpString, tempString);
	strcat(gHelpString, "    p: pause\n");
	strcat(gHelpString, "    o: single step\n");
#ifndef NX_DISABLE_HARDWARE
	strcat(gHelpString, "    h: hardware on/off\n");
#endif
	strcat(gHelpString, "    w,a,s,d: move/strafe\n");
	strcat(gHelpString, "    q,e: move up/down\n");
	strcat(gHelpString, "    mouse right: pick\n");
	strcat(gHelpString, "    space: shoot sphere\n");
	strcat(gHelpString, "    x: toggle shadows\n");
	strcat(gHelpString, "    n: toggle wireframe\n");
	strcat(gHelpString, "    F1: toggle help\n");
	strcat(gHelpString, "    F3,F4: pick push/pull\n");
	strcat(gHelpString, "    F5: toggle debug rendering\n");
	strcat(gHelpString, "    F9: toggle vsync\n");
	strcat(gHelpString, "    F10: Reset scene\n");
#endif

	if (demoKeyString)
	{
		strcat(gHelpString, "\nDemo specific:\n");
		strcat(gHelpString, demoKeyString);
	}
}
bool NxuPhysicsExport::Write(NxJoint *j,const char *userProperties,const char *id)
{
	bool ret = false;

	NxSceneDesc *current = getCurrentScene();

	CustomCopy cc(mCollection,current);

	NxJointDesc *joint = 0;

	switch ( j->getType() )
	{
		case NX_JOINT_PRISMATIC:
			if ( 1 )
			{
				::NxPrismaticJointDesc d1;
				NxPrismaticJoint *sj = j->isPrismaticJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxPrismaticJointDesc *desc = new NxPrismaticJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_REVOLUTE:
			if ( 1 )
			{
				::NxRevoluteJointDesc d1;
				NxRevoluteJoint *sj = j->isRevoluteJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxRevoluteJointDesc *desc = new NxRevoluteJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_CYLINDRICAL:
			if ( 1 )
			{
				::NxCylindricalJointDesc d1;
				NxCylindricalJoint *sj = j->isCylindricalJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxCylindricalJointDesc *desc = new NxCylindricalJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_SPHERICAL:
			if ( 1 )
			{
				::NxSphericalJointDesc d1;
				NxSphericalJoint *sj = j->isSphericalJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxSphericalJointDesc *desc = new NxSphericalJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_POINT_ON_LINE:
			if ( 1 )
			{
				::NxPointOnLineJointDesc d1;
				NxPointOnLineJoint *sj = j->isPointOnLineJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxPointOnLineJointDesc *desc = new NxPointOnLineJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_POINT_IN_PLANE:
			if ( 1 )
			{
				::NxPointInPlaneJointDesc d1;
				NxPointInPlaneJoint *sj = j->isPointInPlaneJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxPointInPlaneJointDesc *desc = new NxPointInPlaneJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_DISTANCE:
			if ( 1 )
			{
				::NxDistanceJointDesc d1;
				NxDistanceJoint *sj = j->isDistanceJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxDistanceJointDesc *desc = new NxDistanceJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_PULLEY:
			if ( 1 )
			{
				::NxPulleyJointDesc d1;
				NxPulleyJoint *sj = j->isPulleyJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxPulleyJointDesc *desc = new NxPulleyJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_FIXED:
			if ( 1 )
			{
				::NxFixedJointDesc d1;
				NxFixedJoint *sj = j->isFixedJoint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxFixedJointDesc *desc = new NxFixedJointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		case NX_JOINT_D6:
			if ( 1 )
			{
				::NxD6JointDesc d1;
				NxD6Joint *sj = j->isD6Joint();
				sj->saveToDesc(d1);
				addActor( d1.actor[0] );
				addActor( d1.actor[1] );
				NxD6JointDesc *desc = new NxD6JointDesc;
				desc->copyFrom(d1,cc);
				joint = static_cast<NxJointDesc *>(desc);
			}
			break;
		default:
			break;

	}


	//Add	Limits
	// in	addition,	we also	have to	write	out	its	limit	planes!
	j->resetLimitPlaneIterator();
	if (j->hasMoreLimitPlanes())
	{
		// write limit point
		joint->mOnActor2 = j->getLimitPoint(joint->mPlaneLimitPoint);

		NxArray< NxPlaneInfoDesc *> plist;


		// write the plane normals
		while	(j->hasMoreLimitPlanes())
		{
			NxPlaneInfoDesc *pInfo	=	new	NxPlaneInfoDesc();
#if NX_SDK_VERSION_NUMBER >= 272
			j->getNextLimitPlane(pInfo->mPlaneNormal,	pInfo->mPlaneD, &pInfo->restitution);
#else
			j->getNextLimitPlane(pInfo->mPlaneNormal,	pInfo->mPlaneD);
#endif
			plist.push_back(pInfo);
		}

		if ( plist.size() )
		{
			for (int i=plist.size()-1; i>=0; i--)
			{
				NxPlaneInfoDesc *p = plist[i];
				joint->mPlaneInfo.pushBack(p);
			}
		}

	}


	if ( joint )
	{
		if ( id )
		{
			joint->mId = id;
		}
		else
		{
      char scratch[512];
      sprintf(scratch,"Joint_%d", current->mJoints.size());
      joint->mId = getGlobalString(scratch);
      joint->mUserProperties = getGlobalString(userProperties);
    }
		current->mJoints.push_back(joint);
		ret = true;
	}

  return ret;
}
Example #20
0
// -----------------------------------------------------------------------
void VertexWelder::initialize(const NxClothMeshDesc& unweldedMesh)
{
	NxArray<NxU32> mapping;
	NxReal squaredEpsilon = mEpsilon * mEpsilon;
	for (NxU32 i = 0; i < unweldedMesh.numVertices; i++)
	{
		const NxVec3& curVec = *(const NxVec3*)(((const char*)unweldedMesh.points) + (i * unweldedMesh.pointStrideBytes));

		// Find Vertex in newVertices
		NxU32 newIndex = 0;
		for (newIndex = 0; newIndex < mNewVertices.size(); newIndex++)
		{
			NxVec3& newVec = mNewVertices[newIndex];
			if ((mEpsilon == 0 && newVec == curVec) || (newVec.distanceSquared(curVec) < squaredEpsilon))
			//if (newVec == curVec)
			{
				break;
			}
		}

		if (newIndex == mNewVertices.size())
		{
			// Not found in previous list
			mNewVertices.push_back(curVec);
		}

		mapping.push_back(newIndex);
	}

	// Store mapping
	mMappingSize = mapping.size();
	mMappingSpace = unweldedMesh.numTriangles * 3;
	mMappingDomain = mNewVertices.size();
	mMapping = (NxU32*)malloc(sizeof(NxU32) * mMappingSpace);
	memcpy(mMapping, &mapping[0], sizeof(NxU32) * mMappingSize);
	memset(((NxU32*)mMapping) + mMappingSize, 0, sizeof(NxU32) * (mMappingSpace - mMappingSize));
	mapping.clear();

	if (mNewVertices.size() < unweldedMesh.numVertices)
	{
		mUsed = true;
	}
	else
	{
		return;
	}

	if (unweldedMesh.flags & NX_MF_16_BIT_INDICES)
	{
		mNewFaces16 = (NxU16*)malloc(sizeof(NxU16) * unweldedMesh.numTriangles * 3);
	}
	else
	{
		mNewFaces32 = (NxU32*)malloc(sizeof(NxU32) * unweldedMesh.numTriangles * 3);
	}

	for (NxU32 i = 0; i < unweldedMesh.numTriangles; i++)
	{
		NxU32 triangles[3];
		const char* triangleChar = ((const char*)unweldedMesh.triangles) + (unweldedMesh.triangleStrideBytes * i);
		if (mNewFaces16)
		{
			const NxU16* tris = (const NxU16*)triangleChar;
			triangles[0] = tris[0];
			triangles[1] = tris[1];
			triangles[2] = tris[2];
		}
		else
		{
			assert(mNewFaces32 != NULL);
			const NxU32* tris = (const NxU32*)triangleChar;
			triangles[0] = tris[0];
			triangles[1] = tris[1];
			triangles[2] = tris[2];
		}

		for (NxU32 j = 0; j < 3; j++)
		{
			triangles[j] = getMapping(triangles[j]);
		}

		if (mNewFaces16)
		{
			for (NxU32 j = 0; j < 3; j++)
			{
				mNewFaces16[3*i+j] = (NxU16)(triangles[j] & 0xffff);
			}
		}
		else
		{
			for (NxU32 j = 0; j < 3; j++)
			{
				mNewFaces32[3*i+j] = triangles[j];
			}
		}
	}
}
Example #21
0
void VertexWelder::update(NxMeshData meshData)
{
	assert(mWriteVerticesPtr != NULL);

	bool updateVertices = (*(meshData.dirtyBufferFlagsPtr) & (NX_MDF_VERTICES_POS_DIRTY | NX_MDF_VERTICES_NORMAL_DIRTY)) > 0;
	bool updateIndices = (*(meshData.dirtyBufferFlagsPtr) & (NX_MDF_INDICES_DIRTY | NX_MDF_PARENT_INDICES_DIRTY)) > 0;

	NxU32 numNewVertices = *meshData.numVerticesPtr;
	NxU32 numTriangles = *meshData.numIndicesPtr / 3;
	NxU32 oldMappingDomain = mMappingDomain;
	
	NxArray<NewVertex> newVertices;
	NxArray<DifficultVertex> difficultVertices;

	mMappingDomainAddition = 0;

	if (updateVertices)
	{
		
		if (mMappingDomain < numNewVertices)
		{
#ifdef DEBUG_WELDER
			printf("------------------------------------\n");
#endif
			for (NxU32 i = mMappingDomain; i < numNewVertices; i++)
			{
				NewVertex v;
				v.index = i;
				v.parent = *(NxU32*)(((char*)meshData.parentIndicesBegin) + meshData.parentIndicesByteStride * i);
				while (v.parent >= (NxI32)mMappingDomain) {
					v.parent = *(NxU32*)(((char*)meshData.parentIndicesBegin) + meshData.parentIndicesByteStride * v.parent);
				}
#ifdef DEBUG_WELDER
				printf("New Vertex: %d %d\n", v.index, v.parent);
#endif
				newVertices.push_back(v);
			}
			std::sort(newVertices.begin(), newVertices.end(), sortParent);
		}
		
		for (NxU32 i = 0; i < mMappingSize; i++)
		{
			NxU32 mappedIndex = getMapping(i);

			NewVertex newV;
			newV.parent = mappedIndex;
			// Find all vertices that are a parent for a newly created vertex
			NxArray<NewVertex>::iterator found = std::lower_bound(newVertices.begin(), newVertices.end(), newV, sortParent);
			while (found != NULL && found->parent == mappedIndex)
			{
				found->mappedVertices ++;
				if (found->mappedVertices == 1)
				{
					found->unMapParent = i;
#ifdef DEBUG_WELDER
					printf("New Vertex Update, %d %d %d\n", found->index, found->parent, found->unMapParent);
#endif
				}
				else
				{
					// several unmapped parents
					DifficultVertex v;
					v.mappedIndex = found->index;
					v.unMappedIndex = i;
					difficultVertices.push_back(v);
#ifdef DEBUG_WELDER
					printf("Difficult Vertex %d %d\n", v.unMappedIndex, v.mappedIndex);
#endif

					if (found->mappedVertices == 2)
					{
						v.unMappedIndex = found->unMapParent;
						difficultVertices.push_back(v);
#ifdef DEBUG_WELDER
						printf("Difficult Vertex %d %d\n", v.unMappedIndex, v.mappedIndex);
#endif
					}

					found->unMapParent = -2;
				}
				found++;
			}
			

			NxVec3& vertex = *(NxVec3*)(((char*)mWriteVerticesPtr) + mWriteVerticesStride * i);
			NxVec3& normal = *(NxVec3*)(((char*)mWriteNormalsPtr) + mWriteNormalsStride* i);
			//float* texCoord = (float*)(((char*)texCoords) + texStride * i);

			const NxVec3& oldVertex = *(NxVec3*)(((char*)meshData.verticesPosBegin) + meshData.verticesPosByteStride * mappedIndex);
			const NxVec3& oldNormal = *(NxVec3*)(((char*)meshData.verticesNormalBegin) + meshData.verticesNormalByteStride * mappedIndex);

			vertex = oldVertex;
			normal = oldNormal;
		}
		// Adapt the mapping table
		std::sort(newVertices.begin(), newVertices.end(), sortIndex);
		std::sort(difficultVertices.begin(), difficultVertices.end(), sortDifficultExt);	
	}

	if (updateIndices)
	{
		std::vector<bool> bitVector(mMappingSpace, false);
#ifdef DEBUG_WELDER
		printf("updateIndices: Vertices: %d, Indices %d, gfx Vertices: %d\n", *meshData.numVerticesPtr, *meshData.numIndicesPtr, mMappingSize);
#endif
		if (difficultVertices.size() > 0)
		{
#ifdef DEBUG_WELDER
			printf("    Difficult Vertices:\n");
#endif
			for (NxU32 i = 0; i < difficultVertices.size(); i++)
			{
				DifficultVertex& v = difficultVertices[i];
#ifdef DEBUG_WELDER
				printf("      V %d %d\n", v.unMappedIndex, v.mappedIndex);
#endif
			}
		}
		assert((meshData.flags & NX_MF_16_BIT_INDICES) == 0);
		assert(meshData.indicesByteStride == 4);
		for (NxU32 i = 0; i < numTriangles; i++)
		{
			const NxU32* simTriangle = (NxU32*)(((char*)meshData.indicesBegin) + meshData.indicesByteStride * (i*3));
			NxU32* gfxTriangle = (NxU32*)(((char*)mWriteIndicesPtr) + mWriteIndicesStride* i);
			
			if (simTriangle[0] == simTriangle[1] && simTriangle[1] == simTriangle[2])
			{
				// Face was deleted (outside valid bounds probably)
				gfxTriangle[0] = gfxTriangle[1] = gfxTriangle[2] = 0;
				continue;
			}
			for (NxU32 j = 0; j < 3; j++)
			{

				DifficultVertex v;
				v.mappedIndex = simTriangle[j];
				v.unMappedIndex = gfxTriangle[j];
				if (std::binary_search(difficultVertices.begin(), difficultVertices.end(), v, sortDifficult))
				{
					NxArray<DifficultVertex>::iterator it = std::lower_bound(difficultVertices.begin(), difficultVertices.end(), v, sortDifficultExt);
#ifdef DEBUG_WELDER
					printf("-- Triangle %d (%d) (%d %d %d) (%d %d %d)", i, j, simTriangle[0], simTriangle[1], simTriangle[2], gfxTriangle[0], gfxTriangle[1], gfxTriangle[2]);
					printf(" %d %d\n", v.unMappedIndex, v.mappedIndex);
#endif

					if (it == NULL || it->mappedIndex != simTriangle[j])
					{
						// element hasn't been found

						//insert element
#ifdef DEBUG_WELDER
						printf("Adding Diff %d %d\n", v.unMappedIndex, v.mappedIndex);
#endif
						difficultVertices.push_back(v);

						// sort now, don't know whether this could be done less often, so far the list is extremely small
						std::sort(difficultVertices.begin(), difficultVertices.end(), sortDifficultExt);

						// get the freshly created item
						it = std::lower_bound(difficultVertices.begin(), difficultVertices.end(), v, sortDifficultExt);

						// element has to exist
						assert(it != NULL);
					}

					if (it->newUnMappedIndex >= 0)
					{
						gfxTriangle[j] = it->newUnMappedIndex;
					}
					else if (bitVector[it->unMappedIndex])
					{
#ifdef DEBUG_WELDER
						printf("Bit %d is true\n", it->unMappedIndex);
#endif
						// create a new gfx vertex
						it->newUnMappedIndex = mMappingSize;
						addNewVertex(gfxTriangle[j]);
						setMapping(it->newUnMappedIndex, simTriangle[j]);
						gfxTriangle[j] = it->newUnMappedIndex;
						bitVector[it->newUnMappedIndex] = true;
					}
					else
					{
#ifdef DEBUG_WELDER
						printf("Set Bit %d to true\n", it->unMappedIndex);
#endif
						bitVector[it->unMappedIndex] = true;
						it->newUnMappedIndex = it->unMappedIndex;
						setMapping(it->newUnMappedIndex, simTriangle[j]);
					}
				}
				else if (simTriangle[j] >= oldMappingDomain) // only used when not a difficult vertex
				{
					// unamp index and update
					for (NxU32 k = 0; k < newVertices.size(); k++)
					{
						NewVertex& v = newVertices[k];
						if (v.index == simTriangle[j] && v.mappedVertices == 1)
						{
#ifdef DEBUG_WELDER
							printf("- Triangle %d (%d %d %d) (%d %d %d)", i, simTriangle[0], simTriangle[1], simTriangle[2], gfxTriangle[0], gfxTriangle[1], gfxTriangle[2]);
							printf(" %d %d\n", v.unMapIndex, v.index);
#endif
							if (v.unMapIndex == -1)
							{
#ifdef DEBUG_WELDER
								printf("Add Simple\n");
#endif
								v.unMapIndex = mMappingSize;
								//addNewVertex(vertices, vertexStride, normals, normalStride, texCoords, texStride, v.unMapParent);
								addNewVertex(gfxTriangle[j]);
								gfxTriangle[j] = v.unMapIndex;
								setMapping(v.unMapIndex, v.index);
							}
							else
							{
#ifdef DEBUG_WELDER
								printf("Use Simple\n");
#endif
								gfxTriangle[j] = v.unMapIndex;
							}
							break; // for (k)
						}
					}
				}
			}
		}
	}

	if (updateVertices)
	{
		mMappingDomain = *meshData.numVerticesPtr;

#ifdef DEBUG_WELDER
		static bool sanityCheck = true;
		if (sanityCheck)
		{
			// sanity check
			NxU32 temp = 0;
			for (NxU32 i = 0; i < mMappingSize; i++)
			{
				temp = NxMath::max(getMapping(i), temp);
			}
			if (temp != mMappingDomain - 1)
			{
				printf("Mapping Domain not right, is %d, should be %d\n", temp, mMappingDomain-1);
				assert(0);
			}
			for (NxU32 i = 0; i < numTriangles; i++)
			{
				const NxU32* simTriangle = (NxU32*)(((char*)meshData.indicesBegin) + meshData.indicesByteStride * (i*3));
				NxU32* gfxTriangle = (NxU32*)(((char*)mWriteIndicesPtr) + mWriteIndicesStride * i);
				for (NxU32 j = 0; j < 3; j++)
				{
					if (simTriangle[j] != getMapping(gfxTriangle[j]))
					{
						printf("Triangle %d (%d) not correct (%d %d %d) -> (%d %d %d) != (%d %d %d)\n",
							i, 3*i+j,
							gfxTriangle[0], gfxTriangle[1], gfxTriangle[2],
							getMapping(gfxTriangle[0]), getMapping(gfxTriangle[1]), getMapping(gfxTriangle[2]),
							simTriangle[0], simTriangle[1], simTriangle[2]);
						assert(0);
					}
				}
			}
		}
#endif
	}

	return;
}
Example #22
0
void render()
{
	static Timer t;
	if(!gMyPhysX.isPaused())
	{
		for (NxU32 i = 0; i < gKinematicActors.size(); i++)
		{
			NxActor* actor = gKinematicActors[i].actor;
			NxVec3 pos = actor->getGlobalPosition();
			pos += gKinematicActors[i].vel * 1.f/60.f;
			actor->moveGlobalPosition(pos);
		}
	}	
	gMyPhysX.simulate(t.elapsed_time());
	t.reset(); 
	// Clear buffers
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glColor4f(0.5,0.9,0.5,1.0);
	DrawSkyBox(SKYEXTENTS);
	drawPlane(SKYEXTENTS);
	// Keep physics & graphics in sync
	for (NxU32 pass = 0; pass < 2; pass++) {
		int nbActors = gMyPhysX.getScene()->getNbActors();
		NxActor** actors = gMyPhysX.getScene()->getActors();
		actors += nbActors;
		while(nbActors--)
		{
			NxActor* actor = *--actors;

			float size;
			bool isTrigger = false;
			bool isKinematic = actor->isDynamic() && actor->readBodyFlag(NX_BF_KINEMATIC);
			NxVec3 color;
			NxF32 alpha = 1;
			if (actor->isDynamic()) {
				if (actor->readBodyFlag(NX_BF_KINEMATIC)) {
					color.set(1,0,0);
				} else {
					color.set(0,1,0);
				}
			} else {
				color.set(0.2f,0.2f,0.2f);
			}

			if (*(int *)(&actor->userData) < 0)
			{
				NxI32 triggerNumber = -(*(NxI32 *)(&actor->userData));
				NxI32 triggerIndex = triggerNumber - 1;
				// This is our trigger
				isTrigger = true;

				size = 10.0f;
				color.z = gNbTouchedBodies[triggerIndex] > 0.5f ? 1.0f:0.0f;
				alpha = 0.5f;
				if (pass == 0)
					continue;
			}
			else
			{
				// This is a normal object
				size = float(*(int *)(&actor->userData));
				if (pass == 1)
					continue;
			}
			float glmat[16];
			glPushMatrix();
			actor->getGlobalPose().getColumnMajor44(glmat);
			glMultMatrixf(glmat);
			glColor4f(color.x, color.y, color.z, 1.0f);
			glutSolidCube(size*2.0f);
			glPopMatrix();

			// Handle shadows
			if( !isTrigger)
			{
				glPushMatrix();

				const static float ShadowMat[]={ 1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1 };

				glMultMatrixf(ShadowMat);
				glMultMatrixf(glmat);

				glDisable(GL_LIGHTING);
				glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
				glutSolidCube(size*2.0f);
				glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
				glEnable(GL_LIGHTING);

				glPopMatrix();
			}
		}
	}
}
Example #23
0
// 增加一辆车
NxVehicle* NxAllVehicle::addVehicle(const NxVec3& pos, VehicleInfo vinfo, std::string name, NxScene* nxScene, NxPhysicsSDK* nxPhysics)
{
	NxVehicleDesc vehicleDesc;
	NxBoxShapeDesc boxShapes[2];
	NxConvexShapeDesc carShape[2];

	NxArray<NxVec3> points;
	NxArray<NxVec3> points2;
	NxReal halfWidth = vinfo.width / 2;//1.1529f;
	NxReal halfLength = vinfo.length / 2;//2.5278f;
	NxReal halfHeight = vinfo.height / 2; //0.6027;

	points.pushBack().set(halfLength,-halfHeight * 0.1f, 0);
	points.pushBack().set(halfLength * 0.7f, 0, 0);
	points.pushBack().set(0.2f * halfLength, halfHeight * 0.2f, 0);
	points.pushBack().set(-halfLength, halfHeight * 0.2f, 0);
	points.pushBack().set(0.1*halfLength, halfHeight * 0.2f, halfWidth * 0.9f);
	points.pushBack().set(0.1*halfLength, halfHeight * 0.2f,-halfWidth * 0.9f);
	points.pushBack().set(-0.8*halfLength, halfHeight * 0.2f, halfWidth * 0.9f);
	points.pushBack().set(-0.8*halfLength, halfHeight * 0.2f,-halfWidth * 0.9f);

	points.pushBack().set(halfLength * 0.9f,-halfHeight * 0.25f, halfWidth * 0.8f);
	points.pushBack().set(halfLength * 0.9f,-halfHeight * 0.25f,-halfWidth * 0.8f);
	points.pushBack().set(0,-halfHeight * 0.2f, halfWidth);
	points.pushBack().set(0,-halfHeight * 0.2f,-halfWidth);
	points.pushBack().set(-halfLength * 0.9f,-halfHeight * 0.2f, halfWidth * 0.9f);
	points.pushBack().set(-halfLength * 0.9f,-halfHeight * 0.2f,-halfWidth * 0.9f);

	points.pushBack().set(halfLength * 0.8f, -halfHeight, halfWidth * 0.79f);
	points.pushBack().set(halfLength * 0.8f, -halfHeight,-halfWidth * 0.79f);
	points.pushBack().set(-halfLength * 0.8f, -halfHeight, halfWidth * 0.79f);
	points.pushBack().set(-halfLength * 0.8f, -halfHeight,-halfWidth * 0.79f);

	for(NxU32 i = 2; i < 8; i++)
	{
		points2.pushBack(points[i]);
	}

	points2.pushBack().set(-0.5*halfLength, halfHeight*0.8f, halfWidth*0.7f);
	points2.pushBack().set(-0.5*halfLength, halfHeight*0.8f,-halfWidth*0.7f);
	points2.pushBack().set(-0.7*halfLength, halfHeight*0.7f, halfWidth*0.7f);
	points2.pushBack().set(-0.7*halfLength, halfHeight*0.7f,-halfWidth*0.7f);


	static NxConvexMeshDesc convexMesh;
	convexMesh.numVertices = points.size();
	convexMesh.points = &(points[0].x);
	convexMesh.pointStrideBytes = sizeof(NxVec3);
	convexMesh.flags |= NX_CF_COMPUTE_CONVEX|NX_CF_USE_LEGACY_COOKER;

	MemoryWriteBuffer buf;
	bool status = NxCookConvexMesh(convexMesh, buf);
	if(status)
	{
		carShape[0].meshData = nxPhysics->createConvexMesh(MemoryReadBuffer(buf.data));
		vehicleDesc.carShapes.pushBack(&carShape[0]);
	}

	static NxConvexMeshDesc convexMesh2;
	convexMesh2.numVertices = points2.size();
	convexMesh2.points = (&points2[0].x);
	convexMesh2.pointStrideBytes = sizeof(NxVec3);
	convexMesh2.flags = NX_CF_COMPUTE_CONVEX|NX_CF_USE_LEGACY_COOKER;

	MemoryWriteBuffer buf2;
	status = NxCookConvexMesh(convexMesh2, buf2);
	if(status)
	{
		carShape[1].meshData = nxPhysics->createConvexMesh(MemoryReadBuffer(buf2.data));
		vehicleDesc.carShapes.pushBack(&carShape[1]);
	}

	vehicleDesc.position				= pos;
	vehicleDesc.mass					= vinfo.mass;//1200;//monsterTruck ? 12000 : 
	vehicleDesc.digitalSteeringDelta	= vinfo.steerablity;//0.04f;
	vehicleDesc.steeringMaxAngle		= vinfo.maxSteeringAngle;	//30.f;
	vehicleDesc.motorForce				= vinfo.maxAcceleraion * vinfo.mass;//3500.f;//monsterTruck?180.f:
	
	NxVehicleMotorDesc motorDesc;
	NxVehicleGearDesc gearDesc;
	NxReal wheelRadius = 0.4f;

	vehicleDesc.maxVelocity = vinfo.maxVelocity;	//80.f;//(monsterTruck)?40.f:80.f;
	motorDesc.setToCorvette();
	vehicleDesc.motorDesc = &motorDesc;
	gearDesc.setToCorvette();
	vehicleDesc.gearDesc = &gearDesc;
	vehicleDesc.differentialRatio = 3.42f;

	wheelRadius = 0.3622f;
	vehicleDesc.centerOfMass.set(0,-0.7f,0);


	NxWheelDesc wheelDesc[4];
	for(NxU32 i=0;i<4;i++)
	{
		wheelDesc[i].wheelApproximation = 10;
		//wheelDesc[i].wheelFlags |= NX_WF_BUILD_LOWER_HALF;
		wheelDesc[i].wheelRadius = wheelRadius;//(monsterTruck)?wheelRadius*3.f:wheelRadius;
		wheelDesc[i].wheelWidth = 0.1923f;//(monsterTruck)?0.3f:0.1923f;
		wheelDesc[i].wheelSuspension = 0.2f;//(monsterTruck)?0.6f:0.2f;
		wheelDesc[i].springRestitution = 7000;//monsterTruck?(crovette?5000:4000):7000;
		wheelDesc[i].springDamping = 800;
		wheelDesc[i].springBias = 0.0f;	// 设为1.0后居然会出错!!!!!!!!
		//wheelDesc[i].maxHandBraking = 1.f; //monsterTruck?0.5f:1.f;
		wheelDesc[i].inverseWheelMass = 4.0f / vinfo.maxAcceleraion;	// 换算成动力
		wheelDesc[i].frictionToFront = 1.f;
		wheelDesc[i].frictionToSide = 2.f;
		
		vehicleDesc.carWheels.pushBack(&wheelDesc[i]);
	}

	NxReal heightPos = -0.3622f;	//(monsterTruck)?1.f:
	wheelDesc[0].position.set( 1.02f, heightPos, 1.26);
	wheelDesc[1].position.set( 1.12f, heightPos,-1.54);
	wheelDesc[2].position.set(-1.02f, heightPos, 1.26);
	wheelDesc[3].position.set(-1.12f, heightPos,-1.54);
	NxU32 flags = NX_WF_BUILD_LOWER_HALF;

	wheelDesc[0].wheelFlags |= ((vinfo.driven==FrontDriven)?NX_WF_ACCELERATED:0) | NX_WF_STEERABLE_INPUT | flags;
	wheelDesc[1].wheelFlags |= ((vinfo.driven==FrontDriven)?NX_WF_ACCELERATED:0) | NX_WF_STEERABLE_INPUT | flags;
	wheelDesc[2].wheelFlags |= ((vinfo.driven==BackDriven)?NX_WF_ACCELERATED:0) | NX_WF_AFFECTED_BY_HANDBRAKE | flags;
	wheelDesc[3].wheelFlags |= ((vinfo.driven==BackDriven)?NX_WF_ACCELERATED:0) | NX_WF_AFFECTED_BY_HANDBRAKE | flags;

	vehicleDesc.steeringSteerPoint.set(1.8, 0, 0);
	vehicleDesc.steeringTurnPoint.set(-1.5, 0, 0);

	NxVehicle* vehicle = NxVehicle::createVehicle(nxScene, &vehicleDesc, name);
	NxQuat q;
	// 少转过90度,可能会有问题
	q.fromAngleAxis(90.0f, NxVec3(0.0f, 1.0f, 0.0f));
	vehicle->getActor()->setGlobalOrientationQuat(q);

	vehicle->mVInfo = vinfo;
	vehicle->setOilAmount(vinfo.oilAmount);

	// 加到队列中
	mAllVehicle.pushBack(vehicle);
	mIsLive.pushBack(0);
//	miUserVehicle = mAllVehicle.size() - 1;

	return vehicle;
}
Example #24
0
void TickCar ( void )
{
	g_iValue = 10;

	NxReal steeringAngle = gSteeringValue * gMaxSteeringAngle;

	NxArray<CarWheelContact>::iterator i = wheelContactPoints.begin();
	while(i != wheelContactPoints.end())
	{
		CarWheelContact& cwc = *i;

		WheelShapeUserData* wheelData = (WheelShapeUserData *)(cwc.wheel->userData);

		/*
		struct CarWheelContact
		{
			NxActor* car;
			NxShape* wheel;
			NxVec3 contactPoint;
			NxVec3 contactNormalForce;
			NxVec3 contactFrictionForce;
		};
		*/

		{
			NxMat34 pose   = cwc.wheel->getGlobalPose ( );
			NxMat33 orient = pose.M;
			NxVec3  pos    = pose.t;

			float glmat[16];
			orient.getColumnMajorStride4(&(glmat[0]));
			pos.get(&(glmat[12]));
			glmat[3] = glmat[7] = glmat[11] = 0.0f;
			glmat[15] = 1.0f;

			SetWorldMatrix ( g_iValue, ( D3DXMATRIX* ) &glmat );
			sObject* pObject = dbGetObject ( g_iValue );
			pObject->position.vecPosition = D3DXVECTOR3 ( glmat [ 12 ], glmat [ 13 ], glmat [ 14 ] );

			//dbPositionObject ( g_iValue, glmat [ 12 ], glmat [ 13 ], glmat [ 14 ] );

			g_iValue++;
		}

		//apply to powered wheels only.
		if (wheelData->frontWheel)
	    {
			//steering:
			NxMat33 wheelOrientation = cwc.wheel->getLocalOrientation();
			wheelOrientation.setColumn(0,  NxVec3(NxMath::cos(steeringAngle), 0,  NxMath::sin(steeringAngle) ));
			wheelOrientation.setColumn(2,  NxVec3(NxMath::sin(steeringAngle), 0, -NxMath::cos(steeringAngle) ));
			cwc.wheel->setLocalOrientation(wheelOrientation);

			if (frontWheelIsPowered)
			{
				//get the world space orientation:
				wheelOrientation = cwc.wheel->getGlobalOrientation();
				NxVec3 steeringDirection;
				wheelOrientation.getColumn(0, steeringDirection);

				//the power direction of the front wheel is the wheel's axis as it is steered.
				if (gMotorForce)
				{
					cwc.car->addForceAtPos(steeringDirection * gMotorForce,cwc.contactPoint);
				}
			}
		}
		if (!wheelData->frontWheel && rearWheelIsPowered)
		{
			//get the orientation of this car:
			NxMat33 m = cwc.car->getGlobalOrientation();
			NxVec3 carForwardAxis;
			m.getColumn(0, carForwardAxis);
			//the power direction of the rear wheel is always the car's length axis.
			cwc.car->addForceAtPos(carForwardAxis * gMotorForce,cwc.contactPoint);
		}
		i++;
	}

	wheelContactPoints.clear();
}
Example #25
0
int main(int argc, char **argv)
{
    //init and PVD
    bool initialized = false;
    NxPhysicsSDK *physicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
    if (!physicsSDK)
        return 0;
    else
        physicsSDK->getFoundationSDK().getRemoteDebugger()->connect("localhost", 5425);
    physicsSDK->setParameter(NX_CONTINUOUS_CD, true);

    initialized = true;

    //create a scene
    bool sceneInit = false;
    NxSceneDesc sceneDesc;
    sceneDesc.gravity.set(0, -9.81f, 0);
    gScene = physicsSDK->createScene(sceneDesc);

    if (gScene != NULL)
        sceneInit = true;

    //create a plane
    {
        NxActorDesc actorDesc;
        NxPlaneShapeDesc planeDesc;
        //planeDesc.normal = NxVec3(0, 0, 1);
        //planeDesc.d = -10.0f;

        actorDesc.shapes.pushBack(&planeDesc);
        gScene->createActor(actorDesc);
    }

    //create material
    NxMaterial *defaultMaterial = gScene->getMaterialFromIndex(0);
    defaultMaterial->setRestitution(0.3f);
    defaultMaterial->setStaticFriction(0.5f);
    defaultMaterial->setDynamicFriction(0.5f);



    //create a box
    {
        NxActorDesc actorDesc;
        NxBodyDesc bodyDesc;
        bodyDesc.angularDamping = 0.5;
        bodyDesc.linearVelocity = NxVec3(1, 0, 0);
        actorDesc.body = &bodyDesc;

        NxBoxShapeDesc boxDesc;
        boxDesc.dimensions = NxVec3(2.0f, 3.0f, 4.0f);
        actorDesc.shapes.pushBack(&boxDesc);
        actorDesc.density = 10.0f;
        actorDesc.globalPose.t = NxVec3(10.0f, 10.0f, 10.0f);
        gScene->createActor(actorDesc)->userData = NULL;
    }

    //create a cloth
    {
        // Create the objects in the scene
        NxActor* sphere1 = CreateSphere(NxVec3(-1, 0, -0.5), 1, 10);
        NxActor* box1 = CreateBox(NxVec3(1, 0, -1), NxVec3(1, 1, 1), 10);
        NxActor* box2 = CreateBox(NxVec3(0, 6.5, 0), NxVec3(5, 0.5, 0.5), 10);
        NxActor* box3 = CreateBox(NxVec3(0, 6.5, -7), NxVec3(5, 0.5, 0.5), 10);

        box2->setLinearDamping(5);
        box3->setLinearDamping(5);
        NxD6JointDesc d6Desc;
        d6Desc.actor[0] = NULL;
        d6Desc.actor[1] = box2;
        NxVec3 globalAnchor(0, 7, 0);
        d6Desc.localAnchor[0] = globalAnchor;
        box2->getGlobalPose().multiplyByInverseRT(globalAnchor, d6Desc.localAnchor[1]);
        box2->raiseBodyFlag(NX_BF_DISABLE_GRAVITY);

        box3->getGlobalPose().multiplyByInverseRT(globalAnchor, d6Desc.localAnchor[1]);
        box3->raiseBodyFlag(NX_BF_DISABLE_GRAVITY);

        d6Desc.localAxis[0] = NxVec3(1, 0, 0);
        d6Desc.localNormal[0] = NxVec3(0, 1, 0);
        d6Desc.localAxis[1] = NxVec3(1, 0, 0);
        d6Desc.localNormal[1] = NxVec3(0, 1, 0);

        d6Desc.twistMotion = NX_D6JOINT_MOTION_LOCKED;
        d6Desc.swing1Motion = NX_D6JOINT_MOTION_LOCKED;
        d6Desc.swing2Motion = NX_D6JOINT_MOTION_LOCKED;
        d6Desc.xMotion = NX_D6JOINT_MOTION_FREE;
        d6Desc.yMotion = NX_D6JOINT_MOTION_FREE;
        d6Desc.zMotion = NX_D6JOINT_MOTION_FREE;

        NxJoint* d6Joint = gScene->createJoint(d6Desc);

        NxClothDesc clothDesc;
        clothDesc.globalPose.t = NxVec3(4, 7, 0);
        clothDesc.thickness = 0.2;
        //clothDesc.density = 1;
        clothDesc.bendingStiffness = 0.5;
        clothDesc.stretchingStiffness = 1;
        //clothDesc.dampingCoefficient = 0.5;
        clothDesc.friction = 0.5;
        //clothDesc.collisionResponseCoefficient = 1;
        //clothDesc.attachmentResponseCoefficient = 1;
        //clothDesc.solverIterations = 5;
        //clothDesc.flags |= NX_CLF_STATIC;
        //clothDesc.flags |= NX_CLF_DISABLE_COLLISION;
        //clothDesc.flags |= NX_CLF_VISUALIZATION;
        //clothDesc.flags |= NX_CLF_GRAVITY;
        clothDesc.flags |= NX_CLF_BENDING;
        //clothDesc.flags |= NX_CLF_BENDING_ORTHO;
        clothDesc.flags |= NX_CLF_DAMPING;
        //clothDesc.flags |= NX_CLF_COMDAMPING;
        clothDesc.flags |= NX_CLF_COLLISION_TWOWAY;

        clothDesc.flags &= ~NX_CLF_HARDWARE;
        clothDesc.flags |= NX_CLF_FLUID_COLLISION;
        clothDesc.selfCollisionThickness = 10.0f;


        NxReal w = 8;
        NxReal h = 7;
        NxReal d = 0.05;
        NxClothMeshDesc meshDesc;
        bool mInitDone = false;

        int numX = (int)(w / d) + 1;
        int numY = (int)(h / d) + 1;


        meshDesc.numVertices = (numX + 1) * (numY + 1);
        meshDesc.numTriangles = numX*numY * 2;
        meshDesc.pointStrideBytes = sizeof(NxVec3);
        meshDesc.triangleStrideBytes = 3 * sizeof(NxU32);
        meshDesc.vertexMassStrideBytes = sizeof(NxReal);
        meshDesc.vertexFlagStrideBytes = sizeof(NxU32);
        meshDesc.points = (NxVec3*)malloc(sizeof(NxVec3)*meshDesc.numVertices);
        meshDesc.triangles = (NxU32*)malloc(sizeof(NxU32)*meshDesc.numTriangles * 3);
        meshDesc.vertexMasses = 0;
        meshDesc.vertexFlags = 0;
        meshDesc.flags = 0;

        int i, j;
        NxVec3 *p = (NxVec3*)meshDesc.points;
        for (i = 0; i <= numY; i++) {
            for (j = 0; j <= numX; j++) {
                p->set(-d*j, 0.0f, -d*i);
                p++;
            }
        }

        NxU32 *id = (NxU32*)meshDesc.triangles;
        for (i = 0; i < numY; i++) {
            for (j = 0; j < numX; j++) {
                NxU32 i0 = i * (numX + 1) + j;
                NxU32 i1 = i0 + 1;
                NxU32 i2 = i0 + (numX + 1);
                NxU32 i3 = i2 + 1;
                if ((j + i) % 2) {
                    *id++ = i0;
                    *id++ = i2;
                    *id++ = i1;
                    *id++ = i1;
                    *id++ = i2;
                    *id++ = i3;
                }
                else {
                    *id++ = i0;
                    *id++ = i2;
                    *id++ = i3;
                    *id++ = i0;
                    *id++ = i3;
                    *id++ = i1;
                }
            }
        }
        // if we want tearing we must tell the cooker
        // this way it will generate some space for particles that will be generated during tearing
        if (meshDesc.flags & NX_CLF_TEARABLE)
            meshDesc.flags |= NX_CLOTH_MESH_TEARABLE;


        //cooking
        static NxCookingInterface *gCooking = 0;
        gCooking = NxGetCookingLib(NX_PHYSICS_SDK_VERSION);
        gCooking->NxInitCooking();

        gCooking->NxCookClothMesh(meshDesc, UserStream("e:\\cooked.bin", false));

        //Meshdata Buffers
        NxMeshData mReceiveBuffers;
        // here we setup the buffers through which the SDK returns the dynamic cloth data
        // we reserve more memory for vertices than the initial mesh takes
        // because tearing creates new vertices
        // the SDK only tears cloth as long as there is room in these buffers
        NxU32 numVertices = meshDesc.numVertices;
        NxU32 numTriangles = meshDesc.numTriangles;

        NxU32 maxVertices = 2 * numVertices;
        mReceiveBuffers.verticesPosBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices);
        mReceiveBuffers.verticesNormalBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices);
        mReceiveBuffers.verticesPosByteStride = sizeof(NxVec3);
        mReceiveBuffers.verticesNormalByteStride = sizeof(NxVec3);
        mReceiveBuffers.maxVertices = maxVertices;
        mReceiveBuffers.numVerticesPtr = (NxU32*)malloc(sizeof(NxU32));

        // the number of triangles is constant, even if the cloth is torn
        NxU32 maxIndices = 3 * numTriangles;
        mReceiveBuffers.indicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxIndices);
        mReceiveBuffers.indicesByteStride = sizeof(NxU32);
        mReceiveBuffers.maxIndices = maxIndices;
        mReceiveBuffers.numIndicesPtr = (NxU32*)malloc(sizeof(NxU32));

        // the parent index information would be needed if we used textured cloth
        NxU32 maxParentIndices = maxVertices;
        mReceiveBuffers.parentIndicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxParentIndices);
        mReceiveBuffers.parentIndicesByteStride = sizeof(NxU32);
        mReceiveBuffers.maxParentIndices = maxParentIndices;
        mReceiveBuffers.numParentIndicesPtr = (NxU32*)malloc(sizeof(NxU32));

        // init the buffers in case we want to draw the mesh
        // before the SDK as filled in the correct values
        *mReceiveBuffers.numVerticesPtr = 0;
        *mReceiveBuffers.numIndicesPtr = 0;



        clothDesc.clothMesh = physicsSDK->createClothMesh(UserStream("e:\\cooked.bin", true));
        clothDesc.meshData = mReceiveBuffers;

        NxCloth *mCloth;
        mCloth = gScene->createCloth(clothDesc);
        mCloth->attachToShape(*box2->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY);
        mCloth->attachToShape(*box3->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY);
    }

    //create fluid 1
    {
        //fluid = CreateFluid(NxVec3(0, 12, -3.5), 15, 0.1, gScene);
    }
    //create fluid 2
    {
        //Create a set of initial particles
        ParticleSDK*	initParticles = new ParticleSDK[max_particles];
        unsigned initParticlesNum = 0;

        //Create particle filled sphere in buffer.
        NxVec3 fluidPos(0, 2, 0);
        NxVec3 offsetPos(0, 12, -3.5);
        float distance = 0.1f;
        //#ifdef __PPCGEKKO__
        //	unsigned sideNum = 12;
        //#else
        unsigned sideNum = 16;
        //#endif

        //Setup structure to pass initial particles.
        NxParticleData initParticleData;
        initParticlesNum = 0;
        initParticleData.numParticlesPtr = &initParticlesNum;
        initParticleData.bufferPos = &initParticles[0].position.x;
        initParticleData.bufferPosByteStride = sizeof(ParticleSDK);
        initParticleData.bufferVel = &initParticles[0].velocity.x;
        initParticleData.bufferVelByteStride = sizeof(ParticleSDK);

        CreateParticleSphere(initParticleData, max_particles, false, offsetPos, NxVec3(0, 0, 0), 0.0f, distance, sideNum);

        //Setup fluid descriptor
        NxFluidDesc fluidDesc;
        fluidDesc.maxParticles = max_particles;
        fluidDesc.kernelRadiusMultiplier = 2.0f;
        fluidDesc.restParticlesPerMeter = 10.0f;
        fluidDesc.motionLimitMultiplier = 3.0f;
        fluidDesc.packetSizeMultiplier = 8;
        fluidDesc.collisionDistanceMultiplier = 0.1;
        fluidDesc.stiffness = 50.0f;
        fluidDesc.viscosity = 40.0f;
        fluidDesc.restDensity = 1000.0f;
        fluidDesc.damping = 0.0f;
        fluidDesc.restitutionForStaticShapes = 0.0f;
        fluidDesc.dynamicFrictionForStaticShapes = 0.05f;
        fluidDesc.simulationMethod = NX_F_SPH;
        fluidDesc.flags &= ~NX_FF_HARDWARE;

        //Add initial particles to fluid creation.
        fluidDesc.initialParticleData = initParticleData;

        //Create user fluid.
        //- create NxFluid in NxScene
        //- setup the buffers to read from data from the SDK
        //- set NxFluid::userData field to MyFluid instance
        bool trackUserData = false;
        bool provideCollisionNormals = false;
        MyFluid* fluid = new MyFluid(gScene, fluidDesc, trackUserData, provideCollisionNormals, NxVec3(0.4f, 0.5f, 0.9f), 0.03f);
        assert(fluid);
        gMyFluids.pushBack(fluid);
    }
    //simulate
    for (int i = 0; i < 3000; i++)
    {
        gScene->simulate(1.0f / 60.f);
        gScene->flushStream();
        //GetPhysicsResults
        gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);

        // update fluid status
        if (i == 400)
        {
            MyFluid* fluid = gMyFluids[0];
            const ParticleSDK* particles = fluid->getParticles();
            unsigned particlesNum = fluid->getParticlesNum();
            if (!gUpdates)
            {
                gUpdates = new ParticleUpdateSDK[max_particles];
            }
            for (unsigned i = 0; i < particlesNum; i++)
            {
                ParticleUpdateSDK& update = gUpdates[i];
                NxVec3& force = update.force;
                force.set(0, 0, 0);
                NxU32& flags = update.flags;
                if (i >= particlesNum/2)
                {
                    flags = 0;
                    flags |= NX_FP_DELETE;
                }
                else
                {
                    flags = 0;
                }

            }
            //在这里更改粒子的属性
            NxParticleUpdateData updateData;
            updateData.bufferFlag = &gUpdates[0].flags;
            updateData.bufferFlagByteStride = sizeof(ParticleUpdateSDK);
            fluid->getNxFluid()->updateParticles(updateData);
        }
    }


    //release
    if (physicsSDK != NULL)
    {
        if (gScene != NULL)
            physicsSDK->releaseScene(*gScene);
        gScene = NULL;
        NxReleasePhysicsSDK(physicsSDK);
        physicsSDK = NULL;
    }
    return 1;
}
void SampleCollision::setup()
{

	SetTitleString(getName());
#ifdef __PPCGEKKO__
	SetHelpString("    a: create rigid bodies");
#else	
	SetHelpString("    b: create rigid bodies");
#endif	

	gShadows = false;

	// Create objects in the scene

	if (!InitCooking(gAllocator, &gErrorStream)) 
	{
		printf("\nError: Unable to initialize the cooking library, exiting the sample.\n\n");
		return;
	}

	// Load ASE file
	CookASE("fluidSample.ase", gScene, NxVec3(1,10,0));
	CookASE("coolFlow.ase", gScene, NxVec3(1,6,-0), NxVec3(1,0.2,1));
	CloseCooking();

	// Add a box shaped drain.
	NxActorDesc boxDrainActor;
	NxBoxShapeDesc boxDrainShape;
	boxDrainActor.shapes.pushBack(&boxDrainShape);
	boxDrainShape.dimensions.set(40,1,40);
	boxDrainShape.shapeFlags |= NX_SF_FLUID_DRAIN;
	boxDrainActor.globalPose.t.set(0, 0, 0);
	gScene->createActor(boxDrainActor);

	//Pre cook hotspots
	NxBounds3 precookAABB;
	precookAABB.set(NxVec3(-20,-20,-20), NxVec3(20,20,20));
//	gScene->cookFluidMeshHotspot(precookAABB, PACKET_SIZE_MULTIPLIER, REST_PARTICLES_PER_METER, KERNEL_RADIUS_MULTIPLIER, MOTION_LIMIT_MULTIPLIER, COLLISION_DISTANCE_MULTIPLIER );


	//Create a set of initial particles
	ParticleSDK*	initParticles = new ParticleSDK[MAX_PARTICLES];
	unsigned initParticlesNum = 0;

	NxVec3 fluidPos(0, 11.6, 0);
	float distance = 0.1f;
	unsigned sideNum = 16;	
	float rad = sideNum*distance*0.5f;
	for (unsigned i=0; i<sideNum; i++)
		for (unsigned j=0; j<sideNum; j++)
			for (unsigned k=0; k<sideNum; k++)
			{
				NxVec3 p = NxVec3(i*distance,j*distance,k*distance);
				if (p.distance(NxVec3(rad,rad,rad)) < rad)
				{
					p += fluidPos;
					ParticleSDK& newParticle = initParticles[initParticlesNum++];
					newParticle.position = p;
					newParticle.velocity = NxVec3(0,0,0);
				}
			}
	//Setup structure to pass initial particles.
	NxParticleData initParticleData;
	initParticleData.numParticlesPtr		= &initParticlesNum;
	initParticleData.bufferPos				= &initParticles[0].position.x;
	initParticleData.bufferPosByteStride	= sizeof(ParticleSDK);
	initParticleData.bufferVel				= &initParticles[0].velocity.x;
	initParticleData.bufferVelByteStride	= sizeof(ParticleSDK);

	//Setup fluid descriptor
	NxFluidDesc fluidDesc;
	fluidDesc.maxParticles                  	= initParticlesNum;
	fluidDesc.kernelRadiusMultiplier			= KERNEL_RADIUS_MULTIPLIER;
	fluidDesc.restParticlesPerMeter				= REST_PARTICLES_PER_METER;
	fluidDesc.collisionDistanceMultiplier   	= COLLISION_DISTANCE_MULTIPLIER;
	fluidDesc.stiffness							= 50.0f;
	fluidDesc.viscosity							= 22.0f;
	fluidDesc.damping							= 0.0f;
	fluidDesc.restitutionForStaticShapes		= 0.4f;
	fluidDesc.dynamicFrictionForStaticShapes	= 0.03f;
	fluidDesc.simulationMethod					= NX_F_SPH; //NX_F_NO_PARTICLE_INTERACTION;

	if (!gHardwareSimulation)
		fluidDesc.flags &= ~NX_FF_HARDWARE;

	fluidDesc.initialParticleData			= initParticleData;

	//Create user fluid.
	//- create NxFluid in NxScene
	//- setup the buffers to read from data from the SDK
	//- set NxFluid::userData field to MyFluid instance
	bool trackUserData = false;
	bool provideCollisionNormals = false;
	MyFluid* fluid = new MyFluid(gScene, fluidDesc, trackUserData, provideCollisionNormals, NxVec3(0.2f,0.3f,0.7f), 0.03f);
	assert(fluid);
	gMyFluids.pushBack(fluid);

	delete[] initParticles;

	gCameraPos.set(23, 14, 23);
	gCameraForward = fluidPos - NxVec3(0, 3, 0) - gCameraPos;
	gCameraForward.normalize();

}