Showing the changes to interface/src/VoxelSystem.cpp (1 of 22 files). Show all
Unified · Split
| @@ -15,9 +15,10 @@ · 14 unmodified lines | |||
| 15 | #include <fstream> // to load voxels from file | 15 | #include <fstream> // to load voxels from file |
| 16 | #include <SharedUtil.h> | 16 | #include <SharedUtil.h> |
| 17 | #include <OctalCode.h> | 17 | #include <OctalCode.h> |
| 18 | #include <pthread.h> | ||
| 18 | #include "VoxelSystem.h" | 19 | #include "VoxelSystem.h" |
| 19 | 20 | ||
| 20 | const int MAX_VOXELS_PER_SYSTEM = 250000; | 21 | const int MAX_VOXELS_PER_SYSTEM = 1500000; //250000; |
| 21 | 22 | ||
| 22 | const int VERTICES_PER_VOXEL = 8; | 23 | const int VERTICES_PER_VOXEL = 8; |
| 23 | const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; | 24 | const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; |
| @@ -42,12 +43,20 @@ GLubyte identityIndices[] = { 0,1,2, 0,2,3, · 18 unmodified lines | |||
| 42 | VoxelSystem::VoxelSystem() { | 43 | VoxelSystem::VoxelSystem() { |
| 43 | voxelsRendered = 0; | 44 | voxelsRendered = 0; |
| 44 | tree = new VoxelTree(); | 45 | tree = new VoxelTree(); |
| 46 | pthread_mutex_init(&bufferWriteLock, NULL); | ||
| 45 | } | 47 | } |
| 46 | 48 | ||
| 47 | VoxelSystem::~VoxelSystem() { | 49 | VoxelSystem::~VoxelSystem() { |
| 48 | delete[] verticesArray; | 50 | delete[] readVerticesArray; |
| 49 | delete[] colorsArray; | 51 | delete[] writeVerticesArray; |
| 52 | delete[] readColorsArray; | ||
| 53 | delete[] writeColorsArray; | ||
| 50 | delete tree; | 54 | delete tree; |
| 55 | pthread_mutex_destroy(&bufferWriteLock); | ||
| 56 | } | ||
| 57 | |||
| 58 | void VoxelSystem::setViewerHead(Head *newViewerHead) { | ||
| 59 | viewerHead = newViewerHead; | ||
| 51 | } | 60 | } |
| 52 | 61 | ||
| 53 | ////////////////////////////////////////////////////////////////////////////////////////// | 62 | ////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -57,65 +66,11 @@ VoxelSystem::~VoxelSystem() { · 3 unmodified lines | |||
| 57 | // colors are set randomly | 66 | // colors are set randomly |
| 58 | // Complaints: Brad :) | 67 | // Complaints: Brad :) |
| 59 | // To Do: Need to add color data to the file. | 68 | // To Do: Need to add color data to the file. |
| 60 | void VoxelSystem::loadVoxelsFile(char* fileName) { | 69 | void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { |
| 61 | int vCount = 0; | ||
| 62 | |||
| 63 | std::ifstream file(fileName, std::ios::in|std::ios::binary); | ||
| 64 | |||
| 65 | char octets; | ||
| 66 | unsigned int lengthInBytes; | ||
| 67 | 70 | ||
| 68 | int totalBytesRead = 0; | 71 | tree->loadVoxelsFile(fileName,wantColorRandomizer); |
| 69 | if(file.is_open()) | ||
| 70 | { | ||
| 71 | bool bail = false; | ||
| 72 | while (!file.eof() && !bail) { | ||
| 73 | file.get(octets); | ||
| 74 | totalBytesRead++; | ||
| 75 | lengthInBytes = bytesRequiredForCodeLength(octets)-1; //(octets*3/8)+1; | ||
| 76 | unsigned char * voxelData = new unsigned char[lengthInBytes+1+3]; | ||
| 77 | voxelData[0]=octets; | ||
| 78 | char byte; | ||
| 79 | |||
| 80 | for (size_t i = 0; i < lengthInBytes; i++) { | ||
| 81 | file.get(byte); | ||
| 82 | totalBytesRead++; | ||
| 83 | voxelData[i+1] = byte; | ||
| 84 | } | ||
| 85 | // read color data | ||
| 86 | char red,green,blue; | ||
| 87 | file.get(red); | ||
| 88 | file.get(green); | ||
| 89 | file.get(blue); | ||
| 90 | |||
| 91 | //printf("red:%d\n",red); | ||
| 92 | //printf("green:%d\n",green); | ||
| 93 | //printf("blue:%d\n",blue); | ||
| 94 | vCount++; | ||
| 95 | //printf("vCount:%d\n",vCount); | ||
| 96 | |||
| 97 | //randomColorValue(65); | ||
| 98 | float rf = randFloatInRange(.5,1); // add a little bit of variance to colors so we can see the voxels | ||
| 99 | voxelData[lengthInBytes+1] = red * rf; | ||
| 100 | voxelData[lengthInBytes+2] = green * rf; | ||
| 101 | voxelData[lengthInBytes+3] = blue * rf; | ||
| 102 | |||
| 103 | //printVoxelCode(voxelData); | ||
| 104 | tree->readCodeColorBufferToTree(voxelData); | ||
| 105 | delete voxelData; | ||
| 106 | } | ||
| 107 | file.close(); | ||
| 108 | } | ||
| 109 | 72 | ||
| 110 | tree->pruneTree(tree->rootNode); | 73 | copyWrittenDataToReadArrays(); |
| 111 | |||
| 112 | // reset the verticesEndPointer so we're writing to the beginning of the array | ||
| 113 | verticesEndPointer = verticesArray; | ||
| 114 | // call recursive function to populate in memory arrays | ||
| 115 | // it will return the number of voxels added | ||
| 116 | voxelsRendered = treeToArrays(tree->rootNode); | ||
| 117 | // set the boolean if there are any voxels to be rendered so we re-fill the VBOs | ||
| 118 | voxelsToRender = (voxelsRendered > 0); | ||
| 119 | } | 74 | } |
| 120 | 75 | ||
| 121 | ////////////////////////////////////////////////////////////////////////////////////////// | 76 | ////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -125,107 +80,10 @@ void VoxelSystem::loadVoxelsFile(char* fileName) { · 3 unmodified lines | |||
| 125 | // mechanism to tell the system to redraw it's arrays after voxels are done | 80 | // mechanism to tell the system to redraw it's arrays after voxels are done |
| 126 | // being added. This is a concept mostly only understood by VoxelSystem. | 81 | // being added. This is a concept mostly only understood by VoxelSystem. |
| 127 | // Complaints: Brad :) | 82 | // Complaints: Brad :) |
| 128 | void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid) | 83 | void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { |
| 129 | { | ||
| 130 | // About the color of the sphere... we're going to make this sphere be a gradient | ||
| 131 | // between two RGB colors. We will do the gradient along the phi spectrum | ||
| 132 | unsigned char r1 = randomColorValue(165); | ||
| 133 | unsigned char g1 = randomColorValue(165); | ||
| 134 | unsigned char b1 = randomColorValue(165); | ||
| 135 | unsigned char r2 = randomColorValue(65); | ||
| 136 | unsigned char g2 = randomColorValue(65); | ||
| 137 | unsigned char b2 = randomColorValue(65); | ||
| 138 | |||
| 139 | // we don't want them to match!! | ||
| 140 | if (r1==r2 && g1==g2 && b1==b2) | ||
| 141 | { | ||
| 142 | r2=r1/2; | ||
| 143 | g2=g1/2; | ||
| 144 | b2=b1/2; | ||
| 145 | } | ||
| 146 | |||
| 147 | /** | ||
| 148 | std::cout << "creatSphere COLORS "; | ||
| 149 | std::cout << " r1=" << (int)r1; | ||
| 150 | std::cout << " g1=" << (int)g1; | ||
| 151 | std::cout << " b1=" << (int)b1; | ||
| 152 | std::cout << " r2=" << (int)r2; | ||
| 153 | std::cout << " g2=" << (int)g2; | ||
| 154 | std::cout << " b2=" << (int)b2; | ||
| 155 | std::cout << std::endl; | ||
| 156 | **/ | ||
| 157 | |||
| 158 | // Psuedocode for creating a sphere: | ||
| 159 | // | ||
| 160 | // for (theta from 0 to 2pi): | ||
| 161 | // for (phi from 0 to pi): | ||
| 162 | // x = xc+r*cos(theta)*sin(phi) | ||
| 163 | // y = yc+r*sin(theta)*sin(phi) | ||
| 164 | // z = zc+r*cos(phi) | ||
| 165 | |||
| 166 | int t=0; // total points | ||
| 167 | 84 | ||
| 168 | // We want to make sure that as we "sweep" through our angles | 85 | tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer); |
| 169 | // we use a delta angle that's small enough to not skip any voxels | 86 | setupNewVoxelsForDrawing(); |
| 170 | // we can calculate theta from our desired arc length | ||
| 171 | // | ||
| 172 | // lenArc = ndeg/360deg * 2pi*R | ||
| 173 | // lenArc = theta/2pi * 2pi*R | ||
| 174 | // lenArc = theta*R | ||
| 175 | // theta = lenArc/R | ||
| 176 | // theta = g/r | ||
| 177 | float angleDelta = (s/r); | ||
| 178 | |||
| 179 | // assume solid for now | ||
| 180 | float ri = 0.0; | ||
| 181 | if (!solid) | ||
| 182 | { | ||
| 183 | ri=r; // just the outer surface | ||
| 184 | } | ||
| 185 | // If you also iterate form the interior of the sphere to the radius, makeing | ||
| 186 | // larger and larger sphere's you'd end up with a solid sphere. And lots of voxels! | ||
| 187 | for (; ri <= r; ri+=s) | ||
| 188 | { | ||
| 189 | for (float theta=0.0; theta <= 2*M_PI; theta += angleDelta) | ||
| 190 | { | ||
| 191 | for (float phi=0.0; phi <= M_PI; phi += angleDelta) | ||
| 192 | { | ||
| 193 | t++; // total voxels | ||
| 194 | float x = xc+r*cos(theta)*sin(phi); | ||
| 195 | float y = yc+r*sin(theta)*sin(phi); | ||
| 196 | float z = zc+r*cos(phi); | ||
| 197 | /* | ||
| 198 | std::cout << " r=" << r; | ||
| 199 | std::cout << " theta=" << theta; | ||
| 200 | std::cout << " phi=" << phi; | ||
| 201 | std::cout << " x=" << x; | ||
| 202 | std::cout << " y=" << y; | ||
| 203 | std::cout << " z=" << z; | ||
| 204 | std::cout << " t=" << t; | ||
| 205 | std::cout << std::endl; | ||
| 206 | */ | ||
| 207 | |||
| 208 | // gradient color data | ||
| 209 | float gradient = (phi/M_PI); | ||
| 210 | unsigned char red = r1+((r2-r1)*gradient); | ||
| 211 | unsigned char green = g1+((g2-g1)*gradient); | ||
| 212 | unsigned char blue = b1+((b2-b1)*gradient); | ||
| 213 | |||
| 214 | unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); | ||
| 215 | tree->readCodeColorBufferToTree(voxelData); | ||
| 216 | delete voxelData; | ||
| 217 | |||
| 218 | } | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | // reset the verticesEndPointer so we're writing to the beginning of the array | ||
| 223 | verticesEndPointer = verticesArray; | ||
| 224 | // call recursive function to populate in memory arrays | ||
| 225 | // it will return the number of voxels added | ||
| 226 | voxelsRendered = treeToArrays(tree->rootNode); | ||
| 227 | // set the boolean if there are any voxels to be rendered so we re-fill the VBOs | ||
| 228 | voxelsToRender = (voxelsRendered > 0); | ||
| 229 | } | 87 | } |
| 230 | 88 | ||
| 231 | 89 | ||
| @@ -233,32 +91,74 @@ void VoxelSystem::parseData(void *data, int size) { · 1 unmodified line | |||
| 233 | // output the bits received from the voxel server | 91 | // output the bits received from the voxel server |
| 234 | unsigned char *voxelData = (unsigned char *) data + 1; | 92 | unsigned char *voxelData = (unsigned char *) data + 1; |
| 235 | 93 | ||
| 236 | printf("Received a packet of %d bytes from VS\n", size); | ||
| 237 | |||
| 238 | // ask the VoxelTree to read the bitstream into the tree | 94 | // ask the VoxelTree to read the bitstream into the tree |
| 239 | tree->readBitstreamToTree(voxelData, size - 1); | 95 | tree->readBitstreamToTree(voxelData, size - 1); |
| 240 | 96 | ||
| 97 | setupNewVoxelsForDrawing(); | ||
| 98 | } | ||
| 99 | |||
| 100 | void VoxelSystem::setupNewVoxelsForDrawing() { | ||
| 241 | // reset the verticesEndPointer so we're writing to the beginning of the array | 101 | // reset the verticesEndPointer so we're writing to the beginning of the array |
| 242 | verticesEndPointer = verticesArray; | 102 | writeVerticesEndPointer = writeVerticesArray; |
| 243 | |||
| 244 | // call recursive function to populate in memory arrays | 103 | // call recursive function to populate in memory arrays |
| 245 | // it will return the number of voxels added | 104 | // it will return the number of voxels added |
| 246 | voxelsRendered = treeToArrays(tree->rootNode); | 105 | float treeRoot[3] = {0,0,0}; |
| 106 | voxelsRendered = treeToArrays(tree->rootNode, treeRoot); | ||
| 107 | |||
| 108 | // copy the newly written data to the arrays designated for reading | ||
| 109 | copyWrittenDataToReadArrays(); | ||
| 110 | } | ||
| 111 | |||
| 112 | void VoxelSystem::copyWrittenDataToReadArrays() { | ||
| 113 | // lock on the buffer write lock so we can't modify the data when the GPU is reading it | ||
| 114 | pthread_mutex_lock(&bufferWriteLock); | ||
| 115 | // store a pointer to the current end so it doesn't change during copy | ||
| 116 | GLfloat *endOfCurrentVerticesData = writeVerticesEndPointer; | ||
| 117 | // copy the vertices and colors | ||
| 118 | memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat)); | ||
| 119 | memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte)); | ||
| 247 | 120 | ||
| 248 | // set the boolean if there are any voxels to be rendered so we re-fill the VBOs | 121 | // set the read vertices end pointer to the correct spot so the GPU knows how much to pull |
| 249 | voxelsToRender = (voxelsRendered > 0); | 122 | readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray); |
| 123 | pthread_mutex_unlock(&bufferWriteLock); | ||
| 250 | } | 124 | } |
| 251 | 125 | ||
| 252 | int VoxelSystem::treeToArrays(VoxelNode *currentNode) { | 126 | int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) { |
| 253 | int voxelsAdded = 0; | 127 | int voxelsAdded = 0; |
| 254 | 128 | ||
| 255 | for (int i = 0; i < 8; i++) { | 129 | float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); |
| 256 | // check if there is a child here | 130 | glm::vec3 viewerPosition = viewerHead->getPos(); |
| 257 | if (currentNode->children[i] != NULL) { | 131 | |
| 258 | voxelsAdded += treeToArrays(currentNode->children[i]); | 132 | float distanceToVoxelCenter = sqrtf(powf(viewerPosition[0] - nodePosition[0] - halfUnitForVoxel, 2) + |
| 133 | powf(viewerPosition[1] - nodePosition[1] - halfUnitForVoxel, 2) + | ||
| 134 | powf(viewerPosition[2] - nodePosition[2] - halfUnitForVoxel, 2)); | ||
| 135 | |||
| 136 | if (distanceToVoxelCenter < boundaryDistanceForRenderLevel(*currentNode->octalCode + 1)) { | ||
| 137 | for (int i = 0; i < 8; i++) { | ||
| 138 | // check if there is a child here | ||
| 139 | if (currentNode->children[i] != NULL) { | ||
| 140 | |||
| 141 | // calculate the child's position based on the parent position | ||
| 142 | float childNodePosition[3]; | ||
| 143 | |||
| 144 | for (int j = 0; j < 3; j++) { | ||
| 145 | childNodePosition[j] = nodePosition[j]; | ||
| 146 | |||
| 147 | if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode, | ||
| 148 | currentNode->children[i]->octalCode), | ||
| 149 | (7 - j))) { | ||
| 150 | childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | |||
| 155 | voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition); | ||
| 156 | } | ||
| 259 | } | 157 | } |
| 260 | } | 158 | } |
| 261 | 159 | ||
| 160 | |||
| 161 | |||
| 262 | // if we didn't get any voxels added then we're a leaf | 162 | // if we didn't get any voxels added then we're a leaf |
| 263 | // add our vertex and color information to the interleaved array | 163 | // add our vertex and color information to the interleaved array |
| 264 | if (voxelsAdded == 0 && currentNode->color[3] == 1) { | 164 | if (voxelsAdded == 0 && currentNode->color[3] == 1) { |
| @@ -268,10 +168,10 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode) { · 3 unmodified lines | |||
| 268 | // populate the array with points for the 8 vertices | 168 | // populate the array with points for the 8 vertices |
| 269 | // and RGB color for each added vertex | 169 | // and RGB color for each added vertex |
| 270 | for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { | 170 | for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { |
| 271 | *verticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); | 171 | *writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); |
| 272 | *(colorsArray + (verticesEndPointer - verticesArray)) = currentNode->color[j % 3]; | 172 | *(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->color[j % 3]; |
| 273 | 173 | ||
| 274 | verticesEndPointer++; | 174 | writeVerticesEndPointer++; |
| 275 | } | 175 | } |
| 276 | 176 | ||
| 277 | voxelsAdded++; | 177 | voxelsAdded++; |
| @@ -289,8 +189,10 @@ VoxelSystem* VoxelSystem::clone() const { · 11 unmodified lines | |||
| 289 | 189 | ||
| 290 | void VoxelSystem::init() { | 190 | void VoxelSystem::init() { |
| 291 | // prep the data structures for incoming voxel data | 191 | // prep the data structures for incoming voxel data |
| 292 | verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | 192 | writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; |
| 293 | colorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | 193 | readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; |
| 194 | writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | ||
| 195 | readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | ||
| 294 | 196 | ||
| 295 | GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | 197 | GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; |
| 296 | 198 | ||
| @@ -321,7 +223,9 @@ void VoxelSystem::init() { · 24 unmodified lines | |||
| 321 | // VBO for the indicesArray | 223 | // VBO for the indicesArray |
| 322 | glGenBuffers(1, &vboIndicesID); | 224 | glGenBuffers(1, &vboIndicesID); |
| 323 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); | 225 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); |
| 324 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, indicesArray, GL_STATIC_DRAW); | 226 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, |
| 227 | INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, | ||
| 228 | indicesArray, GL_STATIC_DRAW); | ||
| 325 | 229 | ||
| 326 | // delete the indices array that is no longer needed | 230 | // delete the indices array that is no longer needed |
| 327 | delete[] indicesArray; | 231 | delete[] indicesArray; |
| @@ -331,16 +235,24 @@ void VoxelSystem::render() { · 3 unmodified lines | |||
| 331 | 235 | ||
| 332 | glPushMatrix(); | 236 | glPushMatrix(); |
| 333 | 237 | ||
| 334 | if (voxelsToRender) { | 238 | |
| 335 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); | 239 | if (readVerticesEndPointer != readVerticesArray) { |
| 336 | glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); | 240 | // try to lock on the buffer write |
| 337 | glBufferSubData(GL_ARRAY_BUFFER, 0, (verticesEndPointer - verticesArray) * sizeof(GLfloat), verticesArray); | 241 | // just avoid pulling new data if it is currently being written |
| 338 | 242 | if (pthread_mutex_trylock(&bufferWriteLock) == 0) { | |
| 339 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | 243 | |
| 340 | glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); | 244 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); |
| 341 | glBufferSubData(GL_ARRAY_BUFFER, 0, (verticesEndPointer - verticesArray) * sizeof(GLubyte), colorsArray); | 245 | glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); |
| 342 | 246 | glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); | |
| 343 | voxelsToRender = false; | 247 | |
| 248 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | ||
| 249 | glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); | ||
| 250 | glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); | ||
| 251 | |||
| 252 | readVerticesEndPointer = readVerticesArray; | ||
| 253 | |||
| 254 | pthread_mutex_unlock(&bufferWriteLock); | ||
| 255 | } | ||
| 344 | } | 256 | } |
| 345 | 257 | ||
| 346 | // tell OpenGL where to find vertex and color information | 258 | // tell OpenGL where to find vertex and color information |