Showing the changes to interface/src/VoxelSystem.cpp (1 of 17 files). Show all
Unified · Split
| @@ -7,24 +7,25 @@ · 6 unmodified lines | |||
| 7 | // | 7 | // |
| 8 | 8 | ||
| 9 | #include "VoxelSystem.h" | 9 | #include "VoxelSystem.h" |
| 10 | #include <AgentList.h> | ||
| 10 | 11 | ||
| 11 | const float MAX_Y_AXIS = 2.0; | 12 | const int MAX_VOXELS_PER_SYSTEM = 500000; |
| 12 | const float MAX_X_AXIS = 20.0; | ||
| 13 | const float MAX_Z_AXIS = 20.0; | ||
| 14 | 13 | ||
| 15 | const int VERTICES_PER_VOXEL = 8; | 14 | const int VERTICES_PER_VOXEL = 8; |
| 16 | const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; | 15 | const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL; |
| 17 | const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; | 16 | const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; |
| 18 | const int INDICES_PER_VOXEL = 3 * 12; | 17 | const int INDICES_PER_VOXEL = 3 * 12; |
| 19 | 18 | ||
| 20 | GLfloat identityVertices[] = { -1, -1, 1, | 19 | const float CUBE_WIDTH = 0.025f; |
| 21 | 1, -1, 1, | 20 | |
| 22 | 1, -1, -1, | 21 | float identityVertices[] = { -1, -1, 1, |
| 23 | -1, -1, -1, | 22 | 1, -1, 1, |
| 24 | 1, 1, 1, | 23 | 1, -1, -1, |
| 25 | -1, 1, 1, | 24 | -1, -1, -1, |
| 26 | -1, 1, -1, | 25 | 1, 1, 1, |
| 27 | 1, 1, -1 }; | 26 | -1, 1, 1, |
| 27 | -1, 1, -1, | ||
| 28 | 1, 1, -1 }; | ||
| 28 | 29 | ||
| 29 | GLubyte identityIndices[] = { 0,1,2, 0,2,3, | 30 | GLubyte identityIndices[] = { 0,1,2, 0,2,3, |
| 30 | 0,4,1, 0,4,5, | 31 | 0,4,1, 0,4,5, |
| @@ -33,73 +34,71 @@ GLubyte identityIndices[] = { 0,1,2, 0,2,3, · 2 unmodified lines | |||
| 33 | 2,3,6, 2,6,7, | 34 | 2,3,6, 2,6,7, |
| 34 | 4,5,6, 4,6,7 }; | 35 | 4,5,6, 4,6,7 }; |
| 35 | 36 | ||
| 36 | 37 | VoxelSystem::VoxelSystem() { | |
| 37 | bool onSphereShell(float radius, float scale, glm::vec3 * position) { | 38 | voxelsRendered = 0; |
| 38 | float vRadius = glm::length(*position); | ||
| 39 | return ((vRadius + scale/2.0 > radius) && (vRadius - scale/2.0 < radius)); | ||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | void VoxelSystem::init() { | 41 | VoxelSystem::~VoxelSystem() { |
| 43 | root = new Voxel; | 42 | delete[] verticesArray; |
| 43 | delete[] colorsArray; | ||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | float randomFloat(float maximumValue) { | 46 | void VoxelSystem::parseData(void *data, int size) { |
| 47 | return ((float) rand() / ((float) RAND_MAX / maximumValue)); | 47 | // ignore the first char, it's a V to tell us that this is voxel data |
| 48 | } | 48 | char *voxelDataPtr = (char *) data + 1; |
| 49 | 49 | ||
| 50 | void VoxelSystem::init(int numberOfRandomVoxels) { | 50 | float *position = new float[3]; |
| 51 | // create the arrays needed to pass to glDrawElements later | 51 | char *color = new char[3]; |
| 52 | // position / color are random for now | 52 | |
| 53 | 53 | // get pointers to position of last append of data | |
| 54 | voxelsRendered = numberOfRandomVoxels; | 54 | GLfloat *parseVerticesPtr = lastAddPointer; |
| 55 | 55 | GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray); | |
| 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]; | ||
| 64 | 56 | ||
| 65 | // new seed based on time now so voxels are different each time | 57 | int voxelsInData = 0; |
| 66 | srand((unsigned)time(0)); | ||
| 67 | 58 | ||
| 68 | for (int n = 0; n < numberOfRandomVoxels; n++) { | 59 | // pull voxels out of the received data and put them into our internal memory structure |
| 69 | // pick a random point for the center of the cube | 60 | while ((voxelDataPtr - (char *) data) < size) { |
| 70 | const float DEATH_STAR_RADIUS = 4.0; | 61 | |
| 71 | const float MAX_CUBE = 0.05; | 62 | memcpy(position, voxelDataPtr, 3 * sizeof(float)); |
| 72 | float azimuth = randFloat()*2*PI; | 63 | voxelDataPtr += 3 * sizeof(float); |
| 73 | float altitude = randFloat()*PI - PI/2; | 64 | memcpy(color, voxelDataPtr, 3); |
| 74 | float radius = DEATH_STAR_RADIUS; | 65 | voxelDataPtr += 3; |
| 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 | ); | ||
| 83 | 66 | ||
| 84 | // fill the vertices array, and scale the voxels | ||
| 85 | GLfloat *currentVerticesPos = verticesArray + (n * VERTEX_POINTS_PER_VOXEL); | ||
| 86 | for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) { | 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 | 71 | parseVerticesPtr += VERTEX_POINTS_PER_VOXEL; |
| 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; | ||
| 96 | 72 | ||
| 97 | for (int c = 0; c < VERTICES_PER_VOXEL; c++) { | 73 | for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) { |
| 98 | currentColorPos[0 + (c * 3)] = voxelR; | 74 | parseColorsPtr[c] = color[c % 3]; |
| 99 | currentColorPos[1 + (c * 3)] = voxelG; | ||
| 100 | currentColorPos[2 + (c * 3)] = voxelB; | ||
| 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 | } | ||
| 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 | } | ||
| 102 | 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 | // fill the indices array | 102 | // fill the indices array |
| 104 | int voxelIndexOffset = n * INDICES_PER_VOXEL; | 103 | int voxelIndexOffset = n * INDICES_PER_VOXEL; |
| 105 | GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; | 104 | GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; |
| @@ -114,135 +113,51 @@ void VoxelSystem::init(int numberOfRandomVoxels) { · 8 unmodified lines | |||
| 114 | // VBO for the verticesArray | 113 | // VBO for the verticesArray |
| 115 | glGenBuffers(1, &vboVerticesID); | 114 | glGenBuffers(1, &vboVerticesID); |
| 116 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); | 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 | // VBO for colorsArray | 118 | // VBO for colorsArray |
| 120 | glGenBuffers(1, &vboColorsID); | 119 | glGenBuffers(1, &vboColorsID); |
| 121 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | 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 | // VBO for the indicesArray | 123 | // VBO for the indicesArray |
| 125 | glGenBuffers(1, &vboIndicesID); | 124 | glGenBuffers(1, &vboIndicesID); |
| 126 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); | 125 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); |
| 127 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, numberOfRandomVoxels * INDICES_PER_VOXEL * sizeof(GLuint), indicesArray, GL_STATIC_DRAW); | 126 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, indicesArray, GL_STATIC_DRAW); |
| 128 | 127 | ||
| 129 | // delete the verticesArray, indicesArray | 128 | // delete the indices array that is no longer needed |
| 130 | delete[] verticesArray; | ||
| 131 | delete[] indicesArray; | 129 | delete[] indicesArray; |
| 132 | delete[] colorsArray; | ||
| 133 | } | 130 | } |
| 134 | 131 | ||
| 135 | // | 132 | void VoxelSystem::render() { |
| 136 | // Recursively initialize the voxel tree | 133 | // check if there are new voxels to draw |
| 137 | // | 134 | int vertexValuesToDraw = lastAddPointer - lastDrawPointer; |
| 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; | ||
| 146 | 135 | ||
| 147 | // | 136 | if (vertexValuesToDraw > 0) { |
| 148 | // First, randomly decide whether to stop here without recursing for children | 137 | // calculate the offset into each VBO, in vertex point values |
| 149 | // | 138 | int vertexBufferOffset = lastDrawPointer - verticesArray; |
| 150 | if (onSphereShell(RADIUS, scale, position) && (scale < 0.25) && (randFloat() < 0.01)) | 139 | |
| 151 | { | 140 | // bind the vertices VBO, copy in new data |
| 152 | voxel->color.x = 0.1; | 141 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); |
| 153 | voxel->color.y = 0.5 + randFloat()*0.5; | 142 | glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(float), vertexValuesToDraw * sizeof(float), lastDrawPointer); |
| 154 | voxel->color.z = 0.1; | 143 | |
| 155 | for (unsigned char i = 0; i < NUM_CHILDREN; i++) voxel->children[i] = NULL; | 144 | // bind the colors VBO, copy in new data |
| 156 | return 0; | 145 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); |
| 157 | } else { | 146 | glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(GLubyte), vertexValuesToDraw * sizeof(GLubyte), (colorsArray + (lastDrawPointer - verticesArray))); |
| 158 | // Decide whether to make kids, recurse into them | 147 | |
| 159 | for (unsigned char i = 0; i < NUM_CHILDREN; i++) { | 148 | // increment the lastDrawPointer to the lastAddPointer value used for this draw |
| 160 | if (scale > 0.01) { | 149 | lastDrawPointer += vertexValuesToDraw; |
| 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++; | ||
| 231 | } | 150 | } |
| 232 | return vRendered; | ||
| 233 | } | ||
| 234 | 151 | ||
| 235 | void VoxelSystem::render() { | 152 | // tell OpenGL where to find vertex and color information |
| 236 | glEnableClientState(GL_VERTEX_ARRAY); | 153 | glEnableClientState(GL_VERTEX_ARRAY); |
| 237 | glEnableClientState(GL_COLOR_ARRAY); | 154 | glEnableClientState(GL_COLOR_ARRAY); |
| 238 | 155 | ||
| 239 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); | ||
| 240 | |||
| 241 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); | 156 | glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); |
| 242 | glVertexPointer(3, GL_FLOAT, 0, 0); | 157 | glVertexPointer(3, GL_FLOAT, 0, 0); |
| 243 | 158 | ||
| 244 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | 159 | glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); |
| 245 | glColorPointer(3, GL_FLOAT, 0, 0); | 160 | glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); |
| 246 | 161 | ||
| 247 | glNormal3f(0, 1, 0); | 162 | glNormal3f(0, 1, 0); |
| 248 | 163 | ||