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); }
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); }
/** * @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(); }