예제 #1
0
void SampleParticles::Raygun::update(float dtime)
{
	if(!isEnabled())
		return;
	
	PX_ASSERT(mSample && mForceSmokeCapsule && mForceWaterCapsule && mRenderActor);

	// access properties from sample
	PxScene& scene = mSample->getActiveScene();
	PxVec3 position = mSample->getCamera().getPos();
	PxTransform cameraPose = mSample->getCamera().getViewMatrix();
	PxMat33 cameraBase(cameraPose.q);
	PxVec3 cameraForward = -cameraBase[2];
	PxVec3 cameraUp = -cameraBase[1];
	
	// perform raycast here and update impact point
	PxRaycastHit hit;
	mIsImpacting = scene.raycastSingle(cameraPose.p, cameraForward, 500.0f, PxSceneQueryFlags(0xffffffff), hit);
	float impactParam = mIsImpacting ? (hit.impact - position).magnitude() : FLT_MAX;	

	PxTransform rayPose(position + cameraUp * 0.5f, cameraPose.q*PxQuat(PxHalfPi, PxVec3(0,1,0)));

	updateRayCapsule(mForceSmokeCapsule, rayPose, 1.0f);
	updateRayCapsule(mForceWaterCapsule, rayPose, 0.3f);
	mRenderActor->setTransform(rayPose);

	// if we had an impact
	if (impactParam < FLT_MAX)
	{
		PxVec3 impactPos = position + cameraForward*impactParam;
		// update emitter with new impact point and direction
		if(mSmokeEmitter.emitter)
			mSmokeEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));
		if(mDebrisEmitter.emitter)
			mDebrisEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));

		// spawn new RB debris
		if(mRbDebrisTimer < 0.0f && impactParam < FLT_MAX) 
		{
			mRbDebrisTimer = RAYGUN_RB_DEBRIS_RATE;

			PxVec3 randDir(getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f));
			PxVec3 vel = -7.0f * (cameraForward + RAYGUN_RB_DEBRIS_ANGLE_RANDOMNESS * randDir.getNormalized());
			PxVec3 dim(getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE));
			// give spawn position, initial velocity and dimensions, spawn convex
			// which will not act in scene queries
			PxConvexMesh* convexMesh = generateConvex(mSample->getPhysics(), mSample->getCooking(), RAYGUN_RB_DEBRIS_SCALE);
			mSample->runtimeAssert(convexMesh, "Error generating convex for debris.\n");
			PxRigidDynamic* debrisActor = PxCreateDynamic(
				mSample->getPhysics(), 
				PxTransform(impactPos - cameraForward * 0.5f), 
				PxConvexMeshGeometry(convexMesh), 
				mSample->getDefaultMaterial(), 1.f);  
			mSample->getActiveScene().addActor(*debrisActor);

			PX_ASSERT(debrisActor->getNbShapes() == 1);
			PxShape* debrisShape;
			debrisActor->getShapes(&debrisShape, 1);
			debrisShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
			debrisActor->setLinearVelocity(vel);
			debrisActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
			debrisActor->setAngularDamping(0.5f);
			
			// default material is green for debris
			RenderMaterial* debriMaterial = mSample->getMaterial(MATERIAL_HEIGHTFIELD);
			if(!debriMaterial) 
			{
				debriMaterial = mSample->mRenderMaterials[MATERIAL_GREEN];				
			}
			mSample->createRenderObjectsFromActor(debrisActor, debriMaterial);
			mDebrisLifetime[debrisShape] = RAYGUN_RB_DEBRIS_LIFETIME;
		}
	}

	// update debris lifetime, remove if life ends
	DebrisLifetimeMap::iterator it = mDebrisLifetime.begin();
	while(it != mDebrisLifetime.end()) 
	{
		(*it).second -= dtime;
		if((*it).second < 0.0f) 
		{
			PxShape* debrisShape = (*it).first;
			PX_ASSERT(debrisShape);

			// remove convex mesh
			PxConvexMeshGeometry geometry;
			bool isConvex = debrisShape->getConvexMeshGeometry(geometry);
			PX_ASSERT(isConvex);
			PX_UNUSED(isConvex);
			geometry.convexMesh->release();
			
			// remove render and physics actor
			PxRigidActor& actorToRemove = debrisShape->getActor();
			mSample->removeActor(&actorToRemove);			
			actorToRemove.release();
			
			// remove actor from lifetime map
			mDebrisLifetime.erase(it);
			it = mDebrisLifetime.begin();
			continue;
		}
		++it;
	}
}
예제 #2
0
osg::Node* createNodeForActor( PxRigidActor* actor )
{
    if ( !actor ) return NULL;
    std::vector<PxShape*> shapes( actor->getNbShapes() );
    
    osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
    transform->setMatrix( toMatrix(PxMat44(actor->getGlobalPose())) );
    
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    transform->addChild( geode.get() );
    
    PxU32 num = actor->getShapes( &(shapes[0]), actor->getNbShapes() );
    for ( PxU32 i=0; i<num; ++i )
    {
        PxShape* shape = shapes[i];
        osg::Matrix localMatrix = toMatrix( PxMat44(actor->getGlobalPose()) );
        osg::Vec3 localPos = toVec3( shape->getLocalPose().p );
        osg::Quat localQuat(shape->getLocalPose().q.x, shape->getLocalPose().q.y,
                            shape->getLocalPose().q.z, shape->getLocalPose().q.w);
        
        switch ( shape->getGeometryType() )
        {
        case PxGeometryType::eSPHERE:
            {
                PxSphereGeometry sphere;
                shape->getSphereGeometry( sphere );
                
                osg::Sphere* sphereShape = new osg::Sphere(localPos, sphere.radius);
                geode->addDrawable( new osg::ShapeDrawable(sphereShape) );
            }
            break;
        case PxGeometryType::ePLANE:
            // TODO
            break;
        case PxGeometryType::eCAPSULE:
            {
                PxCapsuleGeometry capsule;
                shape->getCapsuleGeometry( capsule );
                
                osg::Capsule* capsuleShape = new osg::Capsule(
                    localPos, capsule.radius, capsule.halfHeight * 2.0f);
                capsuleShape->setRotation( localQuat );
                geode->addDrawable( new osg::ShapeDrawable(capsuleShape) );
            }
            break;
        case PxGeometryType::eBOX:
            {
                PxBoxGeometry box;
                shape->getBoxGeometry( box );
                
                osg::Box* boxShape = new osg::Box(localPos,
                    box.halfExtents[0] * 2.0f, box.halfExtents[1] * 2.0f, box.halfExtents[2] * 2.0f);
                boxShape->setRotation( localQuat );
                geode->addDrawable( new osg::ShapeDrawable(boxShape) );
            }
            break;
        case PxGeometryType::eCONVEXMESH:
            {
                PxConvexMeshGeometry convexMeshGeom;
                shape->getConvexMeshGeometry( convexMeshGeom );
                // TODO: consider convexMeshGeom.scale
                
                PxConvexMesh* convexMesh = convexMeshGeom.convexMesh;
                if ( convexMesh )
                {
                    /*for ( unsigned int i=0; i<convexMesh->getNbPolygons(); ++i )
                    {
                        
                    }*/
                    // TODO
                }
            }
            break;
        case PxGeometryType::eTRIANGLEMESH:
            {
                PxTriangleMeshGeometry triangleMeshGeom;
                shape->getTriangleMeshGeometry( triangleMeshGeom );
                // TODO: consider triangleMeshGeom.scale
                
                PxTriangleMesh* triangleMesh = triangleMeshGeom.triangleMesh;
                if ( triangleMesh )
                {
                    osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array( triangleMesh->getNbVertices() );
                    for ( unsigned int i=0; i<va->size(); ++i )
                        (*va)[i] = toVec3( *(triangleMesh->getVertices() + i) ) * localMatrix;
                    
                    osg::ref_ptr<osg::DrawElements> de;
                    if ( triangleMesh->getTriangleMeshFlags()&PxTriangleMeshFlag::eHAS_16BIT_TRIANGLE_INDICES )
                    {
                        osg::DrawElementsUShort* de16 = new osg::DrawElementsUShort(GL_TRIANGLES);
                        de = de16;
                        
                        const PxU16* indices = (const PxU16*)triangleMesh->getTriangles();
                        for ( unsigned int i=0; i<triangleMesh->getNbTriangles(); ++i )
                        {
                            de16->push_back( indices[3 * i + 0] );
                            de16->push_back( indices[3 * i + 1] );
                            de16->push_back( indices[3 * i + 2] );
                        }
                    }
                    else
                    {
                        osg::DrawElementsUInt* de32 = new osg::DrawElementsUInt(GL_TRIANGLES);
                        de = de32;
                        
                        const PxU32* indices = (const PxU32*)triangleMesh->getTriangles();
                        for ( unsigned int i=0; i<triangleMesh->getNbTriangles(); ++i )
                        {
                            de32->push_back( indices[3 * i + 0] );
                            de32->push_back( indices[3 * i + 1] );
                            de32->push_back( indices[3 * i + 2] );
                        }
                    }
                    geode->addDrawable( createGeometry(va.get(), NULL, NULL, de.get()) );
                }
            }
            break;
        case PxGeometryType::eHEIGHTFIELD:
            {
                PxHeightFieldGeometry hfGeom;
                shape->getHeightFieldGeometry( hfGeom );
                // TODO: consider hfGeom.*scale
                
                PxHeightField* heightField = hfGeom.heightField;
                if ( heightField )
                {
                    // TODO
                }
            }
            break;
        }
    }
    return transform.release();
}