PxRigidStatic* CPhysicManager::createStaticBox(const Vector3 &position, const Vector3 &dimensions, bool trigger, int group, const IPhysic *component) { assert(m_scene); PxVec3 p = Vector3ToPxVec3(position); PxVec3 d = Vector3ToPxVec3(dimensions); PxTransform pose(p); PxBoxGeometry geom(d); PxTransform localPose(PxVec3(0,dimensions.y,0)); PxRigidStatic *actor = PxCreateStatic(*m_physics,pose,geom,*m_defaultMaterial,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; }
physx::PxRigidStatic* CPhysicManager::createStaticSphere(const Vector3 &position, const float &radius, bool trigger, int group, const Logic::Component::IPhysic *component) { assert(m_scene); PxVec3 p = Vector3ToPxVec3(position); PxTransform pose(p); PxSphereGeometry geom(radius); PxRigidStatic *actor = PxCreateStatic(*m_physics,pose,geom,*m_defaultMaterial); 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 SampleParticles::createDrain() { float lakeHeight = 5.5f; //Creates a drain plane for the particles. This is good practice to avoid unnecessary //spreading of particles, which is bad for performance. The drain represents a lake in this case. { PxRigidStatic* actor = getPhysics().createRigidStatic(PxTransform(PxVec3(0.0f, lakeHeight - 1.0f, 0.0f), PxQuat(PxHalfPi, PxVec3(0,0,1)))); runtimeAssert(actor, "PxPhysics::createRigidStatic returned NULL\n"); PxShape* shape = actor->createShape(PxPlaneGeometry(), getDefaultMaterial()); runtimeAssert(shape, "PxRigidStatic::createShape returned NULL\n"); shape->setSimulationFilterData(collisionGroupDrain); shape->setFlags(PxShapeFlag::ePARTICLE_DRAIN | PxShapeFlag::eSIMULATION_SHAPE); getActiveScene().addActor(*actor); mPhysicsActors.push_back(actor); } //Creates the surface of the lake (the particles actually just collide with the underlaying drain). { PxBoxGeometry bg; bg.halfExtents = PxVec3(130.0f, lakeHeight + 1.0f, 130.0f); PxRigidStatic* actor = getPhysics().createRigidStatic(PxTransform(PxVec3(0.0f, 0.0f, 0.0f), PxQuat::createIdentity())); runtimeAssert(actor, "PxPhysics::createRigidStatic returned NULL\n"); PxShape* shape = actor->createShape(bg, getDefaultMaterial()); runtimeAssert(shape, "PxRigidStatic::createShape returned NULL\n"); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false); getActiveScene().addActor(*actor); mPhysicsActors.push_back(actor); createRenderObjectsFromActor(actor, getMaterial(MATERIAL_LAKE)); } }
void UDestructibleComponent::SetCollisionResponseForActor(const FCollisionResponse& ColResponse, PxRigidDynamic* Actor, int32 ChunkIdx) { // Get collision channel and response PxFilterData PQueryFilterData, PSimFilterData; uint8 MoveChannel = GetCollisionObjectType(); if(IsCollisionEnabled()) { AActor* Owner = GetOwner(); CreateShapeFilterData(MoveChannel, (Owner ? Owner->GetUniqueID() : 0), ColResponse.GetResponseContainer(), 0, ChunkIdxToBoneIdx(ChunkIdx), PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, BodyInstance.bNotifyRigidBodyCollision, false); PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision; SCOPED_SCENE_WRITE_LOCK(Actor->getScene()); TArray<PxShape*> Shapes; Shapes.AddUninitialized(Actor->getNbShapes()); int ShapeCount = Actor->getShapes(Shapes.GetTypedData(), Shapes.Num()); for (int32 i=0; i < ShapeCount; ++i) { PxShape* Shape = Shapes[i]; Shape->setQueryFilterData(PQueryFilterData); Shape->setSimulationFilterData(PSimFilterData); Shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true); Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); Shape->setFlag(PxShapeFlag::eVISUALIZATION, true); } } }
void PhysicsEngine::createPizzaPickup(physx::PxVec3 location, physx::PxF32 radius) { PxBoxGeometry geometry(radius, radius, radius); PxTransform transform(location, PxQuat::createIdentity()); PxMaterial* material = physics->createMaterial(0.5f, 0.5f, 0.5f); PxRigidStatic* actor = PxCreateStatic(*physics, transform, geometry, *material); PxShape* shape; actor->getShapes(&shape, 1); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true); shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false); scene->addActor(*actor); }
PxRigidDynamic* SampleParticles::Raygun::createRayCapsule(bool enableCollision, PxFilterData filterData) { PxRigidDynamic* actor = mSample->getPhysics().createRigidDynamic(PxTransform::createIdentity()); mSample->runtimeAssert(actor, "PxPhysics::createRigidDynamic returned NULL\n"); PxShape* shape = actor->createShape(PxCapsuleGeometry(0.1f, 150.0f), mSample->getDefaultMaterial()); mSample->runtimeAssert(shape, "PxRigidDynamic::createShape returned NULL\n"); shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, enableCollision); shape->setSimulationFilterData(filterData); actor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true); actor->setMass(1.0f); actor->setMassSpaceInertiaTensor(PxVec3(1.0f)); mSample->getActiveScene().addActor(*actor); return actor; }
// add some physics objects into the scene void AddPhyObjects() { PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0, 1, 0, 0), *gMaterial); gScene->addActor(*groundPlane); PxShape* shape = gPhysics->createShape(PxBoxGeometry(1.0f, 1.0f, 1.0f), *gMaterial); PxTransform localTm(PxVec3(-3.0f, 5.0f, 0.f)); PxRigidDynamic* body = gPhysics->createRigidDynamic(localTm); body->attachShape(*shape); PxRigidBodyExt::updateMassAndInertia(*body, 10.0f); gScene->addActor(*body); shape->release(); shape = gPhysics->createShape(PxSphereGeometry(1.0f), *gMaterial); PxTransform localTmS(PxVec3(3.0f, 5.0f, 0.f)); body = gPhysics->createRigidDynamic(localTmS); body->attachShape(*shape); PxRigidBodyExt::updateMassAndInertia(*body, 10.0f); gScene->addActor(*body); shape->release(); PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, PxTransform(PxVec3(0, 20, 20)), PxSphereGeometry(1), *gMaterial, 10.0f); dynamic->setAngularDamping(0.5f); dynamic->setLinearVelocity(PxVec3(0, -5, -10)); gScene->addActor(*dynamic); // add capsule into the scene shape = gPhysics->createShape(PxCapsuleGeometry(1.0f, 3.0f), *gMaterial); PxTransform localTmC(PxVec3(3.0f, 5.0f, -3.f)); body = gPhysics->createRigidDynamic(localTmC); body->attachShape(*shape); PxRigidBodyExt::updateMassAndInertia(*body, 10.0f); gScene->addActor(*body); // add a static box as the trigger shape = gPhysics->createShape(PxBoxGeometry(1.0f, 1.0f, 1.0f), *gMaterial); PxTransform localTmTrigger(PxVec3(0.0f, 1.0f, -10.f)); body = gPhysics->createRigidDynamic(localTmTrigger); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true); body->attachShape(*shape); body->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true); gScene->addActor(*body); shape->release(); }
PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk, const PxTransform& transform, const PxGeometry& geometry, PxMaterial& material, PxReal density, const PxTransform& shapeOffset) { PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid."); PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateKinematic: shapeOffset is not valid."); bool isDynGeom = isDynamicGeometry(geometry); if(isDynGeom && density <= 0.0f) return NULL; PxShape* shape; PxRigidDynamic* actor = setShape(sdk.createRigidDynamic(transform), geometry, material, shapeOffset, shape); if(actor) { actor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true); if(isDynGeom) PxRigidBodyExt::updateMassAndInertia(*actor, density); else { shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); actor->setMass(1); actor->setMassSpaceInertiaTensor(PxVec3(1,1,1)); } } return actor; }
void UDestructibleComponent::SetCollisionResponseForActor(PxRigidDynamic* Actor, int32 ChunkIdx, const FCollisionResponseContainer* ResponseOverride /*= NULL*/) { #if WITH_APEX if (ApexDestructibleActor == NULL) { return; } // Get collision channel and response PxFilterData PQueryFilterData, PSimFilterData; uint8 MoveChannel = GetCollisionObjectType(); if(IsCollisionEnabled()) { UDestructibleMesh* TheDestructibleMesh = GetDestructibleMesh(); AActor* Owner = GetOwner(); bool bLargeChunk = IsChunkLarge(ChunkIdx); const FCollisionResponseContainer& UseResponse = ResponseOverride == NULL ? (bLargeChunk ? LargeChunkCollisionResponse.GetResponseContainer() : SmallChunkCollisionResponse.GetResponseContainer()) : *ResponseOverride; physx::PxU32 SupportDepth = TheDestructibleMesh->ApexDestructibleAsset->getChunkDepth(ChunkIdx); const bool bEnableImpactDamage = IsImpactDamageEnabled(TheDestructibleMesh, SupportDepth); CreateShapeFilterData(MoveChannel, GetUniqueID(), UseResponse, 0, ChunkIdxToBoneIdx(ChunkIdx), PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, bEnableImpactDamage, false); PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision; SCOPED_SCENE_WRITE_LOCK(Actor->getScene()); TArray<PxShape*> Shapes; Shapes.AddUninitialized(Actor->getNbShapes()); int ShapeCount = Actor->getShapes(Shapes.GetData(), Shapes.Num()); for (int32 i=0; i < ShapeCount; ++i) { PxShape* Shape = Shapes[i]; Shape->setQueryFilterData(PQueryFilterData); Shape->setSimulationFilterData(PSimFilterData); Shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true); Shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); Shape->setFlag(PxShapeFlag::eVISUALIZATION, true); } } #endif }
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; }
void SampleNorthPole::setCCDActive(PxShape& shape) { shape.setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS,true); PxFilterData fd = shape.getSimulationFilterData(); fd.word3 |= CCD_FLAG; shape.setSimulationFilterData(fd); }
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; }
void Apex::LoadTriangleMesh(int numVerts, PxVec3* verts, ObjectInfo info) { PxRigidStatic* meshActor = mPhysics->createRigidStatic(PxTransform::createIdentity()); PxShape* meshShape; if(meshActor) { PxTriangleMeshDesc meshDesc; meshDesc.points.count = numVerts; meshDesc.points.stride = sizeof(PxVec3); meshDesc.points.data = verts; //meshDesc.triangles.count = numInds/3.; //meshDesc.triangles.stride = 3*sizeof(int); //meshDesc.triangles.data = inds; PxToolkit::MemoryOutputStream writeBuffer; bool status = mCooking->cookTriangleMesh(meshDesc, writeBuffer); if(!status) return; PxToolkit::MemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize()); PxTriangleMeshGeometry triGeom; triGeom.triangleMesh = mPhysics->createTriangleMesh(readBuffer); triGeom.scale = PxMeshScale(PxVec3(info.sx,info.sy,info.sz),physx::PxQuat::createIdentity()); meshShape = meshActor->createShape(triGeom, *defaultMaterial); meshShape->setLocalPose(PxTransform(PxVec3(info.x,info.y,info.z), PxQuat(info.ry, PxVec3(0.0f,1.0f,0.0f)))); meshShape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, true); meshShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); mScene[mCurrentScene]->addActor(*meshActor); } }
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; }
PxActor* addSimpleObject( PxScene* scene, PxPhysics* physics, PxTransform* transform, PxGeometry* geometry, PxMaterial* material, bool isStatic, bool isKinematic ) { PxActor* actor; if( isStatic ) actor = physics->createRigidStatic( *transform ); else { actor = physics->createRigidDynamic( *transform ); ((PxRigidDynamic*)(actor))->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, isKinematic); } PxShape* shape = ((PxRigidBody*)(actor))->createShape( *geometry, *material ); if( isKinematic ) shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); scene->addActor( *actor ); return actor; }
PxRigidActor* SampleSubmarine::loadTerrain(const char* name, const PxReal heightScale, const PxReal rowScale, const PxReal columnScale) { PxRigidActor* heightFieldActor = NULL; BmpLoader loader; if(loader.loadBmp(getSampleMediaFilename(name))) { PxU16 nbColumns = PxU16(loader.mWidth), nbRows = PxU16(loader.mHeight); PxHeightFieldDesc heightFieldDesc; heightFieldDesc.nbColumns = nbColumns; heightFieldDesc.nbRows = nbRows; PxU32* samplesData = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*nbColumns * nbRows); heightFieldDesc.samples.data = samplesData; heightFieldDesc.samples.stride = sizeof(PxU32); PxU8* currentByte = (PxU8*)heightFieldDesc.samples.data; PxU8* loader_ptr = loader.mRGB; PxVec3Alloc* vertexesA = SAMPLE_NEW(PxVec3Alloc)[nbRows * nbColumns]; PxF32* uvs = (PxF32*)SAMPLE_ALLOC(sizeof(PxF32) * nbRows * nbColumns * 2); PxVec3* vertexes = vertexesA; for (PxU32 row = 0; row < nbRows; row++) { for (PxU32 column = 0; column < nbColumns; column++) { PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte; currentSample->height = *loader_ptr; vertexes[row * nbColumns + column] = PxVec3(PxReal(row)*rowScale, PxReal(currentSample->height * heightScale), PxReal(column)*columnScale); uvs[(row * nbColumns + column)*2 + 0] = (float)column/7.0f; uvs[(row * nbColumns + column)*2 + 1] = (float)row/7.0f; currentSample->materialIndex0 = 0; currentSample->materialIndex1 = 0; currentSample->clearTessFlag(); currentByte += heightFieldDesc.samples.stride; loader_ptr += 3 * sizeof(PxU8); } } PxHeightField* heightField = getPhysics().createHeightField(heightFieldDesc); if(!heightField) fatalError("createHeightField failed!"); // create shape for heightfield PxTransform pose(PxVec3(-((PxReal)nbRows*rowScale) / 2.0f, 0.0f, -((PxReal)nbColumns*columnScale) / 2.0f), PxQuat::createIdentity()); heightFieldActor = getPhysics().createRigidStatic(pose); if(!heightFieldActor) fatalError("createRigidStatic failed!"); PxShape* shape = heightFieldActor->createShape(PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), heightScale, rowScale, columnScale), getDefaultMaterial()); if(!shape) fatalError("createShape failed!"); // add actor to the scene getActiveScene().addActor(*heightFieldActor); // create indices PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*((nbColumns - 1) * (nbRows - 1) * 3 * 2)); for(int i = 0; i < (nbColumns - 1); ++i) { for(int j = 0; j < (nbRows - 1); ++j) { // first triangle indices[6 * (i * (nbRows - 1) + j) + 0] = (i + 1) * nbRows + j; indices[6 * (i * (nbRows - 1) + j) + 1] = i * nbRows + j; indices[6 * (i * (nbRows - 1) + j) + 2] = i * nbRows + j + 1; // second triangle indices[6 * (i * (nbRows - 1) + j) + 3] = (i + 1) * nbRows + j + 1; indices[6 * (i * (nbRows - 1) + j) + 4] = (i + 1) * nbRows + j; indices[6 * (i * (nbRows - 1) + j) + 5] = i * nbRows + j + 1; } } // add mesh to renderer RAWMesh data; data.mName = name; data.mTransform = PxTransform::createIdentity(); data.mNbVerts = nbColumns * nbRows; data.mVerts = vertexes; data.mVertexNormals = NULL; data.mUVs = uvs; data.mMaterialID = MATERIAL_TERRAIN_MUD; data.mNbFaces = (nbColumns - 1) * (nbRows - 1) * 2; data.mIndices = indices; RenderMeshActor* hf_mesh = createRenderMeshFromRawMesh(data); if(!hf_mesh) fatalError("createRenderMeshFromRawMesh failed!"); hf_mesh->setPhysicsShape(shape); shape->setFlag(PxShapeFlag::eVISUALIZATION, false); SAMPLE_FREE(indices); SAMPLE_FREE(uvs); DELETEARRAY(vertexesA); SAMPLE_FREE(samplesData); } return heightFieldActor; }
void PhysX::CreateShapes(const PINT_OBJECT_CREATE& desc, PxRigidActor* actor) { ASSERT(actor); ASSERT(mDefaultMaterial); const PINT_SHAPE_CREATE* CurrentShape = desc.mShapes; while(CurrentShape) { PxTransform LocalPose; LocalPose.p = ToPxVec3(CurrentShape->mLocalPos); LocalPose.q = ToPxQuat(CurrentShape->mLocalRot); PxMaterial* ShapeMaterial = mDefaultMaterial; if(CurrentShape->mMaterial) { ShapeMaterial = CreateMaterial(*CurrentShape->mMaterial); ASSERT(ShapeMaterial); } PxShape* shape = null; if(CurrentShape->mType==PINT_SHAPE_SPHERE) { const PINT_SPHERE_CREATE* SphereCreate = static_cast<const PINT_SPHERE_CREATE*>(CurrentShape); shape = actor->createShape(PxSphereGeometry(SphereCreate->mRadius), *ShapeMaterial, LocalPose); ASSERT(shape); } else if(CurrentShape->mType==PINT_SHAPE_BOX) { const PINT_BOX_CREATE* BoxCreate = static_cast<const PINT_BOX_CREATE*>(CurrentShape); shape = actor->createShape(PxBoxGeometry(ToPxVec3(BoxCreate->mExtents)), *ShapeMaterial, LocalPose); ASSERT(shape); } else if(CurrentShape->mType==PINT_SHAPE_CAPSULE) { const PINT_CAPSULE_CREATE* CapsuleCreate = static_cast<const PINT_CAPSULE_CREATE*>(CurrentShape); /* // ### PhysX is weird with capsules Matrix3x3 Rot; Rot.RotY(HALFPI); LocalPose.q *= ToPxQuat(Quat(Rot)); */ const PxQuat q = PxShortestRotation(PxVec3(1.0f, 0.0f, 0.0f), PxVec3(0.0f, 1.0f, 0.0f)); LocalPose.q *= q; shape = actor->createShape(PxCapsuleGeometry(CapsuleCreate->mRadius, CapsuleCreate->mHalfHeight), *ShapeMaterial, LocalPose); ASSERT(shape); } else if(CurrentShape->mType==PINT_SHAPE_CONVEX) { const PINT_CONVEX_CREATE* ConvexCreate = static_cast<const PINT_CONVEX_CREATE*>(CurrentShape); ASSERT(mCooking); // PxConvexMesh* ConvexMesh = CreateConvexMesh(ConvexCreate->mVerts, ConvexCreate->mNbVerts, PxConvexFlag::eCOMPUTE_CONVEX|PxConvexFlag::eINFLATE_CONVEX, CurrentShape->mRenderer); PxConvexMesh* ConvexMesh = CreateConvexMesh(ConvexCreate->mVerts, ConvexCreate->mNbVerts, PxConvexFlag::eCOMPUTE_CONVEX, CurrentShape->mRenderer); ASSERT(ConvexMesh); shape = actor->createShape(PxConvexMeshGeometry(ConvexMesh), *ShapeMaterial, LocalPose); ASSERT(shape); } else if(CurrentShape->mType==PINT_SHAPE_MESH) { const PINT_MESH_CREATE* MeshCreate = static_cast<const PINT_MESH_CREATE*>(CurrentShape); ASSERT(mCooking); PxTriangleMesh* TriangleMesh = CreateTriangleMesh(MeshCreate->mSurface, CurrentShape->mRenderer); ASSERT(TriangleMesh); shape = actor->createShape(PxTriangleMeshGeometry(TriangleMesh), *ShapeMaterial, LocalPose); ASSERT(shape); } else ASSERT(0); if(shape) { SetupShape(mParams, CurrentShape, *shape, desc.mCollisionGroup, gDebugVizParams[0]); shape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, mParams.mUseCCD); } CurrentShape = CurrentShape->mNext; } }
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::loadTerrain(const char* path, PxReal xScale, PxReal yScale, PxReal zScale) { SampleFramework::SampleAsset* asset = getAsset(terrain_hf, SampleFramework::SampleAsset::ASSET_TEXTURE); mManagedAssets.push_back(asset); PX_ASSERT(asset->getType() == SampleFramework::SampleAsset::ASSET_TEXTURE); SampleFramework::SampleTextureAsset* texAsset = static_cast<SampleFramework::SampleTextureAsset*>(asset); SampleRenderer::RendererTexture2D* heightfieldTexture = texAsset->getTexture(); // NOTE: Assuming that heightfield texture has B8G8R8A8 format. if(heightfieldTexture) { PxU16 nbColumns = PxU16(heightfieldTexture->getWidth()); PxU16 nbRows = PxU16(heightfieldTexture->getHeight()); PxHeightFieldDesc heightFieldDesc; heightFieldDesc.nbColumns = nbColumns; heightFieldDesc.nbRows = nbRows; PxU32* samplesData = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32) * nbColumns * nbRows); heightFieldDesc.samples.data = samplesData; heightFieldDesc.samples.stride = sizeof(PxU32); heightFieldDesc.convexEdgeThreshold = 0; PxU8* currentByte = (PxU8*)heightFieldDesc.samples.data; PxU32 texturePitch = 0; PxU8* loaderPtr = static_cast<PxU8*>(heightfieldTexture->lockLevel(0, texturePitch)); PxVec3Alloc* verticesA = SAMPLE_NEW(PxVec3Alloc)[nbRows * nbColumns]; PxVec3* vertices = verticesA; PxReal* UVs = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal) * nbRows * nbColumns * 2); for (PxU32 row = 0; row < nbRows; row++) { for (PxU32 column = 0; column < nbColumns; column++) { PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte; currentSample->height = *loaderPtr; vertices[row * nbColumns + column] = PxVec3(PxReal(row) * xScale, PxReal(currentSample->height * zScale), PxReal(column) * yScale); UVs[2 * (row * nbColumns + column)] = (PxReal(row) / PxReal(nbRows)) * 7.0f; UVs[2 * (row * nbColumns + column) + 1] = (PxReal(column) / PxReal(nbColumns)) * 7.0f; currentSample->materialIndex0 = 0; currentSample->materialIndex1 = 0; currentSample->clearTessFlag(); currentByte += heightFieldDesc.samples.stride; loaderPtr += 4 * sizeof(PxU8); } } PxHeightField* heightField = getPhysics().createHeightField(heightFieldDesc); // free allocated memory for heightfield samples description SAMPLE_FREE(samplesData); // create shape for heightfield PxTransform pose(PxVec3(-((PxReal)nbRows*yScale) / 2.0f, 0.0f, -((PxReal)nbColumns*xScale) / 2.0f), PxQuat::createIdentity()); PxRigidActor* hf = getPhysics().createRigidStatic(pose); runtimeAssert(hf, "PxPhysics::createRigidStatic returned NULL\n"); PxShape* shape = hf->createShape(PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), zScale, xScale, yScale), getDefaultMaterial()); runtimeAssert(shape, "PxRigidActor::createShape returned NULL\n"); shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, false); shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); // add actor to the scene getActiveScene().addActor(*hf); mPhysicsActors.push_back(hf); // create indices and UVs PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32) * (nbColumns - 1) * (nbRows - 1) * 3 * 2); for(int i = 0; i < (nbColumns - 1); ++i) { for(int j = 0; j < (nbRows - 1); ++j) { // first triangle indices[6 * (i * (nbRows - 1) + j) + 0] = (i + 1) * nbRows + j; indices[6 * (i * (nbRows - 1) + j) + 1] = i * nbRows + j; indices[6 * (i * (nbRows - 1) + j) + 2] = i * nbRows + j + 1; // second triangle indices[6 * (i * (nbRows - 1) + j) + 3] = (i + 1) * nbRows + j + 1; indices[6 * (i * (nbRows - 1) + j) + 4] = (i + 1) * nbRows + j; indices[6 * (i * (nbRows - 1) + j) + 5] = i * nbRows + j + 1; } } // add mesh to renderer RAWMesh data; data.mName = "terrain"; data.mTransform = PxTransform::createIdentity(); data.mNbVerts = nbColumns * nbRows; data.mVerts = (PxVec3*)vertices; data.mVertexNormals = NULL; data.mUVs = UVs; data.mMaterialID = MATERIAL_HEIGHTFIELD; data.mNbFaces = (nbColumns - 1) * (nbRows - 1) * 2; data.mIndices = indices; RenderMeshActor* hf_mesh = createRenderMeshFromRawMesh(data); hf_mesh->setPhysicsShape(shape); SAMPLE_FREE(indices); SAMPLE_FREE(UVs); DELETEARRAY(verticesA); } else { char errMsg[256]; physx::string::sprintf_s(errMsg, 256, "Couldn't load %s\n", path); fatalError(errMsg); } }
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; } }
void SampleSubmarine::createDynamicActors() { // create mines static const PxU32 numMines = 20; static const PxVec3 mineFieldCenter = PxVec3(0, 64, 0); static const PxReal minMineDistance = 3.0f; static const PxI32 mineFieldRadius = 30; for(PxU32 i = 0; i < numMines; i++) { // raycast against floor (height field) to find the height to attach the mine PxRaycastHit rayHit; bool hit = false; do { PxVec3 offset = PxVec3(PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius)), 0, PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius))); PxVec3 raycastStart = mineFieldCenter + offset*minMineDistance; hit = getActiveScene().raycastSingle(raycastStart, PxVec3(0,-1,0), 100.0f, PxSceneQueryFlag::eIMPACT, rayHit); } while(!hit || (rayHit.impact.y > 25.0f) || rayHit.shape->getActor().is<PxRigidDynamic>()); createSeamine(rayHit.impact, getSampleRandom().rand(10.0f, 25.0f)); } // create treasure { static const PxVec3 treasureDim = PxVec3(5, 3, 4)*0.5f; PxRaycastHit rayHit; PxVec3 raycastStart = PxVec3(-19, 64, -24); getActiveScene().raycastSingle(raycastStart, PxVec3(0,-1,0), 100.0f, PxSceneQueryFlag::eIMPACT, rayHit); #ifdef RENDERER_PSP2 gTreasureActor = createBox(rayHit.impact+treasureDim, treasureDim, NULL, mTreasureMaterial, 1)->is<PxRigidDynamic>(); #else gTreasureActor = createBox(rayHit.impact+treasureDim, treasureDim, NULL, mManagedMaterials[MATERIAL_BLUE], 1)->is<PxRigidDynamic>(); #endif if(!gTreasureActor) fatalError("createBox failed!"); gTreasureActor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true); PxShape* treasureShape; gTreasureActor->getShapes(&treasureShape, 1); treasureShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); treasureShape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true); } // create submarine createSubmarine(PxVec3(-110, 50, 110), 2.1f); char theCrabName[256]; sprintf(theCrabName, "crab_%s.bin", getPlatformName()); // If we have already had crab copy, just load it, or will create crab and export it char thePathBuffer[1024]; const char* theCrabPath = getSampleOutputDirManager().getFilePath( theCrabName, thePathBuffer, false ); FILE *fp = fopen( theCrabPath, "r" ); if( fp ) { printf("loading the crab from file status: "); gCrab = SAMPLE_NEW(Crab)(*this, theCrabPath, mManagedMaterials[MATERIAL_RED]); if (gCrab && !gCrab->getCrabBody()) { delete gCrab; gCrab = NULL; } printf(gCrab ? "successful\n":"failed\n"); fclose (fp); } if( !gCrab ) { gCrab = SAMPLE_NEW(Crab)(*this, PxVec3(0, 50, 0), mManagedMaterials[MATERIAL_RED]); printf("crab file not found ... exporting crab file\n"); gCrab->save(theCrabPath); } PX_ASSERT( gCrab ); mCrabs.push_back(gCrab); static const PxU32 numCrabs = 3; for(PxU32 i = 0; i < numCrabs; i++) { Crab* crab = SAMPLE_NEW(Crab)(*this, PxVec3(getSampleRandom().rand(-20.0f,20.0f), 50, getSampleRandom().rand(-20.0f,20.0f)), mManagedMaterials[MATERIAL_RED]); mCrabs.push_back(crab); } }
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; }