bool Actor::patternFracture(const PxVec3& hitLocation, const PxVec3& dirIn, float scale, float vel, float radiusIn) { int compoundNr = -1; int convexNr = -1; PxVec3 normal; float dist; bool ret = false; PxVec3 dir = dirIn; mScene->getScene()->lockWrite(); bool hit = false; if (dir.magnitudeSquared() < 0.5f) { dir = PxVec3(1.f,0.f,0.f); hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); if(!hit) { dir = PxVec3(0.f,1.f,0.f); hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); if(!hit) { dir = PxVec3(0.f,0.f,1.f); hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); } } } else { hit = base::Actor::rayCast(hitLocation-dir,dir,dist,compoundNr,convexNr,normal); } if (hit) { float radius = mMinRadius + mRadiusMultiplier*radiusIn; float impulseMagn = scale*vel*mImpulseScale; if (mSheetFracture) { normal = ((Compound*)mCompounds[(uint32_t)compoundNr])->mNormal; } PxVec3 a(0.f,0.f,1.f); normal.normalize(); a -= a.dot(normal)*normal; if( a.magnitudeSquared() < 0.1f ) { a = PxVec3(0.f,1.f,0.f); a -= a.dot(normal)*normal; } a.normalize(); PxVec3 b(normal.cross(a)); PxMat33 trans(a,b,normal); ret = base::Actor::patternFracture(hitLocation,dir,compoundNr,trans,radius,impulseMagn,impulseMagn); } mScene->getScene()->unlockWrite(); mRenderResourcesDirty = true; return ret; }
void AddRadialImpulseToPxRigidBody_AssumesLocked(PxRigidBody& PRigidBody, const FVector& Origin, float Radius, float Strength, uint8 Falloff, bool bVelChange) { #if WITH_PHYSX if (!(PRigidBody.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) { float Mass = PRigidBody.getMass(); PxTransform PCOMTransform = PRigidBody.getGlobalPose().transform(PRigidBody.getCMassLocalPose()); PxVec3 PCOMPos = PCOMTransform.p; // center of mass in world space PxVec3 POrigin = U2PVector(Origin); // origin of radial impulse, in world space PxVec3 PDelta = PCOMPos - POrigin; // vector from origin to COM float Mag = PDelta.magnitude(); // Distance from COM to origin, in Unreal scale : @todo: do we still need conversion scale? // If COM is outside radius, do nothing. if (Mag > Radius) { return; } PDelta.normalize(); // Scale by U2PScale here, because units are velocity * mass. float ImpulseMag = Strength; if (Falloff == RIF_Linear) { ImpulseMag *= (1.0f - (Mag / Radius)); } PxVec3 PImpulse = PDelta * ImpulseMag; PxForceMode::Enum Mode = bVelChange ? PxForceMode::eVELOCITY_CHANGE : PxForceMode::eIMPULSE; PRigidBody.addForce(PImpulse, Mode); } #endif // WITH_PHYSX }
void BasicRandom::unitRandomPt(PxVec3& v) { v.x = randomFloat(); v.y = randomFloat(); v.z = randomFloat(); v.normalize(); }
void AddRadialForceToPxRigidBody_AssumesLocked(PxRigidBody& PRigidBody, const FVector& Origin, float Radius, float Strength, uint8 Falloff, bool bAccelChange) { #if WITH_PHYSX if (!(PRigidBody.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) { float Mass = PRigidBody.getMass(); PxTransform PCOMTransform = PRigidBody.getGlobalPose().transform(PRigidBody.getCMassLocalPose()); PxVec3 PCOMPos = PCOMTransform.p; // center of mass in world space PxVec3 POrigin = U2PVector(Origin); // origin of radial impulse, in world space PxVec3 PDelta = PCOMPos - POrigin; // vector from float Mag = PDelta.magnitude(); // Distance from COM to origin, in Unreal scale : @todo: do we still need conversion scale? // If COM is outside radius, do nothing. if (Mag > Radius) { return; } PDelta.normalize(); // If using linear falloff, scale with distance. float ForceMag = Strength; if (Falloff == RIF_Linear) { ForceMag *= (1.0f - (Mag / Radius)); } // Apply force PxVec3 PImpulse = PDelta * ForceMag; PRigidBody.addForce(PImpulse, bAccelChange ? PxForceMode::eACCELERATION : PxForceMode::eFORCE); } #endif // WITH_PHYSX }
void Enemy::CheckFutureCollision(int attempts) { attempts++; if(attempts > 10) return; PxVec3 pos = actor->getGlobalPose().p; PxVec3 dirMove = PxVec3(moveDir.x,0,moveDir.z); while(dirMove.isZero()) { float xspeed = rand()% (int)ceil(movementSpeed); //getal van 0 tot 10 float xfSpeed = xspeed - (int)ceil(movementSpeed)/2; // getal van -5 tot 5 float zspeed = rand()%(int)ceil(movementSpeed); //getal van 0 tot 10 float zfSpeed = zspeed -(int)ceil( movementSpeed)/2; // getal van -5 tot 5 dirMove = PxVec3(xfSpeed, 0, zfSpeed); } dirMove.normalize(); int numHits; PxRaycastHit* hit = physics->RaycastMultiple(pos-PxVec3(0,1.5f,0),dirMove,3.5f,&numHits,PxQueryFlag::eSTATIC | PxQueryFlag::eDYNAMIC); for(unsigned int i= 0; i < numHits; i++) { if(hit[i].actor != actor && hit[i].actor != NULL) { currentMoveTime = 0; float xspeed = rand()% (int)ceil(movementSpeed); //number from 0 to movementSpeed float xfSpeed = xspeed - (int)ceil(movementSpeed)/2; // number from -movementSpeed/2 to movementSpeed/2 float zspeed = rand()%(int)ceil(movementSpeed); float zfSpeed = zspeed -(int)ceil( movementSpeed)/2; moveDir = D3DXVECTOR3(xfSpeed, 0, zfSpeed); i = 999; CheckFutureCollision(attempts); } } }
void Enemy::CheckShooting(float dist, float deltaTime) { PxExtendedVec3 tpPos = physics->player->getPosition(); PxVec3 pPos = playerPos; PxVec3 ori = actor->getGlobalPose().p; PxVec3 dir = pPos - ori; dir.normalize(); int numHits = 0; PxRaycastHit* hit = physics->RaycastMultiple(ori,dir,dist,&numHits, PxQueryFlag::eSTATIC | PxQueryFlag::eDYNAMIC); for(unsigned int i = 1; i < numHits; i++) { if(hit[i-1].actor == actor && hit[i].actor == physics->player->getActor()) { sawPlayer = true; lastTimeShot+=deltaTime; if(lastTimeShot > shootDelay) { obj->PlayAnimation("Shoot",true); moveDir *= 0.1f; if(obj->GetCurrentAnim()->doAction) { CreateBullet(ori+dir*2,dir); currentMoveTime = 9999.0f; lastTimeShot = 0; resources->GetSoundHandler()->PlayWaveFile("piew"); obj->GetCurrentAnim()->doAction = false; } } } } }
int RayCastManagerImpl::CastRayAgainstCharacterController(const DirectX::XMFLOAT3& p_origin, const DirectX::XMFLOAT3& p_direction, const float& p_range) { if(p_range <= 0.0f) { // TODOKO log error return -1; } // Cast directx things to physx PxVec3 origin = PxVec3(p_origin.x, p_origin.y, p_origin.z); PxVec3 direction = PxVec3(p_direction.x, p_direction.y, p_direction.z); direction.normalize(); PxRaycastBuffer hit; // Used to save the hit // casts a ray vs the physics scene. various hit information is saved in the hit variable. For now we only care about the object we hit // eMESH_BOTH_SIDES specifices that no culling should be used, shouldnt need to be there but let's be safe bool status = m_utils.m_worldScene->raycast(origin, direction, p_range, hit, PxHitFlag::eMESH_BOTH_SIDES); // hit.block.position; if(!status && !hit.hasBlock) { // No hit detected, return -1 TODOKO Maybee i should return something better? return -1; } // Now comes the difficult task of checking vs character controllers unordered_map<PxController*, int> idsByCharacterController = m_utils.m_characterControlManager->GetIdsByControllers(); for(auto pairs : idsByCharacterController) // Loop through every pair in the list { if(pairs.first->getActor() == hit.block.actor) // The first part contains the actor pointer { return pairs.second; // If this is true we found a hit vs character controller, second contains ID } } return -1; }
int RayCastManagerImpl::CastSweep(const XMFLOAT3& p_origin, XMFLOAT3& p_direction, float p_width, const float& p_range, int& o_flag) { if(p_range <= 0.0f) { cout << "Physcs. Raytracer. Sweep. Range of sweep was zero or below" << endl; return -1; } // Cast directx things to physx PxVec3 origin = PxVec3(p_origin.x, p_origin.y, p_origin.z); PxVec3 direction = PxVec3(p_direction.x, p_direction.y, p_direction.z); direction.normalize(); PxSweepBuffer hit; // Used to save the hit /// Paramters for the sweep // PxGeometry* geometry bool status = m_utils.m_worldScene->sweep(PxSphereGeometry(p_width), PxTransform(origin), direction, p_range, hit, PxHitFlag::eMESH_BOTH_SIDES); // hit.block.position; if(!status && !hit.hasBlock) { // No hit detected, return -1 TODOKO Maybee i should return something better? return -1; } // Start with checking static and dynamic rigid bodies unordered_map<PxRigidActor*, int> idsByRigidBody = m_utils.m_rigidBodyManager->GetIDsByBodies(); if(idsByRigidBody.find(hit.block.actor) != idsByRigidBody.end()) { PxRigidActor* actorAsRigic = (PxRigidActor*)hit.block.actor; if(actorAsRigic->isRigidDynamic()) { PxRigidDynamic* actorsAsDynamic = (PxRigidDynamic*)hit.block.actor; if(actorsAsDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC) { o_flag = 0; } } else if(actorAsRigic->isRigidStatic()) { o_flag = 3; } return idsByRigidBody.find(hit.block.actor)->second; } else { // Nothing } // Now comes the difficult task of checking vs character controllers unordered_map<PxController*, int> idsByCharacterController = m_utils.m_characterControlManager->GetIdsByControllers(); for(auto pairs : idsByCharacterController) // Loop through every pair in the list { if(pairs.first->getActor() == hit.block.actor) // The first part contains the actor pointer { o_flag = 1; return pairs.second; // If this is true we found a hit vs character controller, second contains ID } } return -1; }
// ------------------------------------------------------------------------------------- void PolygonTriangulator::importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex) { // find projection 3d -> 2d; PxVec3 n; isConvex = true; if (planeNormal) n = *planeNormal; else { PX_ASSERT(numPoints >= 3); n = PxVec3(0.0f, 0.0f, 0.0f); for (int i = 1; i < numPoints-1; i++) { int i0 = 0; int i1 = i; int i2 = i+1; if (indices) { i0 = indices[i0]; i1 = indices[i1]; i2 = indices[i2]; } const PxVec3 &p0 = points[i0]; const PxVec3 &p1 = points[i1]; const PxVec3 &p2 = points[i2]; PxVec3 ni = (p1-p0).cross(p2-p0); if (i > 1 && ni.dot(n) < 0.0f) isConvex = false; n += ni; } } n.normalize(); PxVec3 t0,t1; if (fabs(n.x) < fabs(n.y) && fabs(n.x) < fabs(n.z)) t0 = PxVec3(1.0f, 0.0f, 0.0f); else if (fabs(n.y) < fabs(n.z)) t0 = PxVec3(0.0f, 1.0f, 0.0f); else t0 = PxVec3(0.0f, 0.0f, 1.0f); t1 = n.cross(t0); t1.normalize(); t0 = t1.cross(n); mPoints.resize((uint32_t)numPoints); if (indices == NULL) { for (uint32_t i = 0; i < (uint32_t)numPoints; i++) mPoints[i] = PxVec3(points[i].dot(t0), points[i].dot(t1), 0.0f); } else { for (uint32_t i = 0; i < (uint32_t)numPoints; i++) { const PxVec3 &p = points[(uint32_t)indices[i]]; mPoints[i] = PxVec3(p.dot(t0), p.dot(t1), 0.0f); } } }
PxTransform Camera::getTransform() const { PxVec3 viewY = mDir.cross(PxVec3(0, 1, 0)); if (viewY.normalize() < 1e-6f) return PxTransform(mEye); PxMat33 m(mDir.cross(viewY), viewY, -mDir); return PxTransform(mEye, PxQuat(m)); }
static void normalToTangents(const PxVec3& n, PxVec3& t1, PxVec3& t2) { const PxReal m_sqrt1_2 = PxReal(0.7071067811865475244008443621048490); if(fabsf(n.z) > m_sqrt1_2) { const PxReal a = n.y*n.y + n.z*n.z; const PxReal k = PxReal(1.0)/PxSqrt(a); t1 = PxVec3(0,-n.z*k,n.y*k); t2 = PxVec3(a*k,-n.x*t1.z,n.x*t1.y); } else { const PxReal a = n.x*n.x + n.y*n.y; const PxReal k = PxReal(1.0)/PxSqrt(a); t1 = PxVec3(-n.y*k,n.x*k,0); t2 = PxVec3(-n.z*t1.y,n.z*t1.x,a*k); } t1.normalize(); t2.normalize(); }
void RandomVelocities(PhysXObject* object, int powerMax, int seedMultiplier) { PxVec3 dir = CreateRandomVector(powerMax, seedMultiplier); srand((time(NULL) * seedMultiplier) + time(NULL)); int power = rand() % powerMax; dir.normalize(); SetVelocity(dir * power, object); }
/** @brief setting control diagramnode @date 2014-03-02 */ void COrientationEditController::SetControlDiagram(CGenotypeNode *node) { RemoveGenotypeTree(m_sample, m_rootNode); m_nodes.clear(); m_rootNode = NULL; vector<CGenotypeNode*> nodes; m_genotypeController.GetDiagramsLinkto(node, nodes); if (nodes.empty()) return; // Create Phenotype Node CGenotypeNode *parentNode = nodes[ 0]; map<const genotype_parser::SExpr*, CGenotypeNode*> symbols; const PxTransform identTm = PxTransform::createIdentity(); m_rootNode = CreatePhenotypeDiagram(identTm,identTm,identTm, parentNode->m_expr, symbols); // Camera Setting const PxVec3 parentPos = parentNode->GetWorldTransform().p; PxVec3 dir = parentPos - node->GetWorldTransform().p; dir.normalize(); PxVec3 left = PxVec3(0,1,0).cross(dir); left.normalize(); PxVec3 camPos = node->GetWorldTransform().p + (left*3.f) + PxVec3(0,2.5f,0); PxVec3 camDir = parentPos - camPos; camDir.normalize(); camPos -= (camDir * .5f); m_sample.getCamera().lookAt(camPos, parentPos); const PxTransform viewTm = m_sample.getCamera().getViewMatrix(); m_camera->init(viewTm); // select Orientation Control node if (CGenotypeNode *selectNode = m_rootNode->GetConnectNode(node->m_name)) { selectNode->SetHighLight(true); SelectNode(selectNode); } }
void Jumper::RunningJump::update(float dt) { updateAnimation( dt ); _clump->getFrame()->getLTM(); if( _actionTime < _blendTime ) { Vector3f dir = _clump->getFrame()->getAt(); dir.normalize(); _clump->getFrame()->setPos( _clump->getFrame()->getPos() + dir * dt * _vel ); return; } if( _phActor->isSleeping() ) { // setup physics Matrix4f sampleLTM = Jumper::getCollisionFF( _clump )->getFrame()->getLTM(); _phActor->setGlobalPose(PxTransform(wrap( sampleLTM ))); _phActor->wakeUp(); PxVec3 velH = wrap( _clump->getFrame()->getAt() ); velH.normalize(); velH *= _vel * 0.01f; PxVec3 velV = wrap( _clump->getFrame()->getUp() ); velV.normalize(); velV *= 1.5f; _phActor->setLinearVelocity( velH + velV + wrap(_clump->getFrame()->getAt() * 600.0f * dt)) ; _jumper->initOverburdenCalculator( velH + velV ); } else { _clump->getFrame()->setMatrix( _matrixConversion->convert( wrap( _phActor->getGlobalPose() ) ) ); } if( _clump->getAnimationController()->isEndOfAnimation( 0 ) ) { _endOfAction = true; } }
/** @brief generate triangle index buffer @date 2014-01-30 */ void SampleRenderer::GenerateTriangleFrom3Vector( void *positions, void *normals, PxU32 stride, const PxVec3 ¢er, const vector<PxU16> &triangle, OUT vector<PxU16> &outTriangle ) { const PxVec3 p0 = *(PxVec3*)(((PxU8*)positions) + (stride * triangle[ 0])); const PxVec3 p1 = *(PxVec3*)(((PxU8*)positions) + (stride * triangle[ 1])); const PxVec3 p2 = *(PxVec3*)(((PxU8*)positions) + (stride * triangle[ 2])); PxVec3 faceCenter = (p0 + p1 + p2) / 3.f; PxVec3 n = faceCenter - center; n.normalize(); // ccw check // // p0 // / \ // / \ // p2 ------ p1 // PxVec3 v10 = p1 - p0; v10.normalize(); PxVec3 v20 = p2 - p0; v20.normalize(); PxVec3 crossV = v10.cross(v20); crossV.normalize(); if (n.dot(crossV) >= 0) { outTriangle.push_back( triangle[ 0] ); outTriangle.push_back( triangle[ 2] ); outTriangle.push_back( triangle[ 1] ); } else { outTriangle.push_back( triangle[ 0] ); outTriangle.push_back( triangle[ 1] ); outTriangle.push_back( triangle[ 2] ); } }
void SampleNorthPoleCameraController::update(Camera& camera, PxReal dtime) { // Update CCT if(!mBase.isPaused()) { PxVec3 targetKeyDisplacement(0); PxVec3 targetPadDisplacement(0); PxVec3 forward = camera.getViewDir(); forward.y = 0; forward.normalize(); PxVec3 up = PxVec3(0,1,0); PxVec3 right = forward.cross(up); if(mFwd) targetKeyDisplacement += forward; if(mBwd) targetKeyDisplacement -= forward; if(mRight) targetKeyDisplacement += right; if(mLeft) targetKeyDisplacement -= right; targetKeyDisplacement *= mKeyShiftDown ? mRunningSpeed : mWalkingSpeed; targetKeyDisplacement += PxVec3(0,-9.81,0); targetKeyDisplacement *= dtime; targetPadDisplacement += forward * mGamepadForwardInc * mRunningSpeed; targetPadDisplacement += right * mGamepadLateralInc * mRunningSpeed; targetPadDisplacement += PxVec3(0,-9.81,0); targetPadDisplacement *= dtime; PxU32 flags = mCCT.move(targetKeyDisplacement + targetPadDisplacement, 0.001f, dtime, PxControllerFilters(0)); PX_UNUSED(flags); } // Update camera { mTargetYaw += mGamepadYawInc * dtime; mTargetPitch += mGamepadPitchInc * dtime; // Clamp pitch if(mTargetPitch<mPitchMin) mTargetPitch = mPitchMin; if(mTargetPitch>mPitchMax) mTargetPitch = mPitchMax; camera.setRot(PxVec3(-mTargetPitch,-mTargetYaw,0)); PxExtendedVec3 camTarget = computeCameraTarget(); const float filteredHeight = feedbackFilter((float)camTarget.y, mFilterMemory, dtime*6.0f); camTarget.y = filteredHeight; const PxF32 distanceToTarget = 0.0f; const PxVec3 target = toVec3(camTarget) - camera.getViewDir()*distanceToTarget; camera.setPos(target); } }
void Camera::lookAt(const PxVec3& position, const PxVec3& target) { PxVec3 dir = target - position; dir.normalize(); PxVec3 right, up; computeBasis(dir, right, up); PxTransform view; view.p = position; view.q = PxQuat(PxMat33(-right, up, -dir)); setView(view); }
void ApplyOrbitVelocity(PxRigidActor* box, float power) { for(int i = 0; i < planets.size(); i++) { PxVec3 dir = planets[i]->actor->getGlobalPose().p - box->getGlobalPose().p; dir.normalize(); PxVec3 velocity = RandomOrthogonalVector(dir) * power; box->isRigidDynamic()->addForce(velocity,PxForceMode::eACCELERATION); } }
bool ParticleEmitterPressure::stepEmissionSite( SiteData& siteData, ParticleData& spawnData, PxU32& spawnNum, const PxU32 spawnMax, const PxVec3 &sitePos, const PxVec3 &siteVel, const PxReal dt) { PxReal maxDistanceMoved = 5.0f * mSpacingZ; // don't generate long particle beams /** * Find displacement vector of the particle's motion this frame * this is not necessarily v*stepSize because a collision might have occured */ PxVec3 displacement = siteData.position - sitePos; PxVec3 normal = displacement; PxReal distanceMoved = normal.normalize(); if (distanceMoved > maxDistanceMoved) distanceMoved = maxDistanceMoved; /** * Place particles along line between emission point and new position * starting backwards from the new position * spacing between the particles is the rest spacing of the fluid */ PxReal lastPlaced = 0.0f; while((lastPlaced + mSpacingZ) <= distanceMoved) { PxVec3 pos = sitePos + normal * (distanceMoved - (lastPlaced + mSpacingZ)); PxVec3 posNoise; posNoise.x = randInRange(-mRandomPos.x, mRandomPos.x); posNoise.y = randInRange(-mRandomPos.y, mRandomPos.y); pos += mAxisX*posNoise.x + mAxisY*posNoise.y; bool isSpawned = spawnParticle(spawnData, spawnNum, spawnMax, pos, siteVel); if(isSpawned) { updatePredecessor(siteData, pos, siteVel); lastPlaced += mSpacingZ; } else { return false; } } return true; }
void TParticleData::ForcesCircle(std::vector<PxVec3>* forces, CParticlesEmitter* emitter) { float r = emitter->m_shape_emitter.radius; auto forces_vec = *forces; for (int idx = 0; idx < forces_vec.size(); idx++) { PxVec3 dir = positionBuffer[idx] - positionInitBuffer[idx]; float w = 2 * PI / sinf(shader_ctes_globals.world_time); float a = w*w*r; dir.normalize(); forces_vec[idx] = dir * a; } *forces = forces_vec; }
bool Gu::sweepSphereSphere(const PxVec3& center0, PxReal radius0, const PxVec3& center1, PxReal radius1, const PxVec3& motion, PxReal& d, PxVec3& nrm) { const PxVec3 movedCenter = center1 + motion; PxReal tmp; if(!sphereSphereSweep(radius0, center0, center0, radius1, center1, movedCenter, d, tmp)) return false; // Compute normal // PT: if spheres initially overlap, the convention is that returned normal = -sweep direction if(d==0.0f) nrm = -motion; else nrm = (center1 + d * motion) - center0; nrm.normalize(); return true; }
PxVec3 Scene::getWindAtPoint(const PxVec3& point) { if( !database::LocationInfo::getRecord( _location->getDatabaseId() )->wind ) { return PxVec3( 0,0,0 ); } float windAmbient = _location->getWindAmbient(); float windBlast = _location->getWindBlast(); float windAmplitude = ( windBlast - windAmbient ) / 2; float windMagnitude = windAmbient + windAmplitude + windAmplitude * blast( _windTime ); PxVec3 windN = wrap( _location->getWindDirection() ); windN.normalize(); return windN * windMagnitude; }
bool Character::setForward(void) { PxVec3 p = mCharacterPose.p; PxVec3 dir = mGoalPosition - p; dir.normalize(); dir = mCharacterPose.q.rotate(dir); PxU32 nbFrames = mCurrentMotion->mNbFrames; PxReal distance = mCurrentMotion->mDistance; PxReal frameDelta = distance / PxReal(nbFrames); mTargetPosition = p + frameDelta * dir; return true; }
bool ParticleChain::checkPenetration(const Ogre::Vector3 &position, Ogre::Vector3 &closestSurfacePos, Ogre::Vector3 &collisionNormal) { PxShape *hit = nullptr; PxVec3 pxPos = Convert::toPx(position); if (mPhysXScene->getPxScene()->overlapAny(PxSphereGeometry(0.05f), PxTransform(pxPos), hit)) { PxVec3 actorCenter = hit->getActor().getWorldBounds().getCenter(); PxVec3 rayDir = actorCenter - pxPos; rayDir.normalize(); PxVec3 rayOrigin = pxPos - rayDir.multiply(PxVec3(0.2f, 0.2f, 0.2f)); if (mPhysXScene->getPxScene()->overlapAny(PxSphereGeometry(0.05f), PxTransform(rayOrigin), hit)) return false; PxRaycastHit rayHit; if (mPhysXScene->getPxScene()->raycastSingle(rayOrigin, rayDir, 0.2f, PxSceneQueryFlag::eIMPACT|PxSceneQueryFlag::eNORMAL|PxSceneQueryFlag::eDISTANCE, rayHit)) { closestSurfacePos = Convert::toOgre(rayHit.impact); collisionNormal = Convert::toOgre(rayHit.normal); return true; } } return false; }
void ParticleEmitter::computeSiteVelocity(PxVec3& siteVel, const PxVec3& sitePos) { //velocity dir noise PxReal noiseXYAngle = randInRange(0.0f, PxTwoPi); PxReal noiseZAngle = randInRange(0.0f, mRandomAngle); PxVec3 noiseDirVec = mAxisX * PxCos(noiseXYAngle) + mAxisY * PxSin(noiseXYAngle); noiseDirVec.normalize(); noiseDirVec = mAxisZ * PxCos(noiseZAngle) + noiseDirVec * PxSin(noiseZAngle); siteVel = noiseDirVec * mVelocity; //add emitter repulsion if (mParticleMass > 0.0f) { mLinMomentum -= siteVel; mAngMomentum -= (sitePos - mBodyCenter).cross(siteVel); } if (mFrameBody) siteVel += mBodyLinVel + (mBodyAngVel.cross(sitePos - mBodyCenter)); }
void SampleSubmarine::explode(PxRigidActor* actor, const PxVec3& explosionPos, const PxReal explosionStrength) { size_t numRenderActors = mRenderActors.size(); for(PxU32 i = 0; i < numRenderActors; i++) { if(&(mRenderActors[i]->getPhysicsShape()->getActor()) == actor) { PxShape* shape = mRenderActors[i]->getPhysicsShape(); PxTransform pose = PxShapeExt::getGlobalPose(*shape); PxGeometryHolder geom = shape->getGeometry(); // create new actor from shape (to split compound) PxRigidDynamic* newActor = mPhysics->createRigidDynamic(pose); if(!newActor) fatalError("createRigidDynamic failed!"); PxShape* newShape = newActor->createShape(geom.any(), *mMaterial); newShape->userData = mRenderActors[i]; mRenderActors[i]->setPhysicsShape(newShape); newActor->setActorFlag(PxActorFlag::eVISUALIZATION, true); newActor->setLinearDamping(10.5f); newActor->setAngularDamping(0.5f); PxRigidBodyExt::updateMassAndInertia(*newActor, 1.0f); mScene->addActor(*newActor); mPhysicsActors.push_back(newActor); PxVec3 explosion = pose.p - explosionPos; PxReal len = explosion.normalize(); explosion *= (explosionStrength / len); newActor->setLinearVelocity(explosion); newActor->setAngularVelocity(PxVec3(1,2,3)); } } removeActor(actor); }
void PxSetJointGlobalFrame(PxJoint& joint, const PxVec3* wsAnchor, const PxVec3* axisIn) { PxRigidActor* actors[2]; joint.getActors(actors[0], actors[1]); PxTransform localPose[2]; for(PxU32 i=0; i<2; i++) localPose[i] = PxTransform::createIdentity(); // 1) global anchor if(wsAnchor) { //transform anchorPoint to local space for(PxU32 i=0; i<2; i++) localPose[i].p = actors[i] ? actors[i]->getGlobalPose().transformInv(*wsAnchor) : *wsAnchor; } // 2) global axis if(axisIn) { PxVec3 localAxis[2], localNormal[2]; //find 2 orthogonal vectors. //gotta do this in world space, if we choose them //separately in local space they won't match up in worldspace. PxVec3 axisw = *axisIn; axisw.normalize(); PxVec3 normalw, binormalw; ::normalToTangents(axisw, binormalw, normalw); //because axis is supposed to be the Z axis of a frame with the other two being X and Y, we need to negate //Y to make the frame right handed. Note that the above call makes a right handed frame if we pass X --> Y,Z, so //it need not be changed. for(PxU32 i=0; i<2; i++) { if(actors[i]) { const PxTransform& m = actors[i]->getGlobalPose(); PxMat33Legacy mM(m.q); localAxis[i] = mM % axisw; localNormal[i] = mM % normalw; } else { localAxis[i] = axisw; localNormal[i] = normalw; } PxMat33Legacy rot; rot.setColumn(0, localAxis[i]); rot.setColumn(1, localNormal[i]); rot.setColumn(2, localAxis[i].cross(localNormal[i])); localPose[i].q = rot.toQuat(); localPose[i].q.normalize(); } } for(PxU32 i=0; i<2; i++) joint.setLocalPose(static_cast<PxJointActorIndex::Enum>( i ), localPose[i]); }
void GOCCharacterController::ReceiveMessage(Msg &msg) { GOComponent::ReceiveMessage(msg); if (msg.typeID == GlobalMessageIDs::PHYSICS_SUBSTEP && !mFreezed) { GameObjectPtr owner = mOwnerGO.lock(); float time = msg.params.GetFloat("TIME"); Ogre::Vector3 finalDir = Ogre::Vector3(0,0,0); Ogre::Vector3 userDir = owner->GetGlobalOrientation() * mDirection; if (mActor.getPxActor()->isSleeping()) mActor.getPxActor()->wakeUp(); //Gravity fix Ogre::Vector3 playerHalfSize = mDimensions * 0.5f; PxTransform transform(OgrePhysX::toPx(owner->GetGlobalPosition()), OgrePhysX::toPx(owner->GetGlobalOrientation())); transform.p.y += playerHalfSize.y; //sweep filter data - only check against shapes with filter data DYNAMICBODY or STATICBODY PxSceneQueryFilterData filterData; filterData.data.word0 = CollisionGroups::DYNAMICBODY|CollisionGroups::STATICBODY; filterData.flags = PxSceneQueryFilterFlag::eDYNAMIC|PxSceneQueryFilterFlag::eSTATIC; //touches ground check PxBoxGeometry playerGeometry(playerHalfSize.x, playerHalfSize.y+0.1f, playerHalfSize.z); PxShape *outShape; mTouchesGround = Main::Instance().GetPhysXScene()->getPxScene()->overlapAny(playerGeometry, transform, outShape, filterData); //stair maxStepHeight float maxStepHeight = 0.6f; PxVec3 currPos = OgrePhysX::Convert::toPx(owner->GetGlobalPosition()); //feet capsule PxBoxGeometry feetVolume(playerHalfSize.x, maxStepHeight*0.5f, playerHalfSize.z); //body capsule float bodyHeight = mDimensions.y-maxStepHeight; PxBoxGeometry bodyVolume(playerHalfSize.x, bodyHeight*0.5f, playerHalfSize.z); PxVec3 sweepDirection = OgrePhysX::toPx(userDir); float userDirLength = sweepDirection.normalize(); /* We perform two sweeps: O ==> bodyHit? | ==> bodyHit? / \ ==> feetHit? If there are no hits character can walk in the desired direction. If there is a feetHit but no bodyHit player can climb stairs (we add an y-Offset). If there is a bodyHit the player can not move. */ PxSweepHit sweepHit; transform.p.y = owner->GetGlobalPosition().y + maxStepHeight + bodyHeight*0.5f; bool bodyHit = Main::Instance().GetPhysXScene()->getPxScene()->sweepSingle(bodyVolume, transform, sweepDirection, time*userDirLength, PxSceneQueryFlags(), sweepHit, filterData); transform.p.y = owner->GetGlobalPosition().y + maxStepHeight*0.5f; bool feetHit = Main::Instance().GetPhysXScene()->getPxScene()->sweepSingle(feetVolume, transform, sweepDirection, time*userDirLength, PxSceneQueryFlags(), sweepHit, filterData); if (!bodyHit) { finalDir += userDir; //add player movement if (feetHit) finalDir += Ogre::Vector3(0,3,0); //climb stairs } if (finalDir != Ogre::Vector3(0,0,0)) mActor.getPxActor()->setGlobalPose(PxTransform(currPos + OgrePhysX::Convert::toPx(finalDir*time))); if (mJumping && mTouchesGround && (timeGetTime() - mJumpStartTime > 400)) { mJumping = false; Msg jump_response; jump_response.typeID = ObjectMessageIDs::END_JUMP; BroadcastObjectMessage(jump_response); } } if (msg.typeID == GlobalMessageIDs::PHYSICS_END && !mFreezed) { SetOwnerPosition(mActor.getGlobalPosition()); //SetOwnerOrientation(mActor->getGlobalOrientation()); } if (msg.typeID == ObjectMessageIDs::UPDATE_CHARACTER_MOVEMENTSTATE) { mDirection = Ogre::Vector3(0,0,0); int movementFlags = msg.params.GetInt("CharacterMovementState"); if (movementFlags & CharacterMovement::FORWARD) mDirection.z += 1; if (movementFlags & CharacterMovement::BACKWARD) mDirection.z -= 1; if (movementFlags & CharacterMovement::LEFT) mDirection.x += 1; if (movementFlags & CharacterMovement::RIGHT) mDirection.x -= 1; mDirection.normalise(); mDirection*=(mMovementSpeed*mSpeedFactor); } if (msg.typeID == ObjectMessageIDs::INPUT_START_JUMP) { if (mTouchesGround && !mJumping) { mJumping = true; mJumpStartTime = timeGetTime(); mActor.getPxActor()->addForce(PxVec3(0, mActor.getPxActor()->getMass()*8, 0), PxForceMode::eIMPULSE); Msg startJumpMsg; startJumpMsg.typeID = ObjectMessageIDs::START_JUMP; BroadcastObjectMessage(startJumpMsg); } } if (msg.typeID == ObjectMessageIDs::CHARACTER_KILL) { mFreezed = true; } }
// PT: ray-capsule intersection code, originally from the old Magic Software library. PxU32 Gu::intersectRayCapsuleInternal(const PxVec3& origin, const PxVec3& dir, const PxVec3& p0, const PxVec3& p1, float radius, PxReal s[2]) { // set up quadratic Q(t) = a*t^2 + 2*b*t + c PxVec3 kW = p1 - p0; const float fWLength = kW.magnitude(); if(fWLength!=0.0f) kW /= fWLength; // PT: if the capsule is in fact a sphere, switch back to dedicated sphere code. // This is not just an optimization, the rest of the code fails otherwise. if(fWLength<=1e-6f) { const float d0 = (origin - p0).magnitudeSquared(); const float d1 = (origin - p1).magnitudeSquared(); const float approxLength = (PxMax(d0, d1) + radius)*2.0f; return PxU32(Gu::intersectRaySphere(origin, dir, approxLength, p0, radius, s[0])); } // generate orthonormal basis PxVec3 kU(0.0f); if (fWLength > 0.0f) { PxReal fInvLength; if ( PxAbs(kW.x) >= PxAbs(kW.y) ) { // W.x or W.z is the largest magnitude component, swap them fInvLength = PxRecipSqrt(kW.x*kW.x + kW.z*kW.z); kU.x = -kW.z*fInvLength; kU.y = 0.0f; kU.z = kW.x*fInvLength; } else { // W.y or W.z is the largest magnitude component, swap them fInvLength = PxRecipSqrt(kW.y*kW.y + kW.z*kW.z); kU.x = 0.0f; kU.y = kW.z*fInvLength; kU.z = -kW.y*fInvLength; } } PxVec3 kV = kW.cross(kU); kV.normalize(); // PT: fixed november, 24, 2004. This is a bug in Magic. // compute intersection PxVec3 kD(kU.dot(dir), kV.dot(dir), kW.dot(dir)); const float fDLength = kD.magnitude(); const float fInvDLength = fDLength!=0.0f ? 1.0f/fDLength : 0.0f; kD *= fInvDLength; const PxVec3 kDiff = origin - p0; const PxVec3 kP(kU.dot(kDiff), kV.dot(kDiff), kW.dot(kDiff)); const PxReal fRadiusSqr = radius*radius; // Is the velocity parallel to the capsule direction? (or zero) if ( PxAbs(kD.z) >= 1.0f - PX_EPS_REAL || fDLength < PX_EPS_REAL ) { const float fAxisDir = dir.dot(kW); const PxReal fDiscr = fRadiusSqr - kP.x*kP.x - kP.y*kP.y; if ( fAxisDir < 0 && fDiscr >= 0.0f ) { // Velocity anti-parallel to the capsule direction const PxReal fRoot = PxSqrt(fDiscr); s[0] = (kP.z + fRoot)*fInvDLength; s[1] = -(fWLength - kP.z + fRoot)*fInvDLength; return 2; } else if ( fAxisDir > 0 && fDiscr >= 0.0f ) { // Velocity parallel to the capsule direction const PxReal fRoot = PxSqrt(fDiscr); s[0] = -(kP.z + fRoot)*fInvDLength; s[1] = (fWLength - kP.z + fRoot)*fInvDLength; return 2; } else { // sphere heading wrong direction, or no velocity at all return 0; } } // test intersection with infinite cylinder PxReal fA = kD.x*kD.x + kD.y*kD.y; PxReal fB = kP.x*kD.x + kP.y*kD.y; PxReal fC = kP.x*kP.x + kP.y*kP.y - fRadiusSqr; PxReal fDiscr = fB*fB - fA*fC; if ( fDiscr < 0.0f ) { // line does not intersect infinite cylinder return 0; } PxU32 iQuantity = 0; if ( fDiscr > 0.0f ) { // line intersects infinite cylinder in two places const PxReal fRoot = PxSqrt(fDiscr); const PxReal fInv = 1.0f/fA; PxReal fT = (-fB - fRoot)*fInv; PxReal fTmp = kP.z + fT*kD.z; const float epsilon = 1e-3f; // PT: see TA35174 if ( fTmp >= -epsilon && fTmp <= fWLength+epsilon ) s[iQuantity++] = fT*fInvDLength; fT = (-fB + fRoot)*fInv; fTmp = kP.z + fT*kD.z; if ( fTmp >= -epsilon && fTmp <= fWLength+epsilon ) s[iQuantity++] = fT*fInvDLength; if ( iQuantity == 2 ) { // line intersects capsule wall in two places return 2; } } else { // line is tangent to infinite cylinder const PxReal fT = -fB/fA; const PxReal fTmp = kP.z + fT*kD.z; if ( 0.0f <= fTmp && fTmp <= fWLength ) { s[0] = fT*fInvDLength; return 1; } } // test intersection with bottom hemisphere // fA = 1 fB += kP.z*kD.z; fC += kP.z*kP.z; fDiscr = fB*fB - fC; if ( fDiscr > 0.0f ) { const PxReal fRoot = PxSqrt(fDiscr); PxReal fT = -fB - fRoot; PxReal fTmp = kP.z + fT*kD.z; if ( fTmp <= 0.0f ) { s[iQuantity++] = fT*fInvDLength; if ( iQuantity == 2 ) return 2; } fT = -fB + fRoot; fTmp = kP.z + fT*kD.z; if ( fTmp <= 0.0f ) { s[iQuantity++] = fT*fInvDLength; if ( iQuantity == 2 ) return 2; } } else if ( fDiscr == 0.0f ) { const PxReal fT = -fB; const PxReal fTmp = kP.z + fT*kD.z; if ( fTmp <= 0.0f ) { s[iQuantity++] = fT*fInvDLength; if ( iQuantity == 2 ) return 2; } } // test intersection with top hemisphere // fA = 1 fB -= kD.z*fWLength; fC += fWLength*(fWLength - 2.0f*kP.z); fDiscr = fB*fB - fC; if ( fDiscr > 0.0f ) { const PxReal fRoot = PxSqrt(fDiscr); PxReal fT = -fB - fRoot; PxReal fTmp = kP.z + fT*kD.z; if ( fTmp >= fWLength ) { s[iQuantity++] = fT*fInvDLength; if ( iQuantity == 2 ) return 2; } fT = -fB + fRoot; fTmp = kP.z + fT*kD.z; if ( fTmp >= fWLength ) { s[iQuantity++] = fT*fInvDLength; if ( iQuantity == 2 ) return 2; } } else if ( fDiscr == 0.0f ) { const PxReal fT = -fB; const PxReal fTmp = kP.z + fT*kD.z; if ( fTmp >= fWLength ) { s[iQuantity++] = fT*fInvDLength; if ( iQuantity == 2 ) return 2; } } return iQuantity; }
/** @brief vector 4개로 triangle 2개를 그리는 index buffer를 생성한다. @date 2014-01-30 */ void SampleRenderer::GenerateTriangleFrom4Vector2( void *positions, void *normals, void *bones, void *colors, PxU32 stride, PxU32 startVtxIdx, PxU16 *indices, PxU32 startIndexIdx, const PxVec3 ¢er, const vector<PxU16> &faceIndices, OUT vector<PxU16> &outfaceIndices ) { vector<PxU16> triangle0; triangle0.reserve(3); vector<PxU16> triangle1; triangle1.reserve(3); triangle0.push_back( faceIndices[ 0] ); triangle0.push_back( faceIndices[ 2] ); triangle0.push_back( faceIndices[ 3] ); triangle1.push_back( faceIndices[ 0] ); triangle1.push_back( faceIndices[ 1] ); triangle1.push_back( faceIndices[ 3] ); GenerateTriangleFrom3Vector(positions, normals, stride, center, triangle0, outfaceIndices); GenerateTriangleFrom3Vector(positions, normals, stride, center, triangle1, outfaceIndices); if (outfaceIndices.size() != 6) return; // error occur for (u_int i=0; i < outfaceIndices.size();) { const PxVec3 p0 = *(PxVec3*)(((PxU8*)positions) + (stride * outfaceIndices[ i])); const PxVec3 p1 = *(PxVec3*)(((PxU8*)positions) + (stride * outfaceIndices[ i+1])); const PxVec3 p2 = *(PxVec3*)(((PxU8*)positions) + (stride * outfaceIndices[ i+2])); *(PxVec3*)(((PxU8*)positions) + (stride * startVtxIdx)) = p0; *(PxVec3*)(((PxU8*)positions) + (stride * (startVtxIdx+1))) = p1; *(PxVec3*)(((PxU8*)positions) + (stride * (startVtxIdx+2))) = p2; if (bones) { const PxU32 b0 = *(PxU32*)(((PxU8*)bones) + (stride * outfaceIndices[ i])); const PxU32 b1 = *(PxU32*)(((PxU8*)bones) + (stride * outfaceIndices[ i+1])); const PxU32 b2 = *(PxU32*)(((PxU8*)bones) + (stride * outfaceIndices[ i+2])); *(PxU32*)(((PxU8*)bones) + (stride * startVtxIdx)) = b0; *(PxU32*)(((PxU8*)bones) + (stride * (startVtxIdx+1))) = b1; *(PxU32*)(((PxU8*)bones) + (stride * (startVtxIdx+2))) = b2; } if (colors) { const PxU32 c0 = *(PxU32*)(((PxU8*)colors) + (stride * outfaceIndices[ i])); const PxU32 c1 = *(PxU32*)(((PxU8*)colors) + (stride * outfaceIndices[ i+1])); const PxU32 c2 = *(PxU32*)(((PxU8*)colors) + (stride * outfaceIndices[ i+2])); *(PxU32*)(((PxU8*)colors) + (stride * startVtxIdx)) = c0; *(PxU32*)(((PxU8*)colors) + (stride * (startVtxIdx+1))) = c1; *(PxU32*)(((PxU8*)colors) + (stride * (startVtxIdx+2))) = c2; } if (normals) { PxVec3 v01 = p1 - p0; PxVec3 v02 = p2 - p0; v01.normalize(); v02.normalize(); PxVec3 n = v01.cross(v02); n.normalize(); n = -n; *(PxVec3*)(((PxU8*)normals) + (stride * startVtxIdx)) = n; *(PxVec3*)(((PxU8*)normals) + (stride * (startVtxIdx+1))) = n; *(PxVec3*)(((PxU8*)normals) + (stride * (startVtxIdx+2))) = n; } indices[ startIndexIdx] = startVtxIdx; indices[ startIndexIdx+1] = startVtxIdx+1; indices[ startIndexIdx+2] = startVtxIdx+2; startIndexIdx += 3; startVtxIdx += 3; i += 3; } }