// extract surface mesh void TriSurfMesh( vector< MCCube*>& input, vector< MCTri*>& output){ vector< MCCube* >::const_iterator itr_cube; MCCube* pCube; for ( itr_cube = input.begin(); itr_cube != input.end(); ++itr_cube ){ pCube = *itr_cube; Polygonise( pCube, output ); } }
void generate_terrain(density_func_t function, std::vector<VtxPosNormTex>& vertices, std::vector<uint32_t>& indices) { static const float size = 10.0f; static const float granularity = 0.125f; static const float gran_div_2 = granularity * 0.5f; uint32_t vtx_index = 0; float x, y, z; for(x=-size;x<=size;x += granularity) { for(y=-size;y<=size;y += granularity) { for(z=-size;z<=size;z += granularity) { gridcell_t cell; int ii = 0; float xx = x-gran_div_2; float xadder = granularity; for(float yy=y-gran_div_2; yy <= y+gran_div_2; yy += granularity) { for(float zz=z-gran_div_2; zz <= z+gran_div_2; zz += granularity) { cell.p[ii].x = xx; cell.p[ii].y = yy; cell.p[ii].z = zz; ++ii; xx += xadder; cell.p[ii].x = xx; cell.p[ii].y = yy; cell.p[ii].z = zz; ++ii; xadder *= -1.0f; } } for(ii=0;ii<8;++ii) { cell.val[ii] = function(cell.p[ii]); } triangle_t triangles[5]; int num_triangles = Polygonise(cell, 0.0f, triangles); for(ii=0;ii<num_triangles;++ii) { triangle_t tri = triangles[ii]; float3 norm; float3 edge0 = float3subtract(&tri.p[1], &tri.p[0]); float3 edge1 = float3subtract(&tri.p[2], &tri.p[0]); norm = float3cross(&edge1, &edge0); norm = float3normalize(&norm); for(int jj=2; jj>=0; --jj) { float2 tex = {tri.p[jj].x, tri.p[jj].z}; VtxPosNormTex v = { tri.p[jj], norm, tex }; vertices.push_back(v); indices.push_back(vtx_index++); } } } } } }
int Sculpture::createMesh() { vector<Triangle> triangles; for (int i = 0 ; i < SCULPTURE_SIZE - 1 ; i++) { for (int j = 0 ; j < SCULPTURE_SIZE - 1 ; j++) { for (int k = 0 ; k < SCULPTURE_SIZE - 1 ; k++) { GRIDCELL grid; this->initGrid(grid, i, j, k); Polygonise(grid, 0.5, triangles); } } } updateColors(triangles); mesh.clear(); trianglesToMesh(triangles); return mesh.getNumberOfTriangles(); }
void runInterpTest() { GRIDCELL cell = { { { 0,0,1 },{ 1,0,1 },{ 1,0,0 } ,{ 0,0,0 } ,{ 0,1,1 } ,{ 1,1,1 } ,{ 1,1,0 } ,{ 0,1,0 } },{ 0,1,0,0,0,0,0,0 } }; const int times = 10000000; TRIANGLE* triangles = new TRIANGLE[times]; double start = clock(); std::cout << "Starting test "; std::cout << start << std::endl; for (int i = 0; i < times; i++) { triangles += Polygonise(cell, 0.5, triangles); } double end = clock(); std::cout << "Completed test "; std::cout << end << std::endl; auto msPerKernel = (end - start) / times; std::cout << "Time per kernel in ms: " << msPerKernel << std::endl; auto kernelsPerFrame_60 = 1.0 / msPerKernel * 1000 / 60; std::cout << "Kernels per frame at 60 FPS: " << kernelsPerFrame_60 << std::endl; auto cubeSize60FPS = pow(kernelsPerFrame_60, 1.0 / 3); std::cout << "Kernel Cube per frame at 60 FPS: " << cubeSize60FPS << std::endl; }
//Software marching cubes //VERY far to be optimal ! void MarchingCubesRenderer::RenderMarchCube(float *data, ivec3 size, ivec3 gridsize, float isolevel){ vec3 gridStep = vec3(2.0, 2.0, 2.0) / vec3(gridsize.x, gridsize.y, gridsize.z); ivec3 dataGridStep = size / gridsize; vec3 *triangles = new vec3[16]; std::vector<Vector3>& positions = _mesh->getPositionVector(); positions.clear(); for (int k = 0; k < gridsize.z - 1; k++) for (int j = 0; j < gridsize.y - 1; j++) for (int i = 0; i < gridsize.x - 1; i++){ GridCell cell; vec3 vcurf(i, j, k); ivec3 vcuri(i, j, k); cell.pos[0] = vcurf*gridStep - 1.0f; ivec3 valPos0 = vcuri*dataGridStep; cell.val[0] = data[valPos0.x + valPos0.y*size.x + valPos0.z*size.x*size.y]; ivec3 valPos; cell.pos[1] = cell.pos[0] + vec3(gridStep.x, 0, 0); if (i == gridsize.x - 1) valPos = valPos0; else valPos = valPos0 + ivec3(dataGridStep.x, 0, 0); cell.val[1] = data[valPos.x + valPos.y*size.x + valPos.z*size.x*size.y]; cell.pos[2] = cell.pos[0] + vec3(gridStep.x, gridStep.y, 0); valPos = valPos0 + ivec3(i == gridsize.x - 1 ? 0 : dataGridStep.x, j == gridsize.y - 1 ? 0 : dataGridStep.y, 0); cell.val[2] = data[valPos.x + valPos.y*size.x + valPos.z*size.x*size.y]; cell.pos[3] = cell.pos[0] + vec3(0, gridStep.y, 0); valPos = valPos0 + ivec3(0, j == gridsize.y - 1 ? 0 : dataGridStep.y, 0); cell.val[3] = data[valPos.x + valPos.y*size.x + valPos.z*size.x*size.y]; cell.pos[4] = cell.pos[0] + vec3(0, 0, gridStep.z); valPos = valPos0 + ivec3(0, 0, k == gridsize.z - 1 ? 0 : dataGridStep.z); cell.val[4] = data[valPos.x + valPos.y*size.x + valPos.z*size.x*size.y]; cell.pos[5] = cell.pos[0] + vec3(gridStep.x, 0, gridStep.z); valPos = valPos0 + ivec3(i == gridsize.x - 1 ? 0 : dataGridStep.x, 0, k == gridsize.z - 1 ? 0 : dataGridStep.z); cell.val[5] = data[valPos.x + valPos.y*size.x + valPos.z*size.x*size.y]; cell.pos[6] = cell.pos[0] + vec3(gridStep.x, gridStep.y, gridStep.z); valPos = valPos0 + ivec3(i == gridsize.x - 1 ? 0 : dataGridStep.x, j == gridsize.y - 1 ? 0 : dataGridStep.y, k == gridsize.z - 1 ? 0 : dataGridStep.z); cell.val[6] = data[valPos.x + valPos.y*size.x + valPos.z*size.x*size.y]; cell.pos[7] = cell.pos[0] + vec3(0, gridStep.y, gridStep.z); valPos = valPos0 + ivec3(0, j == gridsize.y - 1 ? 0 : dataGridStep.y, k == gridsize.z - 1 ? 0 : dataGridStep.z); cell.val[7] = data[valPos.x + valPos.y*size.x + valPos.z*size.x*size.y]; int numvert = Polygonise(cell, isolevel, triangles); //Put the triangles into the mesh for (int n = 0; n < numvert; n++){ positions.push_back(Vector3(triangles[n].x, triangles[n].y, triangles[n].z)); } } if (positions.empty() == false) { GetGLError(); _mesh->constructBuffer(); GetGLError(); _mesh->drawBuffers(); GetGLError(); } }
void Engine::render() { float i,j,k; int num_cubes = 16; int grid_width = 16; float step_size = (float)grid_width / num_cubes; float half_step = step_size / 2.0; TRIANGLE triangle[5]; GRIDCELL cube; int num_triangle = 0; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor3f(1.0, 0.0, 0.0); glTranslatef(0.0f, 0.0f, -40.0f); // glRotatef(time, 0.0f, 1.0f, 0.0f); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); for(i = 0; i <= grid_width; i += step_size ) { for(j = 0; j <= grid_width; j += step_size ) { for(k = 0; k <= grid_width; k += step_size ) { set_zero(cube); set_metaball(cube, grid_width, half_step, 2.0, i, j, k, 5.5 * cos(time / 50.0), 5 * sin(time / 50.0), 0); set_metaball(cube, grid_width, half_step, 2.0, i, j, k, 5.5 * sin(time / 50.0), 5 * sin(time / 50.0), 0); num_triangle = Polygonise(cube, 0.25, triangle); // glColor3f((int)(i + j + k) % 2, 0, 0); if (num_triangle) { for(int t = 0; t < num_triangle; t++) { glBegin(GL_TRIANGLES); glVertex3f(triangle[t].p[0].x, triangle[t].p[0].y, triangle[t].p[0].z); glVertex3f(triangle[t].p[1].x, triangle[t].p[1].y, triangle[t].p[1].z); glVertex3f(triangle[t].p[2].x, triangle[t].p[2].y, triangle[t].p[2].z); glEnd(); } } } } } /* glColor3f(1.0, 1.0, 1.0); glTranslatef(-8.0, -8.0, -8.0); for(i = 0; i <= num_cubes; i += 1.0f) { for(j = 0; j <= num_cubes; j += 1.0f) { for(k = 0; k <= num_cubes; k += 1.0f) { draw_box(); glTranslatef(0.0, 0.0, 1.0); } glTranslatef(0.0, 1.0, 0.0); if (k == num_cubes + 1) glTranslatef(0.0, 0.0, -num_cubes - 1); } if (j == num_cubes + 1) glTranslatef(0.0, -num_cubes - 1, 0.0); glTranslatef(1.0, 0.0, 0.0); } */ SwapBuffers(hdc); }
void runKernelTest() { /*auto s = new MarchingCubesService(); auto gridP = MarchingCubesService.Vertices.Select(f = > f.ToVector3()).ToArray(); auto gridVals = new double[8]; gridVals[0] = 1; auto triangles = new List<Vector3>(); auto watch = new Stopwatch(); watch.Start(); */ GRIDCELL cell = { { { 0,0,1 },{ 1,0,1 },{ 1,0,0 } ,{ 0,0,0 } ,{ 0,1,1 } ,{ 1,1,1 } ,{ 1,1,0 } ,{ 0,1,0 } },{ 0,1,0,0,0,0,0,0 } }; const int times = 10000000; TRIANGLE* triangles = new TRIANGLE[times]; double start = clock(); std::cout << "Starting test "; std::cout << start << std::endl; for (int i = 0; i < times; i++) { triangles += Polygonise(cell, 0.5, triangles); } double end = clock(); std::cout << "Completed test "; std::cout << end << std::endl; auto msPerKernel = (end - start) / times; std::cout << "Time per kernel in ms: " << msPerKernel << std::endl; auto kernelsPerFrame_60 = 1.0 / msPerKernel * 1000 / 60; std::cout << "Kernels per frame at 60 FPS: " << kernelsPerFrame_60 << std::endl; auto cubeSize60FPS = pow(kernelsPerFrame_60, 1.0 / 3); std::cout << "Kernel Cube per frame at 60 FPS: " << cubeSize60FPS << std::endl; start = clock(); std::cout << "Starting test "; std::cout << start << std::endl; for (int i = 0; i < times; i++) { //VertexInterp(cell, 10, triangles); } end = clock(); std::cout << "Completed test "; std::cout << end << std::endl; msPerKernel = (end - start) / times; std::cout << "Time per kernel in ms: " << msPerKernel << std::endl; kernelsPerFrame_60 = 1.0 / msPerKernel * 1000 / 60; std::cout << "Kernels per frame at 60 FPS: " << kernelsPerFrame_60 << std::endl; cubeSize60FPS = pow(kernelsPerFrame_60, 1.0 / 3); std::cout << "Kernel Cube per frame at 60 FPS: " << cubeSize60FPS << std::endl; getchar(); }
static void AEMarchingCubes(uint8_t* voxels, uint32_t stepX, uint32_t stepY, uint32_t stepZ, double isovalue, uint32_t w, uint32_t h, uint32_t d, AEMCTriangleArray* triangleArray) { // Run the processCube function on every cube in the grid for(uint32_t x = stepX; x < w-2*stepX; x += stepX) { for(uint32_t y = stepY; y < h-2*stepY; y += stepY) { for(uint32_t z = stepZ; z < d-2*stepZ; z += stepZ) { /*GRIDCELL c = {{ {x,y,z, (double)(voxels[Index(x+stepX,y,z,w,h,d)]-voxels[Index(x-stepX,y,z,w,h,d)]) / -stepX, (double)(voxels[Index(x,y+stepY,z,w,h,d)]-voxels[Index(x,y-stepY,z,w,h,d)]) / -stepY, (double)(voxels[Index(x,y,z+stepZ,w,h,d)]-voxels[Index(x,y,z-stepZ,w,h,d)]) / -stepZ }, {x+stepX,y,z, (double)(voxels[Index(x+2*stepX,y,z,w,h,d)]-voxels[Index(x,y,z,w,h,d)]) / -stepX, (double)(voxels[Index(x+stepX,y+stepY,z,w,h,d)]-voxels[Index(x+stepX,y-stepY,z,w,h,d)]) / -stepY, (double)(voxels[Index(x+stepX,y,z+stepZ,w,h,d)]-voxels[Index(x+stepX,y,z-stepZ,w,h,d)]) / -stepZ }, {x+stepX,y,z+stepZ, (double)(voxels[Index(x+2*stepX,y,z+stepZ,w,h,d)]-voxels[Index(x,y,z+stepZ,w,h,d)]) / -stepX, (double)(voxels[Index(x+stepX,y+stepY,z+stepZ,w,h,d)]-voxels[Index(x+stepX,y-stepY,z+stepZ,w,h,d)]) / -stepY, (double)(voxels[Index(x+stepX,y,z+2*stepZ,w,h,d)]-voxels[Index(x+stepX,y,z,w,h,d)]) / -stepZ }, {x,y,z+stepZ, (double)(voxels[Index(x+stepX,y,z+stepZ,w,h,d)]-voxels[Index(x-stepX,y,z+stepZ,w,h,d)]) / -stepX, (double)(voxels[Index(x,y+stepY,z+stepZ,w,h,d)]-voxels[Index(x,y-stepY,z+stepZ,w,h,d)]) / -stepY, (double)(voxels[Index(x,y,z+2*stepZ,w,h,d)]-voxels[Index(x,y,z,w,h,d)]) / -stepZ }, {x,y+stepY,z, (double)(voxels[Index(x+stepX,y+stepY,z,w,h,d)]-voxels[Index(x-stepX,y+stepY,z,w,h,d)]) / -stepX, (double)(voxels[Index(x,y+2*stepY,z,w,h,d)]-voxels[Index(x,y,z,w,h,d)]) / -stepY, (double)(voxels[Index(x,y+stepY,z+stepZ,w,h,d)]-voxels[Index(x,y+stepY,z-stepZ,w,h,d)]) / -stepZ }, {x+stepX,y+stepY,z, (double)(voxels[Index(x+2*stepX,y+stepY,z,w,h,d)]-voxels[Index(x+stepX,y+stepY,z,w,h,d)]) / -stepX, (double)(voxels[Index(x+stepX,y+2*stepY,z,w,h,d)]-voxels[Index(x+stepX,y,z,w,h,d)]) / -stepY, (double)(voxels[Index(x+stepX,y+stepY,z+stepZ,w,h,d)]-voxels[Index(x+stepX,y+stepY,z-stepZ,w,h,d)]) / -stepZ }, {x+stepX,y+stepY,z+stepZ, (double)(voxels[Index(x+2*stepX,y+stepY,z+stepZ,w,h,d)]-voxels[Index(x,y+stepY,z+stepZ,w,h,d)]) / -stepX, (double)(voxels[Index(x+stepX,y+2*stepY,z+stepZ,w,h,d)]-voxels[Index(x+stepX,y,z+stepZ,w,h,d)]) / -stepY, (double)(voxels[Index(x+stepX,y+stepY,z+2*stepZ,w,h,d)]-voxels[Index(x+stepX,y+stepY,z,w,h,d)]) / -stepZ }, {x,y+stepY,z+stepZ, (double)(voxels[Index(x+stepX,y+stepY,z+stepZ,w,h,d)]-voxels[Index(x-stepX,y+stepY,z+stepZ,w,h,d)]) / -stepX, (double)(voxels[Index(x,y+2*stepY,z+stepZ,w,h,d)]-voxels[Index(x,y,z+stepZ,w,h,d)]) / -stepY, (double)(voxels[Index(x,y+stepY,z+2*stepZ,w,h,d)]-voxels[Index(x,y+stepY,z,w,h,d)]) / -stepZ } },{ voxels[Index(x,y,z,w,h,d)], voxels[Index(x+stepX,y,z,w,h,d)], voxels[Index(x+stepX,y,z+stepZ,w,h,d)], voxels[Index(x,y,z+stepZ,w,h,d)], voxels[Index(x,y+stepY,z,w,h,d)], voxels[Index(x+stepX,y+stepY,z,w,h,d)], voxels[Index(x+stepX,y+stepY,z+stepZ,w,h,d)], voxels[Index(x,y+stepY,z+stepZ,w,h,d)] }};*/ GRIDCELL c={{ {x,y,z,0,0,0}, {x+stepX,y,z,0,0,0}, {x+stepX,y,z+stepZ,0,0,0}, {x,y,z+stepZ,0,0,0}, {x,y+stepY,z,0,0,0}, {x+stepX,y+stepY,z,0,0,0}, {x+stepX,y+stepY,z+stepZ,0,0,0}, {x,y+stepY,z+stepZ,0,0,0} },{ voxels[Index(x,y,z,w,h,d)], voxels[Index(x+stepX,y,z,w,h,d)], voxels[Index(x+stepX,y,z+stepZ,w,h,d)], voxels[Index(x,y,z+stepZ,w,h,d)], voxels[Index(x,y+stepY,z,w,h,d)], voxels[Index(x+stepX,y+stepY,z,w,h,d)], voxels[Index(x+stepX,y+stepY,z+stepZ,w,h,d)], voxels[Index(x,y+stepY,z+stepZ,w,h,d)] }}; ///Polygonise(c, isovalue); TRIANGLE triangles[5]; size_t count=Polygonise(c, isovalue, triangles); for (size_t i=0; i<count; i++) { AEArrayAddBytes(triangleArray, triangles+i); } } } } }
void CMarchCube::MultiMaterial(CMesh* pMeshOut, void* pArrays, bool SumMat, CColor* pColors, float Thresh, float Scale) { std::vector<CArray3Df>* pDA = (std::vector<CArray3Df>*) pArrays; int NumMat = (*pDA).size(); int Resolution=1; Scale=Scale/Resolution; //of course, assumes cubic structure!!! GRIDCELL GridCell; pMeshOut->Clear(); //innefficient! CArray3Df Padded; CArray3Df aR; CArray3Df aG; CArray3Df aB; Padded.IniSpace(((*pDA)[0].GetXSize()*Resolution)+2, ((*pDA)[0].GetYSize()*Resolution)+2, ((*pDA)[0].GetZSize()*Resolution)+2, 0); aR.IniSpace(Padded.GetXSize()*Resolution, Padded.GetYSize()*Resolution, Padded.GetZSize()*Resolution, 0.0); aG.IniSpace(Padded.GetXSize()*Resolution, Padded.GetYSize()*Resolution, Padded.GetZSize()*Resolution, 0.0); aB.IniSpace(Padded.GetXSize()*Resolution, Padded.GetYSize()*Resolution, Padded.GetZSize()*Resolution, 0.0); for (int i=0; i<(*pDA)[0].GetXSize()*Resolution; i++) for (int j=0; j<(*pDA)[0].GetYSize()*Resolution; j++) for (int k=0; k<(*pDA)[0].GetZSize()*Resolution; k++){ //find the max, for color (or for thresh, as well if !SumMat) float max = -9e9f; // float max = 0.0f; for (int m=0; m<NumMat; m++){ if ((*pDA)[m](i, j, k) > max){ max = (*pDA)[m](i, j, k); if (pColors != NULL){ //grab the colors! aR(i+1, j+1, k+1) = pColors[m].r; aG(i+1, j+1, k+1) = pColors[m].g; aB(i+1, j+1, k+1) = pColors[m].b; //fill in outside of padded here if we wish... } } } if (SumMat){ //if we're summing the materials to create the mesh... for (int m=0; m<NumMat; m++){ float ToAdd = ((*pDA)[m])(i, j, k); if (m==0) Padded(i+1, j+1, k+1) = ToAdd; else Padded(i+1, j+1, k+1) += ToAdd; } } else { //if we're not summing the materials... Padded(i+1, j+1, k+1) = max; } //TRACE("%f\n", Padded(i+1, j+1, k+1)); } //form cubes float ai, aj, ak; //jmc: for speed, declare them only once for (int i=0; i<Padded.GetXSize()*Resolution-1; i++){ for (int j=0; j<Padded.GetYSize()*Resolution-1; j++){ for (int k=0; k<Padded.GetZSize()*Resolution-1; k++){ ai = i-0.5f; aj = j-0.5f; ak = k-0.5f; GridCell.p[0] = CVertex(Vec3D<>(Scale*ai, Scale*aj, Scale*ak), CColor(aR(i, j, k), aG(i, j, k), aB(i, j, k))); GridCell.val[0] = Padded(i, j, k); GridCell.p[1] = CVertex(Vec3D<>(Scale*(ai+1), Scale*aj, Scale*ak), CColor(aR(i+1, j, k), aG(i+1, j, k), aB(i+1, j, k))); GridCell.val[1] = Padded(i+1, j, k); GridCell.p[2] = CVertex(Vec3D<>(Scale*(ai+1), Scale*(aj+1), Scale*ak), CColor(aR(i+1, j+1, k), aG(i+1, j+1, k), aB(i+1, j+1, k))); GridCell.val[2] = Padded(i+1, j+1, k); GridCell.p[3] = CVertex(Vec3D<>(Scale*ai, Scale*(aj+1), Scale*ak), CColor(aR(i, j+1, k), aG(i, j+1, k), aB(i, j+1, k))); GridCell.val[3] = Padded(i, j+1, k); GridCell.p[4] = CVertex(Vec3D<>(Scale*ai, Scale*aj, Scale*(ak+1)), CColor(aR(i, j, k+1), aG(i, j, k+1), aB(i, j, k+1))); GridCell.val[4] = Padded(i, j, k+1); GridCell.p[5] = CVertex(Vec3D<>(Scale*(ai+1), Scale*aj, Scale*(ak+1)), CColor(aR(i+1, j, k+1), aG(i+1, j, k+1), aB(i+1, j, k+1))); GridCell.val[5] = Padded(i+1, j, k+1); GridCell.p[6] = CVertex(Vec3D<>(Scale*(ai+1), Scale*(aj+1), Scale*(ak+1)), CColor(aR(i+1, j+1, k+1), aG(i+1, j+1, k+1), aB(i+1, j+1, k+1))); GridCell.val[6] = Padded(i+1, j+1, k+1); GridCell.p[7] = CVertex(Vec3D<>(Scale*ai, Scale*(aj+1), Scale*(ak+1)), CColor(aR(i, j+1, k+1), aG(i, j+1, k+1), aB(i, j+1, k+1))); GridCell.val[7] = Padded(i, j+1, k+1); Polygonise(GridCell, Thresh, pMeshOut); //crunch this cube and add the vertices... } } } pMeshOut->WeldClose(Scale/2); pMeshOut->CalcFaceNormals(); pMeshOut->CalcVertNormals(); //pMeshOut->WeldClose(Scale); }
void CMarchCube::SingleMaterialMultiColor(CMesh* pMeshOut, CArray3Df* pArray, CArray3Df* rColorArray, CArray3Df* gColorArray, CArray3Df* bColorArray, float Thresh, float Scale) { std::vector<CArray3Df> tmpVec; //put in an stl vector to call MultiMaterial() tmpVec.push_back(*pArray); //of course, assumes cubic structure!!! GRIDCELL GridCell; pMeshOut->Clear(); //innefficient! CArray3Df Padded; CArray3Df aR; CArray3Df aG; CArray3Df aB; Padded.IniSpace(pArray->GetXSize()+2, pArray->GetYSize()+2, pArray->GetZSize()+2, -1e6); aR.IniSpace(Padded.GetXSize(), Padded.GetYSize(), Padded.GetZSize(), 0.0); aG.IniSpace(Padded.GetXSize(), Padded.GetYSize(), Padded.GetZSize(), 0.0); aB.IniSpace(Padded.GetXSize(), Padded.GetYSize(), Padded.GetZSize(), 0.0); for (int i=0; i<pArray->GetXSize(); i++) for (int j=0; j<pArray->GetYSize(); j++) for (int k=0; k<pArray->GetZSize(); k++){ //existince array Padded(i+1, j+1, k+1) = (*pArray)(i,j,k); //color arrays aR(i+1, j+1, k+1) = (*rColorArray)(i,j,k); aG(i+1, j+1, k+1) = (*gColorArray)(i,j,k); aB(i+1, j+1, k+1) = (*bColorArray)(i,j,k); } //form cubes float ai, aj, ak; //jmc: for speed, declare them only once for (int i=0; i<Padded.GetXSize()-1; i++){ for (int j=0; j<Padded.GetYSize()-1; j++){ for (int k=0; k<Padded.GetZSize()-1; k++){ ai = i-0.5f; aj = j-0.5f; ak = k-0.5f; GridCell.p[0] = CVertex(Vec3D<>(Scale*ai, Scale*aj, Scale*ak), CColor(aR(i, j, k), aG(i, j, k), aB(i, j, k))); //put in ccppn-generated rgb here. GridCell.val[0] = Padded(i, j, k); GridCell.p[1] = CVertex(Vec3D<>(Scale*(ai+1), Scale*aj, Scale*ak), CColor(aR(i+1, j, k), aG(i+1, j, k), aB(i+1, j, k))); GridCell.val[1] = Padded(i+1, j, k); GridCell.p[2] = CVertex(Vec3D<>(Scale*(ai+1), Scale*(aj+1), Scale*ak), CColor(aR(i+1, j+1, k), aG(i+1, j+1, k), aB(i+1, j+1, k))); GridCell.val[2] = Padded(i+1, j+1, k); GridCell.p[3] = CVertex(Vec3D<>(Scale*ai, Scale*(aj+1), Scale*ak), CColor(aR(i, j+1, k), aG(i, j+1, k), aB(i, j+1, k))); GridCell.val[3] = Padded(i, j+1, k); GridCell.p[4] = CVertex(Vec3D<>(Scale*ai, Scale*aj, Scale*(ak+1)), CColor(aR(i, j, k+1), aG(i, j, k+1), aB(i, j, k+1))); GridCell.val[4] = Padded(i, j, k+1); GridCell.p[5] = CVertex(Vec3D<>(Scale*(ai+1), Scale*aj, Scale*(ak+1)), CColor(aR(i+1, j, k+1), aG(i+1, j, k+1), aB(i+1, j, k+1))); GridCell.val[5] = Padded(i+1, j, k+1); GridCell.p[6] = CVertex(Vec3D<>(Scale*(ai+1), Scale*(aj+1), Scale*(ak+1)), CColor(aR(i+1, j+1, k+1), aG(i+1, j+1, k+1), aB(i+1, j+1, k+1))); GridCell.val[6] = Padded(i+1, j+1, k+1); GridCell.p[7] = CVertex(Vec3D<>(Scale*ai, Scale*(aj+1), Scale*(ak+1)), CColor(aR(i, j+1, k+1), aG(i, j+1, k+1), aB(i, j+1, k+1))); GridCell.val[7] = Padded(i, j+1, k+1); Polygonise(GridCell, Thresh, pMeshOut); //crunch this cube and add the vertices... } } } pMeshOut->WeldClose(Scale/2); }
void MyWidget::MarchingCubes() { Vector **triangles = new Vector*[5]; for (int i = 0; i < 5; i++) { triangles[i] = new Vector[3]; } Matrix T(4, 4); T.Diag(1); T(0, 3) = Tx + 200; T(1, 3) = Ty + 150; T(2, 3) = Tz; Matrix Sc(4, 4); Sc(0, 0) = ScX; Sc(1, 1) = ScY; Sc(2, 2) = ScZ; Sc(3, 3) = 1; Matrix RX(4, 4); RX.Diag(1); RX(1, 1) = cos(AlfaX); RX(1, 2) = sin(AlfaX); RX(2, 1) = -sin(AlfaX); RX(2, 2) = cos(AlfaX); Matrix RY(4, 4); RY.Diag(1); RY(0, 0) = cos(AlfaY); RY(0, 2) = -sin(AlfaY); RY(2, 0) = sin(AlfaY); RY(2, 2) = cos(AlfaY); Matrix RZ(4, 4); RZ.Diag(1); RZ(0, 0) = cos(AlfaZ); RZ(0, 1) = sin(AlfaZ); RZ(1, 0) = -sin(AlfaZ); RZ(1, 1) = cos(AlfaZ); Matrix m = T.multi(Sc.multi(RX.multi(RY.multi(RZ)))); T.free(); Sc.free(); RX.free(); RY.free(); RZ.free(); Matrix p; for (int x = _S; x < fR2; x += _S) { for (int y = _S; y < fR2; y += _S) { for (int z = _S; z < fR2; z += _S) { int n = Polygonise(x, y, z, 1, triangles); for (int i = 0; i < n; i++) { Vector tab[3]; for (int j = 0; j < 3; j++) { p = m.multi(triangles[i][j]); tab[j] = Vector(p(X, 0), p(Y, 0), p(Z, 0)); } Triangle(_bitsDest, tab[0], tab[1], tab[2]); tab[0].free(); tab[1].free(); tab[2].free(); } } } } m.free(); p.free(); for (int i = 0; i < 5; i++) { for (int j = 0; j < 3; j++) { triangles[i][j].free(); } } }
void update(void) { // if no spheres nothing todo. static float frame = 0.0; if (!nbSpeheres) { return; } else { frame += 0.05; spheres[0].x = 0.2f * (float)sin(frame * 1.0f) + 0.5f; spheres[0].y = 0.2f * (float)cos(frame * 1.0f) + 0.5f; spheres[1].y = 0.2f * (float)sin(frame * 0.7f) + 0.5f; spheres[1].z = 0.2f * (float)cos(frame * 0.7f) + 0.5f; spheres[2].z = 0.2f * (float)sin(frame * 1.3f) + 0.5f; spheres[2].x = 0.2f * (float)cos(frame * 1.3f) + 0.5f; } DWORD dwNbVertex = 0; // (from dake calodox) // modified to fill my needs double diffx, diffy, diffz; double dist; // calculate the metasphere for (int gz=0;gz<GRID_Z;gz++) { for (int gy=0;gy<GRID_Y;gy++) { for (int gx=0;gx<GRID_X;gx++) { //efface la grille metagrille[gx][gy][gz]=0.0; // double s = gy*gy; // metagrille[gx][gy][gz] = s != 0 ? 1/s : 0; for (int n = 0; n < nbSpeheres; ++n) { diffx= gx - ((spheres[n].x + 1.0) * (GRID_X / 2.0)); diffy= gy - ((spheres[n].y + 1.0) * (GRID_Y / 2.0)); diffz= gz - ((spheres[n].z + 1.0) * (GRID_Z / 2.0)); dist = 1.0/ ((diffx * diffx) + (diffy * diffy) + (diffz * diffz)); metagrille[gx][gy][gz] += dist; } } } } // TODO add an algo to go faster HERE!!! for (int jz = 0; jz < (GRID_Z - 1); ++ jz) { for (int jy = 0; jy < (GRID_Y - 1); ++ jy) { for (int jx = 0; jx < (GRID_X - 1); ++ jx) { gride[jx][jy][jz].val[0] = metagrille[jx][jy][jz]; gride[jx][jy][jz].val[1] = metagrille[jx + 1][jy][jz]; gride[jx][jy][jz].val[2] = metagrille[jx + 1][jy + 1][jz]; gride[jx][jy][jz].val[3] = metagrille[jx][jy + 1][jz]; gride[jx][jy][jz].val[4] = metagrille[jx][jy][jz + 1]; gride[jx][jy][jz].val[5] = metagrille[jx + 1][jy][jz + 1]; gride[jx][jy][jz].val[6] = metagrille[jx + 1][jy + 1][jz + 1]; gride[jx][jy][jz].val[7] = metagrille[jx][jy + 1][jz + 1]; DWORD newVert = Polygonise( gride[jx][jy][jz], ISO_LEVEL, (TRIANGLE*)&cvVertices[dwNbVertex]) * 3; // make the Normals calculation for (DWORD pu = 0; pu < newVert; ++pu) { float vect[3] = {0.0f, 0.0f, 0.0f}; for (int no = 0; no < nbSpeheres; ++no) { float dx, dy, dz; dx = cvVertices[dwNbVertex + pu].x - spheres[no].x; dy = cvVertices[dwNbVertex + pu].y - spheres[no].y; dz = cvVertices[dwNbVertex + pu].z - spheres[no].z; double mdist = 1.0 / sqrt((dx * dx) + (dy * dy) + (dz * dz)); vect[0] += (float)(dx * mdist); vect[1] += (float)(dy * mdist); vect[2] += (float)(dz * mdist); } // Normalize float d = sqrt( (vect[0] * vect[0]) + (vect[1] * vect[1]) + (vect[2] * vect[2])); cvVertices[dwNbVertex + pu].nx = vect[0] / d; cvVertices[dwNbVertex + pu].ny = vect[1] / d; cvVertices[dwNbVertex + pu].nz = vect[2] / d; } dwNbVertex += newVert; } } } dwNbVertices = dwNbVertex; }
void generate_terrain_points(density_func_t function, float3 min, float3 max, float granularity, std::vector<float3>& vertices) { const float inv_gran = 1.0f/granularity; // Calculate the grid size int32_t x_size = (int32_t)((max.x - min.x) * inv_gran) + 1; int32_t y_size = (int32_t)((max.y - min.y) * inv_gran) + 1; int32_t z_size = (int32_t)((max.z - min.z) * inv_gran) + 1; uint32_t grid_size = x_size * y_size * z_size; #define ARRAY_INDEX(_x,_y,_z) ((_z)*x_size*y_size + (_y)*x_size + (_x)) float4* grid = (float4*)calloc(grid_size, sizeof(float4)); float xf, yf, zf; int xi, yi, zi; for(zf = min.z, zi = 0; zi < z_size; ++zi, zf += granularity) { for(yf = min.y, yi = 0; yi < y_size; ++yi, yf += granularity) { for(xf = min.x, xi = 0; xi < x_size; ++xi, xf += granularity) { float4 pt = { xf, yf, zf, 0.0f }; pt.w = function(*(float3*)&pt); grid[ARRAY_INDEX(xi,yi,zi)] = pt; } } } for(zi = 0; zi < z_size-1; ++zi) { for(yi = 0; yi < y_size-1; ++yi) { for(xi = 0; xi < x_size-1; ++xi) { gridcell_t cell; float4 val; int ii=0; // Get the cell corners val = grid[ARRAY_INDEX(xi, yi, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi, yi, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi, yi+1, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi+1, zi)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi+1, yi+1, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; val = grid[ARRAY_INDEX(xi, yi+1, zi+1)]; cell.p[ii] = *(float3*)&val; cell.val[ii++] = val.w; // Polygonize the cell triangle_t triangles[5]; int num_triangles = Polygonise(cell, 0.0f, triangles); for(ii=0;ii<num_triangles;++ii) { triangle_t tri = triangles[ii]; if(degenerate(tri)) continue; for(int jj=2; jj>=0; --jj) { vertices.push_back(tri.p[jj]); } } } } } free(grid); }