void SetupShapesUserData(const VehicleDescriptor &vd) { PxRigidDynamic *a = vd.vehicle->mActor; if (!a) return; PxU32 numShapes = a->getNbShapes(); r3d_assert(numShapes <= vd.numWheels + vd.numHullParts); for (PxU32 i = 0; i < numShapes; ++i) { PxShape *s = 0; a->getShapes(&s, 1, i); if (!s) continue; if (i < vd.numWheels) { s->userData = reinterpret_cast<void*>(vd.wheelBonesRemapIndices[i]); } else { s->userData = reinterpret_cast<void*>(vd.hullBonesRemapIndices[i - vd.numWheels]); } } }
/** @brief @date 2013-12-03 */ void CEvc::pickup() { PxU32 width; PxU32 height; mApplication.getPlatform()->getWindowSize(width, height); mPicking->moveCursor(width/2,height/2); mPicking->lazyPick(); PxActor *actor = mPicking->letGo(); //PxRigidDynamic *rigidActor = static_cast<PxRigidDynamic*>(actor->is<PxRigidDynamic>()); PxRigidDynamic *rigidActor = (PxRigidDynamic*)actor; if (rigidActor) { const PxVec3 pos = getCamera().getPos() + (getCamera().getViewDir()*10.f); const PxVec3 vel = getCamera().getViewDir() * 20.f; rigidActor->addForce( getCamera().getViewDir()*g_pDbgConfig->force ); PxU32 nbShapes = rigidActor->getNbShapes(); if(!nbShapes) return; PxShape** shapes = (PxShape**)SAMPLE_ALLOC(sizeof(PxShape*)*nbShapes); PxU32 nb = rigidActor->getShapes(shapes, nbShapes); PX_ASSERT(nb==nbShapes); for(PxU32 i=0;i<nbShapes;i++) { RenderBaseActor *renderActor = getRenderActor(rigidActor, shapes[i]); if (renderActor) { renderActor->setRenderMaterial(mManagedMaterials[ 1]); } } SAMPLE_FREE(shapes); } }
void getSimplePose( PxActor* actor, float* data ) //TODO rework { PxShape* shp[1]; PxRigidDynamic* rigid = (PxRigidDynamic*)actor; rigid->getShapes( shp, PxU32(1) ); PxMat44 shape_pose = rigid->getGlobalPose(); //(PxShapeExt::getGlobalPose(*shp[0], *rigid)); for( int i = 0; i < 4; i++ ) for( int j = 0; j < 4; j++ ) data[i*4 + j] = shape_pose[j][i]; }
void defaultCCTInteraction(const PxControllerShapeHit& hit) { PxRigidDynamic* actor = hit.shape->getActor()->is<PxRigidDynamic>(); if(actor) { if(actor->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC) return; if(0) { const PxVec3 p = actor->getGlobalPose().p + hit.dir * 10.0f; PxShape* shape; actor->getShapes(&shape, 1); PxRaycastHit newHit; PxU32 n = PxShapeExt::raycast(*shape, *shape->getActor(), p, -hit.dir, 20.0f, PxHitFlag::ePOSITION, 1, &newHit, false); if(n) { // We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates // useless stress on the solver. It would be possible to enable/disable vertical pushes on // particular objects, if the gameplay requires it. const PxVec3 upVector = hit.controller->getUpDirection(); const PxF32 dp = hit.dir.dot(upVector); // shdfnd::printFormatted("%f\n", fabsf(dp)); if(fabsf(dp)<1e-3f) // if(hit.dir.y==0.0f) { const PxTransform globalPose = actor->getGlobalPose(); const PxVec3 localPos = globalPose.transformInv(newHit.position); ::addForceAtLocalPos(*actor, hit.dir*hit.length*1000.0f, localPos, PxForceMode::eACCELERATION); } } } // We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates // useless stress on the solver. It would be possible to enable/disable vertical pushes on // particular objects, if the gameplay requires it. const PxVec3 upVector = hit.controller->getUpDirection(); const PxF32 dp = hit.dir.dot(upVector); // shdfnd::printFormatted("%f\n", fabsf(dp)); if(fabsf(dp)<1e-3f) // if(hit.dir.y==0.0f) { const PxTransform globalPose = actor->getGlobalPose(); const PxVec3 localPos = globalPose.transformInv(toVec3(hit.worldPos)); ::addForceAtLocalPos(*actor, hit.dir*hit.length*1000.0f, localPos, PxForceMode::eACCELERATION); } } }
PxRigidDynamic* CServer::createDynamicBox(const Vector3 &position, const Vector3 &dimensions, float mass, bool kinematic, bool trigger, int group, const IPhysics *component) { assert(_scene); // Nota: PhysX coloca el sistema de coordenadas local en el centro de la caja, mientras // que la lógica asume que el origen del sistema de coordenadas está en el centro de la // cara inferior. Para unificar necesitamos realizar una traslación en el eje Y. // Afortunadamente, el descriptor que se usa para crear el actor permite definir esta // transformación local, por lo que la conversión entre sistemas de coordenadas es transparente. // Crear un cubo dinámico PxTransform pose(Vector3ToPxVec3(position)); PxBoxGeometry geom(Vector3ToPxVec3(dimensions)); PxMaterial *material = _defaultMaterial; float density = mass / (dimensions.x * dimensions.y * dimensions.z); PxTransform localPose(PxVec3(0, dimensions.y, 0)); // Transformación de coordenadas lógicas a coodenadas de PhysX // Crear cubo dinámico o cinemático PxRigidDynamic *actor; if (kinematic) actor = PxCreateKinematic(*_physics, pose, geom, *material, density, localPose); else actor = PxCreateDynamic(*_physics, pose, geom, *material, density, localPose); // Transformarlo en trigger si es necesario if (trigger) { PxShape *shape; actor->getShapes(&shape, 1, 0); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true); } // Anotar el componente lógico asociado a la entidad física actor->userData = (void *) component; // Establecer el grupo de colisión PxSetGroup(*actor, group); // Añadir el actor a la escena _scene->addActor(*actor); return actor; }
physx::PxRigidDynamic* CPhysicManager::createDynamicSphere(const Vector3 &position, const float &radius, float mass, bool kinematic, bool trigger, int group, const Logic::Component::IPhysic *component) { assert(m_scene); PxTransform pose(Vector3ToPxVec3(position)); PxSphereGeometry geom(radius); PxMaterial *material = m_defaultMaterial; float density = mass / ((4/3) * Common::Util::Math::PI * radius * radius * radius); PxRigidDynamic *actor = nullptr; if(kinematic) { actor = PxCreateKinematic(*m_physics,pose,geom,*material,density); } else { actor = PxCreateDynamic(*m_physics,pose,geom,*material,density); } if(trigger) { PxShape *shape; actor->getShapes(&shape,1,0); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true); } actor->userData = (void*)component; PxSetGroup(*actor,group); setupFiltering(actor,FilterGroup::eSPACE_FILTER,FilterGroup::eSPACE_FILTER); PxD6Joint* joint = PxD6JointCreate(*m_physics, actor, PxTransform::createIdentity(), nullptr, actor->getGlobalPose()); joint->setMotion(PxD6Axis::eX,PxD6Motion::eFREE); joint->setMotion(PxD6Axis::eY,PxD6Motion::eLOCKED); joint->setMotion(PxD6Axis::eZ,PxD6Motion::eFREE); joint->setMotion(PxD6Axis::eSWING1,PxD6Motion::eFREE); joint->setMotion(PxD6Axis::eSWING2,PxD6Motion::eLOCKED); joint->setMotion(PxD6Axis::eTWIST,PxD6Motion::eLOCKED); //TODO release //m_scene->addActor(*actor); return actor; }
Entity* CreateBall(float _fRadius, SimpleTree& _rParentNode) { Entity* pBall = new Entity(EntityCategories::BALL); // The model Sphere* pSphere = new Sphere(Vector2(), _fRadius); pSphere->setColour(BALL_COLOUR); pSphere->setLevelOfDetail(10); pBall->addComponent(pSphere); pSphere->setEntity(pBall); // The physical body Body::Material material; material.density = 0.5f; material.friction = 0.5f; material.restitution = 0.5f; PhysXBody* pBody = static_cast<PhysXBody*>(PhysicsFactory::getInstance()->createBody(material, pSphere, BALL_POSITION, true)); pBall->addComponent(pBody); pBody->setEntity(pBall); // Collision detection PxRigidDynamic* pRigidDynamic = pBody->getActor()->isRigidDynamic(); PxFilterData filterData; filterData.word0 = EntityCategories::BALL; filterData.word1 = EntityCategories::WALL_BLOCK; PxShape* shapes; pRigidDynamic->getShapes(&shapes, 1); shapes->setSimulationFilterData(filterData); pRigidDynamic->setContactReportThreshold(DESTRUCTION_FORCE_THRESHOLD); // The scene SimpleTree* pNode = new SimpleTree; setTranslation(pNode->getTransformation(), BALL_POSITION); pNode->setModel(pSphere); pBody->setNode(pNode); _rParentNode.addChild(pNode); GazEngine::addEntity(pBall); return pBall; }
Entity* CreateWallBlock(const Matrix44& _rTransformation, float _fBlockSize, SimpleTree& _rParentNode) { Entity* pWallBlock = new Entity(EntityCategories::WALL_BLOCK); // The model Cube* pCube = new Cube(Vector2(), _fBlockSize); pCube->setColour(Vector4(Math::getRandomFloat(0.0f, 1.0f), Math::getRandomFloat(0.0f, 1.0f), Math::getRandomFloat(0.0f, 1.0f), 1.0f)); pWallBlock->addComponent(pCube); pCube->setEntity(pWallBlock); // The physical body Body::Material material; material.density = 0.5f; material.friction = 0.5f; material.restitution = 0.5f; PhysXBody* pBody = static_cast<PhysXBody*>(PhysicsFactory::getInstance()->createBody(material, pCube, getTranslation3(_rTransformation), true)); pWallBlock->addComponent(pBody); pBody->setEntity(pWallBlock); // Collision detection PxRigidDynamic* pRigidDynamic = pBody->getActor()->isRigidDynamic(); PxFilterData filterData; filterData.word0 = EntityCategories::WALL_BLOCK; filterData.word1 = EntityCategories::BALL | EntityCategories::WALL_BLOCK; PxShape* shapes; pRigidDynamic->getShapes(&shapes, 1); shapes->setSimulationFilterData(filterData); pRigidDynamic->setContactReportThreshold(DESTRUCTION_FORCE_THRESHOLD); // The scene SimpleTree* pNode = new SimpleTree; pNode->setTransformation(_rTransformation); pNode->setModel(pCube); pBody->setNode(pNode); _rParentNode.addChild(pNode); GazEngine::addEntity(pWallBlock); return pWallBlock; }
PxRigidDynamic* CPhysicManager::createDynamicBox(const Vector3 &position, const Vector3 &dimensions, float mass, bool kinematic, bool trigger, int group, const IPhysic *component) { assert(m_scene); PxTransform pose(Vector3ToPxVec3(position)); PxBoxGeometry geom(Vector3ToPxVec3(dimensions)); PxMaterial *material = m_defaultMaterial; float density = mass / (dimensions.x * dimensions.y * dimensions.z); PxTransform localPose(PxVec3(0, dimensions.y, 0)); PxRigidDynamic *actor = nullptr; if(kinematic) { actor = PxCreateKinematic(*m_physics,pose,geom,*material,density,localPose); } else { actor = PxCreateDynamic(*m_physics,pose,geom,*material,density,localPose); } if(trigger) { PxShape *shape; actor->getShapes(&shape,1,0); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true); } actor->userData = (void*)component; PxSetGroup(*actor,group); setupFiltering(actor,FilterGroup::eSPACE_FILTER,FilterGroup::eSPACE_FILTER); //m_scene->addActor(*actor); return actor; }
void FBXActor::createCollisionShapes(PhysicsDemoScene *a_app) { float density = 300; //pole PxBoxGeometry box = PxBoxGeometry(0.1f,4,0.1f); PxTransform transform(*((PxMat44*)(&m_world))); //cast from glm to PhysX matrices PxRigidDynamic* dynamicActor = PxCreateDynamic(*a_app->g_Physics, transform, box, *a_app->g_PhysicsMaterial, density); dynamicActor->userData = this; //set the user data to point at this FBXActor class //offset int nShapes = dynamicActor->getNbShapes(); PxShape* shapes; dynamicActor->getShapes(&shapes, nShapes); PxTransform relativePose = PxTransform(PxVec3(0.0f,4.0f,0.0f)); shapes->setLocalPose(relativePose); //head box = PxBoxGeometry(0.8f,0.5f,0.3f); relativePose = PxTransform(PxVec3(0.0f,2.0f,0.0f)); PxShape* shape = dynamicActor->createShape(box, *a_app->g_PhysicsMaterial); if (shape) { shape->setLocalPose(relativePose); } PxRigidBodyExt::updateMassAndInertia(*dynamicActor, (PxReal)density); //add to scene a_app->g_PhysicsScene->addActor(*dynamicActor); a_app->g_PhysXActors.push_back(dynamicActor); }
PxController* ControlledActor::init(const ControlledActorDesc& desc, PxControllerManager* manager) { const float radius = desc.mRadius; float height = desc.mHeight; float crouchHeight = desc.mCrouchHeight; PxControllerDesc* cDesc; PxBoxControllerDesc boxDesc; PxCapsuleControllerDesc capsuleDesc; if(desc.mType==PxControllerShapeType::eBOX) { height *= 0.5f; height += radius; crouchHeight *= 0.5f; crouchHeight += radius; boxDesc.halfHeight = height; boxDesc.halfSideExtent = radius; boxDesc.halfForwardExtent = radius; cDesc = &boxDesc; } else { PX_ASSERT(desc.mType==PxControllerShapeType::eCAPSULE); capsuleDesc.height = height; capsuleDesc.radius = radius; capsuleDesc.climbingMode = PxCapsuleClimbingMode::eCONSTRAINED; cDesc = &capsuleDesc; } cDesc->density = desc.mProxyDensity; cDesc->scaleCoeff = desc.mProxyScale; cDesc->material = &mOwner.getDefaultMaterial(); cDesc->position = desc.mPosition; cDesc->slopeLimit = desc.mSlopeLimit; cDesc->contactOffset = desc.mContactOffset; cDesc->stepOffset = desc.mStepOffset; cDesc->invisibleWallHeight = desc.mInvisibleWallHeight; cDesc->maxJumpHeight = desc.mMaxJumpHeight; // cDesc->nonWalkableMode = PxControllerNonWalkableMode::ePREVENT_CLIMBING_AND_FORCE_SLIDING; cDesc->reportCallback = desc.mReportCallback; cDesc->behaviorCallback = desc.mBehaviorCallback; cDesc->volumeGrowth = desc.mVolumeGrowth; mType = desc.mType; mInitialPosition = desc.mPosition; mStandingSize = height; mCrouchingSize = crouchHeight; mControllerRadius = radius; PxController* ctrl = static_cast<PxBoxController*>(manager->createController(*cDesc)); PX_ASSERT(ctrl); // remove controller shape from scene query for standup overlap test PxRigidDynamic* actor = ctrl->getActor(); if(actor) { if(actor->getNbShapes()) { PxShape* ctrlShape; actor->getShapes(&ctrlShape,1); ctrlShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false); Renderer* renderer = mOwner.getRenderer(); if(desc.mType==PxControllerShapeType::eBOX) { const PxVec3 standingExtents(radius, height, radius); const PxVec3 crouchingExtents(radius, crouchHeight, radius); mRenderActorStanding = SAMPLE_NEW(RenderBoxActor)(*renderer, standingExtents); mRenderActorCrouching = SAMPLE_NEW(RenderBoxActor)(*renderer, crouchingExtents); } else if(desc.mType==PxControllerShapeType::eCAPSULE) { mRenderActorStanding = SAMPLE_NEW(RenderCapsuleActor)(*renderer, radius, height*0.5f); mRenderActorCrouching = SAMPLE_NEW(RenderCapsuleActor)(*renderer, radius, crouchHeight*0.5f); } } } mController = ctrl; return ctrl; }
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; } }
PxCapsuleController* SampleCustomGravity::createCharacter(const PxExtendedVec3& position) #endif { const float height = 2.0f; // const float height = 1e-6f; // PT: TODO: make it work with 0? #ifdef USE_BOX_CONTROLLER PxBoxControllerDesc cDesc; cDesc.halfHeight = height; cDesc.halfSideExtent = mControllerRadius; cDesc.halfForwardExtent = mControllerRadius; #else PxCapsuleControllerDesc cDesc; cDesc.height = height; cDesc.radius = mControllerRadius; #endif cDesc.material = &getDefaultMaterial(); cDesc.position = position; cDesc.slopeLimit = SLOPE_LIMIT; cDesc.contactOffset = CONTACT_OFFSET; cDesc.stepOffset = STEP_OFFSET; cDesc.invisibleWallHeight = INVISIBLE_WALLS_HEIGHT; cDesc.maxJumpHeight = MAX_JUMP_HEIGHT; cDesc.callback = this; mControllerInitialPosition = cDesc.position; #ifdef USE_BOX_CONTROLLER PxBoxController* ctrl = static_cast<PxBoxController*>(mControllerManager->createController(getPhysics(), &getActiveScene(), cDesc)); #else PxCapsuleController* ctrl = static_cast<PxCapsuleController*>(mControllerManager->createController(getPhysics(), &getActiveScene(), cDesc)); #endif // remove controller shape from scene query for standup overlap test PxRigidDynamic* actor = ctrl->getActor(); if(actor) { if(actor->getNbShapes()) { PxShape* ctrlShape; actor->getShapes(&ctrlShape,1); ctrlShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false); #ifdef USE_BOX_CONTROLLER const PxVec3 standingExtents(mControllerRadius, height, mControllerRadius); mRenderActor = SAMPLE_NEW(RenderBoxActor)(*getRenderer(), standingExtents); #else mRenderActor = SAMPLE_NEW(RenderCapsuleActor)(*getRenderer(), mControllerRadius, height*0.5f); #endif if(mRenderActor) mRenderActors.push_back(mRenderActor); } else fatalError("character actor has no shape"); } else fatalError("character could not create actor"); // uncomment the next line to render the character //createRenderObjectsFromActor(ctrl->getActor()); return ctrl; }