From 7cb99688646fe15c6bb780941611ce219f71d0ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 25 Aug 2015 05:53:36 -0700 Subject: [PATCH] more work on polyvox threading --- .../src/RenderablePolyVoxEntityItem.cpp | 282 ++++++++++++++---- .../src/RenderablePolyVoxEntityItem.h | 58 ++-- libraries/entities/src/PolyVoxEntityItem.cpp | 14 + libraries/entities/src/PolyVoxEntityItem.h | 5 +- 4 files changed, 281 insertions(+), 78 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 1b7d53549f..cc0a4f3e91 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -38,7 +38,6 @@ #include #include "model/Geometry.h" -#include "gpu/Context.h" #include "EntityTreeRenderer.h" #include "polyvox_vert.h" #include "polyvox_frag.h" @@ -46,6 +45,8 @@ #include "EntityEditPacketSender.h" #include "PhysicalEntitySimulation.h" +#define THREAD_POLYVOX 1 + gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr; const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; @@ -56,21 +57,46 @@ EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entit RenderablePolyVoxEntityItem::RenderablePolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : PolyVoxEntityItem(entityItemID, properties), + _mesh(new model::Mesh()), _xTexture(nullptr), _yTexture(nullptr), _zTexture(nullptr), _async(DEFAULT_VOXEL_SURFACE_STYLE, DEFAULT_VOXEL_VOLUME_SIZE, this) { - model::Mesh* mesh = new model::Mesh(); - model::MeshPointer meshPtr(mesh); - receiveNewMesh(meshPtr, _modelVersion); + // model::Mesh* mesh = new model::Mesh(); + // model::MeshPointer meshPtr(mesh); + + // mesh->setIndexBuffer(nullptr); + + // auto vertexBuffer = std::make_shared(0, (gpu::Byte*)""); + // auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer); + // auto vertexBufferView = new gpu::BufferView(vertexBufferPtr, + // 0, + // vertexBufferPtr->getSize() - sizeof(float) * 3, + // sizeof(PolyVox::PositionMaterialNormal), + // gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)); + // mesh->setVertexBuffer(*vertexBufferView); + + // _mesh = meshPtr; + // _modelGeometry.setMesh(meshPtr); + + // qDebug() << "5d301155-faf9-44dd-8e8b-061a03d42c0f" << "IN CONSTRUCTOR" << getID() << _voxelData; + // _async.decompressVolumeData(_voxelData, ++_modelVersion); + // _async.updateVoxelSurfaceStyle(_voxelSurfaceStyle, ++_modelVersion); } RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() { } -void RenderablePolyVoxEntityItem::receiveNewVoxelData(QByteArray newVoxelData, uint64_t dataVersion) { +void RenderablePolyVoxEntityItem::receiveNewVoxelData(QByteArray newVoxelData, quint64 dataVersion) { + if (dataVersion <= _dataVersion) { + // qDebug() << _id << "OKOKOK NOPE" << QString(__PRETTY_FUNCTION__) << getName() << dataVersion << _dataVersion; + return; + } + + // qDebug() << _id << "OKOKOK!!!" << QString(__PRETTY_FUNCTION__) << getName() << dataVersion << _dataVersion << "mesh-size is" << _mesh->getNumVertices(); + _voxelData = newVoxelData; _dataVersion = dataVersion; @@ -93,44 +119,79 @@ void RenderablePolyVoxEntityItem::receiveNewVoxelData(QByteArray newVoxelData, u } -void RenderablePolyVoxEntityItem::receiveNewMesh(model::MeshPointer newMeshPtr, uint64_t meshVersion) { +void RenderablePolyVoxEntityItem::receiveNewMesh(model::MeshPointer newMeshPtr, quint64 meshVersion) { + if (meshVersion <= _meshVersion) { + // qDebug() << _id << "OKOKOK NOPE" << QString(__PRETTY_FUNCTION__) << getName() << meshVersion << _meshVersion; + return; + } + + // int meshSize = -1; + // const model::MeshPointer mesh = _modelGeometry.getMesh(); + // if (mesh) { + // mesh->getVertexBuffer()._size; + // } + + // qDebug() << _id << "OKOKOK!!!" << QString(__PRETTY_FUNCTION__) << getName() << meshVersion << _meshVersion << "mesh-size is" << meshSize; + // qDebug() << _id << "OKOKOK!!!" << QString(__PRETTY_FUNCTION__) << getName() << meshVersion << _meshVersion << "mesh-size is" << _mesh->getNumVertices() << "new mesh-size is" << newMeshPtr->getNumVertices(); + _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; _modelGeometryLock.lockForWrite(); - _modelGeometry.setMesh(newMeshPtr); + // _modelGeometry.setMesh(newMeshPtr); + _mesh = newMeshPtr; _meshVersion = meshVersion; _modelGeometryLock.unlock(); + // qDebug() << _id << "OKOKOK after" << getName() << " mesh-size is" << _modelGeometry.getMesh()->getVertexBuffer()._size << "\n"; + // qDebug() << _id << "OKOKOK after" << getName() << " mesh-size is" << _mesh->getNumVertices(); + // qDebug() << _id << "OKOKOK after" << getName() << " mesh-size is" << newMeshPtr->getNumVertices(); + computeShapeInfoWorker(); } void RenderablePolyVoxEntityItem::setVoxelData(QByteArray voxelData) { - if (voxelData == _voxelData) { + // qDebug() << "5d301155-faf9-44dd-8e8b-061a03d42c0f setVoxelData for" << getName() << getID() << ((void *)this); + + _voxelDataLock.lockForWrite(); + if (/*_dataVersion > 1 &&*/ _voxelData == voxelData) { + // qDebug() << _id << "OKOKOK NOPE" << QString(__PRETTY_FUNCTION__) << getName() << _dataVersion << getID() << ((void *)this); + _voxelDataLock.unlock(); return; } + // qDebug() << _id << "OKOKOK" << QString(__PRETTY_FUNCTION__) << getName() << _dataVersion; + _voxelData = voxelData; _async.decompressVolumeData(_voxelData, ++_modelVersion); + _voxelDataLock.unlock(); } void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) { - if (voxelVolumeSize == _voxelVolumeSize) { + if (/*_meshVersion > 1 && _shapeVersion > 1 &&*/ _voxelVolumeSize == voxelVolumeSize) { + // qDebug() << _id << "OKOKOK NOPE" << QString(__PRETTY_FUNCTION__) << getName() << _meshVersion << ((void *)this); return; } + // qDebug() << _id << "OKOKOK" << QString(__PRETTY_FUNCTION__) << getName() << ((void *)this); + PolyVoxEntityItem::setVoxelVolumeSize(voxelVolumeSize); _async.setVoxelVolumeSize(_voxelVolumeSize); // decompress the old data here, because the data includes its original dimensions along with the voxel data, // and writing voxels outside the bounds of the new space is harmless. This allows adjusting of the // voxel-space size without overly mangling the shape. Shrinking the space and then restoring the previous // size (without any edits in between) will put the original shape back. + _voxelDataLock.lockForRead(); _async.decompressVolumeData(_voxelData, ++_modelVersion); + _voxelDataLock.unlock(); } void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) { - if (_voxelSurfaceStyle == voxelSurfaceStyle) { + if (/*_meshVersion > 1 && _shapeVersion > 1 &&*/ _voxelSurfaceStyle == voxelSurfaceStyle) { + // qDebug() << _id << "OKOKOK NOPE" << QString(__PRETTY_FUNCTION__) << getName() << _meshVersion; return; } + // qDebug() << _id << "OKOKOK" << QString(__PRETTY_FUNCTION__) << getName(); + _voxelSurfaceStyle = voxelSurfaceStyle; _async.updateVoxelSurfaceStyle(_voxelSurfaceStyle, ++_modelVersion); } @@ -351,17 +412,15 @@ ShapeType RenderablePolyVoxEntityItem::getShapeType() const { } bool RenderablePolyVoxEntityItem::isReadyToComputeShape() { - #ifdef WANT_DEBUG - qDebug() << "RenderablePolyVoxEntityItem::isReadyToComputeShape" << getName() << _shapeVersion << _modelVersion; - #endif - return (_shapeVersion == _modelVersion); } bool RenderablePolyVoxEntityItem::computeShapeInfoWorker() { ShapeType type = getShapeType(); if (type != SHAPE_TYPE_COMPOUND) { + _shapeInfoLock.lockForWrite(); EntityItem::computeShapeInfo(_shapeInfo); + _shapeInfoLock.unlock(); return true; } @@ -374,12 +433,16 @@ bool RenderablePolyVoxEntityItem::computeShapeInfoWorker() { /* pull each triangle in the mesh into a polyhedron which can be collided with */ unsigned int i = 0; - _modelGeometryLock.lockForRead(); - const model::MeshPointer mesh = _modelGeometry.getMesh(); - _modelGeometryLock.unlock(); + // _modelGeometryLock.lockForRead(); + // const model::MeshPointer mesh = _modelGeometry.getMesh(); + // _modelGeometryLock.unlock(); + model::MeshPointer mesh = _mesh; + _modelGeometryLock.lockForRead(); const gpu::BufferView vertexBufferView = mesh->getVertexBuffer(); const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); + _modelGeometryLock.unlock(); + gpu::BufferView::Iterator it = indexBufferView.cbegin(); while (it != indexBufferView.cend()) { uint32_t p0Index = *(it++); @@ -482,21 +545,26 @@ bool RenderablePolyVoxEntityItem::computeShapeInfoWorker() { } if (points.isEmpty()) { + _shapeInfoLock.lockForWrite(); EntityItem::computeShapeInfo(_shapeInfo); + _shapeInfoLock.unlock(); return true; } glm::vec3 collisionModelDimensions = box.getDimensions(); QByteArray b64 = _voxelData.toBase64(); + _shapeInfoLock.lockForWrite(); _shapeInfo.setParams(type, collisionModelDimensions, QString(b64)); _shapeInfo.setConvexHulls(points); - _shapeVersion = _modelVersion; + _shapeInfoLock.unlock(); return true; } void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { + _shapeInfoLock.lockForRead(); info = _shapeInfo; + _shapeInfoLock.unlock(); } void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) { @@ -516,6 +584,18 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { assert(getType() == EntityTypes::PolyVox); Q_ASSERT(args->_batch); + if (_meshVersion < _modelVersion || + _dataVersion < _modelVersion) { + _async.decompressVolumeData(_voxelData, _modelVersion); + _async.updateVoxelSurfaceStyle(_voxelSurfaceStyle, _modelVersion); + } + + model::MeshPointer mesh = _mesh; + + // if (_meshVersion == 0) { + // return; // we have no mesh + // } + if (!_pipeline) { gpu::ShaderPointer vertexShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(polyvox_vert))); gpu::ShaderPointer pixelShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(polyvox_frag))); @@ -539,9 +619,8 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { gpu::Batch& batch = *args->_batch; batch.setPipeline(_pipeline); - _modelGeometryLock.lockForRead(); - auto mesh = _modelGeometry.getMesh(); - _modelGeometryLock.unlock(); + // _modelGeometryLock.lockForRead(); + // auto mesh = _modelGeometry.getMesh(); Transform transform(voxelToWorldMatrix()); batch.setModelTransform(transform); @@ -583,6 +662,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { batch._glUniform3f(voxelVolumeSizeLocation, _voxelVolumeSize.x, _voxelVolumeSize.y, _voxelVolumeSize.z); batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); + // _modelGeometryLock.unlock(); RenderableDebugableEntityItem::render(this, args); } @@ -648,21 +728,23 @@ RenderablePolyVoxAsynchronous::RenderablePolyVoxAsynchronous(PolyVoxEntityItem:: glm::vec3 voxelVolumeSize, RenderablePolyVoxEntityItem* owner) : _voxelSurfaceStyle(voxelSurfaceStyle), + _onCount(0), _owner(owner) { setVoxelVolumeSize(voxelVolumeSize); } RenderablePolyVoxAsynchronous::~RenderablePolyVoxAsynchronous() { + _volDataLock.lockForWrite(); delete _volData; + _volDataLock.unlock(); } void RenderablePolyVoxAsynchronous::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) { - #ifdef WANT_DEBUG - qDebug() << "resetting voxel-space size" << voxelVolumeSize.x << voxelVolumeSize.y << voxelVolumeSize.z; - #endif + // qDebug() << _owner->getID() << "OKOKOK" << QString(__PRETTY_FUNCTION__) << _owner->getName(); + _volDataLock.lockForWrite(); _voxelVolumeSize = voxelVolumeSize; if (_volData) { @@ -691,15 +773,16 @@ void RenderablePolyVoxAsynchronous::setVoxelVolumeSize(glm::vec3 voxelVolumeSize // having the "outside of voxel-space" value be 255 has helped me notice some problems. _volData->setBorderValue(255); - - #ifdef WANT_DEBUG - qDebug() << " new voxel-space size is" << _volData->getWidth() << _volData->getHeight() << _volData->getDepth(); - #endif + _volDataLock.unlock(); } void RenderablePolyVoxAsynchronous::updateVoxelSurfaceStyle(PolyVoxEntityItem::PolyVoxSurfaceStyle voxelSurfaceStyle, - uint64_t modelVersion) { + quint64 modelVersion) { + + // qDebug() << _owner->getID() << "OKOKOK" << QString(__PRETTY_FUNCTION__) << _owner->getName(); + + _volDataLock.lockForWrite(); // if we are switching to or from "edged" we need to force a resize of _volData. bool wasEdged = (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES); @@ -712,11 +795,23 @@ void RenderablePolyVoxAsynchronous::updateVoxelSurfaceStyle(PolyVoxEntityItem::P } _volData = nullptr; _voxelSurfaceStyle = voxelSurfaceStyle; + _volDataLock.unlock(); setVoxelVolumeSize(_voxelVolumeSize); +# ifdef THREAD_POLYVOX + QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::decompressVolumeDataAsync, + _owner->getVoxelData(), modelVersion); +# else + decompressVolumeDataAsync(_owner->getVoxelData(), modelVersion); +# endif } else { _voxelSurfaceStyle = voxelSurfaceStyle; + _volDataLock.unlock(); +# ifdef THREAD_POLYVOX + QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::getMeshAsync, modelVersion); +# else + getMeshAsync(modelVersion); +# endif } - getModel(modelVersion); } @@ -748,6 +843,13 @@ bool RenderablePolyVoxAsynchronous::inUserBounds(const PolyVox::SimpleVolumereceiveNewVoxelData(_owner->getVoxelData(), modelVersion); + // _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + _owner->setDataVersion(modelVersion); } return result; } -bool RenderablePolyVoxAsynchronous::setAll(uint8_t toValue, uint64_t modelVersion) { +bool RenderablePolyVoxAsynchronous::setAll(uint8_t toValue, quint64 modelVersion) { bool result = false; + _volDataLock.lockForWrite(); for (int z = 0; z < _voxelVolumeSize.z; z++) { for (int y = 0; y < _voxelVolumeSize.y; y++) { for (int x = 0; x < _voxelVolumeSize.x; x++) { @@ -836,20 +947,29 @@ bool RenderablePolyVoxAsynchronous::setAll(uint8_t toValue, uint64_t modelVersio } } } + _volDataLock.unlock(); if (result) { +# ifdef THREAD_POLYVOX + QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::compressVolumeData, modelVersion); + QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::getMeshAsync, modelVersion); +# else compressVolumeData(modelVersion); + getMeshAsync(modelVersion); +# endif } else { // nothing changed. - _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + // _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + _owner->setDataVersion(modelVersion); } return result; } -bool RenderablePolyVoxAsynchronous::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue, uint64_t modelVersion) { +bool RenderablePolyVoxAsynchronous::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue, quint64 modelVersion) { bool result = false; // This three-level for loop iterates over every voxel in the volume + _volDataLock.lockForWrite(); for (int z = 0; z < _voxelVolumeSize.z; z++) { for (int y = 0; y < _voxelVolumeSize.y; y++) { for (int x = 0; x < _voxelVolumeSize.x; x++) { @@ -864,11 +984,19 @@ bool RenderablePolyVoxAsynchronous::setSphereInVolume(glm::vec3 center, float ra } } } + _volDataLock.unlock(); if (result) { +# ifdef THREAD_POLYVOX + QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::compressVolumeData, modelVersion); + QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::getMeshAsync, modelVersion); +# else compressVolumeData(modelVersion); + getMeshAsync(modelVersion); +# endif } else { // nothing changed. - _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + // _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + _owner->setDataVersion(modelVersion); } return result; @@ -880,8 +1008,10 @@ PolyVox::RaycastResult RenderablePolyVoxAsynchronous::doRayCast(glm::vec4 origin PolyVox::Vector3DFloat startPoint(originInVoxel.x, originInVoxel.y, originInVoxel.z); PolyVox::Vector3DFloat endPoint(farInVoxel.x, farInVoxel.y, farInVoxel.z); + _volDataLock.lockForRead(); RaycastFunctor callback(_volData); PolyVox::RaycastResult raycastResult = PolyVox::raycastWithEndpoints(_volData, startPoint, endPoint, callback); + _volDataLock.unlock(); // result is in voxel-space coordinates. result = callback._result - glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); @@ -890,7 +1020,21 @@ PolyVox::RaycastResult RenderablePolyVoxAsynchronous::doRayCast(glm::vec4 origin // take compressed data and expand it into _volData. -void RenderablePolyVoxAsynchronous::decompressVolumeData(QByteArray voxelData, uint64_t modelVersion) { +void RenderablePolyVoxAsynchronous::decompressVolumeData(QByteArray voxelData, quint64 modelVersion) { + // qDebug() << _owner->getID() << "OKOKOK" << QString(__PRETTY_FUNCTION__) << _owner->getName() << modelVersion; + +# ifdef THREAD_POLYVOX + QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::decompressVolumeDataAsync, voxelData, modelVersion); +# else + decompressVolumeDataAsync(voxelData, modelVersion); +# endif +} + + +void RenderablePolyVoxAsynchronous::decompressVolumeDataAsync(QByteArray voxelData, quint64 modelVersion) { + // qDebug() << _owner->getID() << "OKOKOK" << QString(__PRETTY_FUNCTION__) + // << _owner->getName() << _owner->getID() << modelVersion; + QDataStream reader(voxelData); quint16 voxelXSize, voxelYSize, voxelZSize; reader >> voxelXSize; @@ -901,7 +1045,10 @@ void RenderablePolyVoxAsynchronous::decompressVolumeData(QByteArray voxelData, u voxelYSize == 0 || voxelYSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION || voxelZSize == 0 || voxelZSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION) { qDebug() << "voxelSize is not reasonable, skipping decompressions." - << voxelXSize << voxelYSize << voxelZSize; + << voxelXSize << voxelYSize << voxelZSize << _owner->getName() << _owner->getID() << modelVersion + << "5d301155-faf9-44dd-8e8b-061a03d42c0f"; + // _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + _owner->setDataVersion(modelVersion); return; } @@ -912,11 +1059,15 @@ void RenderablePolyVoxAsynchronous::decompressVolumeData(QByteArray voxelData, u QByteArray uncompressedData = qUncompress(compressedData); if (uncompressedData.size() != rawSize) { - qDebug() << "PolyVox decompress -- size is (" << voxelXSize << voxelYSize << voxelZSize << ")" << - "so expected uncompressed length of" << rawSize << "but length is" << uncompressedData.size(); + qDebug() << "PolyVox decompress -- size is (" << voxelXSize << voxelYSize << voxelZSize << ")" + << "so expected uncompressed length of" << rawSize << "but length is" << uncompressedData.size() + << _owner->getName() << _owner->getID() << modelVersion << "5d301155-faf9-44dd-8e8b-061a03d42c0f"; + // _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + _owner->setDataVersion(modelVersion); return; } + _volDataLock.lockForWrite(); for (int z = 0; z < voxelZSize; z++) { for (int y = 0; y < voxelYSize; y++) { for (int x = 0; x < voxelXSize; x++) { @@ -925,18 +1076,27 @@ void RenderablePolyVoxAsynchronous::decompressVolumeData(QByteArray voxelData, u } } } + _volDataLock.unlock(); - getModel(modelVersion); + _owner->receiveNewVoxelData(voxelData, modelVersion); + +# ifdef THREAD_POLYVOX + QFuture future = QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::getMeshAsync, modelVersion); +# else + getMeshAsync(modelVersion); +# endif } -void RenderablePolyVoxAsynchronous::getModel(uint64_t modelVersion) { - model::Mesh* mesh = new model::Mesh(); - model::MeshPointer meshPtr(mesh); +void RenderablePolyVoxAsynchronous::getMeshAsync(quint64 modelVersion) { + // qDebug() << _owner->getID() << "OKOKOK" << QString(__PRETTY_FUNCTION__) << _owner->getName() << modelVersion; + + model::MeshPointer mesh(new model::Mesh()); // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; + _volDataLock.lockForRead(); switch (_voxelSurfaceStyle) { case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: { @@ -953,6 +1113,7 @@ void RenderablePolyVoxAsynchronous::getModel(uint64_t modelVersion) { break; } } + _volDataLock.unlock(); // convert PolyVox mesh to a Sam mesh const std::vector& vecIndices = polyVoxMesh.getIndices(); @@ -966,10 +1127,11 @@ void RenderablePolyVoxAsynchronous::getModel(uint64_t modelVersion) { auto vertexBuffer = std::make_shared(vecVertices.size() * sizeof(PolyVox::PositionMaterialNormal), (gpu::Byte*)vecVertices.data()); auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer); - auto vertexBufferView = new gpu::BufferView(vertexBufferPtr, - 0, - vertexBufferPtr->getSize() - sizeof(float) * 3, - sizeof(PolyVox::PositionMaterialNormal), + gpu::Resource::Size vertexBufferSize = 0; + if (vertexBufferPtr->getSize() > sizeof(float) * 3) { + vertexBufferSize = vertexBufferPtr->getSize() - sizeof(float) * 3; + } + auto vertexBufferView = new gpu::BufferView(vertexBufferPtr, 0, vertexBufferSize, sizeof(PolyVox::PositionMaterialNormal), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)); mesh->setVertexBuffer(*vertexBufferView); mesh->addAttribute(gpu::Stream::NORMAL, @@ -979,7 +1141,10 @@ void RenderablePolyVoxAsynchronous::getModel(uint64_t modelVersion) { sizeof(PolyVox::PositionMaterialNormal), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); - _owner->receiveNewMesh(meshPtr, modelVersion); + // qDebug() << _owner->getID() << "OKOKOK -- MADE NEW MESH" << "index-count =" << vecIndices.size() + // << "vertex-count =" << vecVertices.size() << "mesh-vertg-size =" << mesh->getVertexBuffer()._size; + + _owner->receiveNewMesh(mesh, modelVersion); } int RenderablePolyVoxAsynchronous::getOnCount() const { @@ -990,7 +1155,9 @@ int RenderablePolyVoxAsynchronous::getOnCount() const { // compress the data in _volData and save the results. The compressed form is used during // saves to disk and for transmission over the wire -void RenderablePolyVoxAsynchronous::compressVolumeData(uint64_t modelVersion) { +void RenderablePolyVoxAsynchronous::compressVolumeData(quint64 modelVersion) { + // qDebug() << _owner->getID() << "OKOKOK" << QString(__PRETTY_FUNCTION__) << _owner->getName() << modelVersion; + quint16 voxelXSize = _voxelVolumeSize.x; quint16 voxelYSize = _voxelVolumeSize.y; quint16 voxelZSize = _voxelVolumeSize.z; @@ -998,10 +1165,11 @@ void RenderablePolyVoxAsynchronous::compressVolumeData(uint64_t modelVersion) { QByteArray uncompressedData = QByteArray(rawSize, '\0'); + _volDataLock.lockForRead(); for (int z = 0; z < voxelZSize; z++) { for (int y = 0; y < voxelYSize; y++) { for (int x = 0; x < voxelXSize; x++) { - uint8_t uVoxelValue = getVoxel(x, y, z); + uint8_t uVoxelValue = getVoxelInternal(x, y, z); int uncompressedIndex = z * voxelYSize * voxelXSize + y * voxelXSize + @@ -1010,6 +1178,7 @@ void RenderablePolyVoxAsynchronous::compressVolumeData(uint64_t modelVersion) { } } } + _volDataLock.unlock(); QByteArray newVoxelData; QDataStream writer(&newVoxelData, QIODevice::WriteOnly | QIODevice::Truncate); @@ -1025,7 +1194,10 @@ void RenderablePolyVoxAsynchronous::compressVolumeData(uint64_t modelVersion) { } else { // HACK -- until we have a way to allow for properties larger than MTU, don't update. // revert the active voxel-space to the last version that fit. - qDebug() << "voxel data too large, reverting change."; - decompressVolumeData(_owner->getVoxelData(), modelVersion); + // QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::decompressVolumeDataAsync, + // _owner->getVoxelData(), modelVersion); + // decompressVolumeDataAsync(_owner->getVoxelData(), modelVersion); + // _owner->receiveNewVoxelData(_owner->getVoxelData(), modelVersion); + _owner->setDataVersion(modelVersion); } } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 4a767382d7..405cdd07ff 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -13,15 +13,17 @@ #define hifi_RenderablePolyVoxEntityItem_h #include +#include #include #include + #include #include "PolyVoxEntityItem.h" #include "RenderableDebugableEntityItem.h" #include "RenderableEntityItem.h" - +#include "gpu/Context.h" class PolyVoxPayload { public: @@ -42,7 +44,8 @@ namespace render { class RenderablePolyVoxEntityItem; -class RenderablePolyVoxAsynchronous { +class RenderablePolyVoxAsynchronous : public QObject { + Q_OBJECT public: RenderablePolyVoxAsynchronous(PolyVoxEntityItem::PolyVoxSurfaceStyle voxelSurfaceStyle, glm::vec3 voxelVolumeSize, @@ -50,20 +53,29 @@ class RenderablePolyVoxAsynchronous { ~RenderablePolyVoxAsynchronous(); void setVoxelVolumeSize(glm::vec3 voxelVolumeSize); - void updateVoxelSurfaceStyle(PolyVoxEntityItem::PolyVoxSurfaceStyle voxelSurfaceStyle, uint64_t modelVersion); + void updateVoxelSurfaceStyle(PolyVoxEntityItem::PolyVoxSurfaceStyle voxelSurfaceStyle, quint64 modelVersion); uint8_t getVoxel(int x, int y, int z); - bool setVoxel(int x, int y, int z, uint8_t toValue, uint64_t modelVersion); - bool setAll(uint8_t toValue, uint64_t modelVersion); - bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue, uint64_t modelVersion); + bool setVoxel(int x, int y, int z, uint8_t toValue, quint64 modelVersion); + bool setAll(uint8_t toValue, quint64 modelVersion); + bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue, quint64 modelVersion); PolyVox::RaycastResult doRayCast(glm::vec4 originInVoxel, glm::vec4 farInVoxel, glm::vec4& result) const; int getOnCount() const; - void decompressVolumeData(QByteArray voxelData, uint64_t modelVersion); + void decompressVolumeData(QByteArray voxelData, quint64 modelVersion); + +// signals: +// void doDecompressVolumeDataAsync(QByteArray voxelData, quint64 modelVersion); +// void doGetMeshAsync(quint64 modelVersion); + + private: - void getModel(uint64_t modelVersion); + void decompressVolumeDataAsync(QByteArray voxelData, quint64 modelVersion); + void getMeshAsync(quint64 modelVersion); + + uint8_t getVoxelInternal(int x, int y, int z); bool updateOnCount(int x, int y, int z, uint8_t new_value); bool setVoxelInternal(int x, int y, int z, uint8_t toValue); - void compressVolumeData(uint64_t modelVersion); + void compressVolumeData(quint64 modelVersion); static bool inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, int x, int y, int z); @@ -71,7 +83,7 @@ private: glm::vec3 _voxelVolumeSize; PolyVox::SimpleVolume* _volData = nullptr; mutable QReadWriteLock _volDataLock; // lock for _volData - int _onCount = 0; // how many non-zero voxels are in _volData + std::atomic_int _onCount; // how many non-zero voxels are in _volData RenderablePolyVoxEntityItem* _owner = nullptr; }; @@ -116,7 +128,6 @@ class RenderablePolyVoxEntityItem : public PolyVoxEntityItem { virtual ShapeType getShapeType() const; virtual bool isReadyToComputeShape(); virtual void computeShapeInfo(ShapeInfo& info); - virtual bool computeShapeInfoWorker(); virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const; virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const; @@ -142,17 +153,21 @@ class RenderablePolyVoxEntityItem : public PolyVoxEntityItem { std::shared_ptr scene, render::PendingChanges& pendingChanges); - void receiveNewVoxelData(QByteArray newVoxelData, uint64_t dataVersion); - void receiveNewMesh(model::MeshPointer newMeshPtr, uint64_t meshVersion); + void receiveNewVoxelData(QByteArray newVoxelData, quint64 dataVersion); + void receiveNewMesh(model::MeshPointer newMeshPtr, quint64 meshVersion); + void setDataVersion(quint64 dataVersion) { _dataVersion = dataVersion; } private: // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize. - model::Geometry _modelGeometry; - mutable QReadWriteLock _modelGeometryLock; + virtual bool computeShapeInfoWorker(); - QFuture _getModelWorker; + // model::Geometry _modelGeometry; + mutable QReadWriteLock _modelGeometryLock; + model::MeshPointer _mesh; + + QFuture _getMeshWorker; NetworkTexturePointer _xTexture; NetworkTexturePointer _yTexture; @@ -163,16 +178,17 @@ private: static gpu::PipelinePointer _pipeline; ShapeInfo _shapeInfo; - QFuture _shapeInfoWorker; + // QFuture _shapeInfoWorker; + mutable QReadWriteLock _shapeInfoLock; // this does work outside of the main thread. RenderablePolyVoxAsynchronous _async; - uint64_t _modelVersion = 0; // local idea of how many changes have happened + quint64 _modelVersion = 1; // local idea of how many changes have happened // the following are compared against _modelVersion - uint64_t _meshVersion = 0; // version of most recently computed mesh - uint64_t _dataVersion = 0; // version of most recently compressed voxel data - uint64_t _shapeVersion = 0; // version of most recently computed collision shape + quint64 _meshVersion = 0; // version of most recently computed mesh + quint64 _dataVersion = 0; // version of most recently compressed voxel data + quint64 _shapeVersion = 0; // version of most recently computed collision shape }; diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 1e42f26ff8..df3b6d1608 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -184,3 +184,17 @@ void PolyVoxEntityItem::debugDump() const { qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } + +void PolyVoxEntityItem::setVoxelData(QByteArray voxelData) +{ + qDebug() << "5d301155-faf9-44dd-8e8b-061a03d42c0f parent setVoxelData for" << getName() << getID() << ((void *)this) + << typeid(*this).name(); + + _voxelDataLock.lockForWrite(); + _voxelData = voxelData; + _voxelDataLock.unlock(); +} + +const QByteArray PolyVoxEntityItem::getVoxelData() const { + return _voxelData; +} diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 8e159900cd..118f6cc99b 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -52,8 +52,8 @@ class PolyVoxEntityItem : public EntityItem { virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize); virtual const glm::vec3& getVoxelVolumeSize() const { return _voxelVolumeSize; } - virtual void setVoxelData(QByteArray voxelData) { _voxelData = voxelData; } - virtual const QByteArray& getVoxelData() const { return _voxelData; } + virtual void setVoxelData(QByteArray voxelData); + virtual const QByteArray getVoxelData() const; enum PolyVoxSurfaceStyle { SURFACE_MARCHING_CUBES, @@ -105,6 +105,7 @@ class PolyVoxEntityItem : public EntityItem { protected: glm::vec3 _voxelVolumeSize; // this is always 3 bytes + mutable QReadWriteLock _voxelDataLock; QByteArray _voxelData; PolyVoxSurfaceStyle _voxelSurfaceStyle;