void create(NxScene& scene, const NxVec3& pos, float rad, NxActor* holder)
		{
			NxActorDesc actorDesc;
			NxBodyDesc bodyDesc;
			NxSphereShapeDesc sphereDesc;
			
			bodyDesc.solverIterationCount = 20;

			// wheel
			sphereDesc.radius = rad;
			sphereDesc.materialIndex = wheelMaterialIndex;
			actorDesc.shapes.pushBack(&sphereDesc);
			bodyDesc.mass = 400;
			actorDesc.body = &bodyDesc;
			actorDesc.globalPose.t = pos;
			wheel = scene.createActor(actorDesc);

			// roll axis
			bodyDesc.mass = 50;
			bodyDesc.massSpaceInertia = NxVec3(1,1,1);
			actorDesc.body = &bodyDesc;
			actorDesc.shapes.clear();
			actorDesc.globalPose.t  = pos;
			rollAxis = scene.createActor(actorDesc);
			
			// revolute joint connecting wheel with rollAxis
			NxRevoluteJointDesc revJointDesc;
			revJointDesc.projectionMode = NX_JPM_POINT_MINDIST;
			revJointDesc.actor[0] = wheel;
			revJointDesc.actor[1] = rollAxis;
			revJointDesc.setGlobalAnchor(pos);
			revJointDesc.setGlobalAxis(NxVec3(0,0,1));
			rollJoint = (NxRevoluteJoint*)scene.createJoint(revJointDesc);

			// prismatic joint connecting rollAxis with holder
			NxPrismaticJointDesc prisJointDesc;
			prisJointDesc.actor[0] = rollAxis;
			prisJointDesc.actor[1] = holder;
			prisJointDesc.setGlobalAnchor(pos);
			prisJointDesc.setGlobalAxis(NxVec3(0,1,0));
			scene.createJoint(prisJointDesc);

			// add springs and dampers to the suspension (i.e. the related actors)
			float springLength = 0.1f;
			NxSpringAndDamperEffector * springNdamp = scene.createSpringAndDamperEffector(NxSpringAndDamperEffectorDesc());

			springNdamp->setBodies(rollAxis, pos, holder, pos + NxVec3(0,springLength,0));
			springNdamp->setLinearSpring(0, springLength, 2*springLength, 100000, 100000);
			springNdamp->setLinearDamper(-1, 1, 1e5, 1e5);

			// disable collision detection 
			scene.setActorPairFlags(*wheel, *holder, NX_IGNORE_PAIR);
		}
Exemple #2
0
BoxActor::BoxActor(NxScene &scene, const VC3 &sizes, const VC3 &position, const VC3 &localPosition, bool ccd, float ccdMaxThickness)
{
	NxBodyDesc bodyDesc;
	//bodyDesc.solverIterationCount = 2;

	NxBoxShapeDesc boxDesc;
	boxDesc.dimensions = NxVec3(sizes.x, sizes.y, sizes.z);
	boxDesc.localPose.t.set(NxVec3(localPosition.x, localPosition.y + sizes.y, localPosition.z));

	// CCD, but for thin objects only... --jpk
	if (ccd && (sizes.x*2 < ccdMaxThickness || sizes.y*2 < ccdMaxThickness || sizes.z*2 < ccdMaxThickness))
	{
		VC3 ccdSizes = sizes * 0.6f;
		boxDesc.ccdSkeleton = CreateCCDSkeleton(ccdSizes);
		boxDesc.shapeFlags |= NX_SF_DYNAMIC_DYNAMIC_CCD;

		// also, in this case, a minimal skin width too.
		boxDesc.skinWidth = 0.002f;
	}

	NxActorDesc actorDesc;
	actorDesc.body = &bodyDesc;
	actorDesc.density = 10.f;
	actorDesc.shapes.pushBack(&boxDesc);
	actorDesc.globalPose.t.set(NxVec3(position.x, position.y, position.z));

	// !!!!!!!!!!!!!!
	//actorDesc.managedHwSceneIndex = 1;

	actor = scene.createActor(actorDesc);

	this->scene = &scene;
	init();
}
CarActor::CarActor(NxScene &scene, const VC3 &position)
{
	NxBoxShapeDesc boxDesc1;
	//boxDesc1.dimensions = NxVec3(2.65f, 0.55f, 1.05f);
	boxDesc1.dimensions = NxVec3(1.05f, 0.55f, 2.65f);
	boxDesc1.localPose.t.set(NxVec3(0, boxDesc1.dimensions.y, 0));

	NxBoxShapeDesc boxDesc2;
	//boxDesc2.dimensions = NxVec3(1.30f, 0.77f - boxDesc1.dimensions.y, 0.84f);
	boxDesc2.dimensions = NxVec3(0.84f, 0.77f - boxDesc1.dimensions.y, 1.30f);
	boxDesc2.localPose.t.set(NxVec3(0, (boxDesc1.dimensions.y * 2.f) + boxDesc2.dimensions.y, 0));

	NxBodyDesc bodyDesc;
	NxActorDesc actorDesc;
	actorDesc.body = &bodyDesc;
	actorDesc.density = 10.f;
	actorDesc.shapes.pushBack(&boxDesc1);
	actorDesc.shapes.pushBack(&boxDesc2);
	actorDesc.globalPose.t.set(NxVec3(position.x, position.y, position.z));

	actor = scene.createActor(actorDesc);

	this->scene = &scene;
	init();
}
		void create(NxScene& scene, const NxVec3& pos, float rad, NxActor* holder)
		{
			NxActorDesc actorDesc;
			NxBodyDesc bodyDesc;

			bodyDesc.solverIterationCount = 20;

			// steer axis
			bodyDesc.mass = 50;
			bodyDesc.massSpaceInertia = NxVec3(1,1,1);
			actorDesc.body = &bodyDesc;
			actorDesc.shapes.clear();

			actorDesc.globalPose.t = pos;
			steerAxis = scene.createActor(actorDesc);
			wheel.create(scene, pos, rad, steerAxis);

			// revolute joint connecting steerAxis with the holder
			NxRevoluteJointDesc revJointDesc;
			revJointDesc.projectionMode = NX_JPM_POINT_MINDIST;
			revJointDesc.actor[0] = steerAxis;
			revJointDesc.actor[1] = holder;
			revJointDesc.setGlobalAnchor(pos);
			revJointDesc.setGlobalAxis(NxVec3(0,1,0));
			steerJoint = (NxRevoluteJoint*)scene.createJoint(revJointDesc);

			// disable collision detection 
			scene.setActorPairFlags(*wheel.wheel, *holder, NX_IGNORE_PAIR);
		}
Exemple #5
0
/**
*  @brief
*    Constructor
*/
BodySphere::BodySphere(PLPhysics::World &cWorld, float fRadius, bool bStatic) :
	PLPhysics::BodySphere(cWorld, ((World&)cWorld).CreateBodyImpl(), fRadius)
{
	// Get the PhysX physics scene
	NxScene *pPhysXScene = ((World&)cWorld).GetPhysXScene();
	if (pPhysXScene) {
		// Create body
		NxBodyDesc BodyDesc;
		BodyDesc.angularDamping = 0.5f;
		// [TODO] Do we need this setting?
	//	BodyDesc.maxAngularVelocity = 10.0f;

		NxSphereShapeDesc SphereDesc;
		SphereDesc.radius = m_fRadius;

		NxActorDesc ActorDesc;
		ActorDesc.shapes.pushBack(&SphereDesc);
		if (!bStatic)
			ActorDesc.body = &BodyDesc;
		ActorDesc.density = 10.0f;
		// [TODO] Do we need this setting?
	//	ActorDesc.globalPose.t  = pos;
		NxActor *pPhysXActor = pPhysXScene->createActor(ActorDesc);

		// Initialize the PhysX physics actor
		((BodyImpl&)GetBodyImpl()).InitializePhysXActor(*this, *pPhysXActor);
	}
}
	void create(NxScene& scene )
	{
		NxBodyDesc bodyDesc;	
		NxBoxShapeDesc boxDesc0;
		NxBoxShapeDesc boxDesc1;

		bodyDesc.solverIterationCount = 20;
		
		// tractor actor (two shapes)
		NxActorDesc tractorDesc;
		bodyDesc.mass = 5000;
		tractorDesc.body = &bodyDesc;
		tractorDesc.globalPose.t = NxVec3(0,0,0);

		boxDesc0.dimensions = NxVec3(3.5,3,4);
		boxDesc0.localPose.t = NxVec3(3.5,4,0);
		tractorDesc.shapes.pushBack(&boxDesc0);
		
	

		//boxDesc1.dimensions = NxVec3(8.5,0.7,3);
		//boxDesc1.localPose.t = NxVec3(8.7,1.3,0);
		//tractorDesc.shapes.pushBack(&boxDesc1);

		tractor = scene.createActor(tractorDesc);

		//sPhysObject* pPhys = new sPhysObject;
		//pPhys->iID      = 5;
		//tractor->userData = ( void* )pPhys;

		// remove collision between lower truck parts and ground
		//scene.setShapePairFlags(*tractor->getShapes()[1], *ground.getShapes()[0], NX_IGNORE_PAIR);
		//scene.setShapePairFlags(*trailer->getShapes()[1], *ground.getShapes()[0], NX_IGNORE_PAIR);

		// wheels
		float staticFriction  = 1.2f;
		float dynamicFriction = 1.0f;

		steerWheels[0].create(scene, NxVec3(3.5,1.5,4), 1.5, tractor);
		steerWheels[1].create(scene, NxVec3(3.5,1.5,-4), 1.5, tractor);
		frontWheels[0].create(scene, NxVec3(16,1.5,4), 1.5, tractor);
		frontWheels[1].create(scene, NxVec3(16,1.5,-4), 1.5, tractor);
	}
bool plPXPhysical::Init(PhysRecipe& recipe)
{
    bool    startAsleep = false;
    fBoundsType = recipe.bounds;
    fGroup = recipe.group;
    fReportsOn = recipe.reportsOn;
    fObjectKey = recipe.objectKey;
    fSceneNode = recipe.sceneNode;
    fWorldKey = recipe.worldKey;

    NxActorDesc actorDesc;
    NxSphereShapeDesc sphereDesc;
    NxConvexShapeDesc convexShapeDesc;
    NxTriangleMeshShapeDesc trimeshShapeDesc;
    NxBoxShapeDesc boxDesc;

    plPXConvert::Matrix(recipe.l2s, actorDesc.globalPose);

    switch (fBoundsType)
    {
    case plSimDefs::kSphereBounds:
        {
            hsMatrix44 sphereL2W;
            sphereL2W.Reset();
            sphereL2W.SetTranslate(&recipe.offset);

            sphereDesc.radius = recipe.radius;
            plPXConvert::Matrix(sphereL2W, sphereDesc.localPose);
            sphereDesc.group = fGroup;
            actorDesc.shapes.pushBack(&sphereDesc);
        }
        break;
    case plSimDefs::kHullBounds:
        // FIXME PHYSX - Remove when hull detection is fixed
        // If this is read time (ie, meshStream is nil), turn the convex hull
        // into a box.  That way the data won't have to change when convex hulls
        // actually work right.
        if (fGroup == plSimDefs::kGroupDetector && recipe.meshStream == nil)
        {
#ifdef USE_BOXES_FOR_DETECTOR_HULLS
            MakeBoxFromHull(recipe.convexMesh, boxDesc);
            plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*recipe.convexMesh);
            boxDesc.group = fGroup;
            actorDesc.shapes.push_back(&boxDesc);
#else
#ifdef USE_PHYSX_CONVEXHULL_WORKAROUND
            // make a hull of planes for testing IsInside
            IMakeHull(recipe.convexMesh,recipe.l2s);
#endif  // USE_PHYSX_CONVEXHULL_WORKAROUND
            convexShapeDesc.meshData = recipe.convexMesh;
            convexShapeDesc.userData = recipe.meshStream;
            convexShapeDesc.group = fGroup;
            actorDesc.shapes.pushBack(&convexShapeDesc);
#endif // USE_BOXES_FOR_DETECTOR_HULLS
        }
        else
        {
            convexShapeDesc.meshData = recipe.convexMesh;
            convexShapeDesc.userData = recipe.meshStream;
            convexShapeDesc.group = fGroup;
            actorDesc.shapes.pushBack(&convexShapeDesc);
        }
        break;
    case plSimDefs::kBoxBounds:
        {
            boxDesc.dimensions = plPXConvert::Point(recipe.bDimensions);

            hsMatrix44 boxL2W;
            boxL2W.Reset();
            boxL2W.SetTranslate(&recipe.bOffset);
            plPXConvert::Matrix(boxL2W, boxDesc.localPose);

            boxDesc.group = fGroup;
            actorDesc.shapes.push_back(&boxDesc);
        }
        break;
    case plSimDefs::kExplicitBounds:
    case plSimDefs::kProxyBounds:
        if (fGroup == plSimDefs::kGroupDetector)
        {
            SimLog("Someone using an Exact on a detector region: %s", GetKeyName().c_str());
        }
        trimeshShapeDesc.meshData = recipe.triMesh;
        trimeshShapeDesc.userData = recipe.meshStream;
        trimeshShapeDesc.group = fGroup;
        actorDesc.shapes.pushBack(&trimeshShapeDesc);
        break;
    default:
        hsAssert(false, "Unknown geometry type during read.");
        return false;
        break;
    }

    //  Now fill out the body, or dynamic part of the physical
    NxBodyDesc bodyDesc;
    fMass = recipe.mass;
    if (recipe.mass != 0)
    {
        bodyDesc.mass = recipe.mass;
        actorDesc.body = &bodyDesc;

        if (GetProperty(plSimulationInterface::kPinned))
        {
            bodyDesc.flags |= NX_BF_FROZEN;
            startAsleep = true;             // put it to sleep if they are going to be frozen
        }

        if (fGroup != plSimDefs::kGroupDynamic || GetProperty(plSimulationInterface::kPhysAnim))
        {
            SetProperty(plSimulationInterface::kPassive, true);

            // Even though the code for animated physicals and animated activators are the same
            // keep these code snippets separated for fine tuning. Thanks.
            if (fGroup == plSimDefs::kGroupDynamic)
            {
                // handle the animated physicals.... make kinematic for now.
                fNumberAnimatedPhysicals++;
                bodyDesc.flags |= NX_BF_KINEMATIC;
                startAsleep = true;
            }
            else
            {
                // handle the animated activators.... 
                fNumberAnimatedActivators++;
                bodyDesc.flags |= NX_BF_KINEMATIC;
                startAsleep = true;
            }

        }
    }
    else
    {
        if ( GetProperty(plSimulationInterface::kPhysAnim) )
            SimLog("An animated physical that has no mass: %s", GetKeyName().c_str());
    }

    actorDesc.userData = this;
    actorDesc.name = GetKeyName().c_str();

    // Put the dynamics into actor group 1.  The actor groups are only used for
    // deciding who we get contact reports for.
    if (fGroup == plSimDefs::kGroupDynamic)
        actorDesc.group = 1;

    NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
    try
    {
        fActor = scene->createActor(actorDesc);
    } catch (...)
    {
        hsAssert(false, "Actor creation crashed");
        return false;
    }
    hsAssert(fActor, "Actor creation failed");
    if (!fActor)
        return false;

    NxShape* shape = fActor->getShapes()[0];
    shape->setMaterial(plSimulationMgr::GetInstance()->GetMaterialIdx(scene, recipe.friction, recipe.restitution));

    // Turn on the trigger flags for any detectors.
    //
    // Normally, we'd set these flags on the shape before it's created.  However,
    // in the case where the detector is going to be animated, it'll have a rigid
    // body too, and that will cause problems at creation.  According to Ageia,
    // a detector shape doesn't actually count as a shape, so the SDK will have
    // problems trying to calculate an intertial tensor.  By letting it be
    // created as a normal dynamic first, then setting the flags, we work around
    // that problem.
    if (fGroup == plSimDefs::kGroupDetector)
    {
        shape->setFlag(NX_TRIGGER_ON_ENTER, true);
        shape->setFlag(NX_TRIGGER_ON_LEAVE, true);
    }

    if (GetProperty(plSimulationInterface::kStartInactive) || startAsleep)
    {
        if (!fActor->isSleeping())
        {
            if (plSimulationMgr::fExtraProfile)
                SimLog("Deactivating %s in SetPositionAndRotationSim", GetKeyName().c_str());
            fActor->putToSleep();
        }
    }

    if (GetProperty(plSimulationInterface::kDisable))
        IEnable(false);
    if (GetProperty(plSimulationInterface::kSuppressed_DEAD))
        IEnable(false);

    plNodeRefMsg* refMsg = new plNodeRefMsg(fSceneNode, plRefMsg::kOnCreate, -1, plNodeRefMsg::kPhysical); 
    hsgResMgr::ResMgr()->AddViaNotify(GetKey(), refMsg, plRefFlags::kActiveRef);

    if (fWorldKey)
    {
        plGenRefMsg* ref = new plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefWorld);
        hsgResMgr::ResMgr()->AddViaNotify(fWorldKey, ref, plRefFlags::kActiveRef);
    }

    // only dynamic physicals without noSync need SDLs
    if ( fGroup == plSimDefs::kGroupDynamic && !fProps.IsBitSet(plSimulationInterface::kNoSynchronize) )
    {
        // add SDL modifier
        plSceneObject* sceneObj = plSceneObject::ConvertNoRef(fObjectKey->ObjectIsLoaded());
        hsAssert(sceneObj, "nil sceneObject, failed to create and attach SDL modifier");

        delete fSDLMod;
        fSDLMod = new plPhysicalSDLModifier;
        sceneObj->AddModifier(fSDLMod);
    }

    return true;
}
void plPXPhysicalControllerCore::ICreateController(const hsPoint3& pos)
{
    NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
    NxCapsuleControllerDesc desc;
    desc.position.x     = pos.fX;
    desc.position.y     = pos.fY;
    desc.position.z     = pos.fZ;
    desc.upDirection    = NX_Z;
    desc.slopeLimit     = kSLOPELIMIT;
    desc.skinWidth      = kPhysxSkinWidth;
    desc.stepOffset     = STEP_OFFSET;
    desc.callback       = &gMyReport;
    desc.userData       = this;
    desc.radius         = fRadius;
    desc.height         = fHeight;
    desc.interactionFlag = NXIF_INTERACTION_EXCLUDE;
    //desc.interactionFlag = NXIF_INTERACTION_INCLUDE;
    fController = (NxCapsuleController*)gControllerMgr.createController(scene, desc);

    // Change the avatars shape groups.  The avatar doesn't actually use these when
    // it's determining collision, but if you're standing still and an object runs
    // into you, it'll pass through without this.
    NxActor* actor = fController->getActor();
    NxShape* shape = actor->getShapes()[0];
    shape->setGroup(plSimDefs::kGroupAvatar);

    // need to create the non-bouncing object that can be used to trigger things while the avatar is doing behaviors.
    NxActorDesc actorDesc;
    NxCapsuleShapeDesc capDesc;
    capDesc.radius = fRadius;
    capDesc.height = fHeight;
    capDesc.group = plSimDefs::kGroupAvatar;
    actorDesc.shapes.pushBack(&capDesc);
    capDesc.materialIndex= plSimulationMgr::GetInstance()->GetMaterialIdx(scene, 0.0,0.0);
    actorDesc.globalPose=actor->getGlobalPose();
    NxBodyDesc bodyDesc;
    bodyDesc.mass = kAvatarMass;
    actorDesc.body = &bodyDesc;
    bodyDesc.flags = NX_BF_KINEMATIC;
    bodyDesc.flags |=NX_BF_DISABLE_GRAVITY ;
    actorDesc.name = "AvatarTriggerKinematicGuy";
    fSeeking=false;
    try
    {
        fKinematicActor = scene->createActor(actorDesc);
    }
    catch (...)
    {
        hsAssert(false, "Actor creation crashed");
    }

    // set the matrix to be the same as the controller's actor... that should orient it to be the same
    //fKinematicActor->setGlobalPose(actor->getGlobalPose());

    // the proxy for the debug display
    //hsAssert(!fProxyGen, "Already have proxy gen, double read?");

    hsColorRGBA physColor;
    float opac = 1.0f;

    // local avatar is light purple and transparent
    physColor.Set(.2f, .1f, .2f, 1.f);
    opac = 0.8f;

    /*
    // the avatar proxy doesn't seem to work... not sure why?
    fProxyGen = new plPhysicalProxy(hsColorRGBA().Set(0,0,0,1.f), physColor, opac);
    fProxyGen->Init(this);
    */

}
HeightmapActor::HeightmapActor(NxPhysicsSDK &sdk_, NxScene &scene, const unsigned short *buffer, int samplesX, int samplesY, const VC3 &size)
:	sdk(sdk_),
	heightField(0)
{
	NxHeightFieldDesc heightDesc;
	heightDesc.nbColumns = samplesX;
	heightDesc.nbRows = samplesY;
	heightDesc.verticalExtent = -1000;
	heightDesc.convexEdgeThreshold = 0;
	heightDesc.samples = new NxU32[samplesX * samplesY];
	heightDesc.sampleStride = sizeof(NxU32);

    NxU8 *currentByte = (NxU8 *) heightDesc.samples;
	for(int row = 0; row < samplesY; ++row)
	for(int column = 0; column < samplesX; ++column)
	{            
		NxHeightFieldSample *currentSample = (NxHeightFieldSample *) currentByte;

		//int sample = buffer[row * samplesX + column];
		//int sample = buffer[column * samplesY + row];
		int sample = buffer[(samplesY - row - 1) * samplesX + column];
		//int sample = buffer[column * samplesX + row];
		sample -= 32768;

		currentSample->height = sample;
		currentSample->materialIndex0 = 0;
		currentSample->materialIndex1 = 0;
		currentSample->tessFlag = 0;
		currentByte += heightDesc.sampleStride;
	}

	heightField = sdk.createHeightField(heightDesc);
	delete[] (NxU32 *) heightDesc.samples;

	if(heightField)
	{
		float scaleX = size.x / samplesX;
		float scaleY = 1.f / 65536.f * size.y;
		float scaleZ = size.z / samplesY;

		NxHeightFieldShapeDesc shapeDesc;
		shapeDesc.heightField = heightField;
		shapeDesc.heightScale = scaleY;
		shapeDesc.rowScale = scaleZ;
		shapeDesc.columnScale = scaleX;
		shapeDesc.materialIndexHighBits = 0;
		shapeDesc.holeMaterial = 2;    

		NxVec3 pos;
		pos.x = -size.x * 0.5f;
		pos.y = size.y * 0.5f;
		pos.z = (size.z * 0.5f) - scaleZ;

		NxQuat quat;
		quat.zero();
		quat.fromAngleAxis(90, NxVec3(0, 1, 0));

		NxActorDesc actorDesc;
		actorDesc.shapes.pushBack(&shapeDesc);
		actorDesc.globalPose.t = pos;
		actorDesc.globalPose.M = quat;

		actor = scene.createActor(actorDesc);
	}

	this->scene = &scene;
	init();
}