diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index cc30a011af..7198c0030c 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -57,9 +57,6 @@ const float SKIN_COLOR[] = {1.0, 0.84, 0.66}; const float DARK_SKIN_COLOR[] = {0.9, 0.78, 0.63}; const int NUM_BODY_CONE_SIDES = 9; -const float AVATAR_TREE_SCALE = 1.0f; -const int MAX_VOXELS_PER_AVATAR = 2000; - bool usingBigSphereCollisionTest = true; float chatMessageScale = 0.0015; @@ -91,8 +88,7 @@ Avatar::Avatar(Agent* owningAgent) : _mouseRayDirection(0.0f, 0.0f, 0.0f), _interactingOther(NULL), _cumulativeMouseYaw(0.0f), - _isMouseTurningRight(false), - _voxels(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR) + _isMouseTurningRight(false) { // give the pointer to our head to inherited _headData variable from AvatarData @@ -1153,7 +1149,8 @@ void Avatar::renderBody(bool lookingInMirror) { // Render the body's voxels glPushMatrix(); - glTranslatef(_position.x, _position.y, _position.z); + const glm::vec3& voxelPosition = _joint[AVATAR_JOINT_PELVIS].springyPosition; + glTranslatef(voxelPosition.x, voxelPosition.y, voxelPosition.z); glm::quat rotation = getOrientation(); glm::vec3 axis = glm::axis(rotation); glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z); diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index d1bc651eff..726ae972c2 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -13,13 +13,13 @@ #include #include "world.h" #include "AvatarTouch.h" +#include "AvatarVoxelSystem.h" #include "InterfaceConfig.h" #include "SerialInterface.h" #include "Balls.h" #include "Head.h" #include "Skeleton.h" #include "Transmitter.h" -#include "VoxelSystem.h" enum DriveKeys { @@ -149,7 +149,8 @@ private: Avatar* _interactingOther; float _cumulativeMouseYaw; bool _isMouseTurningRight; - VoxelSystem _voxels; + + AvatarVoxelSystem _voxels; // private methods... glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat) diff --git a/interface/src/AvatarVoxelSystem.cpp b/interface/src/AvatarVoxelSystem.cpp new file mode 100644 index 0000000000..79f3f113b9 --- /dev/null +++ b/interface/src/AvatarVoxelSystem.cpp @@ -0,0 +1,97 @@ +// +// AvatarVoxelSystem.cpp +// interface +// +// Created by Andrzej Kapolka on 5/31/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +#include + +#include "AvatarVoxelSystem.h" + +const float AVATAR_TREE_SCALE = 1.0f; +const int MAX_VOXELS_PER_AVATAR = 2000; +const int BONE_INDEX_ELEMENTS_PER_VOXEL = 4 * VERTICES_PER_VOXEL; +const int BONE_WEIGHT_ELEMENTS_PER_VOXEL = 4 * VERTICES_PER_VOXEL; + +AvatarVoxelSystem::AvatarVoxelSystem() : VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR) { +} + +AvatarVoxelSystem::~AvatarVoxelSystem() { + delete[] _readBoneIndicesArray; + delete[] _readBoneWeightsArray; + delete[] _writeBoneIndicesArray; + delete[] _writeBoneWeightsArray; +} + +void AvatarVoxelSystem::init() { + VoxelSystem::init(); + + // prep the data structures for incoming voxel data + _writeBoneIndicesArray = new GLubyte[BONE_INDEX_ELEMENTS_PER_VOXEL * _maxVoxels]; + _readBoneIndicesArray = new GLubyte[BONE_INDEX_ELEMENTS_PER_VOXEL * _maxVoxels]; + + _writeBoneWeightsArray = new GLfloat[BONE_WEIGHT_ELEMENTS_PER_VOXEL * _maxVoxels]; + _readBoneWeightsArray = new GLfloat[BONE_WEIGHT_ELEMENTS_PER_VOXEL * _maxVoxels]; + + // VBO for the boneIndicesArray + glGenBuffers(1, &_vboBoneIndicesID); + glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID); + glBufferData(GL_ARRAY_BUFFER, BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); + + // VBO for the boneWeightsArray + glGenBuffers(1, &_vboBoneWeightsID); + glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID); + glBufferData(GL_ARRAY_BUFFER, BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); +} + +void AvatarVoxelSystem::render(bool texture) { + VoxelSystem::render(texture); +} + +void AvatarVoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, + float voxelScale, const nodeColor& color) { + VoxelSystem::updateNodeInArrays(nodeIndex, startVertex, voxelScale, color); + + for (int j = 0; j < BONE_INDEX_ELEMENTS_PER_VOXEL; j++) { + GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (nodeIndex * BONE_INDEX_ELEMENTS_PER_VOXEL); + GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (nodeIndex * BONE_WEIGHT_ELEMENTS_PER_VOXEL); + *(writeBoneIndicesAt + j) = 0; + *(writeBoneWeightsAt + j) = 0.0f; + } +} + +void AvatarVoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { + VoxelSystem::copyWrittenDataSegmentToReadArrays(segmentStart, segmentEnd); + + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte); + GLsizeiptr segmentSizeBytes = segmentLength * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readBoneIndicesAt = _readBoneIndicesArray + (segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL); + GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL); + memcpy(readBoneIndicesAt, writeBoneIndicesAt, segmentSizeBytes); + + segmentStartAt = segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat); + segmentSizeBytes = segmentLength * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readBoneWeightsAt = _readBoneWeightsArray + (segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL); + GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL); + memcpy(readBoneWeightsAt, writeBoneWeightsAt, segmentSizeBytes); +} + +void AvatarVoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { + VoxelSystem::updateVBOSegment(segmentStart, segmentEnd); + + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte); + GLsizeiptr segmentSizeBytes = segmentLength * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readBoneIndicesFrom = _readBoneIndicesArray + (segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readBoneIndicesFrom); + + segmentStartAt = segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat); + segmentSizeBytes = segmentLength * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readBoneWeightsFrom = _readBoneWeightsArray + (segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readBoneWeightsFrom); +} + diff --git a/interface/src/AvatarVoxelSystem.h b/interface/src/AvatarVoxelSystem.h new file mode 100644 index 0000000000..d129e046b9 --- /dev/null +++ b/interface/src/AvatarVoxelSystem.h @@ -0,0 +1,43 @@ +// +// AvatarVoxelSystem.h +// interface +// +// Created by Andrzej Kapolka on 5/31/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__AvatarVoxelSystem__ +#define __interface__AvatarVoxelSystem__ + +#include "VoxelSystem.h" + +class AvatarVoxelSystem : public VoxelSystem { +public: + + AvatarVoxelSystem(); + virtual ~AvatarVoxelSystem(); + + virtual void init(); + virtual void render(bool texture); + +protected: + + virtual void updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, + float voxelScale, const nodeColor& color); + virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd); + virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd); + +private: + + GLubyte* _readBoneIndicesArray; + GLfloat* _readBoneWeightsArray; + GLubyte* _writeBoneIndicesArray; + GLfloat* _writeBoneWeightsArray; + + GLuint _vboBoneIndicesID; + GLuint _vboBoneWeightsID; + + ProgramObject* _skinProgram; +}; + +#endif /* defined(__interface__AvatarVoxelSystem__) */ diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index b4202511e6..7f5a926d28 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -231,10 +231,8 @@ void VoxelSystem::cleanupRemovedVoxels() { } void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() { - int bytesOfVertices = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); - int bytesOfColors = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte); - memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices); - memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); + copyWrittenDataSegmentToReadArrays(0, _voxelsInWriteArrays - 1); + _voxelsInReadArrays = _voxelsInWriteArrays; // clear our dirty flags @@ -261,47 +259,37 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { if (!thisVoxelDirty) { // If we got here because because this voxel is NOT dirty, so the last dirty voxel was the one before // this one and so that's where the "segment" ends - segmentEnd = i - 1; + copyWrittenDataSegmentToReadArrays(segmentStart, i - 1); inSegment = false; - int segmentLength = (segmentEnd - segmentStart) + 1; - - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); } } } // if we got to the end of the array, and we're in an active dirty segment... if (inSegment) { - segmentEnd = _voxelsInWriteArrays - 1; - int segmentLength = (segmentEnd - segmentStart) + 1; - - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); + copyWrittenDataSegmentToReadArrays(segmentStart, _voxelsInWriteArrays - 1); } // update our length _voxelsInReadArrays = _voxelsInWriteArrays; } +void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd) { + int segmentLength = (segmentEnd - segmentStart) + 1; + + GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); + + segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readColorsAt = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + memcpy(readColorsAt, writeColorsAt, segmentSizeBytes); +} + void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); if (_voxelsDirty && _voxelsUpdated) { @@ -364,12 +352,7 @@ int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) { // populate the array with points for the 8 vertices // and RGB color for each added vertex - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(writeColorsAt +j) = node->getColor()[j % 3]; - } + updateNodeInArrays(nodeIndex, startVertex, voxelScale, node->getColor()); node->setBufferIndex(nodeIndex); _writeVoxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode _voxelsInWriteArrays++; // our know vertices in the arrays @@ -415,17 +398,23 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { // populate the array with points for the 8 vertices // and RGB color for each added vertex - for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { - GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); - *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); - *(writeColorsAt +j) = node->getColor()[j % 3]; - } + updateNodeInArrays(nodeIndex, startVertex, voxelScale, node->getColor()); + return 1; // updated! } return 0; // not-updated } +void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, + float voxelScale, const nodeColor& color) { + for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); + *(writeColorsAt +j) = color[j % 3]; + } +} + ProgramObject* VoxelSystem::_perlinModulateProgram = 0; GLuint VoxelSystem::_permutationNormalTextureID = 0; @@ -546,20 +535,7 @@ void VoxelSystem::init() { } void VoxelSystem::updateFullVBOs() { - glBufferIndex segmentStart = 0; - glBufferIndex segmentEnd = _voxelsInReadArrays; - - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); + updateVBOSegment(0, _voxelsInReadArrays); // consider the _readVoxelDirtyArray[] clean! memset(_readVoxelDirtyArray, false, _voxelsInReadArrays * sizeof(bool)); @@ -581,39 +557,17 @@ void VoxelSystem::updatePartialVBOs() { if (!thisVoxelDirty) { // If we got here because because this voxel is NOT dirty, so the last dirty voxel was the one before // this one and so that's where the "segment" ends - segmentEnd = i - 1; + updateVBOSegment(segmentStart, i - 1); inSegment = false; - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); } _readVoxelDirtyArray[i] = false; // consider us clean! } } // if we got to the end of the array, and we're in an active dirty segment... - if (inSegment) { - segmentEnd = _voxelsInReadArrays - 1; + if (inSegment) { + updateVBOSegment(segmentStart, _voxelsInReadArrays - 1); inSegment = false; - int segmentLength = (segmentEnd - segmentStart) + 1; - GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); - GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); - segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); - GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); - glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); } } @@ -635,6 +589,20 @@ void VoxelSystem::updateVBOs() { _callsToTreesToArrays = 0; // clear it } +void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd) { + int segmentLength = (segmentEnd - segmentStart) + 1; + GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); + GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); + segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); + GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); +} + void VoxelSystem::render(bool texture) { PerformanceWarning warn(_renderWarningsOn, "render()"); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index de904bb64f..a7824d8326 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -31,11 +31,9 @@ public: int parseData(unsigned char* sourceBuffer, int numBytes); - void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }; - - void init(); + virtual void init(); void simulate(float deltaTime) { }; - void render(bool texture); + virtual void render(bool texture); unsigned long getVoxelsUpdated() const {return _voxelsUpdated;}; unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;}; @@ -80,6 +78,16 @@ public: void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive = false); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, creationMode mode, bool destructive = false, bool debug = false); + +protected: + + int _maxVoxels; + + virtual void updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex, + float voxelScale, const nodeColor& color); + virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd); + virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd); + private: // disallow copying of VoxelSystem objects VoxelSystem(const VoxelSystem&); @@ -107,12 +115,13 @@ private: void copyWrittenDataToReadArraysFullVBOs(); void copyWrittenDataToReadArraysPartialVBOs(); + void updateVBOs(); + // these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here static float _maxDistance; static float _minDistance; - float _treeScale; - int _maxVoxels; + float _treeScale; VoxelTree* _tree; GLfloat* _readVerticesArray; GLubyte* _readColorsArray; @@ -121,8 +130,8 @@ private: bool* _writeVoxelDirtyArray; bool* _readVoxelDirtyArray; unsigned long _voxelsUpdated; - unsigned long _voxelsInWriteArrays; unsigned long _voxelsInReadArrays; + unsigned long _voxelsInWriteArrays; unsigned long _unusedArraySpace; bool _writeRenderFullVBO; @@ -140,7 +149,6 @@ private: pthread_mutex_t _bufferWriteLock; pthread_mutex_t _treeLock; - ViewFrustum* _viewFrustum; ViewFrustum _lastKnowViewFrustum; ViewFrustum _lastStableViewFrustum; @@ -149,17 +157,14 @@ private: void setupNewVoxelsForDrawing(); void copyWrittenDataToReadArrays(bool fullVBOs); + + void updateFullVBOs(); // all voxels in the VBO + void updatePartialVBOs(); // multiple segments, only dirty voxels bool _voxelsDirty; static ProgramObject* _perlinModulateProgram; static GLuint _permutationNormalTextureID; - -public: - void updateVBOs(); - void updateFullVBOs(); // all voxels in the VBO - void updatePartialVBOs(); // multiple segments, only dirty voxels - }; #endif