1
#ifndef JULES_BLOOMENTHAL_H
2
#define JULES_BLOOMENTHAL_H
4
// A C++ Implicit Surface Polygonizer
5
// Copyright 2002-2004, Romain Behar <romainbehar@yahoo.com>
7
// This program is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU General Public
9
// License as published by the Free Software Foundation; either
10
// version 2 of the License, or (at your option) any later version.
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
// General Public License for more details.
17
// You should have received a copy of the GNU General Public
18
// License along with this program; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
\brief Declares bloomenthal_polygonizer, an implicit surface polygonizer
23
\author Romain Behar (romainbehar@yahoo.com)
26
#include "isurface_polygonizer.h"
28
#include <k3dsdk/vectors.h>
33
// It is based on Jules Bloomenthal's work :
35
// C code from the article
36
// "An Implicit Surface Polygonizer"
37
// by Jules Bloomenthal, jbloom@beauty.gmu.edu
38
// in "Graphics Gems IV", Academic Press, 1994
41
// an implicit surface polygonizer, translated from Mesa
42
// applications should call polygonize()
44
// Authored by Jules Bloomenthal, Xerox PARC.
45
// Copyright (c) Xerox Corporation, 1991. All rights reserved.
46
// Permission is granted to reproduce, use and distribute this code for
47
// any and all purposes, provided that this notice appears in all copies.
49
typedef k3d::vector3 vertex_t;
50
typedef std::vector<vertex_t> vertices_t;
51
typedef std::vector<unsigned long> polygon_t;
52
typedef std::vector<polygon_t> polygons_t;
54
typedef unsigned long enum_t;
56
// Lattice position (centered on (0, 0, 0), signed values)
60
Location(const int I = 0, const int J = 0, const int K = 0) :
67
inline friend bool operator == (const Location& a, const Location& b)
69
return (a.i == b.i) && (a.j == b.j) && (a.k == b.k);
71
inline friend Location operator + (const Location& a, const Location& b)
73
return Location(a.i + b.i, a.j + b.j, a.k + b.k);
75
inline friend bool operator <= (const Location& a, const Location& b)
77
return (a.i <= b.i && a.j <= b.j && a.k <= b.k);
79
inline friend bool operator < (const Location& a, const Location& b)
81
return (a.i < b.i && a.j < b.j && a.k < b.k);
84
friend std::ostream& operator << (std::ostream& Stream, const Location& RHS)
86
Stream << RHS.i << " " << RHS.j << " " << RHS.k;
90
Location Left() { return Location(i-1, j, k); }
91
Location Right() { return Location(i+1, j, k); }
92
Location Bottom() { return Location(i, j-1, k); }
93
Location Top() { return Location(i, j+1, k); }
94
Location Near() { return Location(i, j, k-1); }
95
Location Far() { return Location(i, j, k+1); }
106
inline int HashFunc(const Location& Value)
108
static const int HashBit = 5;
109
static const int Mask = (1 << HashBit) - 1;
110
return ((Value.i & Mask) << (HashBit*2)) | ((Value.j & Mask) << HashBit) | (Value.k & Mask);
115
template<typename type_t>
119
typedef std::vector< std::pair<Location, type_t> > table_t;
124
void insert(const Location& loc, const type_t item)
126
int key = loc.i + loc.j + loc.k;
127
m_table[key].push_back(std::pair<Location, type_t>(loc, item));
130
bool get(const Location& loc, type_t& out)
132
int key = loc.i + loc.j + loc.k;
133
table_t& table(m_table[key]);
134
for(typename table_t::const_iterator t = table.begin(); t != table.end(); t++)
145
std::map<unsigned long, std::vector< std::pair<Location, type_t> > > m_table;
148
// bloomenthal_polygonizer implementation
149
class bloomenthal_polygonizer
158
bloomenthal_polygonizer(
159
const polygonization_t polygonization_type,
160
const double voxel_size,
161
const double threshold,
162
const int xmin, const int xmax,
163
const int ymin, const int ymax,
164
const int zmin, const int zmax,
165
const vertex_t& origin,
166
implicit_functor& functor,
167
vertices_t& surface_vertices,
168
vertices_t& surface_normals,
169
polygons_t& surface_polygons);
171
~bloomenthal_polygonizer();
173
bool polygonize_from_inside_point(const vertex_t& startingpoint);
175
void polygonize_whole_grid();
177
void cross_limits() { m_keep_within_limits = false; }
187
Corner(const Location& L) :
192
inline friend bool operator == (const Corner& c1, const Corner& c2)
194
return (c1.l == c2.l) && (c1.p == c2.p) && (c1.value == c2.value);
205
Cube(const Location& L) :
208
for(int i = 0; i < 8; i++)
216
Edge(const Location& L1, const Location& L2, const int VID = -1) :
219
if(L1.i > L2.i || (L1.i == L2.i && (L1.j > L2.j || (L1.j == L2.j && L1.k > L2.k))))
231
inline friend bool operator == (const Edge& e1, const Edge& e2)
233
return (e1.l1 == e2.l1) && (e1.l2 == e2.l2) && (e1.vid == e2.vid);
244
static const int HashBit = 5;
245
static const int Mask = (1 << HashBit) - 1;
246
static const int HashSize = 1 << (3 * HashBit);
248
inline int HashFunc(const Location& l)
250
return ((((l.i & Mask) << HashBit) | (l.j & Mask)) << HashBit) | (l.k & Mask);
256
edges.resize(HashSize*2);
259
void push_back(const Edge& Value)
261
int index = HashFunc(Value.l1) + HashFunc(Value.l2);
262
edges[index].push_back(Value);
265
int GetValue(const Edge& Value)
267
int index = HashFunc(Value.l1) + HashFunc(Value.l2);
268
for(unsigned int n = 0; n < edges[index].size(); n++)
270
if(edges[index][n].l1 == Value.l1 && edges[index][n].l2 == Value.l2)
271
return edges[index][n].vid;
278
std::vector< std::vector<Edge> > edges;
282
/// Polygonizer parameters
284
// Polygonization type
285
polygonization_t m_Decomposition;
286
// Width of the partitioning cube
288
// Threshold value (defining the equipotential surface)
290
// Grid limit corners (left-bottom-near and right-top-far)
291
Location m_MinCorner;
292
Location m_MaxCorner;
293
bool m_keep_within_limits;
294
// Grid center ( Location(0, 0, 0) )
295
vertex_t m_GridOrigin;
297
implicit_functor& m_FieldFunctor;
299
vertices_t& m_Vertices;
300
vertices_t& m_normals;
301
polygons_t& m_Polygons;
306
std::stack<Cube> m_active_cubes;
309
LocationMap<bool> m_centers;
310
// Return true if already set, otherwise set and return false
311
bool mark_center(const Location& l)
314
if(m_centers.get(l, out))
317
m_centers.insert(l, true);
322
LocationMap<Corner*> m_Corners;
323
// Return corner if found, else return 0
324
Corner* get_corner(const Location& l)
327
if(m_Corners.get(l, out))
333
Corner* get_cached_corner(const Location& l);
338
// Build fast Marching Cube tables
339
typedef unsigned long table_item_t;
340
std::vector< std::vector< std::vector<table_item_t> > > m_CubeTable;
343
// Convert between vertex and Location
344
vertex_t location_vertex(const Location& l);
345
Location nearest_location(const vertex_t& p);
347
void PolygonizeSurface(const Location& startinglocation);
350
inline int bit_value(int number, int bit_number) { return (number >> bit_number) & 1; }
351
inline int invert_bit(int i, int bit) { return i ^ (1 << bit); }
353
vertex_t normal(const vertex_t& Point);
355
bool SurfaceLocation(Location& startinglocation);
357
// Tetrahedral Polygonization
358
void TriangulateTet(const Cube& cube1, int c1, int c2, int c3, int c4);
360
// Cubical Polygonization
361
void MakeCubeTable();
362
void MarchingCube(const Cube& cube1);
364
void TestFace(const Location& facelocation, Cube& old, int face, int c1, int c2, int c3, int c4);
366
int VerticeId(Corner *c1, Corner *c2);
367
void Converge(const vertex_t& p1, const vertex_t& p2, double v, vertex_t& p);
369
void SaveTriangle(unsigned long u, unsigned long v, unsigned long w);
372
#endif // JULES_BLOOMENTHAL_H