void Gu::ConvexMesh::debugVisualize(Cm::RenderOutput& out, const PxTransform& pose, const PxMeshScale& scale)	const
{
	const PxU32 scolor = PxU32(PxDebugColor::eARGB_MAGENTA);

	const PxVec3* vertices = mHullData.getHullVertices();
	const PxU8* indexBuffer = mHullData.getVertexData8();
	const PxU32 nbPolygons = getNbPolygonsFast();

	const PxMat44 m44(PxMat33(pose.q) * scale.toMat33(), pose.p);

	out << m44 << scolor;	// PT: no need to output this for each segment!

	for (PxU32 i = 0; i < nbPolygons; i++)
	{
		const PxU32 pnbVertices = mHullData.mPolygons[i].mNbVerts;

		PxVec3 begin = m44.transform(vertices[indexBuffer[0]]);	// PT: transform it only once before the loop starts
		for (PxU32 j = 1; j < pnbVertices; j++)
		{
			PxVec3 end = m44.transform(vertices[indexBuffer[j]]);
			out.outputSegment(begin, end);
			begin = end;
		}
		out.outputSegment(begin, m44.transform(vertices[indexBuffer[0]]));

		indexBuffer += pnbVertices;
	}
}
Esempio n. 2
0
mat4
getMatFromPhysXTransform(PxTransform transform) {
    PxMat44 mat = PxMat44(transform);
    float m[16];
    for (int i = 0; i < 16; ++i) m[i] = *(mat.front() + i);
    return mat4(m);
}
PxVec3 EmitterGeomSphereShellImpl::randomPosInFullVolume(const PxMat44& pose, QDSRand& rand) const
{
	float hemisphere = 2.0f * *mHemisphere - 1.0f;

	bool moreThanHalf = true;

	if (*mHemisphere > 0.5f)
	{
		moreThanHalf = false;
	}

	// There are two cases here - 1-st for hemisphere cut above the center of the sphere
	// and 2-nd for hemisphere cut below the center of the sphere.
	// The reason for this is that in case very high hemisphere cut is set, so the area
	// of the actual emitter is very small in compare to the whole sphere emitter, it would take too
	// much time [on average] to generate suitable point using randomPointOnUnitSphere
	// function, so in this case it is more efficient to use another method.
	// in case we have at least half of the sphere shell present the randomPointOnUnitSphere should
	// be sufficient.
	PxVec3 pos;
	if(!moreThanHalf)
	{
		// 1-st case :
		// * generate random unit vector within a cone
		// * clamp to big radius
		const float sphereCapBaseHeight = -1.0f + 2 * (*mHemisphere);
		const float phi = rand.getScaled(0.0f, PxTwoPi);
		const float cos_theta = sphereCapBaseHeight;
		const float z = rand.getScaled(cos_theta, 1.0f);
		const float oneMinusZSquared = PxSqrt(1.0f - z * z);
		pos = PxVec3(oneMinusZSquared * PxCos(phi), z, oneMinusZSquared * PxSin(phi));
	}
	else
	{
		// 2-nd case :
		// * get random pos on unit sphere, until its height is above hemisphere cut
		do
		{
			pos = randomPointOnUnitSphere(rand);
		} while(pos.y < hemisphere);
	}

	// * add negative offset withing the thickness
	// * solve edge case [for the 1-st case] - regenerate offset from the previous step
	// in case point is below hemisphere cut	

	PxVec3 tmp;
	const float sphereCapBaseHeight = -(*mRadius + *mShellThickness) + 2 * (*mRadius + *mShellThickness) * (*mHemisphere);
	do
	{
		float thickness = rand.getScaled(0, *mShellThickness);
		tmp = pos * (*mRadius + *mShellThickness - thickness);
	} while(tmp.y < sphereCapBaseHeight);

	pos = tmp;
	pos += pose.getPosition();

	return pos;
}
Esempio n. 4
0
void RenderPhysX3Debug::addConvex(const PxConvexMeshGeometry& cg, const PxTransform& tr,  const RendererColor& color, PxU32 renderFlags)
{
	const PxConvexMesh& mesh = *cg.convexMesh;

	const PxMat33 rot = PxMat33(tr.q) * cg.scale.toMat33();

	// PT: you can't use PxTransform with a non-uniform scaling
	const PxMat44 globalPose(rot, tr.p);

	const PxU32 polygonCount = mesh.getNbPolygons();
	const PxU8* indexBuffer = mesh.getIndexBuffer();

	const PxU32 vertexCount = mesh.getNbVertices();
	const PxVec3* vertexBuffer = mesh.getVertices();

	if(renderFlags & RENDER_DEBUG_WIREFRAME)
	{
		for(PxU32 i=0; i<polygonCount; i++)
		{
			PxHullPolygon data;
			mesh.getPolygonData(i, data);

			const PxU32 vertexCount = data.mNbVerts;
			PxU32 i0 = indexBuffer[vertexCount-1];
			PxU32 i1 = *indexBuffer++;
			addLine(globalPose.transform(vertexBuffer[i0]), globalPose.transform(vertexBuffer[i1]), color);
			for(PxU32 j=1; j<vertexCount; j++)
			{
				i0 = indexBuffer[-1];
				i1 = *indexBuffer++;
				addLine(globalPose.transform(vertexBuffer[i0]), globalPose.transform(vertexBuffer[i1]), color);
			}
		}
	}

	if(renderFlags & RENDER_DEBUG_SOLID)
	{
		for(PxU32 i=0; i<polygonCount; i++)
		{
			PxHullPolygon data;
			mesh.getPolygonData(i, data);

			const PxU32 vertexCount = data.mNbVerts;

			const PxVec3& v0 = vertexBuffer[indexBuffer[0]];
			for(PxU32 j=0; j<vertexCount-2; j++)
			{
				const PxVec3& v1 = vertexBuffer[indexBuffer[j+1]];
				const PxVec3& v2 = vertexBuffer[indexBuffer[j+2]];

				addTriangle(globalPose.transform(v0), globalPose.transform(v1), globalPose.transform(v2), color);
			}
			indexBuffer += vertexCount;
		}
	}
}
bool EmitterGeomSphereShellImpl::isInEmitter(const PxVec3& pos, const PxMat44& pose) const
{
	PxVec3 localPos = pose.inverseRT().transform(pos);
	const float sphereCapBaseHeight = -(*mRadius + *mShellThickness) + 2 * (*mRadius + *mShellThickness) * (*mHemisphere);
	float d2 = localPos.x * localPos.x + localPos.y * localPos.y + localPos.z * localPos.z;
	bool isInBigSphere = d2 < (*mRadius + *mShellThickness) * (*mRadius + *mShellThickness);
	bool isInSmallSphere = d2 < *mRadius * *mRadius;
	bool higherThanHemisphereCut = pos.y > sphereCapBaseHeight;
	return isInBigSphere && !isInSmallSphere && higherThanHemisphereCut;
}
void EmitterGeomSphereShellImpl::drawPreview(float scale, RenderDebugInterface* renderDebug) const
{
	using RENDER_DEBUG::DebugColors;

	RENDER_DEBUG_IFACE(renderDebug)->pushRenderState();
	RENDER_DEBUG_IFACE(renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::Yellow),
	                             RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::Yellow));

	RENDER_DEBUG_IFACE(renderDebug)->debugSphere(PxVec3(0.0f), *mRadius * scale);

	RENDER_DEBUG_IFACE(renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::DarkGreen),
	                             RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::DarkGreen));

	RENDER_DEBUG_IFACE(renderDebug)->debugSphere(PxVec3(0.0f), (*mRadius + *mShellThickness) * scale);

	const float radius = *mRadius + *mShellThickness;
	const float radiusSquared = radius * radius;
	const float hemisphere = *mHemisphere;
	const float sphereCapBaseHeight = -radius + 2 * radius * hemisphere;
	const float sphereCapBaseRadius = PxSqrt(radiusSquared - sphereCapBaseHeight * sphereCapBaseHeight);
	if(hemisphere > 0.0f)
	{
		RENDER_DEBUG_IFACE(renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(renderDebug)->getDebugColor(DebugColors::DarkPurple));
		PxMat44 circlePose = PxMat44(PxIdentity);
		circlePose.setPosition(PxVec3(0.0f, sphereCapBaseHeight, 0.0f));
		RENDER_DEBUG_IFACE(renderDebug)->setPose(circlePose);
		RENDER_DEBUG_IFACE(renderDebug)->debugCircle(PxVec3(0.0f), sphereCapBaseRadius, 3);
		RENDER_DEBUG_IFACE(renderDebug)->debugLine(PxVec3(0.0f), PxVec3(0.0f, radius - sphereCapBaseHeight, 0.0f));
		for(float t = 0.0f; t < 2 * PxPi; t += PxPi / 3)
		{
			PxVec3 offset(PxSin(t) * sphereCapBaseRadius, 0.0f, PxCos(t) * sphereCapBaseRadius);
			RENDER_DEBUG_IFACE(renderDebug)->debugLine(offset, PxVec3(0.0f, radius - sphereCapBaseHeight, 0.0f));
		}
		RENDER_DEBUG_IFACE(renderDebug)->setPose(PxIdentity);
	}
	RENDER_DEBUG_IFACE(renderDebug)->popRenderState();
}
void EmitterGeomSphereShellImpl::visualize(const PxTransform& pose, RenderDebugInterface& renderDebug)
{
	using RENDER_DEBUG::DebugColors;
	RENDER_DEBUG_IFACE(&renderDebug)->pushRenderState();

	RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkGreen));

	// outer sphere
	RENDER_DEBUG_IFACE(&renderDebug)->setPose(pose);
	RENDER_DEBUG_IFACE(&renderDebug)->debugSphere(PxVec3(0.0f), *mRadius);

	// intter sphere
	RENDER_DEBUG_IFACE(&renderDebug)->debugSphere(PxVec3(0.0f), *mRadius + *mShellThickness);

	const float radius = *mRadius + *mShellThickness;
	const float radiusSquared = radius * radius;
	const float hemisphere = *mHemisphere;
	const float sphereCapBaseHeight = -radius + 2 * radius * hemisphere;
	const float sphereCapBaseRadius = PxSqrt(radiusSquared - sphereCapBaseHeight * sphereCapBaseHeight);
	// cone depicting the hemisphere
	if(hemisphere > 0.0f) 
	{
		RENDER_DEBUG_IFACE(&renderDebug)->setCurrentColor(RENDER_DEBUG_IFACE(&renderDebug)->getDebugColor(DebugColors::DarkPurple));
		PxMat44 circlePose = PxMat44(PxIdentity);
		circlePose.setPosition(PxVec3(0.0f, sphereCapBaseHeight, 0.0f));
		RENDER_DEBUG_IFACE(&renderDebug)->setPose(circlePose);
		RENDER_DEBUG_IFACE(&renderDebug)->debugCircle(PxVec3(0.0f), sphereCapBaseRadius, 3);
		RENDER_DEBUG_IFACE(&renderDebug)->debugLine(circlePose.getPosition(), circlePose.getPosition() + PxVec3(0.0f, radius - sphereCapBaseHeight, 0.0f));
		for(float t = 0.0f; t < 2 * PxPi; t += PxPi / 3)
		{
			PxVec3 offset(PxSin(t) * sphereCapBaseRadius, 0.0f, PxCos(t) * sphereCapBaseRadius);
			RENDER_DEBUG_IFACE(&renderDebug)->debugLine(circlePose.getPosition() + offset, circlePose.getPosition() + PxVec3(0.0f, radius - sphereCapBaseHeight, 0.0f));
		}
		RENDER_DEBUG_IFACE(&renderDebug)->setPose(PxIdentity);
	}

	RENDER_DEBUG_IFACE(&renderDebug)->popRenderState();
}
Esempio n. 8
0
void CTank::Update( float fDT )
{
	if( m_pActor )
	{							
		PxMat44 Matrix = physx::PxMat44( physx::PxMat33( m_pActor->getGlobalPose().q ), m_pActor->getGlobalPose().p );
		D3DXMATRIX dxmat;				
		memcpy( &dxmat._11, Matrix.front(), 4 * 4 * sizeof(float) );		

		if( GameObject* pBody = GetDetail( BODY ) )
			pBody->SetReleaseMatrix( dxmat, true );			

		if( true )
		{
			if( PxVehicleWheels* pDriveTank = CPhysX::GetPhysX()->GetTank() )
			{
				PxShape* carShapes[ MAX_DETAIL ];
				
				const PxU32 numShapes = m_pActor->getNbShapes();
				m_pActor->getShapes( carShapes, numShapes );
				for( PxU32 i = 0; i < numShapes - 1; ++i )
				{
					const PxTransform& Trans = carShapes[ i ]->getLocalPose();								
					
					PxMat44 MatrixR = physx::PxMat44(physx::PxMat33( Trans.q ), Trans.p );
					D3DXMATRIX dxmatR;
					memcpy( &dxmatR._11, MatrixR.front(), 4 * 4 * sizeof(float) );

					if( GameObject* pObj = GetDetail( (EDetailTank)i ) )
						pObj->SetReleaseMatrix( dxmatR * dxmat, true );
				}

				PxVehicleDriveTank&    vehDriveTank = static_cast< PxVehicleDriveTank& >( *pDriveTank );
				PxVehicleDriveDynData& driveDynData = vehDriveTank.mDriveDynData;

				PxReal e = driveDynData.getEngineRotationSpeed();
				m_fSpeedTank = pDriveTank->computeForwardSpeed();

				static char t[ 256 ] = {0};
				sprintf( t, "EngineRotationSpeed=%f, EngineRotationSpeed=%f", m_fSpeedTank, e );
				//SetWindowText( GetForegroundWindow(), t );
				
				PxVehicleDriveTankRawInputData  carRawInputs( PxVehicleDriveTank::eDRIVE_MODEL_STANDARD );

				carRawInputs.setDigitalAccel( m_bMoveForward || m_bMoveBack || m_bTurnLeft || m_bTurnRight );

				carRawInputs.setDigitalLeftBrake( m_bTurnLeft );						// левая  кнопка тормоза
				carRawInputs.setDigitalRightBrake( m_bTurnRight );						// правая кнопка тормоза
				
				carRawInputs.setDigitalLeftThrust( m_bMoveForward || !m_bTurnLeft );
				carRawInputs.setDigitalRightThrust( m_bMoveForward || !m_bTurnRight );

				if( !m_bMoveForward && !m_bMoveBack && !m_bTurnLeft && !m_bTurnRight )
				{
					carRawInputs.setDigitalLeftBrake( true );	// левая  кнопка тормоза
					carRawInputs.setDigitalRightBrake( true );	// правая кнопка тормоза
				}

				//carRawInputs.setGearUp( !m_bMoveForward && m_bMoveBack);
				//carRawInputs.setGearDown( !m_bMoveBack && m_bMoveForward );				

// 				if( m_bMoveBack )
// 				{
// 					carRawInputs.setDigitalLeftBrake( true );	// левая  кнопка тормоза
// 					carRawInputs.setDigitalRightBrake( true );	// правая кнопка тормоза
// 				}

				static PxVehicleKeySmoothingData KeySmoothingData =
				{
					{
						3.f,	//rise rate eANALOG_INPUT_ACCEL		
						3.f,	//rise rate eANALOG_INPUT_BRAKE		
						5.f,	//rise rate eANALOG_INPUT_HANDBRAKE	
						2.f,	//rise rate eANALOG_INPUT_STEER_LEFT	
						2.f,	//rise rate eANALOG_INPUT_STEER_RIGHT	
					},
					{
						5.f,	//fall rate eANALOG_INPUT__ACCEL		
						5.f,	//fall rate eANALOG_INPUT__BRAKE		
						10.f,	//fall rate eANALOG_INPUT__HANDBRAKE	
						5.f,	//fall rate eANALOG_INPUT_STEER_LEFT	
						5.f		//fall rate eANALOG_INPUT_STEER_RIGHT	
					}
				};

				PxVehicleDriveTankSmoothDigitalRawInputsAndSetAnalogInputs( KeySmoothingData, carRawInputs, fDT, vehDriveTank );			
			}
		}
	}

		if( GameObject* pTankTrack = GetDetail( TRACK_L ) )					
			pTankTrack->SetOffsetUV( D3DXVECTOR4( 0.f, m_fSpeedTank*3, 0.f, 0.f ) );

		if( GameObject* pTankTrack = GetDetail( TRACK_R ) )					
			pTankTrack->SetOffsetUV( D3DXVECTOR4( 0.f, m_fSpeedTank*3, 0.f, 0.f ) );

	for( std::map< EDetailTank, GameObject* >::iterator iter = m_ObjectsTank.begin(), iter_end = m_ObjectsTank.end(); iter != iter_end; ++iter )
	{
		GameObject* pObj = iter->second;
		pObj->Update( fDT );
	}
}
Esempio n. 9
0
osg::Matrix toMatrix( const PxMat44& pmatrix )
{
    double m[16];
    for ( int i=0; i<16; ++i ) m[i] = *(pmatrix.front() + i);
    return osg::Matrix(&m[0]);
}
static void outputConvexToStream(PxShape* convexShape, const PxRigidActor* actor, const PxTransform& absPose_, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray,
								 const PxExtendedVec3& origin, const PxBounds3& tmpBounds, const CCTParams& params, Cm::RenderBuffer* renderBuffer, PxU16& nbTessellation)
{
	PX_ASSERT(convexShape->getGeometryType() == PxGeometryType::eCONVEXMESH);
	PxConvexMeshGeometry cg;
	convexShape->getConvexMeshGeometry(cg);
	PX_ASSERT(cg.convexMesh);

	// Do AABB-mesh query

	PxU32* TF;

	// Collide AABB against current mesh
	// The overlap function doesn't exist for convexes so let's just dump all tris
	PxConvexMesh& cm = *cg.convexMesh;

	// PT: convex triangles are not exposed anymore so we need to access convex polygons & triangulate them

	// PT: TODO: this is copied from "DrawObjects", move this to a shared place. Actually a helper directly in PxConvexMesh would be useful.
	PxU32 Nb = 0;
	{
		const PxU32 nbPolys = cm.getNbPolygons();
		const PxU8* polygons = cm.getIndexBuffer();

		for(PxU32 i=0;i<nbPolys;i++)
		{
			PxHullPolygon data;
			cm.getPolygonData(i, data);
			Nb += data.mNbVerts - 2;
		}

		// PT: revisit this code. We don't use the polygon offset?
		TF = (PxU32*)PxAlloca(sizeof(PxU32)*Nb*3);
		PxU32* t = TF;
		for(PxU32 i=0;i<nbPolys;i++)
		{
			PxHullPolygon data;
			cm.getPolygonData(i, data);

			const PxU32 nbV = data.mNbVerts;

			const PxU32 nbTris = nbV - 2;
			const PxU8 vref0 = *polygons;
			for(PxU32 j=0;j<nbTris;j++)
			{
				const PxU32 vref1 = polygons[(j+1)%nbV];
				const PxU32 vref2 = polygons[(j+2)%nbV];
				*t++ = vref0;
				*t++ = vref1;
				*t++ = vref2;
			}
			polygons += nbV;
		}
	}

	// PT: you can't use PxTransform with a non-uniform scaling
	const PxMat33 rot = PxMat33(absPose_.q) * cg.scale.toMat33();
	const PxMat44 absPose(rot, absPose_.p);

	const PxVec3 p = absPose.getPosition();
	const PxVec3 MeshOffset(float(p.x - origin.x), float(p.y - origin.y), float(p.z - origin.z));	// LOSS OF ACCURACY

	const PxVec3 offset(float(-origin.x), float(-origin.y), float(-origin.z));

	TouchedMesh* touchedMesh			= (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32));
	touchedMesh->mType					= TouchedGeomType::eMESH;
	touchedMesh->mTGUserData			= convexShape;
	touchedMesh->mActor					= actor;
	touchedMesh->mOffset				= origin;
	touchedMesh->mIndexWorldTriangles	= worldTriangles.size();

	const PxVec3* verts = cm.getVertices();
	// Loop through touched triangles
	if(params.mTessellation)
	{
		const PxBoxGeometry boxGeom(tmpBounds.getExtents());
		const PxBounds3 cullingBox = PxBounds3::centerExtents(tmpBounds.getCenter() + offset, boxGeom.halfExtents);

		PxU32 nbCreatedTris = 0;
		while(Nb--)
		{
			// Compute triangle in world space, add to array
			PxTriangle currentTriangle;

			const PxU32 vref0 = *TF++;
			const PxU32 vref1 = *TF++;
			const PxU32 vref2 = *TF++;

			currentTriangle.verts[0] = MeshOffset + absPose.rotate(verts[vref0]);
			currentTriangle.verts[1] = MeshOffset + absPose.rotate(verts[vref1]);
			currentTriangle.verts[2] = MeshOffset + absPose.rotate(verts[vref2]);

			PxU32 nbNewTris = 0;
			tessellateTriangle(nbNewTris, currentTriangle, PX_INVALID_U32, worldTriangles, triIndicesArray, cullingBox, params, nbTessellation);
			nbCreatedTris += nbNewTris;
		}
		touchedMesh->mNbTris = nbCreatedTris;
	}
	else
	{
		// Reserve memory for incoming triangles
		PxTriangle* TouchedTriangles = reserve(worldTriangles, Nb);

		touchedMesh->mNbTris = Nb;
		while(Nb--)
		{
			// Compute triangle in world space, add to array
			PxTriangle& currentTriangle = *TouchedTriangles++;

			const PxU32 vref0 = *TF++;
			const PxU32 vref1 = *TF++;
			const PxU32 vref2 = *TF++;

			currentTriangle.verts[0] = MeshOffset + absPose.rotate(verts[vref0]);
			currentTriangle.verts[1] = MeshOffset + absPose.rotate(verts[vref1]);
			currentTriangle.verts[2] = MeshOffset + absPose.rotate(verts[vref2]);

			triIndicesArray.pushBack(PX_INVALID_U32);
		}
	}
	if(gVisualizeTouchedTris)
		visualizeTouchedTriangles(touchedMesh->mNbTris, touchedMesh->mIndexWorldTriangles, &worldTriangles[0], renderBuffer, offset, params.mUpDirection);
}