void DrawMolItem::draw_volume_isosurface_lines (const VolumetricData * v, float isovalue, int stepsize, int thickness) { int i, usecolor; IsoSurface *s = new IsoSurface; s->clear (); s->compute (v, isovalue, stepsize); if (s->numtriangles > 0) { append (DMATERIALOFF); // enable lighting and shading cmdLineType.putdata (SOLIDLINE, cmdList); cmdLineWidth.putdata (thickness, cmdList); usecolor = draw_volume_get_colorid (); cmdColorIndex.putdata (usecolor, cmdList); // draw triangles for (i = 0; i < s->numtriangles; i++) { float *addr; addr = &(s->v[i * 9]); cmdLine.putdata (&addr[0], &addr[3], cmdList); cmdLine.putdata (&addr[3], &addr[6], cmdList); cmdLine.putdata (&addr[6], &addr[0], cmdList); } } delete s; // we don't need this stuff after this point }
void DrawMolItem::draw_volume_isosurface_trimesh (const VolumetricData * v, float isovalue, int stepsize) { int i, usecolor; IsoSurface s; s.clear (); // initialize isosurface data s.compute (v, isovalue, stepsize); // compute the isosurface s.vertexfusion (v, 36, 36); // identify and eliminate duplicated vertices s.normalize (); // normalize interpolated gradient/surface normals if (s.numtriangles > 0) { append (DMATERIALON); // enable lighting and shading usecolor = draw_volume_get_colorid (); cmdColorIndex.putdata (usecolor, cmdList); // draw surface with per-vertex normals using a vertex array float *c = new float[s.numtriangles * 9]; const float *fp = scene->color_value (usecolor); for (i = 0; i < s.numtriangles; i++) { int ind = i * 9; c[ind] = fp[0]; // Red c[ind + 1] = fp[1]; // Green c[ind + 2] = fp[2]; // Blue ind += 3; c[ind] = fp[0]; // Red c[ind + 1] = fp[1]; // Green c[ind + 2] = fp[2]; // Blue ind += 3; c[ind] = fp[0]; // Red c[ind + 1] = fp[1]; // Green c[ind + 2] = fp[2]; // Blue } // Create a triangle mesh // XXX don't try to stripify it since this triggers a crash in ACTC for // unknown reasons cmdTriMesh.putdata (&s.v[0], &s.n[0], c, s.v.num () / 3, &s.f[0], s.numtriangles, 0, cmdList, &cmdTriMesh); delete[] c; } }
/* * March through the grid, creating the tesselation of an isosurface. * The somewhat convoluted logic is necessary to prevent any single cube * edge from being examined more than once. This allows for a compact * mesh representation, with each vertex stored only once and each face * stored simply as three integer indices into the vertex array. */ void MarchCube::march (IsoSurface& surface) { surface.clear(); ImpSurface* function = surface.getFunction(); /* * */ initVertices(0, vtxGrid[0], function); initVertices(1, vtxGrid[1], function); setCubeFlags(); /* * Fill in the back of the grid first (where "forward" is the +z * direction. This is done by checking the left- and bottom-edges * of each square at the very back of the grid, then all the edges * along the top of the back, then all those along the right. */ for (int i = 0; i < resx; ++i) { for (int j = 0; j < resy; ++j) { if (edgeFlags[i][j] & LEFTBACK) edgeGrid[0][i][j][0] = surface.addVertex(vtxGrid[0][i][j].findSurface( vtxGrid[0][i][j + 1], threshold)); if (edgeFlags[i][j] & BOTBACK) edgeGrid[0][i][j][2] = surface.addVertex(vtxGrid[0][i][j].findSurface( vtxGrid[0][i + 1][j], threshold)); } if (edgeFlags[i][resy - 1] & TOPBACK) edgeGrid[0][i][resy][2] = surface.addVertex(vtxGrid[0][i][resy].findSurface( vtxGrid[0][i + 1][resy], threshold)); } for (int i = 0; i < resy; ++i) { if (edgeFlags[resx - 1][i] & RIGHTBACK) edgeGrid[0][resx][i][0] = surface.addVertex(vtxGrid[0][resx][i].findSurface( vtxGrid[0][resx][i + 1], threshold)); } /* * Step forward (in the +z direction) through the grid. We first * consider the bottom-left, front-left, and bottom-front edges from * each cube. The top edges from the top row of cubes are then * examined, followed by those on the right edge of the grid. */ for (int layer = 1; layer <= resz; ++layer) { // cerr << "filling in layer " << layer << endl; if (layer > 1) { initVertices(layer, vtxGrid[1], function); setCubeFlags(); } for (int i = 0; i < resx; ++i) { for (int j = 0; j < resy; ++j) { if (edgeFlags[i][j] & BOTLEFT) edgeGrid[0][i][j][1] = surface.addVertex(vtxGrid[0][i][j].findSurface( vtxGrid[1][i][j], threshold)); if (edgeFlags[i][j] & LEFTFRONT) edgeGrid[1][i][j][0] = surface.addVertex(vtxGrid[1][i][j].findSurface( vtxGrid[1][i][j + 1], threshold)); if (edgeFlags[i][j] & BOTFRONT) edgeGrid[1][i][j][2] = surface.addVertex(vtxGrid[1][i][j].findSurface( vtxGrid[1][i + 1][j], threshold)); } if (edgeFlags[i][resy - 1] & TOPLEFT) edgeGrid[0][i][resy][1] = surface.addVertex(vtxGrid[0][i][resy].findSurface( vtxGrid[1][i][resy], threshold)); if (edgeFlags[i][resy - 1] & TOPFRONT) edgeGrid[1][i][resy][2] = surface.addVertex(vtxGrid[1][i][resy].findSurface( vtxGrid[1][i + 1][resy], threshold)); } for (int i = 0; i < resy; ++i) { if (edgeFlags[resx - 1][i] & RIGHTFRONT) edgeGrid[1][resx][i][0] = surface.addVertex(vtxGrid[1][resx][i].findSurface( vtxGrid[1][resx][i + 1], threshold)); if (edgeFlags[resx - 1][i] & BOTRIGHT) edgeGrid[0][resx][i][1] = surface.addVertex(vtxGrid[0][resx][i].findSurface( vtxGrid[1][resx][i], threshold)); } if (edgeFlags[resx - 1][resy - 1] & TOPRIGHT) edgeGrid[0][resx][resy][1] = surface.addVertex(vtxGrid[0][resx][resy].findSurface( vtxGrid[1][resx][resy], threshold)); /* * Now that we've found all the vertices on the edges of the cubes * in the layer, extract the set of triangles defined. */ int* indices; int e0, e1, e2; int v0, v1, v2; static int badV = 0; for (int i = 0; i < resx; ++i) { for (int j = 0; j < resy; ++j) { indices = triTable[vtxFlags[i][j]]; while(*indices != -1) { e0 = *indices++; e1 = *indices++; e2 = *indices++; v0 = getVertex(i, j, e0); v1 = getVertex(i, j, e1); v2 = getVertex(i, j, e2); surface.addFace(v0, v1, v2); } } } /* * Move the vertex/edge-index grids one step forward */ CubeVtx** vTemp = vtxGrid[0]; vtxGrid[0] = vtxGrid[1]; vtxGrid[1] = vTemp; int*** eTemp = edgeGrid[0]; edgeGrid[0] = edgeGrid[1]; edgeGrid[1] = eTemp; } surface.calcVNorms(); }