//// MetavoxelSystem.cpp// interface/src//// Created by Andrzej Kapolka on 12/10/13.// Copyright 2013 High Fidelity, Inc.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL#include "InterfaceConfig.h" #include <QMutexLocker>#include <QOpenGLFramebufferObject>#include <QReadLocker>#include <QWriteLocker>#include <QThreadPool>#include <QtDebug> #include <glm/gtx/transform.hpp> #include <GeometryUtil.h>#include <SharedUtil.h> #include <MetavoxelMessages.h>#include <MetavoxelUtil.h>#include <PathUtils.h>#include <ScriptCache.h> #include "Application.h"#include "MetavoxelSystem.h"#include "renderer/Model.h"#include "renderer/RenderUtil.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation)REGISTER_META_OBJECT(SphereRenderer)REGISTER_META_OBJECT(CuboidRenderer)REGISTER_META_OBJECT(StaticModelRenderer)REGISTER_META_OBJECT(HeightfieldRenderer) MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate, int minimumDelay, int maximumDelay, int bandwidthLimit) : dropRate(dropRate), repeatRate(repeatRate), minimumDelay(minimumDelay), maximumDelay(maximumDelay), bandwidthLimit(bandwidthLimit) {} MetavoxelSystem::~MetavoxelSystem() { // kill the updater before we delete our network simulation objects _updater->thread()->quit(); _updater->thread()->wait(); _updater = NULL;} void MetavoxelSystem::init() { MetavoxelClientManager::init(); _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( new BufferDataAttribute("voxelBuffer")); _voxelBufferAttribute->setLODThresholdMultiplier( AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier()); _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_base.vert"); _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_base.frag"); _baseHeightfieldProgram.link(); _baseHeightfieldProgram.bind(); _baseHeightfieldProgram.setUniformValue("heightMap", 0); _baseHeightfieldProgram.setUniformValue("diffuseMap", 1); _baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale"); _baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale"); _baseHeightfieldProgram.release(); loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_cursor.vert"); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_cursor.frag"); _heightfieldCursorProgram.link(); _heightfieldCursorProgram.bind(); _heightfieldCursorProgram.setUniformValue("heightMap", 0); _heightfieldCursorProgram.release(); _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_base.vert"); _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_base.frag"); _baseVoxelProgram.link(); loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations); _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_cursor.vert"); _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_cursor.frag"); _voxelCursorProgram.link();} MetavoxelLOD MetavoxelSystem::getLOD() { QReadLocker locker(&_lodLock); return _lod;} void MetavoxelSystem::setNetworkSimulation(const NetworkSimulation& simulation) { QWriteLocker locker(&_networkSimulationLock); _networkSimulation = simulation;} MetavoxelSystem::NetworkSimulation MetavoxelSystem::getNetworkSimulation() { QReadLocker locker(&_networkSimulationLock); return _networkSimulation;} class SimulateVisitor : public MetavoxelVisitor {public: SimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); private: float _deltaTime;}; SimulateVisitor::SimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod), _deltaTime(deltaTime) {} int SimulateVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod); return STOP_RECURSION;} void MetavoxelSystem::simulate(float deltaTime) { // update the lod { QWriteLocker locker(&_lodLock); const float DEFAULT_LOD_THRESHOLD = 0.01f; _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), DEFAULT_LOD_THRESHOLD); } SimulateVisitor simulateVisitor(deltaTime, getLOD()); guideToAugmented(simulateVisitor);} class RenderVisitor : public MetavoxelVisitor {public: RenderVisitor(const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info);}; RenderVisitor::RenderVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod) {} int RenderVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod); return STOP_RECURSION;} class HeightfieldPoint {public: glm::vec3 vertex; glm::vec2 textureCoord;}; const int SPLAT_COUNT = 4;const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; static const int EIGHT_BIT_MAXIMUM = 255;static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() { // update the frustum ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); RenderVisitor renderVisitor(getLOD()); guideToAugmented(renderVisitor, true); if (!_heightfieldBaseBatches.isEmpty()) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_EQUAL, 0.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); _baseHeightfieldProgram.bind(); foreach (const HeightfieldBaseLayerBatch& batch, _heightfieldBaseBatches) { glPushMatrix(); glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); glm::vec3 axis = glm::axis(batch.rotation); glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); glScalef(batch.scale.x, batch.scale.y, batch.scale.z); batch.vertexBuffer->bind(); batch.indexBuffer->bind(); HeightfieldPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); _baseHeightfieldProgram.setUniform(_baseHeightScaleLocation, batch.heightScale); _baseHeightfieldProgram.setUniform(_baseColorScaleLocation, batch.colorScale); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, batch.colorTextureID); glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); batch.vertexBuffer->release(); batch.indexBuffer->release(); glPopMatrix(); } DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false); _baseHeightfieldProgram.release(); glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); if (!_heightfieldSplatBatches.isEmpty()) { glDepthFunc(GL_LEQUAL); glDepthMask(false); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); _splatHeightfieldProgram.bind(); foreach (const HeightfieldSplatBatch& batch, _heightfieldSplatBatches) { glPushMatrix(); glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); glm::vec3 axis = glm::axis(batch.rotation); glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); glScalef(batch.scale.x, batch.scale.y, batch.scale.z); batch.vertexBuffer->bind(); batch.indexBuffer->bind(); HeightfieldPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); _splatHeightfieldProgram.setUniformValue(_splatHeightfieldLocations.heightScale, batch.heightScale.x, batch.heightScale.y); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.textureScale, batch.textureScale); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureOffset, batch.splatTextureOffset); const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesS, batch.splatTextureScalesS); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesT, batch.splatTextureScalesT); _splatHeightfieldProgram.setUniformValue( _splatHeightfieldLocations.textureValueMinima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); _splatHeightfieldProgram.setUniformValue( _splatHeightfieldLocations.textureValueMaxima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, batch.materialTextureID); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]); } glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, 0); } glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); batch.vertexBuffer->release(); batch.indexBuffer->release(); glPopMatrix(); } _splatHeightfieldProgram.release(); glDisable(GL_POLYGON_OFFSET_FILL); glDepthMask(true); glDepthFunc(GL_LESS); _heightfieldSplatBatches.clear(); } glDisable(GL_CULL_FACE); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); _heightfieldBaseBatches.clear(); } if (!_voxelBaseBatches.isEmpty()) { DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_EQUAL, 0.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); _baseVoxelProgram.bind(); foreach (const VoxelBatch& batch, _voxelBaseBatches) { batch.vertexBuffer->bind(); batch.indexBuffer->bind(); VoxelPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex); glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color); glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal); glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); batch.vertexBuffer->release(); batch.indexBuffer->release(); } _baseVoxelProgram.release(); glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false); if (!_voxelSplatBatches.isEmpty()) { glDepthFunc(GL_LEQUAL); glDepthMask(false); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); _splatVoxelProgram.bind(); _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materials); _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materialWeights); foreach (const VoxelSplatBatch& batch, _voxelSplatBatches) { batch.vertexBuffer->bind(); batch.indexBuffer->bind(); VoxelPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex); glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color); glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal); _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materials, GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint)); _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materialWeights, GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint)); const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesS, batch.splatTextureScalesS); _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesT, batch.splatTextureScalesT); _splatVoxelProgram.setUniformValue( _splatVoxelLocations.textureValueMinima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); _splatVoxelProgram.setUniformValue( _splatVoxelLocations.textureValueMaxima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]); } glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, 0); } glActiveTexture(GL_TEXTURE0); batch.vertexBuffer->release(); batch.indexBuffer->release(); } glDisable(GL_POLYGON_OFFSET_FILL); glDepthMask(true); glDepthFunc(GL_LESS); _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materials); _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materialWeights); _voxelSplatBatches.clear(); } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_CULL_FACE); _voxelBaseBatches.clear(); } if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram(); foreach (const HermiteBatch& batch, _hermiteBatches) { batch.vertexBuffer->bind(); glVertexPointer(3, GL_FLOAT, 0, 0); glDrawArrays(GL_LINES, 0, batch.vertexCount); batch.vertexBuffer->release(); } Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram(); glDisableClientState(GL_VERTEX_ARRAY); DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false); } _hermiteBatches.clear(); // give external parties a chance to join in emit rendering();} void MetavoxelSystem::refreshVoxelData() { foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NodeType::MetavoxelServer) {Lines 1–500 of 2337. Load more
// // MetavoxelSystem.cpp // interface/src // // Created by Andrzej Kapolka on 12/10/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // // include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL #include "InterfaceConfig.h" #include <QMutexLocker> #include <QOpenGLFramebufferObject> #include <QReadLocker> #include <QWriteLocker> #include <QThreadPool> #include <QtDebug> #include <glm/gtx/transform.hpp> #include <GeometryUtil.h> #include <SharedUtil.h> #include <MetavoxelMessages.h> #include <MetavoxelUtil.h> #include <PathUtils.h> #include <ScriptCache.h> #include "Application.h" #include "MetavoxelSystem.h" #include "renderer/Model.h" #include "renderer/RenderUtil.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation) REGISTER_META_OBJECT(SphereRenderer) REGISTER_META_OBJECT(CuboidRenderer) REGISTER_META_OBJECT(StaticModelRenderer) REGISTER_META_OBJECT(HeightfieldRenderer) MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate, int minimumDelay, int maximumDelay, int bandwidthLimit) : dropRate(dropRate), repeatRate(repeatRate), minimumDelay(minimumDelay), maximumDelay(maximumDelay), bandwidthLimit(bandwidthLimit) { } MetavoxelSystem::~MetavoxelSystem() { // kill the updater before we delete our network simulation objects _updater->thread()->quit(); _updater->thread()->wait(); _updater = NULL; } void MetavoxelSystem::init() { MetavoxelClientManager::init(); _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( new BufferDataAttribute("voxelBuffer")); _voxelBufferAttribute->setLODThresholdMultiplier( AttributeRegistry::getInstance()->getVoxelColorAttribute()->getLODThresholdMultiplier()); _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_base.vert"); _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_base.frag"); _baseHeightfieldProgram.link(); _baseHeightfieldProgram.bind(); _baseHeightfieldProgram.setUniformValue("heightMap", 0); _baseHeightfieldProgram.setUniformValue("diffuseMap", 1); _baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale"); _baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale"); _baseHeightfieldProgram.release(); loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_heightfield_cursor.vert"); _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_cursor.frag"); _heightfieldCursorProgram.link(); _heightfieldCursorProgram.bind(); _heightfieldCursorProgram.setUniformValue("heightMap", 0); _heightfieldCursorProgram.release(); _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_base.vert"); _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_base.frag"); _baseVoxelProgram.link(); loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations); _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/metavoxel_voxel_cursor.vert"); _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/metavoxel_cursor.frag"); _voxelCursorProgram.link(); } MetavoxelLOD MetavoxelSystem::getLOD() { QReadLocker locker(&_lodLock); return _lod; } void MetavoxelSystem::setNetworkSimulation(const NetworkSimulation& simulation) { QWriteLocker locker(&_networkSimulationLock); _networkSimulation = simulation; } MetavoxelSystem::NetworkSimulation MetavoxelSystem::getNetworkSimulation() { QReadLocker locker(&_networkSimulationLock); return _networkSimulation; } class SimulateVisitor : public MetavoxelVisitor { public: SimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); private: float _deltaTime; }; SimulateVisitor::SimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod), _deltaTime(deltaTime) { } int SimulateVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod); return STOP_RECURSION; } void MetavoxelSystem::simulate(float deltaTime) { // update the lod { QWriteLocker locker(&_lodLock); const float DEFAULT_LOD_THRESHOLD = 0.01f; _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), DEFAULT_LOD_THRESHOLD); } SimulateVisitor simulateVisitor(deltaTime, getLOD()); guideToAugmented(simulateVisitor); } class RenderVisitor : public MetavoxelVisitor { public: RenderVisitor(const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); }; RenderVisitor::RenderVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod) { } int RenderVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod); return STOP_RECURSION; } class HeightfieldPoint { public: glm::vec3 vertex; glm::vec2 textureCoord; }; const int SPLAT_COUNT = 4; const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; static const int EIGHT_BIT_MAXIMUM = 255; static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() { // update the frustum ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); RenderVisitor renderVisitor(getLOD()); guideToAugmented(renderVisitor, true); if (!_heightfieldBaseBatches.isEmpty()) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_EQUAL, 0.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); _baseHeightfieldProgram.bind(); foreach (const HeightfieldBaseLayerBatch& batch, _heightfieldBaseBatches) { glPushMatrix(); glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); glm::vec3 axis = glm::axis(batch.rotation); glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); glScalef(batch.scale.x, batch.scale.y, batch.scale.z); batch.vertexBuffer->bind(); batch.indexBuffer->bind(); HeightfieldPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); _baseHeightfieldProgram.setUniform(_baseHeightScaleLocation, batch.heightScale); _baseHeightfieldProgram.setUniform(_baseColorScaleLocation, batch.colorScale); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, batch.colorTextureID); glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); batch.vertexBuffer->release(); batch.indexBuffer->release(); glPopMatrix(); } DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false); _baseHeightfieldProgram.release(); glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); if (!_heightfieldSplatBatches.isEmpty()) { glDepthFunc(GL_LEQUAL); glDepthMask(false); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); _splatHeightfieldProgram.bind(); foreach (const HeightfieldSplatBatch& batch, _heightfieldSplatBatches) { glPushMatrix(); glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); glm::vec3 axis = glm::axis(batch.rotation); glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); glScalef(batch.scale.x, batch.scale.y, batch.scale.z); batch.vertexBuffer->bind(); batch.indexBuffer->bind(); HeightfieldPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); _splatHeightfieldProgram.setUniformValue(_splatHeightfieldLocations.heightScale, batch.heightScale.x, batch.heightScale.y); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.textureScale, batch.textureScale); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureOffset, batch.splatTextureOffset); const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesS, batch.splatTextureScalesS); _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesT, batch.splatTextureScalesT); _splatHeightfieldProgram.setUniformValue( _splatHeightfieldLocations.textureValueMinima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); _splatHeightfieldProgram.setUniformValue( _splatHeightfieldLocations.textureValueMaxima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, batch.materialTextureID); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]); } glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, 0); } glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); batch.vertexBuffer->release(); batch.indexBuffer->release(); glPopMatrix(); } _splatHeightfieldProgram.release(); glDisable(GL_POLYGON_OFFSET_FILL); glDepthMask(true); glDepthFunc(GL_LESS); _heightfieldSplatBatches.clear(); } glDisable(GL_CULL_FACE); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); _heightfieldBaseBatches.clear(); } if (!_voxelBaseBatches.isEmpty()) { DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_EQUAL, 0.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); _baseVoxelProgram.bind(); foreach (const VoxelBatch& batch, _voxelBaseBatches) { batch.vertexBuffer->bind(); batch.indexBuffer->bind(); VoxelPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex); glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color); glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal); glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); batch.vertexBuffer->release(); batch.indexBuffer->release(); } _baseVoxelProgram.release(); glDisable(GL_ALPHA_TEST); glEnable(GL_BLEND); DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false); if (!_voxelSplatBatches.isEmpty()) { glDepthFunc(GL_LEQUAL); glDepthMask(false); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); _splatVoxelProgram.bind(); _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materials); _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materialWeights); foreach (const VoxelSplatBatch& batch, _voxelSplatBatches) { batch.vertexBuffer->bind(); batch.indexBuffer->bind(); VoxelPoint* point = 0; glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex); glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color); glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal); _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materials, GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint)); _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materialWeights, GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint)); const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesS, batch.splatTextureScalesS); _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesT, batch.splatTextureScalesT); _splatVoxelProgram.setUniformValue( _splatVoxelLocations.textureValueMinima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); _splatVoxelProgram.setUniformValue( _splatVoxelLocations.textureValueMaxima, (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]); } glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); for (int i = 0; i < SPLAT_COUNT; i++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); glBindTexture(GL_TEXTURE_2D, 0); } glActiveTexture(GL_TEXTURE0); batch.vertexBuffer->release(); batch.indexBuffer->release(); } glDisable(GL_POLYGON_OFFSET_FILL); glDepthMask(true); glDepthFunc(GL_LESS); _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materials); _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materialWeights); _voxelSplatBatches.clear(); } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_CULL_FACE); _voxelBaseBatches.clear(); } if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, true); glEnableClientState(GL_VERTEX_ARRAY); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); Application::getInstance()->getDeferredLightingEffect()->bindSimpleProgram(); foreach (const HermiteBatch& batch, _hermiteBatches) { batch.vertexBuffer->bind(); glVertexPointer(3, GL_FLOAT, 0, 0); glDrawArrays(GL_LINES, 0, batch.vertexCount); batch.vertexBuffer->release(); } Application::getInstance()->getDeferredLightingEffect()->releaseSimpleProgram(); glDisableClientState(GL_VERTEX_ARRAY); DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false); } _hermiteBatches.clear(); // give external parties a chance to join in emit rendering(); } void MetavoxelSystem::refreshVoxelData() { foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NodeType::MetavoxelServer) {