| [0b990d] | 1 | //
 | 
|---|
 | 2 | // isosurf.cc
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
 | 7 | // Maintainer: LPS
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // This file is part of the SC Toolkit.
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
 | 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | // any later version.
 | 
|---|
 | 15 | //
 | 
|---|
 | 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
 | 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 19 | // GNU Library General Public License for more details.
 | 
|---|
 | 20 | //
 | 
|---|
 | 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
 | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
 | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | //
 | 
|---|
 | 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
 | 26 | //
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #ifdef __GNUC__
 | 
|---|
 | 29 | #pragma implementation
 | 
|---|
 | 30 | #endif
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | #include <iostream>
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | #include <math/isosurf/isosurf.h>
 | 
|---|
 | 35 | #include <math/isosurf/implicit.h>
 | 
|---|
 | 36 | #include <math/scmat/vector3.h>
 | 
|---|
 | 37 | 
 | 
|---|
 | 38 | using namespace std;
 | 
|---|
 | 39 | using namespace sc;
 | 
|---|
 | 40 | 
 | 
|---|
 | 41 | // This static datum is used to interface to the implicit.c routine
 | 
|---|
 | 42 | // provided in Graphics Gems IV.
 | 
|---|
 | 43 | ImplicitSurfacePolygonizer* ImplicitSurfacePolygonizer::current = 0;
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | // These functions are used to interface to the implicit.c routine provided
 | 
|---|
 | 46 | // in Graphics Gems IV.
 | 
|---|
 | 47 | extern "C" int
 | 
|---|
 | 48 | ImplicitSurfacePolygonizer_add_triangle_to_current(int i1, int i2, int i3,
 | 
|---|
 | 49 |                                                    VERTICES v)
 | 
|---|
 | 50 | {
 | 
|---|
 | 51 |   return ImplicitSurfacePolygonizer::add_triangle_to_current(i1, i2, i3, v);
 | 
|---|
 | 52 | }
 | 
|---|
 | 53 | 
 | 
|---|
 | 54 | extern "C" double
 | 
|---|
 | 55 | ImplicitSurfacePolygonizer_value_of_current(double x,double y,double z)
 | 
|---|
 | 56 | {
 | 
|---|
 | 57 |   return ImplicitSurfacePolygonizer::value_of_current(x,y,z);
 | 
|---|
 | 58 | }
 | 
|---|
 | 59 | 
 | 
|---|
 | 60 | ////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 61 | // IsosurfaceGen members
 | 
|---|
 | 62 | 
 | 
|---|
 | 63 | IsosurfaceGen::IsosurfaceGen():
 | 
|---|
 | 64 |   _resolution(0.25)
 | 
|---|
 | 65 | {
 | 
|---|
 | 66 | }
 | 
|---|
 | 67 | 
 | 
|---|
 | 68 | IsosurfaceGen::~IsosurfaceGen()
 | 
|---|
 | 69 | {
 | 
|---|
 | 70 | }
 | 
|---|
 | 71 | 
 | 
|---|
 | 72 | void
 | 
|---|
 | 73 | IsosurfaceGen::set_resolution(double r)
 | 
|---|
 | 74 | {
 | 
|---|
 | 75 |   _resolution = r;
 | 
|---|
 | 76 | }
 | 
|---|
 | 77 | 
 | 
|---|
 | 78 | ////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 79 | // ImplicitSurfacePolygonizer members
 | 
|---|
 | 80 | 
 | 
|---|
 | 81 | ImplicitSurfacePolygonizer::ImplicitSurfacePolygonizer(const Ref<Volume>&vol):
 | 
|---|
 | 82 |   _volume(vol)
 | 
|---|
 | 83 |   ,_tmp_vertices(0)
 | 
|---|
 | 84 | {
 | 
|---|
 | 85 | }
 | 
|---|
 | 86 | 
 | 
|---|
 | 87 | ImplicitSurfacePolygonizer::~ImplicitSurfacePolygonizer()
 | 
|---|
 | 88 | {
 | 
|---|
 | 89 | }
 | 
|---|
 | 90 | 
 | 
|---|
 | 91 | static SCVector3 current_x;
 | 
|---|
 | 92 | void
 | 
|---|
 | 93 | ImplicitSurfacePolygonizer::isosurface(double value,
 | 
|---|
 | 94 |                                        TriangulatedSurface& surf)
 | 
|---|
 | 95 | {
 | 
|---|
 | 96 |   surf.clear();
 | 
|---|
 | 97 | 
 | 
|---|
 | 98 |   // Find the bounding box.
 | 
|---|
 | 99 |   SCVector3 p0;
 | 
|---|
 | 100 |   SCVector3 p1;
 | 
|---|
 | 101 |   _volume->boundingbox(value - 0.001, value + 0.001, p0, p1);
 | 
|---|
 | 102 |   SCVector3 diag = p1 - p0;
 | 
|---|
 | 103 |   SCVector3 midpoint = 0.5*diag + p0;
 | 
|---|
 | 104 |   double biggest_width = diag.maxabs();
 | 
|---|
 | 105 |   int bounds = (int)(0.5*biggest_width/_resolution) + 2;
 | 
|---|
 | 106 | 
 | 
|---|
 | 107 |   // polygonize will find a starting point and do bounds checking
 | 
|---|
 | 108 |   // from that point.  To make sure the bounding box is big enough
 | 
|---|
 | 109 |   // its size must be doubled.  Since polygonization is implicit
 | 
|---|
 | 110 |   // there is no performance penalty.
 | 
|---|
 | 111 |   bounds *= 2;
 | 
|---|
 | 112 | 
 | 
|---|
 | 113 |   // Initialize the static pointer to this, so the C polygonizer can find us.
 | 
|---|
 | 114 |   current = this;
 | 
|---|
 | 115 |   _surf = &surf;
 | 
|---|
 | 116 |   _value = value;
 | 
|---|
 | 117 |   // Find the polygons.
 | 
|---|
 | 118 |   char *msg = polygonize(ImplicitSurfacePolygonizer_value_of_current, _resolution, bounds,
 | 
|---|
 | 119 |                          midpoint[0], midpoint[1], midpoint[2],
 | 
|---|
 | 120 |                          ImplicitSurfacePolygonizer_add_triangle_to_current,
 | 
|---|
 | 121 |                          NOTET);
 | 
|---|
 | 122 |   current = 0;
 | 
|---|
 | 123 |   _surf = 0;
 | 
|---|
 | 124 |   if (msg) {
 | 
|---|
 | 125 |       ExEnv::errn() << "ImplicitSurfacePolygonizer::isosurface: failed: "
 | 
|---|
 | 126 |            << msg << endl;
 | 
|---|
 | 127 |       abort();
 | 
|---|
 | 128 |     }
 | 
|---|
 | 129 | 
 | 
|---|
 | 130 |   // Clean up temporaries.
 | 
|---|
 | 131 |   _tmp_vertices.clear();
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 |   ExEnv::out0() << "about to complete the surface" << endl;
 | 
|---|
 | 134 | 
 | 
|---|
 | 135 |   // finish the surface
 | 
|---|
 | 136 |   surf.complete_surface();
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 |   ExEnv::out0() << "completed the surface" << endl;
 | 
|---|
 | 139 |   ExEnv::out0() << "flat area = " << surf.flat_area() << endl;
 | 
|---|
 | 140 |   ExEnv::out0() << "  ntri = " << setw(10) << surf.ntriangle()
 | 
|---|
 | 141 |        << " bytes = "
 | 
|---|
 | 142 |        << setw(10) << surf.ntriangle() * sizeof(Triangle)
 | 
|---|
 | 143 |        << endl;
 | 
|---|
 | 144 |   ExEnv::out0() << "  nedg = " << setw(10) << surf.nedge()
 | 
|---|
 | 145 |        << " bytes = "
 | 
|---|
 | 146 |        << setw(10) << surf.nedge() * sizeof(Edge)
 | 
|---|
 | 147 |        << endl;
 | 
|---|
 | 148 |   ExEnv::out0() << "  nver = " << setw(10) << surf.nvertex()
 | 
|---|
 | 149 |        << " bytes = "
 | 
|---|
 | 150 |        << setw(10) << surf.nvertex() * sizeof(Vertex)
 | 
|---|
 | 151 |        << endl;
 | 
|---|
 | 152 | 
 | 
|---|
 | 153 |   // compute normals if they weren't computed from the gradients
 | 
|---|
 | 154 |   if (!_volume->gradient_implemented()) {
 | 
|---|
 | 155 |       int i,j;
 | 
|---|
 | 156 |       // compute the normals as the average of the normals of
 | 
|---|
 | 157 |       // all the connected triangles
 | 
|---|
 | 158 |       for (i=0; i<surf.ntriangle(); i++) {
 | 
|---|
 | 159 |           Ref<Triangle> t = surf.triangle(i);
 | 
|---|
 | 160 |           SCVector3 tmp;
 | 
|---|
 | 161 |           SCVector3 BA = t->vertex(1)->point() - t->vertex(0)->point();
 | 
|---|
 | 162 |           SCVector3 CA = t->vertex(2)->point() - t->vertex(0)->point();
 | 
|---|
 | 163 |           SCVector3 N = BA.cross(CA);
 | 
|---|
 | 164 |           double n = N.norm();
 | 
|---|
 | 165 |           if (n < 1.0e-8) {
 | 
|---|
 | 166 |               tmp = 0.0;
 | 
|---|
 | 167 |             }
 | 
|---|
 | 168 |           else {
 | 
|---|
 | 169 |               n = 1.0/n;
 | 
|---|
 | 170 |               for (int j=0; j<3; j++) {
 | 
|---|
 | 171 |                   tmp[j] = - N[j]*n;
 | 
|---|
 | 172 |                 }
 | 
|---|
 | 173 |             }
 | 
|---|
 | 174 |           for (j=0; j<3; j++) {
 | 
|---|
 | 175 |               int iv = surf.vertex_index(t->vertex(j));
 | 
|---|
 | 176 |               if (iv>=0) {
 | 
|---|
 | 177 |                   Ref<Vertex> v = surf.vertex(iv);
 | 
|---|
 | 178 |                   if (v->has_normal()) {
 | 
|---|
 | 179 |                       tmp += v->normal();
 | 
|---|
 | 180 |                     }
 | 
|---|
 | 181 |                   tmp.normalize();
 | 
|---|
 | 182 |                   v->set_normal(tmp);
 | 
|---|
 | 183 |                 }
 | 
|---|
 | 184 |             }
 | 
|---|
 | 185 |         }
 | 
|---|
 | 186 |       // normalize all the normals
 | 
|---|
 | 187 |       for (i=0; i<surf.nvertex(); i++) {
 | 
|---|
 | 188 |           Ref<Vertex> v = surf.vertex(i);
 | 
|---|
 | 189 |           if (v->has_normal()) {
 | 
|---|
 | 190 |               SCVector3 n = v->normal();
 | 
|---|
 | 191 |               n.normalize();
 | 
|---|
 | 192 |               v->set_normal(n);
 | 
|---|
 | 193 |             }
 | 
|---|
 | 194 |           else {
 | 
|---|
 | 195 |               ExEnv::outn() << "ERROR: isosurf has a vertex without a triangle" << endl;
 | 
|---|
 | 196 |               abort();
 | 
|---|
 | 197 |             }
 | 
|---|
 | 198 |         }
 | 
|---|
 | 199 |     }
 | 
|---|
 | 200 | }
 | 
|---|
 | 201 | 
 | 
|---|
 | 202 | double
 | 
|---|
 | 203 | ImplicitSurfacePolygonizer::value_of_current(double x,double y,double z)
 | 
|---|
 | 204 | {
 | 
|---|
 | 205 |   current_x[0] = x; current_x[1] = y; current_x[2] = z;
 | 
|---|
 | 206 |   current->_volume->set_x(current_x);
 | 
|---|
 | 207 |   return current->_volume->value() - current->_value;
 | 
|---|
 | 208 | }
 | 
|---|
 | 209 | 
 | 
|---|
 | 210 | int
 | 
|---|
 | 211 | ImplicitSurfacePolygonizer::add_triangle_to_current(int i1, int i2, int i3,
 | 
|---|
 | 212 |                                                     VERTICES v)
 | 
|---|
 | 213 | {
 | 
|---|
 | 214 |   int oldlength = current->_tmp_vertices.size();
 | 
|---|
 | 215 |   current->_tmp_vertices.resize(v.count);
 | 
|---|
 | 216 |   for (int i=oldlength; i<v.count; i++) {
 | 
|---|
 | 217 |       SCVector3 newpoint;
 | 
|---|
 | 218 |       newpoint[0] = v.ptr[i].position.x;
 | 
|---|
 | 219 |       newpoint[1] = v.ptr[i].position.y;
 | 
|---|
 | 220 |       newpoint[2] = v.ptr[i].position.z;
 | 
|---|
 | 221 |       current->_volume->set_x(newpoint);
 | 
|---|
 | 222 |       SCVector3 normal;
 | 
|---|
 | 223 |       if (current->_volume->gradient_implemented()) {
 | 
|---|
 | 224 |           current->_volume->get_gradient(normal);
 | 
|---|
 | 225 |           normal.normalize();
 | 
|---|
 | 226 |           current->_tmp_vertices[i] = new Vertex(newpoint, normal);
 | 
|---|
 | 227 |         }
 | 
|---|
 | 228 |       else {
 | 
|---|
 | 229 |           current->_tmp_vertices[i] = new Vertex(newpoint);
 | 
|---|
 | 230 |         }
 | 
|---|
 | 231 |     }
 | 
|---|
 | 232 | 
 | 
|---|
 | 233 |   Ref<Vertex> v1 = current->_tmp_vertices[i1];
 | 
|---|
 | 234 |   Ref<Vertex> v2 = current->_tmp_vertices[i2];
 | 
|---|
 | 235 |   Ref<Vertex> v3 = current->_tmp_vertices[i3];
 | 
|---|
 | 236 |   
 | 
|---|
 | 237 |   static int tricnt = 0;
 | 
|---|
 | 238 |   if (++tricnt%100 == 0) {
 | 
|---|
 | 239 |       ExEnv::out0() << "adding triangle " << tricnt << endl;
 | 
|---|
 | 240 |       ExEnv::out0() << "  ntri = " << setw(10) << current->_surf->ntriangle()
 | 
|---|
 | 241 |            << " bytes = "
 | 
|---|
 | 242 |            << setw(10) << current->_surf->ntriangle() * sizeof(Triangle)
 | 
|---|
 | 243 |            << endl;
 | 
|---|
 | 244 |     }
 | 
|---|
 | 245 |   current->_surf->add_triangle(v1,v2,v3);
 | 
|---|
 | 246 | 
 | 
|---|
 | 247 |   return 1;
 | 
|---|
 | 248 | }
 | 
|---|
 | 249 | 
 | 
|---|
 | 250 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 251 | 
 | 
|---|
 | 252 | // Local Variables:
 | 
|---|
 | 253 | // mode: c++
 | 
|---|
 | 254 | // c-file-style: "CLJ"
 | 
|---|
 | 255 | // End:
 | 
|---|