void PhysXHeightfield::InitHeightfield(PxPhysics* physics, PxScene* scene, const char* filename) { float xScale = 0.0025f; float yScale = 0.0025f; float zScale = 10.00f; // NOTE: Assuming that heightfield texture has B8G8R8A8 format. if(LoadHeightfield(filename)) { PxU16 nbColumns = PxU16(mHeightfield.width); PxU16 nbRows = PxU16(mHeightfield.height); PxHeightFieldDesc heightFieldDesc; heightFieldDesc.format = PxHeightFieldFormat::eS16_TM; heightFieldDesc.nbColumns = nbColumns; heightFieldDesc.nbRows = nbRows; heightFieldDesc.samples.data = mHeightfield.data; heightFieldDesc.samples.stride = sizeof(PxHeightFieldSample); //heightFieldDesc.convexEdgeThreshold = 0; PxHeightField* heightField = physics->createHeightField(heightFieldDesc); // create shape for heightfield PxTransform pose(PxVec3(-((PxReal)nbRows*yScale) / 2.0f, 0.0f, -((PxReal)nbColumns*xScale) / 2.0f), PxQuat::createIdentity()); // PxTransform pose = PxTransform::createIdentity(); pose.p = PxVec3(-((nbColumns/2)*xScale),0.0,-((nbColumns/2)*xScale)); PxRigidActor* hf = physics->createRigidStatic(pose); if(!hf) return; const PxMaterial* mMat = physics->createMaterial(0.9f, 0.9f, 0.001f); //PxShape* shape = hf->createShape((PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), yScale, xScale, xScale)), *mMat); //PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, rowScale, colScale); //PxShape* aHeightFieldShape = aHeightFieldActor->createShape(hfGeom, aMaterialArray, nbMaterials); PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), yScale, xScale, xScale); PxShape* hfShape = hf->createShape(hfGeom, *mMat); if(!hfShape) return; //shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, false); //shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true); //shape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, true); // add actor to the scene scene->addActor(*hf); } }
bool copyStaticProperties(PxRigidActor& to, const PxRigidActor& from,NxMirrorScene::MirrorFilter &mirrorFilter) { physx::shdfnd::InlineArray<PxShape*, 64> shapes; shapes.resize(from.getNbShapes()); PxU32 shapeCount = from.getNbShapes(); from.getShapes(shapes.begin(), shapeCount); physx::shdfnd::InlineArray<PxMaterial*, 64> materials; for(PxU32 i = 0; i < shapeCount; i++) { PxShape* s = shapes[i]; if ( mirrorFilter.shouldMirror(*s) ) { PxU32 materialCount = s->getNbMaterials(); materials.resize(materialCount); s->getMaterials(materials.begin(), materialCount); PxShape* shape = to.createShape(s->getGeometry().any(), materials.begin(), static_cast<physx::PxU16>(materialCount)); shape->setLocalPose( s->getLocalPose()); shape->setContactOffset(s->getContactOffset()); shape->setRestOffset(s->getRestOffset()); shape->setFlags(s->getFlags()); shape->setSimulationFilterData(s->getSimulationFilterData()); shape->setQueryFilterData(s->getQueryFilterData()); mirrorFilter.reviseMirrorShape(*shape); } } to.setActorFlags(from.getActorFlags()); to.setOwnerClient(from.getOwnerClient()); to.setDominanceGroup(from.getDominanceGroup()); if ( to.getNbShapes() ) { mirrorFilter.reviseMirrorActor(to); } return to.getNbShapes() != 0; }
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); } }
// Creates an physics entity from an entity info structure and a starting transform void PhysicsEngine::createEntity(PhysicsEntity* entity, PhysicsEntityInfo* info, PxTransform transform) { transform.p.y += info->yPosOffset; // Set static/dynamic info for actor depending on its type PxRigidActor* actor; if (info->type == PhysicsType::DYNAMIC) { DynamicInfo* dInfo = info->dynamicInfo; PxRigidDynamic* dynamicActor = physics->createRigidDynamic(transform); dynamicActor->setLinearDamping(dInfo->linearDamping); dynamicActor->setAngularDamping(dInfo->angularDamping); dynamicActor->setMaxAngularVelocity(dInfo->maxAngularVelocity); actor = dynamicActor; } else if (info->type == PhysicsType::STATIC) { PxRigidStatic* staticActor = physics->createRigidStatic(transform); actor = staticActor; } // All shapes in actor for (auto sInfo : info->shapeInfo) { // Create material and geometry for shape and add it to actor PxGeometry* geometry; PxMaterial* material; if (sInfo->geometry == Geometry::SPHERE) { SphereInfo* sphInfo = (SphereInfo*)sInfo; geometry = new PxSphereGeometry(sphInfo->radius); } else if (sInfo->geometry == Geometry::BOX) { BoxInfo* boxInfo = (BoxInfo*)sInfo; geometry = new PxBoxGeometry(boxInfo->halfX, boxInfo->halfY, boxInfo->halfZ); } else if (sInfo->geometry == Geometry::CAPSULE) { CapsuleInfo* capInfo = (CapsuleInfo*)sInfo; geometry = new PxCapsuleGeometry(capInfo->radius, capInfo->halfHeight); } else if (sInfo->geometry == Geometry::CONVEX_MESH) { ConvexMeshInfo* cmInfo = (ConvexMeshInfo*)sInfo; PxConvexMesh* mesh = helper->createConvexMesh(cmInfo->verts.data(), cmInfo->verts.size()); geometry = new PxConvexMeshGeometry(mesh); } // Not working until index drawing is set up else if (sInfo->geometry == Geometry::TRIANGLE_MESH) { TriangleMeshInfo* tmInfo = (TriangleMeshInfo*)sInfo; PxTriangleMesh* mesh = helper->createTriangleMesh(tmInfo->verts.data(), tmInfo->verts.size(), tmInfo->faces.data(), tmInfo->faces.size()/3); geometry = new PxTriangleMeshGeometry(mesh); } material = (sInfo->isDrivable) ? drivingSurfaces[0] : physics->createMaterial(sInfo->dynamicFriction, sInfo->staticFriction, sInfo->restitution); PxShape* shape = actor->createShape(*geometry, *material); // TODO support shape flags shape->setLocalPose(sInfo->transform); material->release(); delete geometry; // Set up querry filter data for shape PxFilterData qryFilterData; qryFilterData.word3 = (sInfo->isDrivable) ? (PxU32)Surface::DRIVABLE : (PxU32)Surface::UNDRIVABLE; shape->setQueryFilterData(qryFilterData); // Set up simulation filter data for shape PxFilterData simFilterData; simFilterData.word0 = (PxU32)sInfo->filterFlag0; simFilterData.word1 = (PxU32)sInfo->filterFlag1; simFilterData.word2 = (PxU32)sInfo->filterFlag2; simFilterData.word3 = (PxU32)sInfo->filterFlag3; shape->setSimulationFilterData(simFilterData); if (info->type == PhysicsType::DYNAMIC) { DynamicInfo* dInfo = info->dynamicInfo; PxRigidBodyExt::updateMassAndInertia(*(PxRigidBody*)actor, dInfo->density, &dInfo->cmOffset); PxRigidBody* body = (PxRigidBody*)actor; } } // Add actor to scene, set actor for entity, and set user data for actor. Creates one to one between entities and phyX scene->addActor(*actor); entity->setActor(actor); actor->userData = entity; }
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; }