Esempio n. 1
0
//-------------------------------------------------------------------------------------------------
bool sdPhysicsSystem::CreateEmptyScene(uint uiSize)
{
	NIASSERT(!m_pkScene);
	NIASSERT(!m_pkControllerManager);

	float fSize = (float)uiSize;
	float fWalkHeight = 4000.f;
	NxBounds3 nxBound;
	nxBound.setCenterExtents(NxVec3(fSize * 0.5f, fSize * 0.5f, 0.f), NxVec3(fSize * 0.5f, fSize * 0.5f, fWalkHeight *0.5f));

	NxSceneDesc nxSceneDesc;
	nxSceneDesc.gravity = NxVec3(0.f, 0.f, -9.8f);
	nxSceneDesc.simType = NX_SIMULATION_SW;
	nxSceneDesc.maxBounds = &nxBound;
	nxSceneDesc.upAxis = 2;							///< Z up
	nxSceneDesc.bpType = NX_BP_TYPE_SAP_MULTI;
	nxSceneDesc.nbGridCellsX = 8u;
	nxSceneDesc.nbGridCellsY = 8u;
	nxSceneDesc.subdivisionLevel = 5;

	m_pkScene = m_pkPhysicsSDK->createScene(nxSceneDesc);
	NIASSERT(m_pkScene);

	m_pkControllerManager = NxCreateControllerManager(m_pkAllocator);
	NIASSERT(m_pkControllerManager);

	return true;
}
Esempio n. 2
0
// ----------------------------------------------------------------------
void ObjMesh::getTriangleBounds(int i, NxBounds3 &bounds) const
{
	const ObjMeshTriangle &mt = mTriangles[i];
	bounds.setEmpty();
	bounds.include(mVertices[mt.vertexNr[0]]);
	bounds.include(mVertices[mt.vertexNr[1]]);
	bounds.include(mVertices[mt.vertexNr[2]]);
}
void CCTDebugData::addAABB(const NxBounds3& bounds, NxU32 color, bool renderFrame)
{
	// Reuse OBB code...
	NxVec3 center;	bounds.getCenter(center);
	NxVec3 extents;	bounds.getExtents(extents);
	NxMat33 id;	id.id();
	addOBB(NxBox(center, extents, id), color, renderFrame);
}
void CCTDebugData::addAABB(const NxExtendedBounds3& bounds, NxU32 color)
{
	NxExtendedVec3 center;
	NxVec3 extents;
	bounds.getCenter(center);
	bounds.getExtents(extents);

	NxBounds3 tmp;
	tmp.setCenterExtents(NxVec3((float)center.x, (float)center.y, (float)center.z), extents);

	addAABB(tmp, color, false);
}
Esempio n. 5
0
static void CreateCube(const NxVec3& pos, const NxVec3 * vel = 0)
	{
	// Avoid creating one compound within another
	NxBounds3 bounds;
	bounds.setCenterExtents(pos, NxVec3(10.0f, 10.0f, 10.0f));
	if(gScene->checkOverlapAABB(bounds))
		return;

	// Create cube made up of 6 individual boxes as its faces, with each box having a different material
	NxActorDesc actorDesc;
	NxBodyDesc bodyDesc;
	bodyDesc.linearVelocity.set(0,5,0);
	if (vel)
		bodyDesc.linearVelocity += *vel;

	bodyDesc.angularVelocity.set(NxMath::rand(0.0f,10.0f),NxMath::rand(0.0f,10.0f),NxMath::rand(0.0f,10.0f));	//throw up the ball with a random initial angular vel as if to roll dice.
	
	NxBoxShapeDesc boxDesc[6];
	boxDesc[0].dimensions.set(4,4,1);
	boxDesc[0].localPose.t.set(0,0,4);
	boxDesc[0].materialIndex	= defaultMaterialIndex;
	actorDesc.shapes.pushBack(&boxDesc[0]);
	boxDesc[1].dimensions.set(4,4,1);
	boxDesc[1].localPose.t.set(0,0,-4);
	boxDesc[1].materialIndex	= somewhatBouncyMaterialIndex;
	actorDesc.shapes.pushBack(&boxDesc[1]);
	boxDesc[2].dimensions.set(4,1,4);
	boxDesc[2].localPose.t.set(0,4,0);
	boxDesc[3].materialIndex	= veryBouncyMaterialIndex;
	actorDesc.shapes.pushBack(&boxDesc[2]);
	boxDesc[3].dimensions.set(4,1,4);
	boxDesc[3].localPose.t.set(0,-4,0);
	boxDesc[3].materialIndex	= defaultMaterialIndex;
	actorDesc.shapes.pushBack(&boxDesc[3]);
	boxDesc[4].dimensions.set(1,4,4);
	boxDesc[4].localPose.t.set(4,0,0);
	boxDesc[4].materialIndex	= frictionlessMaterialIndex;
	actorDesc.shapes.pushBack(&boxDesc[4]);
	boxDesc[5].dimensions.set(1,4,4);
	boxDesc[5].localPose.t.set(-4,0,0);
	boxDesc[5].materialIndex	= highFrictionMaterialIndex;
	actorDesc.shapes.pushBack(&boxDesc[5]);

	
	
	actorDesc.body			= &bodyDesc;
	actorDesc.density		= 10.0f;
	actorDesc.globalPose.t  = pos;
	gScene->createActor(actorDesc);
	}
//-----------------------------------------------------------------------------
//  GetWorldBounds
//-----------------------------------------------------------------------------
NxBounds3   CPhysicObj::GetWorldBounds (void) const
{
    assert( m_bActivated );

    int         nNumParts = GetNumParts();
    // NOTA: Siempre tendremos que tener al menos 1 parte. 
    NxBounds3   result = GetWorldBounds (0);
    // El resto de bounds los combinamos con el resultado
    for (int i = 1; i < nNumParts; i++)
    {
        result.combine (GetWorldBounds(i));
    }

    return result;
}
Esempio n. 7
0
static bool SweepBoxMesh(const SweepTest* sweep_test, const SweptVolume* volume, const TouchedGeom* geom, const NxExtendedVec3& center, const NxVec3& dir, SweptContact& impact)
{
	ASSERT(volume->GetType()==SWEPT_BOX);
	ASSERT(geom->mType==TOUCHED_MESH);
	const SweptBox* SB = static_cast<const SweptBox*>(volume);
	const TouchedMesh* TM = static_cast<const TouchedMesh*>(geom);

	NxU32 NbTris = TM->mNbTris;
	if(!NbTris)	return false;

	// Fetch triangle data for current mesh (the stream may contain triangles from multiple meshes)
	const NxTriangle* T		= &sweep_test->mWorldTriangles[TM->mIndexWorldTriangles];
	const NxTriangle* ET	= &sweep_test->mWorldEdgeNormals[TM->mIndexWorldEdgeNormals];
	const NxU32* EdgeFlags	= &sweep_test->mEdgeFlags[TM->mIndexEdgeFlags];

	NxBounds3 Box;
	Box.setCenterExtents(NxVec3(float(center.x - TM->mOffset.x), float(center.y - TM->mOffset.y), float(center.z - TM->mOffset.z)), SB->mExtents);	// Precompute

	// PT: this only really works when the CCT collides with a single mesh, but that's the most common case. When it doesn't, there's just no speedup but it still works.
	NxU32 CachedIndex = sweep_test->mCachedTriIndex[sweep_test->mCachedTriIndexIndex];
	if(CachedIndex>=NbTris)	CachedIndex=0;

	NxVec3 Hit, Normal;
	float t;
	NxU32 Index;
	if(gUtilLib->NxSweepBoxTriangles(NbTris, T, ET, EdgeFlags, Box, dir, impact.mDistance, Hit, Normal, t, Index, &CachedIndex))
	{
		if(t>=impact.mDistance)			return false;

		impact.mDistance	= t;
		impact.mWorldNormal	= Normal;
		impact.mWorldPos.x	= Hit.x + TM->mOffset.x;
		impact.mWorldPos.y	= Hit.y + TM->mOffset.y;
		impact.mWorldPos.z	= Hit.z + TM->mOffset.z;

		// Returned index is only between 0 and NbTris, i.e. it indexes the array of cached triangles, not the original mesh.
		assert(Index<NbTris);
		sweep_test->mCachedTriIndex[sweep_test->mCachedTriIndexIndex] = Index;

		// The CCT loop will use the index from the start of the cache...
		impact.mIndex = Index + TM->mIndexWorldTriangles;
		return true;
	}
	return false;
}
Esempio n. 8
0
Box3F PxBody::getWorldBounds()
{
   AssertFatal( mActor, "PxBody::getTransform - The actor is null!" );
   
   NxBounds3 bounds;
   bounds.setEmpty();   
   NxBounds3 shapeBounds;

   NxShape *const* pShapeArray = mActor->getShapes();
   U32 shapeCount = mActor->getNbShapes();

   for ( U32 i = 0; i < shapeCount; i++ )
   {
      // Get the shape's bounds.
      pShapeArray[i]->getWorldBounds( shapeBounds );

      // Combine them into the total bounds.
      bounds.combine( shapeBounds );   
   }

   return pxCast<Box3F>( bounds );
}
//-----------------------------------------------------------------------------
//  GetWorldBounds
//-----------------------------------------------------------------------------
NxBounds3   CPhysicObj::GetWorldBounds (int nPartIdx) const
{
    assert( m_bActivated && (nPartIdx < GetNumParts()) );

    const NxActor*  pActor = GetActor(nPartIdx);
    // Combinamos los bounds de todas las shapes
    NxBounds3   result;
    NxBounds3   shapeBounds;

    uint        nNumShapes = pActor->getNbShapes();
    assert( nNumShapes > 0 );

    NxShape* const* pShapes = pActor->getShapes(); 
    pShapes[0]->getWorldBounds(result);
    for (uint i = 1; i < nNumShapes; i++)
    {
        pShapes[0]->getWorldBounds (shapeBounds);
        result.combine (shapeBounds);
    }

    return result;
}
Esempio n. 10
0
//-----------------------------------------------------------------------------
//  CalcBBox
//-----------------------------------------------------------------------------
NxBox   CPhysicModelSimple::CalcBBox (void) const
{
    NxBounds3   bounds;
    for (int i = 0; i < (int)m_ActorDesc.shapes.size(); i++)
    {
        NxShapeDesc* pShapeDesc = m_ActorDesc.shapes[i];
        switch (pShapeDesc->getType())
        {
            case NX_SHAPE_BOX:
			{
				NxBoxShapeDesc* pBoxShape = (NxBoxShapeDesc*) pShapeDesc;
				NxBox shapeBBox (pBoxShape->localPose.t, pBoxShape->dimensions, pBoxShape->localPose.M);
				NxBounds3 shapeBounds;
				shapeBounds.boundsOfOBB( shapeBBox.rot, shapeBBox.center, shapeBBox.extents );
				bounds.combine (shapeBounds);
			}
            break;
            case NX_SHAPE_SPHERE:
			{
				NxSphereShapeDesc* pSphereShape = (NxSphereShapeDesc*) pShapeDesc;
				NxBox shapeBBox (pSphereShape->localPose.t, NxVec3(pSphereShape->radius), pSphereShape->localPose.M);
				NxBounds3 shapeBounds;
				shapeBounds.boundsOfOBB( shapeBBox.rot, shapeBBox.center, shapeBBox.extents );
				bounds.combine (shapeBounds);
			}
            break;
            default:
                // Caso no soportado
                assert(0);
            break;
        }
    }

    NxBox   result;
    bounds.getCenter (result.center);
    bounds.getExtents (result.extents);
    return result;
}
Esempio n. 11
0
// -----------------------------------------------------------------------
// compute the links between the surface mesh and tetrahedras
void ObjMesh::buildTetraLinks(const NxVec3 *vertices, const NxU32 *indices, const NxU32 numTets) 
{
	if(!mTetraLinks.empty())
		return;
	
	mTetraLinks.clear();

	MeshHash* hash = new MeshHash();

	// hash tetrahedra for faster search
	hash->setGridSpacing(mBounds.min.distance(mBounds.max) * 0.1f);

	for (NxU32 i = 0; i < numTets; i++) {
		const NxU32 *ix = &indices[4*i];
		NxBounds3 tetraBounds;
		tetraBounds.setEmpty();
		tetraBounds.include(vertices[*ix++]);
		tetraBounds.include(vertices[*ix++]);
		tetraBounds.include(vertices[*ix++]);
		tetraBounds.include(vertices[*ix++]);
		hash->add(tetraBounds, i);
	}

	for (NxU32 i = 0; i < mVertices.size(); i++) {
		// prepare datastructure for drained tetras
		mDrainedTriVertices.push_back(false);

		ObjMeshTetraLink tmpLink;

		NxVec3 triVert = mVertices[i];
		std::vector<int> itemIndices;
		hash->queryUnique(triVert, itemIndices);

		NxReal minDist = 0.0f;
		NxVec3 b;
		int num, isize;
		num = isize = itemIndices.size();
		if (num == 0) num = numTets;

		for (int i = 0; i < num; i++) {
			int j = i;
			if (isize > 0) j = itemIndices[i];

			const NxU32 *ix = &indices[j*4];
			const NxVec3 &p0 = vertices[*ix++];
			const NxVec3 &p1 = vertices[*ix++];
			const NxVec3 &p2 = vertices[*ix++];
			const NxVec3 &p3 = vertices[*ix++];

			NxVec3 b = computeBaryCoords(triVert, p0, p1, p2, p3);

			// is the vertex inside the tetrahedron? If yes we take it
			if (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f && (b.x + b.y + b.z) <= 1.0f) {
				tmpLink.barycentricCoords = b;
				tmpLink.tetraNr = j;
				break;
			}

			// otherwise, if we are not in any tetrahedron we take the closest one
			NxReal dist = 0.0f;
			if (b.x + b.y + b.z > 1.0f) dist = b.x + b.y + b.z - 1.0f;
			if (b.x < 0.0f) dist = (-b.x < dist) ? dist : -b.x;
			if (b.y < 0.0f) dist = (-b.y < dist) ? dist : -b.y;
			if (b.z < 0.0f) dist = (-b.z < dist) ? dist : -b.z;

			if (i == 0 || dist < minDist) {
				minDist = dist;
				tmpLink.barycentricCoords = b;
				tmpLink.tetraNr = j;
			}
		}

		mTetraLinks.push_back(tmpLink);
	}
	delete hash;
}
Esempio n. 12
0
void Update()
{
	NxMat34 mat34;
	NxMat33 mat;
	NxQuat quat(0.0f,NxVec3(0,1,0));  
	mat.fromQuat(quat);
	NxBox worldBox;
	worldBox.extents	= NxVec3(2, 2, 2);
	worldBox.rot		= mat;

	NxSphere	worldSphere;
	NxBounds3	worldBounds;
	NxCapsule	worldCapsule;
	worldCapsule.radius = 2.0f;

	NxU32 nbPlanes = 2;
	NxPlane worldPlanes[2];
	worldPlanes[0].set(NxVec3(-2,0,2), NxVec3(0,0,1));
	worldPlanes[1].set(NxVec3(-2,0,2), NxVec3(1,0,0));

	NxU32 nbDynamicShapes	= gScene->getNbDynamicShapes();
	NxU32 nbStaticShapes	= gScene->getNbStaticShapes();
	NxU32 nbShapes = 0;
	NxShapesType type;

	int i = 0;
	for (i = 0; i < 3; ++ i)
	{
		if (i == 0)
		{
			nbShapes = nbDynamicShapes;
			type	 = NX_DYNAMIC_SHAPES;
			switch(gOverlapType)
			{
			case OVERLAP_AABB:
			case OVERLAP_CHECK_AABB:
				worldBounds.set(gMIN, gMAX);
				break;
			case OVERLAP_OBB:
			case OVERLAP_CHECK_OBB:
				worldBox.center = gBoxCenter;
				break;
			case OVERLAP_CAPSULE:
			case OVERLAP_CHECK_CAPSULE:
				worldCapsule = NxCapsule(gCapsuleSegment, gCapsuleRadius);
				break;
			case OVERLAP_SPHERE:
			case OVERLAP_CHECK_SPHERE:
				worldSphere = NxSphere(gSphereCenter, gSphereRadius);
				break;
			}
		}
		else if (i == 1)
		{
			nbShapes = nbStaticShapes;
			type	 = NX_STATIC_SHAPES;
			switch(gOverlapType)
			{
			case OVERLAP_AABB:
			case OVERLAP_CHECK_AABB:
				worldBounds.set(gMIN+NxVec3(-6.0f,0,0),gMAX+NxVec3(-6.0f,0,0));
				break;
			case OVERLAP_OBB:
			case OVERLAP_CHECK_OBB:
				worldBox.center = gBoxCenter+NxVec3(-6,0,0);
				break;
			case OVERLAP_CAPSULE:
			case OVERLAP_CHECK_CAPSULE:
				worldCapsule.p0.x = gCapsuleSegment.p0.x - 6.0f;
				worldCapsule.p1.x = gCapsuleSegment.p1.x - 6.0f;
				break;
			case OVERLAP_SPHERE:
			case OVERLAP_CHECK_SPHERE:
				worldSphere = NxSphere(gSphereCenter + NxVec3(-6,0,0), gSphereRadius);
				break;
			}
		}
		else if (i == 2)
		{
			nbShapes = nbStaticShapes + nbDynamicShapes;
			type	 = NX_ALL_SHAPES;
			switch(gOverlapType)
			{
			case OVERLAP_AABB:
			case OVERLAP_CHECK_AABB:
				worldBounds.set(gMIN+NxVec3(6.0f,0,0),gMAX+NxVec3(6.0f,0,0));
				break;
			case OVERLAP_OBB:
			case OVERLAP_CHECK_OBB:
				worldBox.center = gBoxCenter+NxVec3(6,0,0);
				break;
			case OVERLAP_CAPSULE:
			case OVERLAP_CHECK_CAPSULE:
				worldCapsule.p0.x = gCapsuleSegment.p0.x + 6.0f;
				worldCapsule.p1.x = gCapsuleSegment.p1.x + 6.0f;
				break;
			case OVERLAP_SPHERE:
			case OVERLAP_CHECK_SPHERE:
				worldSphere = NxSphere(gSphereCenter + NxVec3(6,0,0), gSphereRadius);
				break;
			}
		}

		NxShape** shapes = (NxShape**)NxAlloca(nbShapes*sizeof(NxShape*));
		for (NxU32 j = 0; j < nbShapes; j++)  shapes[j] = NULL;
		NxU32 activeGroups = 0xffffffff;
		NxGroupsMask* groupsMask = NULL;
		bool bResult	= true;
		float linewidth = 1.0f;
		switch(gOverlapType)
		{
		case OVERLAP_AABB:
			gScene->overlapAABBShapes(worldBounds, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask, true);
			NxCreateBox(worldBox, worldBounds, mat34);
			DrawWireBox(worldBox, NxVec3(1,0,0), linewidth);
			break;
		case OVERLAP_CHECK_AABB:
			bResult = gScene->checkOverlapAABB(worldBounds, type, activeGroups, groupsMask);
			NxCreateBox(worldBox, worldBounds, mat34);
			if (bResult == true)
				DrawWireBox(worldBox, NxVec3(1,0,0), linewidth);
			else
				DrawWireBox(worldBox, NxVec3(0,1,0), linewidth);
			break;
		case OVERLAP_OBB:
			gScene->overlapOBBShapes(worldBox, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask);
			DrawWireBox(worldBox, NxVec3(1,0,0), linewidth);
			break;
		case OVERLAP_CHECK_OBB:
			if (gScene->checkOverlapOBB(worldBox, type, activeGroups, groupsMask) == true)
				DrawWireBox(worldBox, NxVec3(1,0,0), linewidth);
			else
				DrawWireBox(worldBox, NxVec3(0,1,0), linewidth);
			break;
		case OVERLAP_CAPSULE:
			gScene->overlapCapsuleShapes(worldCapsule, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask);
			DrawWireCapsule(worldCapsule, NxVec3(1,0,0));
			break;
		case OVERLAP_CHECK_CAPSULE:
			if (gScene->checkOverlapCapsule(worldCapsule, type,activeGroups, groupsMask) == true)
				DrawWireCapsule(worldCapsule, NxVec3(1,0,0));
			else
				DrawWireCapsule(worldCapsule, NxVec3(0,1,0));
			break;
		case OVERLAP_SPHERE:
			gScene->overlapSphereShapes(worldSphere, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask);
			DrawWireSphere(&worldSphere, NxVec3(1,0,0));
			break;
		case OVERLAP_CHECK_SPHERE:
			if (gScene->checkOverlapSphere(worldSphere, type,activeGroups, groupsMask) == true)
				DrawWireSphere(&worldSphere, NxVec3(1,0,0));
			else
				DrawWireSphere(&worldSphere, NxVec3(0,1,0));
			break;
		case OVERLAP_CULL:
			gScene->cullShapes(nbPlanes, worldPlanes, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask);
			DrawLine(NxVec3(-20,0,2), NxVec3(-2,0,2),NxVec3(1,0,0), linewidth);
			DrawLine(NxVec3(-2,0,-20), NxVec3(-2,0,2),NxVec3(1,0,0), linewidth);
			break;
		}
	}
}
Esempio n. 13
0
// -----------------------------------------------------------------------
void MyCloth::draw(bool shadows)
{
	static NxU32 numVertices = mNumVertices;
	NxU32 numElements = mNumIndices;
	numVertices = mNumVertices;

	// Disable pressure if tearing occurs
	if (mTeared && (mCloth->getFlags() & NX_CLF_PRESSURE))
	{
		// Disable Pressure
		mCloth->setFlags(mCloth->getFlags() & ~NX_CLF_PRESSURE);
		mCloth->setPressure(0);

		// Reduce tearing factor
		NxReal oldTearing = mCloth->getTearFactor();
		oldTearing = (oldTearing - 1) / 3 + 1;
		mCloth->setTearFactor(oldTearing);

		// Reduce bending stiffness
		if (mCloth->getBendingStiffness() > 0.9f)
			mCloth->setBendingStiffness(0.2f);

		// Apply explosion in the middle of the cloth
		NxBounds3 bounds;
		mCloth->getWorldBounds(bounds);
		NxVec3 center;
		bounds.getCenter(center);
		NxReal radius = bounds.min.distance(bounds.max);
		mCloth->addForceAtPos(center, 7 * NxMath::pow(radius,3), radius, NX_IMPULSE);
		printf("Pressure disabled\n");
	}

	if (mTexId > 0)
	{
		updateTextureCoordinates();
	}

	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);

	glVertexPointer(3, GL_FLOAT, sizeof(RenderBufferVertexElement), numVertices, &(mVertexRenderBuffer[0].position.x));
	glNormalPointer(GL_FLOAT, sizeof(RenderBufferVertexElement), numVertices, &(mVertexRenderBuffer[0].normal.x));

	if (mTexId) {
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glTexCoordPointer(2, GL_FLOAT, sizeof(RenderBufferVertexElement), numVertices, &(mVertexRenderBuffer[0].texCoord[0]));

		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, mTexId);
		glColor4f(1.0f, 1.0f, 1.0f,1.0f);
	}

#ifdef __CELLOS_LV2__	
	glDrawRangeElements(GL_TRIANGLES, 0, numVertices-1, numElements, GL_UNSIGNED_INT, mIndexRenderBuffer);
#else
	glDrawElements(GL_TRIANGLES, numElements, GL_UNSIGNED_INT, mIndexRenderBuffer);
#endif

	if (mTexId) {
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glDisable(GL_TEXTURE_2D);
	}

	if (shadows) {
		const static float ShadowMat[]={ 1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1 };
		glPushMatrix();
		glMultMatrixf(ShadowMat);
		glDisable(GL_LIGHTING);
		glColor4f(0.05f, 0.1f, 0.15f,1.0f);

#ifdef __CELLOS_LV2__	
		glDrawRangeElements(GL_TRIANGLES, 0, numVertices-1, numElements, GL_UNSIGNED_INT, mIndexRenderBuffer);
#else
		glDrawElements(GL_TRIANGLES, numElements, GL_UNSIGNED_INT, mIndexRenderBuffer);
#endif
		
		glColor4f(1.0f, 1.0f, 1.0f,1.0f);
		glEnable(GL_LIGHTING);
		glPopMatrix();
	}

	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_NORMAL_ARRAY);
}
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();

}
Esempio n. 15
0
// to attach to tetra mesh
void TetraMeshHelper::buildTetraLinks(const NxSoftBodyMeshDesc& desc)
{
	const NxVec3 *vertices = (const NxVec3 *) desc.vertices;
	const void *tetIndices = desc.tetrahedra;
	bool is32Bits = !(desc.flags & NX_SOFTBODY_MESH_16_BIT_INDICES);
	const NxU32 numTets = desc.numTetrahedra;

	mTetraLinks.clear();

	MeshHash* hash = new MeshHash();

	// hash tetrahedra for faster search
	hash->setGridSpacing(mBounds.min.distance(mBounds.max) * 0.1f);

	NxU8* startIndex = (NxU8*) tetIndices;
	if(is32Bits)
	{
		for (NxU32 i = 0; i < numTets; i++) {
			const NxU32 *ix = ((NxU32*) startIndex) + 4*i;
			NxBounds3 tetraBounds;
			tetraBounds.setEmpty();
			tetraBounds.include(vertices[*ix++]);
			tetraBounds.include(vertices[*ix++]);
			tetraBounds.include(vertices[*ix++]);
			tetraBounds.include(vertices[*ix++]);
			hash->add(tetraBounds, i);
		}
		for (NxU32 i = 0; i < maxMesh.numVerts; i++) 
		{
			MeshTetraLink tmpLink;

			NxVec3 triVert(maxMesh.verts[i].x, maxMesh.verts[i].y, maxMesh.verts[i].z);
			std::vector<int> itemIndices;
			hash->queryUnique(triVert, itemIndices);

			NxReal minDist = 0.0f;
			NxVec3 b;
			int num, isize;
			num = isize = itemIndices.size();
			if (num == 0) num = numTets;

			for (int i = 0; i < num; i++) {
				int j = i;
				if (isize > 0) j = itemIndices[i];

				const NxU32 *ix = ((NxU32*) startIndex) + 4*j;
				const NxVec3 &p0 = vertices[*ix++];
				const NxVec3 &p1 = vertices[*ix++];
				const NxVec3 &p2 = vertices[*ix++];
				const NxVec3 &p3 = vertices[*ix++];

				NxVec3 b = computeBaryCoords(triVert, p0, p1, p2, p3);

				// is the vertex inside the tetrahedron? If yes we take it
				if (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f && (b.x + b.y + b.z) <= 1.0f) {
					tmpLink.barycentricCoords = b;
					tmpLink.tetraNr = j;
					break;
				}

				// otherwise, if we are not in any tetrahedron we take the closest one
				NxReal dist = 0.0f;
				if (b.x + b.y + b.z > 1.0f) dist = b.x + b.y + b.z - 1.0f;
				if (b.x < 0.0f) dist = (-b.x < dist) ? dist : -b.x;
				if (b.y < 0.0f) dist = (-b.y < dist) ? dist : -b.y;
				if (b.z < 0.0f) dist = (-b.z < dist) ? dist : -b.z;

				if (i == 0 || dist < minDist) {
					minDist = dist;
					tmpLink.barycentricCoords = b;
					tmpLink.tetraNr = j;
				}
			}

			mTetraLinks.push_back(tmpLink);
		}
	}
	else
	{
		for (NxU32 i = 0; i < numTets; i++) {
			const NxU16 *ix = ((NxU16*) startIndex) + 4*i;
			NxBounds3 tetraBounds;
			tetraBounds.setEmpty();
			tetraBounds.include(vertices[*ix++]);
			tetraBounds.include(vertices[*ix++]);
			tetraBounds.include(vertices[*ix++]);
			tetraBounds.include(vertices[*ix++]);
			hash->add(tetraBounds, i);
		}
		for (NxU32 i = 0; i < maxMesh.numVerts; i++) 
		{
			MeshTetraLink tmpLink;

			NxVec3 triVert(maxMesh.verts[i].x, maxMesh.verts[i].y, maxMesh.verts[i].z);
			std::vector<int> itemIndices;
			hash->queryUnique(triVert, itemIndices);

			NxReal minDist = 0.0f;
			NxVec3 b;
			int num, isize;
			num = isize = itemIndices.size();
			if (num == 0) num = numTets;

			for (int i = 0; i < num; i++) {
				int j = i;
				if (isize > 0) j = itemIndices[i];

				const NxU16 *ix = ((NxU16*) startIndex) + 4*j;
				const NxVec3 &p0 = vertices[*ix++];
				const NxVec3 &p1 = vertices[*ix++];
				const NxVec3 &p2 = vertices[*ix++];
				const NxVec3 &p3 = vertices[*ix++];

				NxVec3 b = computeBaryCoords(triVert, p0, p1, p2, p3);

				// is the vertex inside the tetrahedron? If yes we take it
				if (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f && (b.x + b.y + b.z) <= 1.0f) {
					tmpLink.barycentricCoords = b;
					tmpLink.tetraNr = j;
					break;
				}

				// otherwise, if we are not in any tetrahedron we take the closest one
				NxReal dist = 0.0f;
				if (b.x + b.y + b.z > 1.0f) dist = b.x + b.y + b.z - 1.0f;
				if (b.x < 0.0f) dist = (-b.x < dist) ? dist : -b.x;
				if (b.y < 0.0f) dist = (-b.y < dist) ? dist : -b.y;
				if (b.z < 0.0f) dist = (-b.z < dist) ? dist : -b.z;

				if (i == 0 || dist < minDist) {
					minDist = dist;
					tmpLink.barycentricCoords = b;
					tmpLink.tetraNr = j;
				}
			}

			mTetraLinks.push_back(tmpLink);
		}
	}

	delete hash;
}
bool UpdateCharacterExtents(NxU32 index, bool& increase)
{
	if(index&1)
	{
		NxBoxController* c = static_cast<NxBoxController*>(gManager->getController(index));
		NxVec3 extents = c->getExtents();
		NxF32 inc = 1.0f;
		NxExtendedVec3 pos = GetCharacterPos(index);
		if (increase)
		{
			extents.y += inc;
			pos.y += inc;
		} 
		else 
		{ 
			extents.y -= inc;
			pos.y -= inc;
		}

		if(1)
		{
			NxBounds3 worldBounds;
			worldBounds.setCenterExtents(NxVec3(pos.x, pos.y, pos.z), extents);
			c->setCollision(false);	// Avoid checking overlap with ourself
			bool Status = gScene->checkOverlapAABB(worldBounds);
			c->setCollision(true);
			if(Status)
			{
				printf("Can not resize box!\n");
				return false;
			}
		}

		increase = !increase;	// Increase or decrease height each time we're called

		// WARNING: the SDK currently doesn't check for collisions when changing extents, so if you're close
		// to a wall you might end up penetrating it. In some cases you might also fall through the level.
		// A more advanced implementation will take care of that later.
		c->setPosition(pos);
		return c->setExtents(extents);
	}
	else
	{
		NxCapsuleController* c = static_cast<NxCapsuleController*>(gManager->getController(index));
		NxF32 height = c->getHeight();
		NxF32 radius = c->getRadius();
		NxF32 inc = 1.0f;
		NxExtendedVec3 pos = GetCharacterPos(index);
		if (increase)
		{
			height += inc;
			pos.y += inc*0.5f;
		} 
		else 
		{ 
			height -= inc;
			pos.y -= inc*0.5f;
		}

		if(1)
		{
			NxCapsule worldCapsule;
			worldCapsule.p0.x = worldCapsule.p1.x = pos.x;
			worldCapsule.p0.y = worldCapsule.p1.y = pos.y;
			worldCapsule.p0.z = worldCapsule.p1.z = pos.z;
			worldCapsule.p0.y -= height*0.5f;
			worldCapsule.p1.y += height*0.5f;
			worldCapsule.radius = radius;
			c->setCollision(false);	// Avoid checking overlap with ourself
			bool Status = gScene->checkOverlapCapsule(worldCapsule);
			c->setCollision(true);
			if(Status)
			{
				printf("Can not resize capsule!\n");
				return false;
			}
		}

		increase = !increase;	// Increase or decrease height each time we're called

		// WARNING: the SDK currently doesn't check for collisions when changing height, so if you're close
		// to a wall you might end up penetrating it. In some cases you might also fall through the level.
		// A more advanced implementation will take care of that later.
		c->setPosition(NxExtendedVec3(pos.x, pos.y, pos.z));
		return c->setHeight(height);
	}
}