diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4dd3dba178..12af31234b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -156,8 +156,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _window->setWindowTitle("Interface"); printLog("Interface Startup:\n"); - _voxels.setViewFrustum(&_viewFrustum); - unsigned int listenPort = AGENT_SOCKET_LISTEN_PORT; const char** constArgv = const_cast(argv); const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); @@ -1417,8 +1415,6 @@ void Application::initDisplay() { void Application::init() { _voxels.init(); - _voxels.setViewerAvatar(&_myAvatar); - _voxels.setCamera(&_myCamera); _environment.init(); @@ -1429,6 +1425,7 @@ void Application::init() { _stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0); + _myAvatar.init(); _myAvatar.setPosition(START_LOCATION); _myCamera.setMode(CAMERA_MODE_THIRD_PERSON ); _myCamera.setModeShiftRate(1.0f); @@ -2298,7 +2295,9 @@ QAction* Application::checkedVoxelModeAction() const { void Application::attachNewHeadToAgent(Agent* newAgent) { if (newAgent->getLinkedData() == NULL) { - newAgent->setLinkedData(new Avatar(newAgent)); + Avatar* newAvatar = new Avatar(newAgent); + newAvatar->init(); + newAgent->setLinkedData(newAvatar); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 22694aaae5..c2918f1add 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -65,6 +65,7 @@ public: Avatar* getAvatar() { return &_myAvatar; } Camera* getCamera() { return &_myCamera; } + ViewFrustum* getViewFrustum() { return &_viewFrustum; } VoxelSystem* getVoxels() { return &_voxels; } Environment* getEnvironment() { return &_environment; } bool shouldEchoAudio() { return _echoAudioMode->isChecked(); } diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 3a4162d296..886fb78d97 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -61,6 +61,8 @@ 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; @@ -93,7 +95,8 @@ Avatar::Avatar(Agent* owningAgent) : _mouseRayDirection(0.0f, 0.0f, 0.0f), _interactingOther(NULL), _cumulativeMouseYaw(0.0f), - _isMouseTurningRight(false) + _isMouseTurningRight(false), + _voxels(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR) { // give the pointer to our head to inherited _headData variable from AvatarData @@ -119,6 +122,12 @@ Avatar::~Avatar() { delete _balls; } +void Avatar::init() { + _voxels.init(); + + _voxels.createVoxel(0.0f, 0.0f, 0.0f, 1.0f, 255, 0, 255); +} + void Avatar::reset() { _head.reset(); } @@ -1132,6 +1141,15 @@ void Avatar::renderBody(bool lookingInMirror) { const float RENDER_OPAQUE_BEYOND = 1.0f; // Meters beyond which body is shown opaque const float RENDER_TRANSLUCENT_BEYOND = 0.5f; + // Render the body's voxels + glPushMatrix(); + glTranslatef(_position.x, _position.y, _position.z); + glm::quat rotation = getOrientation(); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z); + _voxels.render(false); + glPopMatrix(); + // Render the body as balls and cones for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { float distanceToCamera = glm::length(_cameraPosition - _joint[b].position); diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index d272514ed1..d1bc651eff 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -19,6 +19,7 @@ #include "Head.h" #include "Skeleton.h" #include "Transmitter.h" +#include "VoxelSystem.h" enum DriveKeys { @@ -46,6 +47,7 @@ public: Avatar(Agent* owningAgent = NULL); ~Avatar(); + void init(); void reset(); void simulate(float deltaTime, Transmitter* transmitter); void updateHeadFromGyros(float frametime, SerialInterface * serialInterface); @@ -147,6 +149,7 @@ private: Avatar* _interactingOther; float _cumulativeMouseYaw; bool _isMouseTurningRight; + VoxelSystem _voxels; // private methods... glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 5e1b72e5c4..b4202511e6 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -19,6 +19,7 @@ #include #include #include +#include "Application.h" #include "Log.h" #include "VoxelConstants.h" #include "InterfaceConfig.h" @@ -37,14 +38,15 @@ GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, -1,0,0, +1,0,0, +1,0,0, -1,0,0, -1,0,0, +1,0,0, +1,0,0, -1,0,0 }; -GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- . +GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- 8,9,13, 8,13,12, // Y- 16,23,19, 16,20,23, // X- 17,18,22, 17,22,21, // X+ 10,11,15, 10,15,14, // Y+ - 4,5,6, 4,6,7 }; // Z+ . + 4,5,6, 4,6,7 }; // Z+ -VoxelSystem::VoxelSystem() : AgentData(NULL) { +VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) : + AgentData(NULL), _treeScale(treeScale), _maxVoxels(maxVoxels) { _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; _writeRenderFullVBO = true; _readRenderFullVBO = true; @@ -312,12 +314,11 @@ void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { } int VoxelSystem::newTreeToArrays(VoxelNode* node) { - assert(_viewFrustum); // you must set up _viewFrustum before calling this int voxelsUpdated = 0; bool shouldRender = false; // assume we don't need to render it // if it's colored, we might need to render it! if (node->isColored()) { - float distanceToNode = node->distanceToCamera(*_viewFrustum); + float distanceToNode = node->distanceToCamera(*Application::getInstance()->getViewFrustum()); float boundary = boundaryDistanceForRenderLevel(node->getLevel()); float childBoundary = boundaryDistanceForRenderLevel(node->getLevel() + 1); bool inBoundary = (distanceToNode <= boundary); @@ -352,7 +353,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) { // If we've run out of room, then just bail... - if (_voxelsInWriteArrays >= MAX_VOXELS_PER_SYSTEM) { + if (_voxelsInWriteArrays >= _maxVoxels) { return 0; } @@ -382,7 +383,7 @@ int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) { int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { // If we've run out of room, then just bail... - if (_voxelsInWriteArrays >= MAX_VOXELS_PER_SYSTEM) { + if (_voxelsInWriteArrays >= _maxVoxels) { return 0; } @@ -425,6 +426,9 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { return 0; // not-updated } +ProgramObject* VoxelSystem::_perlinModulateProgram = 0; +GLuint VoxelSystem::_permutationNormalTextureID = 0; + void VoxelSystem::init() { _renderWarningsOn = false; @@ -440,23 +444,23 @@ void VoxelSystem::init() { _unusedArraySpace = 0; // we will track individual dirty sections with these arrays of bools - _writeVoxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM]; - memset(_writeVoxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); - _readVoxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM]; - memset(_readVoxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); + _writeVoxelDirtyArray = new bool[_maxVoxels]; + memset(_writeVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); + _readVoxelDirtyArray = new bool[_maxVoxels]; + memset(_readVoxelDirtyArray, false, _maxVoxels * sizeof(bool)); // prep the data structures for incoming voxel data - _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; - _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; + _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; - GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * _maxVoxels]; // populate the indicesArray // this will not change given new voxels, so we can set it all up now - for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { + for (int n = 0; n < _maxVoxels; n++) { // fill the indices array int voxelIndexOffset = n * INDICES_PER_VOXEL; GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; @@ -468,11 +472,11 @@ void VoxelSystem::init() { } } - GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; + GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * _maxVoxels]; GLfloat* normalsArrayEndPointer = normalsArray; // populate the normalsArray - for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { + for (int n = 0; n < _maxVoxels; n++) { for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) { *(normalsArrayEndPointer++) = identityNormals[i]; } @@ -481,32 +485,35 @@ void VoxelSystem::init() { // VBO for the verticesArray glGenBuffers(1, &_vboVerticesID); glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); // VBO for the normalsArray glGenBuffers(1, &_vboNormalsID); glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); glBufferData(GL_ARRAY_BUFFER, - VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, + VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, normalsArray, GL_STATIC_DRAW); // VBO for colorsArray glGenBuffers(1, &_vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW); // VBO for the indicesArray glGenBuffers(1, &_vboIndicesID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, - INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, + INDICES_PER_VOXEL * sizeof(GLuint) * _maxVoxels, indicesArray, GL_STATIC_DRAW); // delete the indices and normals arrays that are no longer needed delete[] indicesArray; delete[] normalsArray; - // create our simple fragment shader + // create our simple fragment shader if we're the first system to init + if (_perlinModulateProgram != 0) { + return; + } switchToResourcesParentIfRequired(); _perlinModulateProgram = new ProgramObject(); _perlinModulateProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); @@ -661,7 +668,7 @@ void VoxelSystem::render(bool texture) { // draw the number of voxels we have glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); + glScalef(_treeScale, _treeScale, _treeScale); glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0); @@ -855,7 +862,7 @@ bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { VoxelNode* childNode = node->getChildAtIndex(i); if (childNode) { - ViewFrustum::location inFrustum = childNode->inFrustum(*thisVoxelSystem->_viewFrustum); + ViewFrustum::location inFrustum = childNode->inFrustum(*Application::getInstance()->getViewFrustum()); switch (inFrustum) { case ViewFrustum::OUTSIDE: { args->nodesOutside++; @@ -907,9 +914,9 @@ bool VoxelSystem::hasViewChanged() { } // If our viewFrustum has changed since our _lastKnowViewFrustum - if (_viewFrustum && !_lastStableViewFrustum.matches(_viewFrustum)) { + if (!_lastStableViewFrustum.matches(Application::getInstance()->getViewFrustum())) { result = true; - _lastStableViewFrustum = *_viewFrustum; // save last stable + _lastStableViewFrustum = *Application::getInstance()->getViewFrustum(); // save last stable } return result; } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 7bffb1d33c..de904bb64f 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -16,7 +16,6 @@ #include #include #include -#include "Avatar.h" #include "Camera.h" #include "Util.h" #include "world.h" @@ -27,7 +26,7 @@ const int NUM_CHILDREN = 8; class VoxelSystem : public AgentData { public: - VoxelSystem(); + VoxelSystem(float treeScale = TREE_SCALE, int maxVoxels = MAX_VOXELS_PER_SYSTEM); ~VoxelSystem(); int parseData(unsigned char* sourceBuffer, int numBytes); @@ -41,8 +40,6 @@ public: unsigned long getVoxelsUpdated() const {return _voxelsUpdated;}; unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;}; - void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; }; - void setCamera(Camera* newCamera) { _camera = newCamera; }; void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); long int getVoxelsCreated(); @@ -114,8 +111,8 @@ private: static float _maxDistance; static float _minDistance; - Avatar* _viewerAvatar; - Camera* _camera; + float _treeScale; + int _maxVoxels; VoxelTree* _tree; GLfloat* _readVerticesArray; GLubyte* _readColorsArray; @@ -143,9 +140,6 @@ private: pthread_mutex_t _bufferWriteLock; pthread_mutex_t _treeLock; - ProgramObject* _perlinModulateProgram; - GLuint _permutationNormalTextureID; - ViewFrustum* _viewFrustum; ViewFrustum _lastKnowViewFrustum; ViewFrustum _lastStableViewFrustum; @@ -158,6 +152,9 @@ private: bool _voxelsDirty; + static ProgramObject* _perlinModulateProgram; + static GLuint _permutationNormalTextureID; + public: void updateVBOs(); void updateFullVBOs(); // all voxels in the VBO