Showing the changes to interface/src/VoxelSystem.cpp (1 of 11 files). Show all
Unified · Split
| @@ -7,24 +7,25 @@ · 6 unmodified lines | ||
| 7 | 7 | // |
| 8 | 8 | |
| 9 | 9 | #include "VoxelSystem.h" |
| 10 | +#include <AgentList.h> | |
| 10 | 11 | |
| 11 | −const float MAX_Y_AXIS = 2.0; | |
| 12 | −const float MAX_X_AXIS = 20.0; | |
| 13 | −const float MAX_Z_AXIS = 20.0; | |
| 12 | +const int MAX_VOXELS_PER_SYSTEM = 500000; | |
| 14 | 13 | |
| 15 | 14 | const int VERTICES_PER_VOXEL = 8; |
| 16 | 15 | const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; |
| 17 | 16 | const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; |
| 18 | 17 | const int INDICES_PER_VOXEL = 3 * 12; |
| 19 | 18 | |
| 20 | −GLfloat identityVertices[] = { -1, -1, 1, | |
| 21 | − 1, -1, 1, | |
| 22 | − 1, -1, -1, | |
| 23 | − -1, -1, -1, | |
| 24 | − 1, 1, 1, | |
| 25 | − -1, 1, 1, | |
| 26 | − -1, 1, -1, | |
| 27 | − 1, 1, -1 }; | |
| 19 | +const float CUBE_WIDTH = 0.025f; | |
| 20 | + | |
| 21 | +float identityVertices[] = { -1, -1, 1, | |
| 22 | + 1, -1, 1, | |
| 23 | + 1, -1, -1, | |
| 24 | + -1, -1, -1, | |
| 25 | + 1, 1, 1, | |
| 26 | + -1, 1, 1, | |
| 27 | + -1, 1, -1, | |
| 28 | + 1, 1, -1 }; | |
| 28 | 29 | |
| 29 | 30 | GLubyte identityIndices[] = { 0,1,2, 0,2,3, |
| 30 | 31 | 0,4,1, 0,4,5, |
| @@ -33,73 +34,71 @@ GLubyte identityIndices[] = { 0,1,2, 0,2,3, · 2 unmodified lines | ||
| 33 | 34 | 2,3,6, 2,6,7, |
| 34 | 35 | 4,5,6, 4,6,7 }; |
| 35 | 36 | |
| 36 | − | |
| 37 | −bool onSphereShell(float radius, float scale, glm::vec3 * position) { | |
| 38 | − float vRadius = glm::length(*position); | |
| 39 | − return ((vRadius + scale/2.0 > radius) && (vRadius - scale/2.0 < radius)); | |
| 37 | +VoxelSystem::VoxelSystem() { | |
| 38 | + voxelsRendered = 0; | |
| 40 | 39 | } |
| 41 | 40 | |
| 42 | −void VoxelSystem::init() { | |
| 43 | − root = new Voxel; | |
| 41 | +VoxelSystem::~VoxelSystem() { | |
| 42 | + delete[] verticesArray; | |
| 43 | + delete[] colorsArray; | |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | −float randomFloat(float maximumValue) { | |
| 47 | − return ((float) rand() / ((float) RAND_MAX / maximumValue)); | |
| 48 | −} | |
| 46 | +void VoxelSystem::parseData(void *data, int size) { | |
| 47 | + // ignore the first char, it's a V to tell us that this is voxel data | |
| 48 | + char *voxelDataPtr = (char *) data + 1; | |
| 49 | 49 | |
| 50 | −void VoxelSystem::init(int numberOfRandomVoxels) { | |
| 51 | − // create the arrays needed to pass to glDrawElements later | |
| 52 | − // position / color are random for now | |
| 53 | − | |
| 54 | − voxelsRendered = numberOfRandomVoxels; | |
| 55 | − | |
| 56 | − // there are 3 points for each vertices, 24 vertices in each cube | |
| 57 | − GLfloat *verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels]; | |
| 58 | − | |
| 59 | − // we need a color for each vertex in each voxel | |
| 60 | − GLfloat *colorsArray = new GLfloat[COLOR_VALUES_PER_VOXEL * numberOfRandomVoxels]; | |
| 61 | − | |
| 62 | − // there are 12 triangles in each cube, with three indices for each triangle | |
| 63 | − GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * numberOfRandomVoxels]; | |
| 50 | + float *position = new float[3]; | |
| 51 | + char *color = new char[3]; | |
| 52 | + | |
| 53 | + // get pointers to position of last append of data | |
| 54 | + GLfloat *parseVerticesPtr = lastAddPointer; | |
| 55 | + GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray); | |
| 64 | 56 | |
| 65 | − // new seed based on time now so voxels are different each time | |
| 66 | − srand((unsigned)time(0)); | |
| 57 | + int voxelsInData = 0; | |
| 67 | 58 | |
| 68 | − for (int n = 0; n < numberOfRandomVoxels; n++) { | |
| 69 | − // pick a random point for the center of the cube | |
| 70 | − const float DEATH_STAR_RADIUS = 4.0; | |
| 71 | − const float MAX_CUBE = 0.05; | |
| 72 | − float azimuth = randFloat()*2*PI; | |
| 73 | − float altitude = randFloat()*PI - PI/2; | |
| 74 | − float radius = DEATH_STAR_RADIUS; | |
| 75 | − float thisScale = MAX_CUBE*1/(float)(rand()%8 + 1); | |
| 76 | − float radius_twiddle = (DEATH_STAR_RADIUS/100)*powf(2, (float)(rand()%8)); | |
| 77 | − radius += radius_twiddle + (randFloat()*DEATH_STAR_RADIUS/12 - DEATH_STAR_RADIUS/24); | |
| 78 | − glm::vec3 position = glm::vec3( | |
| 79 | − radius * cosf(azimuth) * cosf(altitude), | |
| 80 | − radius * sinf(azimuth) * cosf(altitude), | |
| 81 | − radius * sinf(altitude) | |
| 82 | − ); | |
| 59 | + // pull voxels out of the received data and put them into our internal memory structure | |
| 60 | + while ((voxelDataPtr - (char *) data) < size) { | |
| 61 | + | |
| 62 | + memcpy(position, voxelDataPtr, 3 * sizeof(float)); | |
| 63 | + voxelDataPtr += 3 * sizeof(float); | |
| 64 | + memcpy(color, voxelDataPtr, 3); | |
| 65 | + voxelDataPtr += 3; | |
| 83 | 66 | |
| 84 | − // fill the vertices array, and scale the voxels | |
| 85 | − GLfloat *currentVerticesPos = verticesArray + (n * VERTEX_POINTS_PER_VOXEL); | |
| 86 | 67 | for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { |
| 87 | − currentVerticesPos[v] = position[v % 3] + (identityVertices[v] * thisScale); | |
| 68 | + parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH); | |
| 88 | 69 | } |
| 89 | 70 | |
| 90 | − // fill the colors array | |
| 91 | − const float MIN_BRIGHTNESS = 0.25; | |
| 92 | − GLfloat *currentColorPos = colorsArray + (n * COLOR_VALUES_PER_VOXEL); | |
| 93 | − float voxelR = MIN_BRIGHTNESS + randomFloat(1)*(1.0 - MIN_BRIGHTNESS); | |
| 94 | − float voxelG = voxelR; | |
| 95 | − float voxelB = voxelR; | |
| 71 | + parseVerticesPtr += VERTEX_POINTS_PER_VOXEL; | |
| 96 | 72 | |
| 97 | − for (int c = 0; c < VERTICES_PER_VOXEL; c++) { | |
| 98 | − currentColorPos[0 + (c * 3)] = voxelR; | |
| 99 | − currentColorPos[1 + (c * 3)] = voxelG; | |
| 100 | − currentColorPos[2 + (c * 3)] = voxelB; | |
| 73 | + for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) { | |
| 74 | + parseColorsPtr[c] = color[c % 3]; | |
| 101 | 75 | } |
| 76 | + | |
| 77 | + parseColorsPtr += COLOR_VALUES_PER_VOXEL; | |
| 78 | + | |
| 79 | + voxelsInData++; | |
| 80 | + } | |
| 81 | + | |
| 82 | + // increase the lastAddPointer to the new spot, increase the number of rendered voxels | |
| 83 | + lastAddPointer = parseVerticesPtr; | |
| 84 | + voxelsRendered += voxelsInData; | |
| 85 | +} | |
| 102 | 86 | |
| 87 | +VoxelSystem* VoxelSystem::clone() const { | |
| 88 | + // this still needs to be implemented, will need to be used if VoxelSystem is attached to agent | |
| 89 | + return NULL; | |
| 90 | +} | |
| 91 | + | |
| 92 | +void VoxelSystem::init() { | |
| 93 | + // prep the data structures for incoming voxel data | |
| 94 | + lastDrawPointer = lastAddPointer = verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 95 | + colorsArray = new GLubyte[COLOR_VALUES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 96 | + | |
| 97 | + GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 98 | + | |
| 99 | + // populate the indicesArray | |
| 100 | + // this will not change given new voxels, so we can set it all up now | |
| 101 | + for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { | |
| 103 | 102 | // fill the indices array |
| 104 | 103 | int voxelIndexOffset = n * INDICES_PER_VOXEL; |
| 105 | 104 | GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; |
| @@ -114,136 +113,54 @@ void VoxelSystem::init(int numberOfRandomVoxels) { · 8 unmodified lines | ||
| 114 | 113 | // VBO for the verticesArray |
| 115 | 114 | glGenBuffers(1, &vboVerticesID); |
| 116 | 115 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); |
| 117 | − glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, verticesArray, GL_STATIC_DRAW); | |
| 116 | + glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); | |
| 118 | 117 | |
| 119 | 118 | // VBO for colorsArray |
| 120 | 119 | glGenBuffers(1, &vboColorsID); |
| 121 | 120 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); |
| 122 | − glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, colorsArray, GL_STATIC_DRAW); | |
| 121 | + glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); | |
| 123 | 122 | |
| 124 | 123 | // VBO for the indicesArray |
| 125 | 124 | glGenBuffers(1, &vboIndicesID); |
| 126 | 125 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); |
| 127 | − glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfRandomVoxels * INDICES_PER_VOXEL * sizeof(GLuint), indicesArray, GL_STATIC_DRAW); | |
| 128 | − | |
| 129 | − // delete the verticesArray, indicesArray | |
| 130 | − delete[] verticesArray; | |
| 126 | + glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, indicesArray, GL_STATIC_DRAW); | |
| 127 | + | |
| 128 | + // delete the indices array that is no longer needed | |
| 131 | 129 | delete[] indicesArray; |
| 132 | − delete[] colorsArray; | |
| 133 | 130 | } |
| 134 | 131 | |
| 135 | −// | |
| 136 | −// Recursively initialize the voxel tree | |
| 137 | −// | |
| 138 | −int VoxelSystem::initVoxels(Voxel * voxel, float scale, glm::vec3 * position) { | |
| 139 | − glm::vec3 averageColor(0,0,0); | |
| 140 | − int childrenCreated = 0; | |
| 141 | − int newVoxels = 0; | |
| 142 | − if (voxel == NULL) voxel = root; | |
| 143 | − averageColor[0] = averageColor[1] = averageColor[2] = 0.0; | |
| 144 | − | |
| 145 | − const float RADIUS = 3.9; | |
| 132 | +void VoxelSystem::render() { | |
| 133 | + // check if there are new voxels to draw | |
| 134 | + int vertexValuesToDraw = lastAddPointer - lastDrawPointer; | |
| 146 | 135 | |
| 147 | − // | |
| 148 | − // First, randomly decide whether to stop here without recursing for children | |
| 149 | − // | |
| 150 | − if (onSphereShell(RADIUS, scale, position) && (scale < 0.25) && (randFloat() < 0.01)) | |
| 151 | − { | |
| 152 | − voxel->color.x = 0.1; | |
| 153 | − voxel->color.y = 0.5 + randFloat()*0.5; | |
| 154 | − voxel->color.z = 0.1; | |
| 155 | − for (unsigned char i = 0; i < NUM_CHILDREN; i++) voxel->children[i] = NULL; | |
| 156 | − return 0; | |
| 157 | − } else { | |
| 158 | − // Decide whether to make kids, recurse into them | |
| 159 | − for (unsigned char i = 0; i < NUM_CHILDREN; i++) { | |
| 160 | − if (scale > 0.01) { | |
| 161 | − glm::vec3 shift(scale/2.0*((i&4)>>2)-scale/4.0, | |
| 162 | − scale/2.0*((i&2)>>1)-scale/4.0, | |
| 163 | − scale/2.0*(i&1)-scale/4.0); | |
| 164 | − *position += shift; | |
| 165 | − // Test to see whether the child is also on edge of sphere | |
| 166 | − if (onSphereShell(RADIUS, scale/2.0, position)) { | |
| 167 | − voxel->children[i] = new Voxel; | |
| 168 | − newVoxels++; | |
| 169 | − childrenCreated++; | |
| 170 | − newVoxels += initVoxels(voxel->children[i], scale/2.0, position); | |
| 171 | − averageColor += voxel->children[i]->color; | |
| 172 | − } else voxel->children[i] = NULL; | |
| 173 | − *position -= shift; | |
| 174 | − } else { | |
| 175 | − // No child made: Set pointer to null, nothing to see here. | |
| 176 | − voxel->children[i] = NULL; | |
| 177 | − } | |
| 178 | − } | |
| 179 | − if (childrenCreated > 0) { | |
| 180 | − // If there were children created, the color of this voxel node is average of children | |
| 181 | − averageColor *= 1.0/childrenCreated; | |
| 182 | − voxel->color = averageColor; | |
| 183 | − return newVoxels; | |
| 184 | − } else { | |
| 185 | − // Tested and didn't make any children, so choose my color as a leaf, return | |
| 186 | − voxel->color.x = voxel->color.y = voxel->color.z = 0.5 + randFloat()*0.5; | |
| 187 | − for (unsigned char i = 0; i < NUM_CHILDREN; i++) voxel->children[i] = NULL; | |
| 188 | − return 0; | |
| 189 | − | |
| 190 | − } | |
| 191 | − } | |
| 192 | −} | |
| 193 | − | |
| 194 | −// | |
| 195 | −// The Render Discard is the ratio of the size of the voxel to the distance from the camera | |
| 196 | −// at which the voxel will no longer be shown. Smaller = show more detail. | |
| 197 | −// | |
| 198 | − | |
| 199 | −const float RENDER_DISCARD = 0.04; //0.01; | |
| 200 | − | |
| 201 | −// | |
| 202 | −// Returns the total number of voxels actually rendered | |
| 203 | −// | |
| 204 | −int VoxelSystem::render(Voxel * voxel, float scale, glm::vec3 * distance) { | |
| 205 | − // If null passed in, start at root | |
| 206 | − if (voxel == NULL) voxel = root; | |
| 207 | − unsigned char i; | |
| 208 | − bool renderedChildren = false; | |
| 209 | − int vRendered = 0; | |
| 210 | − // Recursively render children | |
| 211 | − for (i = 0; i < NUM_CHILDREN; i++) { | |
| 212 | − glm::vec3 shift(scale/2.0*((i&4)>>2)-scale/4.0, | |
| 213 | − scale/2.0*((i&2)>>1)-scale/4.0, | |
| 214 | − scale/2.0*(i&1)-scale/4.0); | |
| 215 | − if ((voxel->children[i] != NULL) && (scale / glm::length(*distance) > RENDER_DISCARD)) { | |
| 216 | − glTranslatef(shift.x, shift.y, shift.z); | |
| 217 | − *distance += shift; | |
| 218 | − vRendered += render(voxel->children[i], scale/2.0, distance); | |
| 219 | − *distance -= shift; | |
| 220 | − glTranslatef(-shift.x, -shift.y, -shift.z); | |
| 221 | − renderedChildren = true; | |
| 222 | − } | |
| 223 | − } | |
| 224 | − // Render this voxel if the children were not rendered | |
| 225 | − if (!renderedChildren) | |
| 226 | − { | |
| 227 | − // This is the place where we need to copy this data to a VBO to make this FAST | |
| 228 | − glColor4f(voxel->color.x, voxel->color.y, voxel->color.z, 1.0); | |
| 229 | − glutSolidCube(scale); | |
| 230 | − vRendered++; | |
| 136 | + if (vertexValuesToDraw > 0) { | |
| 137 | + // calculate the offset into each VBO, in vertex point values | |
| 138 | + int vertexBufferOffset = lastDrawPointer - verticesArray; | |
| 139 | + | |
| 140 | + // bind the vertices VBO, copy in new data | |
| 141 | + glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); | |
| 142 | + glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(float), vertexValuesToDraw * sizeof(float), lastDrawPointer); | |
| 143 | + | |
| 144 | + // bind the colors VBO, copy in new data | |
| 145 | + glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | |
| 146 | + glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(GLubyte), vertexValuesToDraw * sizeof(GLubyte), (colorsArray + (lastDrawPointer - verticesArray))); | |
| 147 | + | |
| 148 | + // increment the lastDrawPointer to the lastAddPointer value used for this draw | |
| 149 | + lastDrawPointer += vertexValuesToDraw; | |
| 231 | 150 | } |
| 232 | − return vRendered; | |
| 233 | −} | |
| 234 | 151 | |
| 235 | −void VoxelSystem::render() { | |
| 152 | + // tell OpenGL where to find vertex and color information | |
| 236 | 153 | glEnableClientState(GL_VERTEX_ARRAY); |
| 237 | 154 | glEnableClientState(GL_COLOR_ARRAY); |
| 238 | 155 | |
| 239 | − glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); | |
| 240 | − | |
| 241 | 156 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); |
| 242 | 157 | glVertexPointer(3, GL_FLOAT, 0, 0); |
| 243 | 158 | |
| 244 | 159 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); |
| 245 | − glColorPointer(3, GL_FLOAT, 0, 0); | |
| 160 | + glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); | |
| 246 | 161 | |
| 162 | + // draw the number of voxels we have | |
| 163 | + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); | |
| 247 | 164 | glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); |
| 248 | 165 | |
| 249 | 166 | // deactivate vertex and color arrays after drawing |