Exemple #1
0
/** 
*	Perform any cleanup of physics engine resources. 
*	This is deferred because when closing down the game, you want to make sure you are not destroying a mesh after the physics SDK has been shut down.
*/
void DeferredPhysResourceCleanup()
{
#if WITH_PHYSX
	// Release all tri meshes and reset array
	for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillTriMesh.Num(); MeshIdx++)
	{
		PxTriangleMesh* PTriMesh = GPhysXPendingKillTriMesh[MeshIdx];
		check(PTriMesh);
		PTriMesh->release();
		GPhysXPendingKillTriMesh[MeshIdx] = NULL;
	}
	GPhysXPendingKillTriMesh.Reset();

	// Release all convex meshes and reset array
	for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillConvex.Num(); MeshIdx++)
	{
		PxConvexMesh* PConvexMesh = GPhysXPendingKillConvex[MeshIdx];
		check(PConvexMesh);
		PConvexMesh->release();
		GPhysXPendingKillConvex[MeshIdx] = NULL;
	}
	GPhysXPendingKillConvex.Reset();

	// Release all heightfields and reset array
	for(int32 HfIdx=0; HfIdx<GPhysXPendingKillHeightfield.Num(); HfIdx++)
	{
		PxHeightField* PHeightfield = GPhysXPendingKillHeightfield[HfIdx];
		check(PHeightfield);
		PHeightfield->release();
		GPhysXPendingKillHeightfield[HfIdx] = NULL;
	}
	GPhysXPendingKillHeightfield.Reset();

	// Release all materials and reset array
	for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillMaterial.Num(); MeshIdx++)
	{
		PxMaterial* PMaterial = GPhysXPendingKillMaterial[MeshIdx];
		check(PMaterial);
		PMaterial->release();
		GPhysXPendingKillMaterial[MeshIdx] = NULL;
	}
	GPhysXPendingKillMaterial.Reset();
#endif
}
/** 
*	Perform any cleanup of physics engine resources. 
*	This is deferred because when closing down the game, you want to make sure you are not destroying a mesh after the physics SDK has been shut down.
*/
void DeferredPhysResourceCleanup()
{
#if WITH_PHYSX

	// Release all tri meshes and reset array
	for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillTriMesh.Num(); MeshIdx++)
	{
		PxTriangleMesh* PTriMesh = GPhysXPendingKillTriMesh[MeshIdx];

		// Check this as it shouldn't be null, but then gate on it so we can
		// avoid a crash if we end up in this state in shipping
		check(PTriMesh);
		if(PTriMesh)
		{
			PTriMesh->release();

			if(GPhysXPendingKillTriMesh.IsValidIndex(MeshIdx))
			{
				GPhysXPendingKillTriMesh[MeshIdx] = NULL;
			}
			else
			{
				UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillTriMesh, another thread may have modified the array."), MeshIdx);
			}
		}
		else
		{
			UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxTriangleMesh in pending kill array, another thread may have modified the array."), MeshIdx);
		}
	}
	GPhysXPendingKillTriMesh.Reset();

	// Release all convex meshes and reset array
	for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillConvex.Num(); MeshIdx++)
	{
		PxConvexMesh* PConvexMesh = GPhysXPendingKillConvex[MeshIdx];

		// Check this as it shouldn't be null, but then gate on it so we can
		// avoid a crash if we end up in this state in shipping
		check(PConvexMesh);
		if(PConvexMesh)
		{
			PConvexMesh->release();

			if(GPhysXPendingKillConvex.IsValidIndex(MeshIdx))
			{
				GPhysXPendingKillConvex[MeshIdx] = NULL;
			}
			else
			{
				UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillConvex (%d), another thread may have modified the array."), MeshIdx);
			}
		}
		else
		{
			UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxConvexMesh in pending kill array (at %d), another thread may have modified the array."), MeshIdx);
		}
	}
	GPhysXPendingKillConvex.Reset();

	// Release all heightfields and reset array
	for(int32 HfIdx=0; HfIdx<GPhysXPendingKillHeightfield.Num(); HfIdx++)
	{
		PxHeightField* PHeightfield = GPhysXPendingKillHeightfield[HfIdx];

		// Check this as it shouldn't be null, but then gate on it so we can
		// avoid a crash if we end up in this state in shipping
		check(PHeightfield);
		if(PHeightfield)
		{
			PHeightfield->release();

			if(GPhysXPendingKillHeightfield.IsValidIndex(HfIdx))
			{
				GPhysXPendingKillHeightfield[HfIdx] = NULL;
			}
			else
			{
				UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillHeightfield (%d), another thread may have modified the array."), HfIdx);
			}
		}
		else
		{
			UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxHeightField in pending kill array (at %d), another thread may have modified the array."), HfIdx);
		}
	}
	GPhysXPendingKillHeightfield.Reset();

	// Release all materials and reset array
	for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillMaterial.Num(); MeshIdx++)
	{
		PxMaterial* PMaterial = GPhysXPendingKillMaterial[MeshIdx];

		// Check this as it shouldn't be null, but then gate on it so we can
		// avoid a crash if we end up in this state in shipping
		check(PMaterial);
		if(PMaterial)
		{
			PMaterial->release();
			if(GPhysXPendingKillMaterial.IsValidIndex(MeshIdx))
			{
				GPhysXPendingKillMaterial[MeshIdx] = NULL;
			}
			else
			{
				UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillMaterial(%d), another thread may have modified the array."), MeshIdx);
			}
		}
		else
		{
			UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxMaterial in pending kill array (at %d), another thread may have modified the array."), MeshIdx);
		}
	}
	GPhysXPendingKillMaterial.Reset();
#endif
}
Exemple #3
0
void PhysicalTile::updatePxHeight()
{
    // do the physx update only when needed
    if (m_pxUpdateBox.maxColumn < m_pxUpdateBox.minColumn)
        return;

    PxHeightFieldGeometry geometry;
    bool result = m_pxShape->getHeightFieldGeometry(geometry);
    assert(result);
    if (!result) {
        glow::warning("TerrainInteractor::setPxHeight could not get height field geometry from physx shape");
        return;
    }
    PxHeightField * hf = geometry.heightField;

    assert(m_pxUpdateBox.minRow <= m_pxUpdateBox.maxRow && m_pxUpdateBox.minColumn <= m_pxUpdateBox.maxColumn);
    unsigned int nbRows = m_pxUpdateBox.maxRow - m_pxUpdateBox.minRow + 1;
    unsigned int nbColumns = m_pxUpdateBox.maxColumn - m_pxUpdateBox.minColumn + 1;
    unsigned int fieldSize = nbRows * nbColumns;

    PxHeightFieldSample * samplesM = new PxHeightFieldSample[fieldSize];
    for (unsigned int r = 0; r < nbRows; ++r) {
        unsigned int rowOffset = r * nbColumns;
        for (unsigned int c = 0; c < nbColumns; ++c) {
            const unsigned int index = c + rowOffset;
            const unsigned int tileValueIndex = (c + m_pxUpdateBox.minColumn) + (r + m_pxUpdateBox.minRow) * samplesPerAxis;
            const float terrainHeight = valueAt(tileValueIndex);
            samplesM[index].height = static_cast<PxI16>(terrainHeight / geometry.heightScale);
            samplesM[index].materialIndex0 = samplesM[index].materialIndex1 = elementIndexAt(tileValueIndex);
        }
    }

    PxHeightFieldDesc descM;
    descM.nbColumns = nbColumns;
    descM.nbRows = nbRows;
    descM.samples.data = samplesM;
    descM.format = hf->getFormat();
    descM.samples.stride = hf->getSampleStride();
    descM.thickness = hf->getThickness();
    descM.convexEdgeThreshold = hf->getConvexEdgeThreshold();
    descM.flags = hf->getFlags();

    PhysicsWrapper::getInstance()->pauseGPUAcceleration();

    bool success = hf->modifySamples(m_pxUpdateBox.minColumn, m_pxUpdateBox.minRow, descM);
    assert(success);
    if (!success) {
        glow::warning("TerrainInteractor::setPxHeight could not modify height field.");
        return;
    }

    PxHeightFieldGeometry newGeometry(hf, PxMeshGeometryFlags(), geometry.heightScale, geometry.rowScale, geometry.columnScale);
    assert(PxGetPhysics().getNbScenes() == 1);
    PxScene * pxScenePtrs[1];
    PxGetPhysics().getScenes(pxScenePtrs, 1);
    pxScenePtrs[0]->lockWrite();
    m_pxShape->setGeometry(newGeometry);
    pxScenePtrs[0]->unlockWrite();

    PhysicsWrapper::getInstance()->restoreGPUAccelerated();

#ifdef PX_WINDOWS
    if (PhysicsWrapper::getInstance()->physxGpuAvailable()) {
        PxParticleGpu::releaseHeightFieldMirror(*hf);
        PxParticleGpu::createHeightFieldMirror(*hf, *PhysicsWrapper::getInstance()->cudaContextManager());
    }
#endif

    clearPxBufferUpdateRange();
}
	void CreateTerrainGeomtry(LevelGeometry &lg)
	{
		const int PATCH_SIZE = 64;

		if (!Terrain)
			return;

		PxHeightFieldGeometry g = Terrain->GetHFShape();
		const float colScale = g.columnScale;
		const float rowScale = g.rowScale;
		const float heightScale = g.heightScale;

		PxHeightField *physHF = g.heightField;

		PxU32 nbCols = physHF->getNbColumns();
		PxU32 nbRows = physHF->getNbRows();

		PxU32 patchCols = static_cast<PxU32>(ceilf(nbCols / static_cast<float>(PATCH_SIZE)));
		PxU32 patchRows = static_cast<PxU32>(ceilf(nbRows / static_cast<float>(PATCH_SIZE)));

		lg.meshes.Resize(patchCols * patchRows);
		lg.meshStartObjectsIdx = lg.meshes.Count();

		for (PxU32 pi = 0; pi < patchCols; ++pi)
		{
			for (PxU32 pj = 0; pj < patchRows; ++pj)
			{
				//	Fill patch vertices first.
				LevelGeometry::Mesh &p = lg.meshes[pi * patchRows + pj];

				PxU32 startCol = pi * PATCH_SIZE;
				PxU32 startRow = pj * PATCH_SIZE;

				PxU32 endCol = (pi + 1) * PATCH_SIZE;
				PxU32 endRow = (pj + 1) * PATCH_SIZE;

				PxU32 w = std::min(endCol - startCol + 1, nbCols - startCol);
				PxU32 h = std::min(endRow - startRow + 1, nbRows - startRow);

				p.vertices.Resize(w * h);

				for(PxU32 i = 0; i < w; ++i)
				{
					for(PxU32 j = 0; j < h; ++j)
					{
						PxReal x = PxReal(i + startCol);
						PxReal z = PxReal(j + startRow);
						PxReal y = physHF->getHeight(x, z) * heightScale;
						PxU32 idx = i * h + j;

						p.vertices[idx] = r3dVector(x * colScale, y, z * rowScale);
					}
				}

				//	Now triangulate patch
				const PxU32 nbFaces = (w - 1) * (h - 1) * 2;

				p.indices.Resize(nbFaces * 3);
				int * indices = &p.indices.GetFirst();
				for (PxU32 i = 0; i < (w - 1); ++i) 
				{
					for (PxU32 j = 0; j < (h - 1); ++j) 
					{
						// first triangle
						uint32_t baseIdx = 6 * (i * (h - 1) + j);

						indices[baseIdx + 0] = (i + 1) * h + j; 
						indices[baseIdx + 1] = i * h + j;
						indices[baseIdx + 2] = i * h + j + 1;
						// second triangle
						indices[baseIdx + 3] = (i + 1) * h + j + 1;
						indices[baseIdx + 4] = (i + 1) * h + j;
						indices[baseIdx + 5] = i * h + j + 1;
					}
				}

				//	Filter outside triangles
  				uint32_t indicesCount = gConvexRegionsManager.FilterOutsideTriangles(&p.vertices.GetFirst(), &p.indices.GetFirst(), p.indices.Count());
  				p.indices.Resize(indicesCount);
			}
		}
	}