Exemplo n.º 1
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);
}
Exemplo n.º 2
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");
						}
					}
				}
			}
		}
	}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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);
	}

}
Exemplo n.º 6
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);
                    }
                }
            }		
        }
	}
Exemplo n.º 7
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;
}
Exemplo n.º 8
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();

}