mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 20:44:14 +02:00
more work on polyvox threading
This commit is contained in:
parent
91254245e4
commit
7cb9968864
4 changed files with 281 additions and 78 deletions
|
@ -38,7 +38,6 @@
|
|||
#include <PolyVoxCore/Material.h>
|
||||
|
||||
#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<gpu::Buffer>(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<const uint32_t> it = indexBufferView.cbegin<uint32_t>();
|
||||
while (it != indexBufferView.cend<uint32_t>()) {
|
||||
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::SimpleVolume<uin
|
|||
|
||||
|
||||
uint8_t RenderablePolyVoxAsynchronous::getVoxel(int x, int y, int z) {
|
||||
_volDataLock.lockForRead();
|
||||
auto result = getVoxelInternal(x, y, z);
|
||||
_volDataLock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t RenderablePolyVoxAsynchronous::getVoxelInternal(int x, int y, int z) {
|
||||
if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -795,7 +897,7 @@ bool RenderablePolyVoxAsynchronous::updateOnCount(int x, int y, int z, uint8_t t
|
|||
return false;
|
||||
}
|
||||
|
||||
uint8_t uVoxelValue = getVoxel(x, y, z);
|
||||
uint8_t uVoxelValue = getVoxelInternal(x, y, z);
|
||||
if (toValue != 0) {
|
||||
if (uVoxelValue == 0) {
|
||||
_onCount++;
|
||||
|
@ -813,22 +915,31 @@ bool RenderablePolyVoxAsynchronous::updateOnCount(int x, int y, int z, uint8_t t
|
|||
}
|
||||
|
||||
|
||||
bool RenderablePolyVoxAsynchronous::setVoxel(int x, int y, int z, uint8_t toValue, uint64_t modelVersion) {
|
||||
bool RenderablePolyVoxAsynchronous::setVoxel(int x, int y, int z, uint8_t toValue, quint64 modelVersion) {
|
||||
_volDataLock.lockForWrite();
|
||||
bool result = setVoxelInternal(x, y, z, toValue);
|
||||
_volDataLock.unlock();
|
||||
if (result) {
|
||||
# ifdef THREAD_POLYVOX
|
||||
QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::compressVolumeData, modelVersion);
|
||||
QtConcurrent::run(this, &RenderablePolyVoxAsynchronous::getMeshAsync, modelVersion);
|
||||
# else
|
||||
compressVolumeData(modelVersion);
|
||||
getModel(modelVersion);
|
||||
getMeshAsync(modelVersion);
|
||||
# endif
|
||||
} else {
|
||||
// nothing changed.
|
||||
_owner->receiveNewVoxelData(_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<void> 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<PolyVox::PositionMaterialNormal> 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<uint32_t>& vecIndices = polyVoxMesh.getIndices();
|
||||
|
@ -966,10 +1127,11 @@ void RenderablePolyVoxAsynchronous::getModel(uint64_t modelVersion) {
|
|||
auto vertexBuffer = std::make_shared<gpu::Buffer>(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,15 +13,17 @@
|
|||
#define hifi_RenderablePolyVoxEntityItem_h
|
||||
|
||||
#include <QFuture>
|
||||
#include <atomic>
|
||||
|
||||
#include <PolyVoxCore/SimpleVolume.h>
|
||||
#include <PolyVoxCore/Raycast.h>
|
||||
|
||||
#include <TextureCache.h>
|
||||
|
||||
#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<uint8_t>* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle,
|
||||
int x, int y, int z);
|
||||
|
||||
|
@ -71,7 +83,7 @@ private:
|
|||
glm::vec3 _voxelVolumeSize;
|
||||
PolyVox::SimpleVolume<uint8_t>* _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<render::Scene> 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<bool> _getModelWorker;
|
||||
// model::Geometry _modelGeometry;
|
||||
mutable QReadWriteLock _modelGeometryLock;
|
||||
model::MeshPointer _mesh;
|
||||
|
||||
QFuture<bool> _getMeshWorker;
|
||||
|
||||
NetworkTexturePointer _xTexture;
|
||||
NetworkTexturePointer _yTexture;
|
||||
|
@ -163,16 +178,17 @@ private:
|
|||
static gpu::PipelinePointer _pipeline;
|
||||
|
||||
ShapeInfo _shapeInfo;
|
||||
QFuture<bool> _shapeInfoWorker;
|
||||
// QFuture<bool> _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
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue