diff --git a/examples/voxels.js b/examples/voxels.js index e110f15260..9627b40701 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -44,7 +44,7 @@ function mousePressEvent(event) { } } - // if the PolyVox entity is empty, we can't pick against its voxel. try picking against its + // if the PolyVox entity is empty, we can't pick against its "on" voxels. try picking against its // bounding box, instead. intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking if (intersection.intersects) { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 4f21fec4d3..ca049e45b1 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -331,6 +331,144 @@ void RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float r setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue); } +void RenderablePolyVoxEntityItem::getModel() { + // A mesh object to hold the result of surface extraction + PolyVox::SurfaceMesh polyVoxMesh; + + switch (_voxelSurfaceStyle) { + case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: { + PolyVox::MarchingCubesSurfaceExtractor> surfaceExtractor + (_volData, _volData->getEnclosingRegion(), &polyVoxMesh); + surfaceExtractor.execute(); + break; + } + case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: + case PolyVoxEntityItem::SURFACE_CUBIC: { + PolyVox::CubicSurfaceExtractorWithNormals> surfaceExtractor + (_volData, _volData->getEnclosingRegion(), &polyVoxMesh); + surfaceExtractor.execute(); + break; + } + } + + // convert PolyVox mesh to a Sam mesh + auto mesh = _modelGeometry.getMesh(); + + const std::vector& vecIndices = polyVoxMesh.getIndices(); + auto indexBuffer = std::make_shared(vecIndices.size() * sizeof(uint32_t), + (gpu::Byte*)vecIndices.data()); + auto indexBufferPtr = gpu::BufferPointer(indexBuffer); + auto indexBufferView = new gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW)); + mesh->setIndexBuffer(*indexBufferView); + + + const std::vector& vecVertices = polyVoxMesh.getVertices(); + 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::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)); + mesh->setVertexBuffer(*vertexBufferView); + mesh->addAttribute(gpu::Stream::NORMAL, + gpu::BufferView(vertexBufferPtr, + sizeof(float) * 3, + vertexBufferPtr->getSize() - sizeof(float) * 3, + sizeof(PolyVox::PositionMaterialNormal), + gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); + + + + // auto normalAttrib = mesh->getAttributeBuffer(gpu::Stream::NORMAL); + // for (auto normal = normalAttrib.begin(); normal != normalAttrib.end(); normal++) { + // (*normal) = -(*normal); + // } + + + // mesh->addAttribute(gpu::Stream::TEXCOORD, + // gpu::BufferView(vertexBufferPtr, + // sizeof(float) * 2, + // vertexBufferPtr->getSize() - sizeof(float) * 2, + // sizeof(PolyVox::PositionMaterialNormal), + // gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::RAW))); + + + + #ifdef WANT_DEBUG + qDebug() << "---- vecIndices.size() =" << vecIndices.size(); + qDebug() << "---- vecVertices.size() =" << vecVertices.size(); + #endif + + _needsModelReload = false; +} + +bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self, + std::shared_ptr scene, + render::PendingChanges& pendingChanges) { + _myItem = scene->allocateID(); + + std::shared_ptr renderData = + RenderableEntityItemProxy::Pointer(new RenderableEntityItemProxy(self)); + // render::PayloadPointer renderPayload = + std::shared_ptr renderPayload = + render::PayloadPointer(new RenderableEntityItemProxy::Payload(renderData)); + + pendingChanges.resetItem(_myItem, renderPayload); + + return true; +} + +void RenderablePolyVoxEntityItem::removeFromScene(EntityItemPointer self, + std::shared_ptr scene, + render::PendingChanges& pendingChanges) { + pendingChanges.removeItem(_myItem); +} + + + +void RenderablePolyVoxEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); + assert(getType() == EntityTypes::PolyVox); + + if (_needsModelReload) { + getModel(); + } + + Transform transform(voxelToWorldMatrix()); + + auto mesh = _modelGeometry.getMesh(); + Q_ASSERT(args->_batch); + gpu::Batch& batch = *args->_batch; + DependencyManager::get()->bindSimpleProgram(batch, true); + batch.setModelTransform(transform); + batch.setInputFormat(mesh->getVertexFormat()); + batch.setInputBuffer(gpu::Stream::POSITION, mesh->getVertexBuffer()); + batch.setInputBuffer(gpu::Stream::NORMAL, + mesh->getVertexBuffer()._buffer, + sizeof(float) * 3, + mesh->getVertexBuffer()._stride); + batch.setIndexBuffer(gpu::UINT32, mesh->getIndexBuffer()._buffer, 0); + batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); + + if (!_xTextureURL.isEmpty() && !_xTexture) { + _xTexture = DependencyManager::get()->getTexture(_xTextureURL); + } + if (!_yTextureURL.isEmpty() && !_yTexture) { + _yTexture = DependencyManager::get()->getTexture(_yTextureURL); + } + if (!_zTextureURL.isEmpty() && !_zTexture) { + _zTexture = DependencyManager::get()->getTexture(_zTextureURL); + } + + if (_xTexture) { + batch.setResourceTexture(0, _xTexture->getGPUTexture()); + } + + RenderableDebugableEntityItem::render(this, args); +} + class RaycastFunctor { public: diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index d495900ce9..40925cb765 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -89,6 +89,14 @@ public: virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue); + virtual bool addToScene(EntityItemPointer self, + std::shared_ptr scene, + render::PendingChanges& pendingChanges); + virtual void removeFromScene(EntityItemPointer self, + std::shared_ptr scene, + render::PendingChanges& pendingChanges); + + virtual void setXTextureURL(QString xTextureURL); virtual void setYTextureURL(QString yTextureURL); virtual void setZTextureURL(QString zTextureURL); @@ -104,6 +112,8 @@ protected: virtual void updateVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle); private: + render::ItemID _myItem; + // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize.