-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1064ffe
Showing
14 changed files
with
1,042 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DS_Store | ||
VolumeRenderer.xcodeproj/project.xcworkspace | ||
VolumeRenderer.xcodeproj/xcuserdata |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// | ||
// Array3D.h | ||
// MarchingCubes | ||
// | ||
// Created by Calvin Loncaric on 6/26/11. | ||
// | ||
|
||
#ifndef ARRAY3D_H | ||
#define ARRAY3D_H | ||
|
||
#include <cstdlib> | ||
|
||
template <class T> | ||
class Array3D | ||
{ | ||
|
||
private: | ||
size_t _xmult, _ymult; | ||
T* _data; | ||
|
||
public: | ||
Array3D(size_t width, size_t height, size_t depth); | ||
~Array3D(); | ||
inline void set(size_t x, size_t y, size_t z, const T& value); | ||
inline const T& get(size_t x, size_t y, size_t z); | ||
|
||
}; | ||
|
||
// ======================================================================== | ||
|
||
template <class T> | ||
Array3D<T>::Array3D(size_t width, size_t height, size_t depth) | ||
:_xmult(width * height), _ymult(height), _data(new T[width*height*depth]) | ||
{ | ||
} | ||
|
||
template <class T> | ||
Array3D<T>::~Array3D() | ||
{ | ||
delete[] _data; | ||
} | ||
|
||
template <class T> | ||
void Array3D<T>::set(size_t x, size_t y, size_t z, const T& value) | ||
{ | ||
_data[x * _xmult + y * _ymult + z] = value; | ||
} | ||
|
||
template <class T> | ||
const T& Array3D<T>::get(size_t x, size_t y, size_t z) | ||
{ | ||
return _data[x * _xmult + y * _ymult + z]; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
// | ||
// Decimator.cpp | ||
// MarchingCubes | ||
// | ||
// Created by Calvin Loncaric on 6/26/11. | ||
// | ||
|
||
#include <cassert> | ||
#include <iostream> | ||
#include <cmath> | ||
#include "common.h" | ||
#include GLUT_INCLUDE | ||
#include "Decimate.h" | ||
#include "Array3D.h" | ||
|
||
static inline void drawVert(const Isosurface& surface, const point& p1, const point& p2, float isolevel) | ||
{ | ||
|
||
float v1 = p1.value; | ||
float v2 = p2.value; | ||
|
||
float x, y, z; | ||
|
||
if (v2 == v1) { | ||
x = (p1.x + p2.x) / 2.0f; | ||
y = (p1.y + p2.y) / 2.0f; | ||
z = (p1.z + p2.z) / 2.0f; | ||
} else { | ||
|
||
/* | ||
<----+-----+---+-----> | ||
v1 | v2 | ||
isolevel | ||
<----+-----+---+-----> | ||
0 | 1 | ||
interp | ||
*/ | ||
|
||
|
||
// interp == 0: vert should be at p1 | ||
// interp == 1: vert should be at p2 | ||
float interp = (isolevel - v1) / (v2 - v1); | ||
float oneMinusInterp = 1 - interp; | ||
|
||
x = p1.x * oneMinusInterp + p2.x * interp; | ||
y = p1.y * oneMinusInterp + p2.y * interp; | ||
z = p1.z * oneMinusInterp + p2.z * interp; | ||
} | ||
|
||
vector normal = surface.gradientAt(x, y, z); | ||
|
||
glNormal3f(normal.x, normal.y, normal.z); | ||
glVertex3f(x, y, z); | ||
} | ||
|
||
static void drawTetrahedron(const Isosurface& surface, const point p[4], float isolevel) | ||
{ | ||
|
||
/* | ||
Tetrahedron layout: | ||
0 | ||
* | ||
/|\ | ||
/ | \ | ||
3 *-----* 1 | ||
\ | / | ||
\|/ | ||
* | ||
2 | ||
*/ | ||
|
||
unsigned char index = 0; | ||
for (int i = 0; i < 4; ++i) | ||
if (p[i].value < isolevel) | ||
index |= (1 << i); | ||
|
||
switch (index) { | ||
|
||
// we don't do anything if everyone is inside or outside | ||
case 0x00: | ||
case 0x0F: | ||
break; | ||
|
||
// only vert 0 is inside | ||
case 0x01: | ||
drawVert(surface, p[0], p[1], isolevel); | ||
drawVert(surface, p[0], p[3], isolevel); | ||
drawVert(surface, p[0], p[2], isolevel); | ||
break; | ||
|
||
// only vert 1 is inside | ||
case 0x02: | ||
drawVert(surface, p[1], p[0], isolevel); | ||
drawVert(surface, p[1], p[2], isolevel); | ||
drawVert(surface, p[1], p[3], isolevel); | ||
break; | ||
|
||
// only vert 2 is inside | ||
case 0x04: | ||
drawVert(surface, p[2], p[0], isolevel); | ||
drawVert(surface, p[2], p[3], isolevel); | ||
drawVert(surface, p[2], p[1], isolevel); | ||
break; | ||
|
||
// only vert 3 is inside | ||
case 0x08: | ||
drawVert(surface, p[3], p[1], isolevel); | ||
drawVert(surface, p[3], p[2], isolevel); | ||
drawVert(surface, p[3], p[0], isolevel); | ||
break; | ||
|
||
// verts 0, 1 are inside | ||
case 0x03: | ||
drawVert(surface, p[3], p[0], isolevel); | ||
drawVert(surface, p[2], p[0], isolevel); | ||
drawVert(surface, p[1], p[3], isolevel); | ||
|
||
drawVert(surface, p[2], p[0], isolevel); | ||
drawVert(surface, p[2], p[1], isolevel); | ||
drawVert(surface, p[1], p[3], isolevel); | ||
break; | ||
|
||
// verts 0, 2 are inside | ||
case 0x05: | ||
drawVert(surface, p[3], p[0], isolevel); | ||
drawVert(surface, p[1], p[2], isolevel); | ||
drawVert(surface, p[1], p[0], isolevel); | ||
|
||
drawVert(surface, p[1], p[2], isolevel); | ||
drawVert(surface, p[3], p[0], isolevel); | ||
drawVert(surface, p[2], p[3], isolevel); | ||
break; | ||
|
||
// verts 0, 3 are inside | ||
case 0x09: | ||
drawVert(surface, p[0], p[1], isolevel); | ||
drawVert(surface, p[1], p[3], isolevel); | ||
drawVert(surface, p[0], p[2], isolevel); | ||
|
||
drawVert(surface, p[1], p[3], isolevel); | ||
drawVert(surface, p[3], p[2], isolevel); | ||
drawVert(surface, p[0], p[2], isolevel); | ||
break; | ||
|
||
// verts 1, 2 are inside | ||
case 0x06: | ||
drawVert(surface, p[0], p[1], isolevel); | ||
drawVert(surface, p[0], p[2], isolevel); | ||
drawVert(surface, p[1], p[3], isolevel); | ||
|
||
drawVert(surface, p[1], p[3], isolevel); | ||
drawVert(surface, p[0], p[2], isolevel); | ||
drawVert(surface, p[3], p[2], isolevel); | ||
break; | ||
|
||
// verts 2, 3 are inside | ||
case 0x0C: | ||
drawVert(surface, p[1], p[3], isolevel); | ||
drawVert(surface, p[2], p[0], isolevel); | ||
drawVert(surface, p[3], p[0], isolevel); | ||
|
||
drawVert(surface, p[2], p[0], isolevel); | ||
drawVert(surface, p[1], p[3], isolevel); | ||
drawVert(surface, p[2], p[1], isolevel); | ||
break; | ||
|
||
// verts 1, 3 are inside | ||
case 0x0A: | ||
drawVert(surface, p[3], p[0], isolevel); | ||
drawVert(surface, p[1], p[0], isolevel); | ||
drawVert(surface, p[1], p[2], isolevel); | ||
|
||
drawVert(surface, p[1], p[2], isolevel); | ||
drawVert(surface, p[2], p[3], isolevel); | ||
drawVert(surface, p[3], p[0], isolevel); | ||
break; | ||
|
||
// verts 0, 1, 2 are inside | ||
case 0x07: | ||
drawVert(surface, p[3], p[0], isolevel); | ||
drawVert(surface, p[3], p[2], isolevel); | ||
drawVert(surface, p[3], p[1], isolevel); | ||
break; | ||
|
||
// verts 0, 1, 3 are inside | ||
case 0x0B: | ||
drawVert(surface, p[2], p[1], isolevel); | ||
drawVert(surface, p[2], p[3], isolevel); | ||
drawVert(surface, p[2], p[0], isolevel); | ||
break; | ||
|
||
// verts 0, 2, 3 are inside | ||
case 0x0D: | ||
drawVert(surface, p[1], p[0], isolevel); | ||
drawVert(surface, p[1], p[3], isolevel); | ||
drawVert(surface, p[1], p[2], isolevel); | ||
break; | ||
|
||
// verts 1, 2, 3 are inside | ||
case 0x0E: | ||
drawVert(surface, p[0], p[1], isolevel); | ||
drawVert(surface, p[0], p[2], isolevel); | ||
drawVert(surface, p[0], p[3], isolevel); | ||
break; | ||
|
||
// what is this I don't even | ||
default: | ||
assert(false); | ||
} | ||
|
||
} | ||
|
||
void decimate(const Isosurface& surface, | ||
float xMin, float xMax, | ||
float yMin, float yMax, | ||
float zMin, float zMax, | ||
float isolevel, | ||
size_t resolution) // resolution indicates # of cubes | ||
{ | ||
|
||
size_t pointRes = resolution + 1; // indicates the # of points per side | ||
|
||
float xrange = xMax - xMin; | ||
float yrange = yMax - yMin; | ||
float zrange = zMax - zMin; | ||
|
||
Array3D<float> grid(pointRes, pointRes, pointRes); | ||
|
||
for (int i = 0; i <= resolution; ++i) { | ||
float x = (float)i/resolution * xrange + xMin; | ||
for (int j = 0; j <= resolution; ++j) { | ||
float y = (float)j/resolution * yrange + yMin; | ||
for (int k = 0; k <= resolution; ++k) { | ||
float z = (float)k/resolution * zrange + zMin; | ||
float value = surface.valueAt(x, y, z); | ||
grid.set(i, j, k, value); | ||
} | ||
} | ||
} | ||
|
||
|
||
glBegin(GL_TRIANGLES); | ||
for (int i = 0; i < resolution; ++i) { | ||
float x1 = (float)i/resolution * xrange + xMin; | ||
float x2 = (float)(i+1)/resolution * xrange + xMin; | ||
for (int j = 0; j < resolution; ++j) { | ||
float y1 = (float)j/resolution * yrange + yMin; | ||
float y2 = (float)(j+1)/resolution * yrange + yMin; | ||
for (int k = 0; k < resolution; ++k) { | ||
float z1 = (float)k/resolution * zrange + zMin; | ||
float z2 = (float)(k+1)/resolution * zrange + zMin; | ||
|
||
/* | ||
Coordinates: | ||
z | ||
| | ||
|___ y | ||
/ | ||
/ | ||
x | ||
Cube layout: | ||
4-------7 | ||
/| /| | ||
/ | / | | ||
5-------6 | | ||
| 0----|--3 | ||
| / | / | ||
|/ |/ | ||
1-------2 | ||
Tetrahedrons are: | ||
0, 7, 3, 2 | ||
0, 7, 2, 6 | ||
0, 4, 6, 7 | ||
0, 6, 1, 2 | ||
0, 6, 1, 4 | ||
5, 6, 1, 4 | ||
*/ | ||
|
||
const point v[8] = { | ||
{x1, y1, z1, grid.get(i, j, k )}, | ||
{x2, y1, z1, grid.get(i + 1, j, k )}, | ||
{x2, y2, z1, grid.get(i + 1, j + 1, k )}, | ||
{x1, y2, z1, grid.get(i, j + 1, k )}, | ||
{x1, y1, z2, grid.get(i, j, k + 1)}, | ||
{x2, y1, z2, grid.get(i + 1, j, k + 1)}, | ||
{x2, y2, z2, grid.get(i + 1, j + 1, k + 1)}, | ||
{x1, y2, z2, grid.get(i, j + 1, k + 1)} | ||
}; | ||
|
||
const point tetrahedra[6][4] = { | ||
{ v[0], v[7], v[3], v[2] }, | ||
{ v[0], v[7], v[2], v[6] }, | ||
{ v[0], v[4], v[7], v[6] }, | ||
{ v[0], v[1], v[6], v[2] }, | ||
{ v[0], v[4], v[6], v[1] }, | ||
{ v[5], v[1], v[6], v[4] } | ||
}; | ||
|
||
for (int t = 0; t < 6; ++t) | ||
drawTetrahedron(surface, tetrahedra[t], isolevel); | ||
|
||
} | ||
} | ||
} | ||
glEnd(); | ||
|
||
} | ||
|
Oops, something went wrong.