//----------------------------------------------------------------------- void PhysXActorExtern::_processParticle( ParticleTechnique* particleTechnique, Particle* particle, Ogre::Real timeElapsed, bool firstParticle) { // Only update after a PhysX simulation step if (mSynchronize) { if (particle->particleType != Particle::PT_VISUAL) return; if (!particle->physicsActor) return; VisualParticle* visualParticle = static_cast<VisualParticle*>(particle); PhysXActor* physXActor = static_cast<PhysXActor*>(particle->physicsActor); NxActor* nxActor = physXActor->nxActor; if (nxActor) { // Synchronize both the particle and the pysicsActor with the nxActor particle->position = PhysXMath::convert(nxActor->getGlobalPosition()); particle->direction = PhysXMath::convert(nxActor->getLinearVelocity()); visualParticle->orientation = PhysXMath::convert(nxActor->getGlobalOrientationQuat()); physXActor->position = particle->position; physXActor->direction = particle->direction; physXActor->orientation = visualParticle->orientation; if (nxActor->getNbShapes()) { NxShape *shape = nxActor->getShapes()[0]; // Max one. switch(shape->getType()) { case NX_SHAPE_BOX: (static_cast<NxBoxShape*>(shape))->setDimensions( PhysXMath::convert(0.5 * Ogre::Vector3( visualParticle->width, visualParticle->height, visualParticle->depth))); break; case NX_SHAPE_SPHERE: (static_cast<NxSphereShape*>(shape))->setRadius(0.5f * visualParticle->width); break; case NX_SHAPE_CAPSULE: { (static_cast<NxCapsuleShape*>(shape))->setRadius(0.5f * visualParticle->width); (static_cast<NxCapsuleShape*>(shape))->setHeight(0.5f * visualParticle->height); } break; } } } } }
void AddUserDataToShapes(NxActor* actor) { NxU32 i = 0; NxShape*const* shapes = actor->getShapes(); NxU32 nbShapes = actor->getNbShapes(); while (nbShapes--) { NxShape* shape = shapes[nbShapes]; shape->userData = new ShapeUserData; ShapeUserData* sud = (ShapeUserData*)(shape->userData); sud->id = i++; if (shape->getType() == NX_SHAPE_CONVEX) { sud->mesh = new NxConvexMeshDesc; shape->isConvexMesh()->getConvexMesh().saveToDesc(*(NxConvexMeshDesc*)sud->mesh); } if (shape->getType() == NX_SHAPE_MESH) { sud->mesh = new NxTriangleMeshDesc; shape->isTriangleMesh()->getTriangleMesh().saveToDesc(*(NxTriangleMeshDesc*)sud->mesh); } } }
void Part::render() { assert(act && "partrender: physics equivalent invalid"); glPushMatrix(); float glMat[16]; NxActor* actor; actor=act; if(NULL==actor) return; actor->getGlobalPose().getColumnMajor44(glMat); glMultMatrixf(glMat); if(actor->userData!=NULL && gRenderUserData) { glPushMatrix(); ((GraphicsObject*)actor->userData)->render(); glPopMatrix(); } else { //render according to shape descriptions in actor for(unsigned s=0; s < actor->getNbShapes(); s++) { NxShape *shape = actor->getShapes()[s]; glPushMatrix(); shape->getLocalPose().getColumnMajor44(glMat); glMultMatrixf(glMat); //render shapes if(shape->getFlag(NX_TRIGGER_ENABLE)) { //do nothing, triggers are not to be rendered and have different userdata } else if(shape->userData!=NULL) { ((GraphicsObject*)shape->userData)->render(); } else { NxShapeType type=shape->getType(); if(NX_SHAPE_BOX==type) { NxBoxShape *sh=(NxBoxShape *)shape; NxVec3 dim=sh->getDimensions(); BoxGraphicsObject g(dim.x,dim.z,dim.y); //wrond dimensions g.render(); } else if(NX_SHAPE_CAPSULE==type) { NxCapsuleShape *sh=(NxCapsuleShape *)shape; float radius=sh->getRadius(); float height=sh->getHeight(); CapsuleGraphicsObject g(radius,height); g.render(); } else if(NX_SHAPE_SPHERE==type) { NxSphereShape *sh=(NxSphereShape *)shape; float radius=sh->getRadius(); SphereGraphicsObject g(radius); g.render(); } else { //render a default sphere if shape type unknown SphereGraphicsObject sg(1); sg.render(); } } glPopMatrix(); } } glPopMatrix(); }
void CPhysicsActor::SetScale( Vec3& scale ) { // do not scale if scale is currently 1:1 or if the scale // has not changed if( scale.x == 1 && scale.y == 1 && scale.z == 1 || scale == m_CurrentScale ) { return; } // make sure the scale is valid // No 0 scales or negative scales! if( scale.x <= 0 && scale.y <= 0 && scale.z <= 0 ) { m_ToolBox->Log( LOGWARNING, _T("CPhysicsActor::SetScale() Invalid scale!\n" ) ); return; } NxVec3 newScale( scale.x, scale.y, scale.z ); // unscale the old scale // Loop through shapes in the actor unsigned int numShapes = m_Actor->getNbShapes(); NxShape*const* shapes = m_Actor->getShapes(); NxShape* currentShape; NxVec3 shapeLocalPosition; // for each shape type scale its dimensions while( numShapes-- >= 1 ) { currentShape = shapes[numShapes]; // get the shape's type NxShapeType type = currentShape->getType(); switch( type ) { case NX_SHAPE_BOX: { // do something NxBoxShape* shape = (NxBoxShape*)currentShape; // rescale box dimensions NxVec3 dimensions = shape->getDimensions(); Vec3 newDimensions(dimensions.x, dimensions.y, dimensions.z); RescaleVector( newDimensions, scale ); // set the shape data with the newly rescaled dimensions shape->setDimensions( NxVec3(newDimensions.x, newDimensions.y, newDimensions.z) ); break; } case NX_SHAPE_SPHERE: { // do something NxSphereShape* shape = (NxSphereShape*)currentShape; float radius = shape->getRadius(); radius /= m_CurrentScale.x; radius *= newScale.x; // set the shape data with the newly rescaled dimensions shape->setRadius( radius ); break; } case NX_SHAPE_CAPSULE: { // do something NxCapsuleShape* shape; shape = (NxCapsuleShape*)currentShape; // rescale radius float radius = shape->getRadius(); radius /= m_CurrentScale.x; radius *= newScale.x; // rescale height float height = shape->getHeight(); height /= m_CurrentScale.z; height *= newScale.z; // set the shape data with the newly rescaled dimensions shape->setRadius( radius ); shape->setHeight( height ); break; } default: m_ToolBox->Log( LOGWARNING, _T("CPhysicsObject::SetScale() Attempting to scale on unsupported shape!\n" ) ); return; } // get the shape's local position and rescale it shapeLocalPosition = currentShape->getLocalPosition(); Vec3 newShapeLocalPosition(shapeLocalPosition.x, shapeLocalPosition.y, shapeLocalPosition.z); RescaleVector( newShapeLocalPosition, scale ); currentShape->setLocalPosition( NxVec3(newShapeLocalPosition.x, newShapeLocalPosition.y, newShapeLocalPosition.z) ); } // Set the current scale to the new scale so we can unscale the scale m_CurrentScale = scale; }
void UpdateWheelShapeUserData() { // Look for wheel shapes NxU32 nbActors = gScene->getNbActors(); NxActor** actors = gScene->getActors(); while (nbActors--) { NxU32 nbShapes = actors[nbActors]->getNbShapes(); NxShape*const* shapes = actors[nbActors]->getShapes(); while (nbShapes--) { NxShape* shape = shapes[nbShapes]; if (shape->getType() == NX_SHAPE_WHEEL) { NxWheelShape* ws = (NxWheelShape*)shape; ShapeUserData* sud = (ShapeUserData*)(shape->userData); if (sud) { // Need to save away roll angle in wheel shape user data NxReal rollAngle = sud->wheelShapeRollAngle; // rollAngle += ws->getAxleSpeed() * 1.0f/60.0f; rollAngle += ws->getAxleSpeed() * gDeltaTime; while (rollAngle > NxTwoPi) //normally just 1x rollAngle -= NxTwoPi; while (rollAngle < -NxTwoPi) //normally just 1x rollAngle += NxTwoPi; // We have the roll angle for the wheel now sud->wheelShapeRollAngle = rollAngle; NxMat34 pose; pose = ws->getGlobalPose(); NxWheelContactData wcd; NxShape* s = ws->getContact(wcd); NxReal r = ws->getRadius(); NxReal st = ws->getSuspensionTravel(); NxReal steerAngle = ws->getSteerAngle(); // NxWheelShapeDesc state; // ws->saveToDesc(state); NxVec3 p0; NxVec3 dir; /* getWorldSegmentFast(seg); seg.computeDirection(dir); dir.normalize(); */ p0 = pose.t; //cast from shape origin pose.M.getColumn(1, dir); dir = -dir; //cast along -Y. NxReal castLength = r + st; //cast ray this long // renderer.addArrow(p0, dir, castLength, 1.0f); //have ground contact? // This code is from WheelShape.cpp in SDKs/core/common/src // if (contactPosition != NX_MAX_REAL) if (s && wcd.contactForce > -1000) { // pose.t = p0 + dir * wcd.contactPoint; // pose.t -= dir * state.radius; //go from contact pos to center pos. pose.t = wcd.contactPoint; pose.t -= dir * r; //go from contact pos to center pos. NxMat33 rot, axisRot; rot.rotY(steerAngle); axisRot.rotY(0); // NxReal rollAngle = ((ShapeUserData*)(wheel->userData))->rollAngle; NxMat33 rollRot; rollRot.rotX(rollAngle); pose.M = rot * pose.M * axisRot * rollRot; sud->wheelShapePose = pose; } else { pose.t = p0 + dir * st; sud->wheelShapePose = pose; } } } } } }
bool FindTouchedGeometry( void* user_data, const NxExtendedBounds3& worldBounds, // ### we should also accept other volumes TriArray& world_triangles, TriArray* world_edge_normals, IntArray& edge_flags, IntArray& geom_stream, NxU32 group_flags, bool static_shapes, bool dynamic_shapes, const NxGroupsMask* groupsMask) { NX_ASSERT(user_data); NxScene* scene = (NxScene*)user_data; NxExtendedVec3 Origin; // Will be TouchedGeom::mOffset worldBounds.getCenter(Origin); // Reserve a stack buffer big enough to hold all shapes in the world. This is a lazy approach that is // acceptable here since the total number of shapes is limited to 64K anyway, which would "only" consume // 256 Kb on the stack (hence, stack overflow is unlikely). // ### TODO: the new callback mechanism would allow us to use less memory here // NxU32 total = scene->getNbStaticShapes() + scene->getNbDynamicShapes(); NxU32 total = scene->getTotalNbShapes(); NxShape** buffer = (NxShape**)NxAlloca(total*sizeof(NxShape*)); // Find touched *boxes* i.e. touched objects' AABBs in the world // We collide against dynamic shapes too, to get back dynamic boxes/etc // TODO: add active groups in interface! NxU32 Flags = 0; if(static_shapes) Flags |= NX_STATIC_SHAPES; if(dynamic_shapes) Flags |= NX_DYNAMIC_SHAPES; // ### this one is dangerous NxBounds3 tmpBounds; // LOSS OF ACCURACY tmpBounds.min.x = (float)worldBounds.min.x; tmpBounds.min.y = (float)worldBounds.min.y; tmpBounds.min.z = (float)worldBounds.min.z; tmpBounds.max.x = (float)worldBounds.max.x; tmpBounds.max.y = (float)worldBounds.max.y; tmpBounds.max.z = (float)worldBounds.max.z; NxU32 nbTouchedBoxes = scene->overlapAABBShapes(tmpBounds, NxShapesType(Flags), total, buffer, NULL, group_flags, groupsMask); // Early exit if no AABBs found if(!nbTouchedBoxes) return false; NX_ASSERT(nbTouchedBoxes<=total); // Else we just trashed some stack memory // Loop through touched world AABBs NxShape** touched = buffer; while(nbTouchedBoxes--) { // Get current shape NxShape* shape = *touched++; // Filtering // Discard all CCT shapes, i.e. kinematic actors we created ourselves. We don't need to collide with them since they're surrounded // by the real CCT volume - and collisions with those are handled elsewhere. We use the userData field for filtering because that's // really our only valid option (filtering groups are already used by clients and we don't have control over them, clients might // create other kinematic actors that we may want to keep here, etc, etc) if(size_t(shape->userData)=='CCTS') continue; // Discard if not collidable // PT: this shouldn't be possible at this point since: // - the SF flag is only used for compounds // - the AF flag is already tested in scene query // - we shouldn't get compound shapes here if(shape->getFlag(NX_SF_DISABLE_COLLISION)) continue; // Ubi (EA) : Discarding Triggers : if ( shape->getFlag(NX_TRIGGER_ENABLE) ) continue; // PT: here you might want to disable kinematic objects. // Output shape to stream NxShapeType type = shape->getType(); if(type==NX_SHAPE_SPHERE) outputSphereToStream((NxSphereShape*)shape, shape, geom_stream, Origin); else if(type==NX_SHAPE_CAPSULE) outputCapsuleToStream((NxCapsuleShape*)shape, shape, geom_stream, Origin); else if(type==NX_SHAPE_BOX) outputBoxToStream((NxBoxShape*)shape, shape, geom_stream, Origin); else if(type==NX_SHAPE_MESH) outputMeshToStream((NxTriangleMeshShape*)shape, shape, geom_stream, world_triangles, world_edge_normals, edge_flags, Origin, tmpBounds); else if(type==NX_SHAPE_HEIGHTFIELD) outputHeightFieldToStream((NxHeightFieldShape*)shape, shape, geom_stream, world_triangles, world_edge_normals, edge_flags, Origin, tmpBounds); else if(type==NX_SHAPE_CONVEX) outputConvexToStream((NxConvexShape*)shape, shape, geom_stream, world_triangles, world_edge_normals, edge_flags, Origin, tmpBounds); } return true; }