layer0/Tetsurf.cpp (1,229 lines of code) (raw):
/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* Copyright (c) Schrodinger, LLC.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#include"os_python.h"
#include"os_predef.h"
#include"os_std.h"
#include"Isosurf.h"
#include"Tetsurf.h"
#include"MemoryDebug.h"
#include"Err.h"
#include"Crystal.h"
#include"Vector.h"
#include"Feedback.h"
#include"P.h"
#define Trace_OFF
#define O3(field,P1,P2,P3,offs) Ffloat3(field,P1+offs[0],P2+offs[1],P3+offs[2])
#define O3Ptr(field,P1,P2,P3,offs) Ffloat3p(field,P1+offs[0],P2+offs[1],P3+offs[2])
#define O4(field,P1,P2,P3,P4,offs) Ffloat4(field,P1+offs[0],P2+offs[1],P3+offs[2],P4)
#define O4Ptr(field,P1,P2,P3,P4,offs) Ffloat4p(field,P1+offs[0],P2+offs[1],P3+offs[2],P4)
#define I3(field,P1,P2,P3) Fint3(field,P1,P2,P3)
#define I3Ptr(field,P1,P2,P3) Fint3p(field,P1,P2,P3)
#define I4(field,P1,P2,P3,P4) Fint4(field,P1,P2,P3,P4)
#define I4Ptr(field,P1,P2,P3,P4) Fint4p(field,P1,P2,P3,P4)
typedef struct {
float Point[3];
float Normal[3];
int NormalFlag;
int Link;
} PointType;
typedef struct {
PointType *p[3];
float n[3];
int done;
} TriangleType;
typedef struct {
int link;
int tri;
} PointLinkType;
#define EdgePtPtr(field,P2,P3,P4,P5) ((PointType*)Fvoid4p(field,P2,P3,P4,P5))
#define EdgePt(field,P2,P3,P4,P5) (*((PointType*)Fvoid4p(field,P2,P3,P4,P5)))
struct _CTetsurf {
PyMOLGlobals *G;
TriangleType *Tri;
PointLinkType *PtLink;
CField *VertexCodes;
CField *ActiveEdges;
CField *Point;
int AbsDim[3], CurDim[3], CurOff[3];
int Max[3];
CField *Coord, *Data, *Grad;
float Level;
int Edge[6020]; /* 6017 */
int EdgeStart[256];
int TotPrim;
};
static int TetsurfAlloc(CTetsurf * II);
static void TetsurfPurge(CTetsurf * II);
static int TetsurfCodeVertices(CTetsurf * II);
static int TetsurfFindActiveBoxes(CTetsurf * II, int mode, int *n_strip, int n_vert,
int **strip_l, float **vert,
MapType * voxelmap, float *a_vert,
float carvebuffer, int side);
#define TetsurfSubSize 50
static void copy3fn(float *v1, float *v2)
{
v2[0] = v1[0];
v2[1] = v1[1];
v2[2] = v1[2];
}
/*===========================================================================*/
static int ProcessTetrahedron(int *edge, int nv, int v0, int v1, int v2, int v3,
int e01, int e02, int e03, int e12, int e13, int e23,
int reflect)
{
int bits = (v3 << 3) + (v2 << 2) + (v1 << 1) + v0;
if(reflect)
bits = 0xF - bits;
switch (bits) {
case 0x0:
break;
case 0x1:
edge[nv++] = e01;
edge[nv++] = e02;
edge[nv++] = e03;
break;
case 0x2:
edge[nv++] = e01;
edge[nv++] = e13;
edge[nv++] = e12;
break;
case 0x3:
edge[nv++] = e13;
edge[nv++] = e12;
edge[nv++] = e02;
edge[nv++] = e03;
edge[nv++] = e13;
edge[nv++] = e02;
break;
case 0x4:
edge[nv++] = e12;
edge[nv++] = e23;
edge[nv++] = e02;
break;
case 0x5:
edge[nv++] = e01;
edge[nv++] = e12;
edge[nv++] = e03;
edge[nv++] = e12;
edge[nv++] = e23;
edge[nv++] = e03;
break;
case 0x6:
edge[nv++] = e01;
edge[nv++] = e13;
edge[nv++] = e02;
edge[nv++] = e13;
edge[nv++] = e23;
edge[nv++] = e02;
break;
case 0x7:
edge[nv++] = e03;
edge[nv++] = e13;
edge[nv++] = e23;
break;
case 0x8:
edge[nv++] = e03;
edge[nv++] = e23;
edge[nv++] = e13;
break;
case 0x9:
edge[nv++] = e13;
edge[nv++] = e01;
edge[nv++] = e02;
edge[nv++] = e02;
edge[nv++] = e23;
edge[nv++] = e13;
break;
case 0xA:
edge[nv++] = e01;
edge[nv++] = e03;
edge[nv++] = e12;
edge[nv++] = e03;
edge[nv++] = e23;
edge[nv++] = e12;
break;
case 0xB:
edge[nv++] = e23;
edge[nv++] = e12;
edge[nv++] = e02;
break;
case 0xC:
edge[nv++] = e13;
edge[nv++] = e02;
edge[nv++] = e12;
edge[nv++] = e03;
edge[nv++] = e02;
edge[nv++] = e13;
break;
case 0xD:
edge[nv++] = e01;
edge[nv++] = e12;
edge[nv++] = e13;
break;
case 0xE:
edge[nv++] = e01;
edge[nv++] = e03;
edge[nv++] = e02;
break;
case 0xF:
break;
}
return nv;
}
/*===========================================================================*/
static CTetsurf *TetsurfNew(PyMOLGlobals * G)
{
/* there are six tetrahedrons in each cube, and there are
sixteen different types of tetrahedrons */
/* one will encounter 2^8 different kinds of cubes. */
/* bits -> tetrahedral vertices
zyx
0: 000
1: 001
2: 010
3: 011
4: 100
5: 101
6: 110
7: 111
*/
/* edges of the tetrahedron
vertex
3210
0:0011
1:0101
2:0110
3:1001
4:1010
5:1100
*/
/* edges of the cube
76543210
0:00000011 edge 000-001
1:00000101 edge 000-010
2:00001001 edge 000-011
3:00010001 edge 000-100
4:00100001 edge 000-101
5:01000001 edge 000-110
6:10000001 edge 000-111
7:00001010 edge 001-011
8:00100010 edge 001-101
9:10000010 edge 001-111
0xA:00001100 edge 010-011
0xB:01000100 edge 010-110
0xC:10000100 edge 010-111
0xD:00110000 edge 100-101
0xE:01010000 edge 100-110
0xF:10010000 edge 100-111
0x10:10001000 edge 011-111
0x11:10100000 edge 101-111
0x12:11000000 edge 110-111
*/
#define cE_000_001 0x00
#define cE_000_010 0x01
#define cE_000_011 0x02
#define cE_000_100 0x03
#define cE_000_101 0x04
#define cE_000_110 0x05
#define cE_000_111 0x06
#define cE_001_011 0x07
#define cE_001_101 0x08
#define cE_001_111 0x09
#define cE_010_011 0x0A
#define cE_010_110 0x0B
#define cE_010_111 0x0C
#define cE_100_101 0x0D
#define cE_100_110 0x0E
#define cE_100_111 0x0F
#define cE_011_111 0x10
#define cE_101_111 0x11
#define cE_110_111 0x12
#define cM_000_001 0x00001
#define cM_000_010 0x00002
#define cM_000_011 0x00004
#define cM_000_100 0x00008
#define cM_000_101 0x00010
#define cM_000_110 0x00020
#define cM_000_111 0x00040
#define cM_001_011 0x00080
#define cM_001_101 0x00100
#define cM_001_111 0x00200
#define cM_010_011 0x00400
#define cM_010_110 0x00800
#define cM_010_111 0x01000
#define cM_100_101 0x02000
#define cM_100_110 0x04000
#define cM_100_111 0x08000
#define cM_011_111 0x10000
#define cM_101_111 0x20000
#define cM_110_111 0x40000
CTetsurf *I = Calloc(CTetsurf, 1);
int c;
int nv = 1;
int last_nv;
int v000, v100, v010, v110, v001, v101, v011, v111;
I->G = G;
I->Tri = NULL;
I->PtLink = NULL;
I->VertexCodes = NULL;
I->ActiveEdges = NULL;
I->Point = NULL;
last_nv = nv;
for(c = 0; c < 256; c++) {
v000 = (c & 0x01) ? 1 : 0;
v001 = (c & 0x02) ? 1 : 0;
v010 = (c & 0x04) ? 1 : 0;
v011 = (c & 0x08) ? 1 : 0;
v100 = (c & 0x10) ? 1 : 0;
v101 = (c & 0x20) ? 1 : 0;
v110 = (c & 0x40) ? 1 : 0;
v111 = (c & 0x80) ? 1 : 0;
/* tetrahedron 0: 000, 001, 011, 111 */
nv = ProcessTetrahedron(I->Edge, nv, v000, v001, v011, v111,
cE_000_001,
cE_000_011,
cE_000_111, cE_001_011, cE_001_111, cE_011_111, 0);
/* tetrahedron 1: 000, 001, 101, 111 */
nv = ProcessTetrahedron(I->Edge, nv, v000, v001, v101, v111,
cE_000_001,
cE_000_101,
cE_000_111, cE_001_101, cE_001_111, cE_101_111, 1);
/* tetrahedron 2: 000, 010, 011, 111 */
nv = ProcessTetrahedron(I->Edge, nv, v000, v010, v011, v111,
cE_000_010,
cE_000_011,
cE_000_111, cE_010_011, cE_010_111, cE_011_111, 1);
/* tetrahedron 3: 000, 010, 110, 111 */
nv = ProcessTetrahedron(I->Edge, nv, v000, v010, v110, v111,
cE_000_010,
cE_000_110,
cE_000_111, cE_010_110, cE_010_111, cE_110_111, 0);
/* tetrahedron 4: 000, 100, 101, 111 */
nv = ProcessTetrahedron(I->Edge, nv, v000, v100, v101, v111,
cE_000_100,
cE_000_101,
cE_000_111, cE_100_101, cE_100_111, cE_101_111, 0);
/* tetrahedron 5: 000, 100, 110, 111 */
nv = ProcessTetrahedron(I->Edge, nv, v000, v100, v110, v111,
cE_000_100,
cE_000_110,
cE_000_111, cE_100_110, cE_100_111, cE_110_111, 1);
I->Edge[nv++] = (-1); /* sentinel */
I->EdgeStart[c] = last_nv;
last_nv = nv;
}
/* printf("%d\n",nv);
for(c=1;c<nv;c++) {
if(Edge[c]<0) {
printf("\n");
} else {
printf("%02X ",Edge[c]);
}
}
*/
return I;
}
int TetsurfInit(PyMOLGlobals * G)
{
G->Tetsurf = TetsurfNew(G);
return 1;
}
/*===========================================================================*/
static void _TetsurfFree(CTetsurf * I)
{
FreeP(I);
}
void TetsurfFree(PyMOLGlobals * G)
{
_TetsurfFree(G->Tetsurf);
G->Tetsurf = NULL;
}
/*===========================================================================*/
void TetsurfGetRange(PyMOLGlobals * G,
Isofield * field, CCrystal * cryst, float *mn, float *mx, int *range)
{
float rmn[3], rmx[3];
float imn[3], imx[3];
float mix[24], imix[24];
int a, b;
PRINTFD(G, FB_Isosurface)
" IsosurfGetRange: entered mn: %4.2f %4.2f %4.2f mx: %4.2f %4.2f %4.2f\n",
mn[0], mn[1], mn[2], mx[0], mx[1], mx[2]
ENDFD;
for(a = 0; a < 3; a++) {
rmn[a] = F4(field->points, 0, 0, 0, a);
rmx[a] = F4(field->points,
field->dimensions[0] - 1,
field->dimensions[1] - 1, field->dimensions[2] - 1, a);
}
/* get min/max extents of map in fractional space */
transform33f3f(cryst->RealToFrac, rmn, imn);
transform33f3f(cryst->RealToFrac, rmx, imx);
mix[0] = mn[0];
mix[1] = mn[1];
mix[2] = mn[2];
mix[3] = mx[0];
mix[4] = mn[1];
mix[5] = mn[2];
mix[6] = mn[0];
mix[7] = mx[1];
mix[8] = mn[2];
mix[9] = mn[0];
mix[10] = mn[1];
mix[11] = mx[2];
mix[12] = mx[0];
mix[13] = mx[1];
mix[14] = mn[2];
mix[15] = mx[0];
mix[16] = mn[1];
mix[17] = mx[2];
mix[18] = mn[0];
mix[19] = mx[1];
mix[20] = mx[2];
mix[21] = mx[0];
mix[22] = mx[1];
mix[23] = mx[2];
/* compute min/max of query in fractional space */
for(b = 0; b < 8; b++) {
transform33f3f(cryst->RealToFrac, mix + 3 * b, imix + 3 * b);
}
for(a = 0; a < 3; a++) {
if(imx[a] != imn[a]) { /* protect against div by zero */
int b;
int mini = 0, maxi = 0, tst_min, tst_max;
float cur;
for(b = 0; b < 8; b++) {
cur =
((field->dimensions[a] - 1) * (imix[a + 3 * b] - imn[a]) / (imx[a] - imn[a]));
tst_min = (int) floor(cur);
tst_max = ((int) ceil(cur)) + 1;
if(!b) {
mini = tst_min;
maxi = tst_max;
} else {
if(mini > tst_min)
mini = tst_min;
if(maxi <= tst_max)
maxi = tst_max;
}
}
range[a] = mini;
range[a + 3] = maxi;
} else {
range[a] = 0;
range[a + 3] = 1;
}
if(range[a] < 0)
range[a] = 0;
if(range[a] > field->dimensions[a])
range[a] = field->dimensions[a];
if(range[a + 3] < 0)
range[a + 3] = 0;
if(range[a + 3] > field->dimensions[a])
range[a + 3] = field->dimensions[a];
}
PRINTFD(G, FB_Isosurface)
" IsosurfGetRange: returning range: %d %d %d %d %d %d\n",
range[0], range[1], range[2], range[3], range[4], range[5]
ENDFD;
}
/*===========================================================================*/
int TetsurfVolume(PyMOLGlobals * G, Isofield * field, float level, int **num,
float **vert, int *range, int mode, MapType * voxelmap, float *a_vert,
float carvebuffer, int side)
{
CTetsurf *I;
if(PIsGlutThread()) {
I = G->Tetsurf;
} else {
I = TetsurfNew(G);
}
{
int ok = true;
int Steps[3];
int c, i, j, k;
int range_store[6];
int n_strip = 0;
int n_vert = 0;
int tot_prim = 0;
if(mode == 3)
IsofieldComputeGradients(G, field);
I->TotPrim = 0;
if(range) {
for(c = 0; c < 3; c++) {
I->AbsDim[c] = field->dimensions[c];
I->CurDim[c] = TetsurfSubSize + 1;
Steps[c] = 1 + ((range[3 + c] - range[c]) - 1) / TetsurfSubSize;
}
} else {
range = range_store;
for(c = 0; c < 3; c++) {
range[c] = 0;
range[3 + c] = field->dimensions[c];
I->AbsDim[c] = field->dimensions[c];
I->CurDim[c] = TetsurfSubSize + 1;
Steps[c] = 1 + (I->AbsDim[c] - 1) / TetsurfSubSize;
}
}
/* for(c=0;c<3;c++) {
printf("range %d %d %d\n",c,range[c],range[c+3]);
printf("steps %d\n",Steps[c]);
}
*/
I->Coord = field->points;
I->Grad = field->gradients;
I->Data = field->data;
I->Level = level;
if(ok)
ok = TetsurfAlloc(I);
if(ok) {
for(i = 0; i < Steps[0]; i++)
for(j = 0; j < Steps[1]; j++)
for(k = 0; k < Steps[2]; k++) {
I->CurOff[0] = TetsurfSubSize * i;
I->CurOff[1] = TetsurfSubSize * j;
I->CurOff[2] = TetsurfSubSize * k;
for(c = 0; c < 3; c++)
I->CurOff[c] += range[c];
for(c = 0; c < 3; c++) {
I->Max[c] = (range[3 + c] - I->CurOff[c]);
if(I->Max[c] > (TetsurfSubSize + 1))
I->Max[c] = (TetsurfSubSize + 1);
}
/*
for(c=0;c<3;c++)
printf(" TetsurfVolume: c: %i I->CurOff[c]: %i I->Max[c] %i\n",c,I->CurOff[c],I->Max[c]);
*/
if(ok) {
if(TetsurfCodeVertices(I))
n_vert = TetsurfFindActiveBoxes(I, mode, &n_strip, n_vert, num, vert,
voxelmap, a_vert, carvebuffer, side);
}
}
TetsurfPurge(I);
}
if(Feedback(G, FB_Isosurface, FB_Blather)) {
if(mode < 2) {
printf(" TetsurfVolume: Surface generated using %d vertices.\n", n_vert);
} else {
printf(" TetsurfVolume: Surface generated using %d triangles.\n", I->TotPrim);
}
}
/* sentinel strip (0 length) */
VLACheck(*num, int, n_strip);
(*num)[n_strip] = 0;
(n_strip)++;
/* shrinks sizes for more efficient RAM usage */
VLASize(*vert, float, n_vert * 3);
VLASize(*num, int, n_strip);
tot_prim = I->TotPrim;
if(!PIsGlutThread()) {
_TetsurfFree(I);
}
return (tot_prim);
}
}
/*===========================================================================*/
static int TetsurfAlloc(CTetsurf * II)
{
CTetsurf *I = II;
PyMOLGlobals *G = I->G;
int ok = true;
int dim4[4];
int a;
for(a = 0; a < 3; a++)
dim4[a] = I->CurDim[a];
dim4[3] = 3;
I->VertexCodes = FieldNew(G, I->CurDim, 3, sizeof(int), cFieldInt);
ErrChkPtr(G, I->VertexCodes);
I->ActiveEdges = FieldNew(G, I->CurDim, 3, sizeof(int), cFieldInt);
ErrChkPtr(G, I->ActiveEdges);
dim4[3] = 7; /* seven different ways now... */
I->Point = FieldNew(G, dim4, 4, sizeof(PointType), cFieldOther);
ErrChkPtr(G, I->Point);
I->Tri = VLAlloc(TriangleType, 50000);
I->PtLink = VLAlloc(PointLinkType, 50000);
if(!(I->VertexCodes && I->ActiveEdges && I->Point)) {
TetsurfPurge(I);
ok = false;
}
#ifdef Trace
printf(" TetsurfAlloc: ok: %i\n", ok);
#endif
return (ok);
}
/*===========================================================================*/
static void TetsurfPurge(CTetsurf * II)
{
CTetsurf *I = II;
if(I->Tri) {
VLAFreeP(I->Tri);
}
if(I->PtLink) {
VLAFreeP(I->PtLink);
}
if(I->VertexCodes) {
FieldFree(I->VertexCodes);
I->VertexCodes = NULL;
}
if(I->ActiveEdges) {
FieldFree(I->ActiveEdges);
I->ActiveEdges = NULL;
}
if(I->Point) {
FieldFree(I->Point);
I->Point = NULL;
}
}
/*===========================================================================*/
#ifdef _PYMOL_INLINE
__inline__
#endif
static void TetsurfInterpolate2(float *pt, float *v0, float l0, float *v1, float l1,
float level)
{
float ratio;
ratio = (level - l0) / (l1 - l0);
pt[0] = v0[0] + (v1[0] - v0[0]) * ratio;
pt[1] = v0[1] + (v1[1] - v0[1]) * ratio;
pt[2] = v0[2] + (v1[2] - v0[2]) * ratio;
}
/*===========================================================================*/
#ifdef _PYMOL_INLINE
__inline__
#endif
static void TetsurfInterpolate4(float *pt, float *v0, float l0, float *v1, float l1,
float l2, float l3, float level)
{
float ratio;
float v[3], l;
average3f(v0, v1, v);
l = (l0 + l1 + l2 + l3) * 0.25F;
if(((l > level) && (l1 > level)) || ((l <= level) && (l0 > level))) { /* l0 vs l */
ratio = (level - l0) / (l - l0);
pt[0] = v0[0] + (v[0] - v0[0]) * ratio;
pt[1] = v0[1] + (v[1] - v0[1]) * ratio;
pt[2] = v0[2] + (v[2] - v0[2]) * ratio;
} else {
ratio = (level - l1) / (l - l1);
pt[0] = v1[0] + (v[0] - v1[0]) * ratio;
pt[1] = v1[1] + (v[1] - v1[1]) * ratio;
pt[2] = v1[2] + (v[2] - v1[2]) * ratio;
}
}
/*===========================================================================*/
#ifdef _PYMOL_INLINE
__inline__
#endif
static void TetsurfInterpolate8(float *pt, float *v0, float l0, float *v1, float l1,
float l2, float l3, float l4,
float l5, float l6, float l7, float level)
{
float ratio;
float v[3], l;
average3f(v0, v1, v);
l = (l0 + l1 + l2 + l3 + l4 + l5 + l6 + l7) * 0.125F;
if(((l > level) && (l1 > level)) || ((l <= level) && (l0 > level))) { /* l0 vs l */
ratio = (level - l0) / (l - l0);
pt[0] = v0[0] + (v[0] - v0[0]) * ratio;
pt[1] = v0[1] + (v[1] - v0[1]) * ratio;
pt[2] = v0[2] + (v[2] - v0[2]) * ratio;
} else {
ratio = (level - l1) / (l - l1);
pt[0] = v1[0] + (v[0] - v1[0]) * ratio;
pt[1] = v1[1] + (v[1] - v1[1]) * ratio;
pt[2] = v1[2] + (v[2] - v1[2]) * ratio;
}
}
/*===========================================================================*/
static int TetsurfFindActiveBoxes(CTetsurf * II, int mode, int *n_strip, int n_vert,
int **strip_l, float **vert,
MapType * voxelmap, float *a_vert,
float carvebuffer, int side)
{
CTetsurf *I = II;
int a, b, c, i, j, k, h, l;
#ifdef Trace
int ECount = 0;
#endif
int i000, i001, i010, i011, i100, i101, i110, i111;
float *c000, *c001, *c010, *c011, *c100, *c101, *c110, *c111;
float d000, d001, d010, d011, d100, d101, d110, d111;
float *g000 = NULL, *g001 = NULL, *g010 = NULL, *g011 = NULL, *g100 = NULL, *g101 =
NULL, *g110 = NULL, *g111 = NULL;
int active;
int n_active = 0;
int n_start = 0;
PointType *e[19], *p0, *p1, *p2;
int code;
int eidx;
int idx;
TriangleType *tt;
int n_tri = 0;
int n_link = 1;
int avoid_flag = false;
if(carvebuffer < 0.0F) {
avoid_flag = true;
carvebuffer = -carvebuffer;
}
FieldZero(I->Point); /* sets initial links to zero */
FieldZero(I->ActiveEdges);
n_start = n_vert;
for(i = 0; i < (I->Max[0] - 1); i++)
for(j = 0; j < (I->Max[1] - 1); j++)
for(k = 0; k < (I->Max[2] - 1); k++) {
active = 0;
i000 = I3(I->VertexCodes, i, j, k);
i001 = I3(I->VertexCodes, i, j, k + 1);
i010 = I3(I->VertexCodes, i, j + 1, k);
i011 = I3(I->VertexCodes, i, j + 1, k + 1);
i100 = I3(I->VertexCodes, i + 1, j, k);
i101 = I3(I->VertexCodes, i + 1, j, k + 1);
i110 = I3(I->VertexCodes, i + 1, j + 1, k);
i111 = I3(I->VertexCodes, i + 1, j + 1, k + 1);
if((i000 != i001) || (i001 != i010) || (i010 != i011) || (i011 != i100) || (i100 != i101) || (i101 != i110) || (i110 != i111)) { /* this is an active box */
c000 = O4Ptr(I->Coord, i, j, k, 0, I->CurOff);
c001 = O4Ptr(I->Coord, i, j, k + 1, 0, I->CurOff);
c010 = O4Ptr(I->Coord, i, j + 1, k, 0, I->CurOff);
c011 = O4Ptr(I->Coord, i, j + 1, k + 1, 0, I->CurOff);
c100 = O4Ptr(I->Coord, i + 1, j, k, 0, I->CurOff);
c101 = O4Ptr(I->Coord, i + 1, j, k + 1, 0, I->CurOff);
c110 = O4Ptr(I->Coord, i + 1, j + 1, k, 0, I->CurOff);
c111 = O4Ptr(I->Coord, i + 1, j + 1, k + 1, 0, I->CurOff);
if(mode == 3) {
g000 = O4Ptr(I->Grad, i, j, k, 0, I->CurOff);
g001 = O4Ptr(I->Grad, i, j, k + 1, 0, I->CurOff);
g010 = O4Ptr(I->Grad, i, j + 1, k, 0, I->CurOff);
g011 = O4Ptr(I->Grad, i, j + 1, k + 1, 0, I->CurOff);
g100 = O4Ptr(I->Grad, i + 1, j, k, 0, I->CurOff);
g101 = O4Ptr(I->Grad, i + 1, j, k + 1, 0, I->CurOff);
g110 = O4Ptr(I->Grad, i + 1, j + 1, k, 0, I->CurOff);
g111 = O4Ptr(I->Grad, i + 1, j + 1, k + 1, 0, I->CurOff);
}
d000 = O3(I->Data, i, j, k, I->CurOff);
d001 = O3(I->Data, i, j, k + 1, I->CurOff);
d010 = O3(I->Data, i, j + 1, k, I->CurOff);
d011 = O3(I->Data, i, j + 1, k + 1, I->CurOff);
d100 = O3(I->Data, i + 1, j, k, I->CurOff);
d101 = O3(I->Data, i + 1, j, k + 1, I->CurOff);
d110 = O3(I->Data, i + 1, j + 1, k, I->CurOff);
d111 = O3(I->Data, i + 1, j + 1, k + 1, I->CurOff);
e[cE_000_001] = EdgePtPtr(I->Point, i, j, k, cE_000_001);
e[cE_000_010] = EdgePtPtr(I->Point, i, j, k, cE_000_010);
e[cE_000_011] = EdgePtPtr(I->Point, i, j, k, cE_000_011);
e[cE_000_100] = EdgePtPtr(I->Point, i, j, k, cE_000_100);
e[cE_000_101] = EdgePtPtr(I->Point, i, j, k, cE_000_101);
e[cE_000_110] = EdgePtPtr(I->Point, i, j, k, cE_000_110);
e[cE_000_111] = EdgePtPtr(I->Point, i, j, k, cE_000_111);
e[cE_001_011] = EdgePtPtr(I->Point, i, j, k + 1, cE_000_010);
e[cE_001_101] = EdgePtPtr(I->Point, i, j, k + 1, cE_000_100);
e[cE_001_111] = EdgePtPtr(I->Point, i, j, k + 1, cE_000_110);
e[cE_010_011] = EdgePtPtr(I->Point, i, j + 1, k, cE_000_001);
e[cE_010_110] = EdgePtPtr(I->Point, i, j + 1, k, cE_000_100);
e[cE_010_111] = EdgePtPtr(I->Point, i, j + 1, k, cE_000_101);
e[cE_100_101] = EdgePtPtr(I->Point, i + 1, j, k, cE_000_001);
e[cE_100_110] = EdgePtPtr(I->Point, i + 1, j, k, cE_000_010);
e[cE_100_111] = EdgePtPtr(I->Point, i + 1, j, k, cE_000_011);
e[cE_011_111] = EdgePtPtr(I->Point, i, j + 1, k + 1, cE_000_100);
e[cE_101_111] = EdgePtPtr(I->Point, i + 1, j, k + 1, cE_000_010);
e[cE_110_111] = EdgePtPtr(I->Point, i + 1, j + 1, k, cE_000_001);
/* Generate interpolated coordinates for all active edges */
if(i000 != i001) {
if(!(I3(I->ActiveEdges, i, j, k) & cM_000_001)) {
I3(I->ActiveEdges, i, j, k) |= cM_000_001;
TetsurfInterpolate2(e[cE_000_001]->Point, c000, d000, c001, d001, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_000_001]->Normal, g000, d000, g001, d001,
I->Level);
}
active |= cM_000_001;
}
if(i000 != i010) {
if(!(I3(I->ActiveEdges, i, j, k) & cM_000_010)) {
I3(I->ActiveEdges, i, j, k) |= cM_000_010;
TetsurfInterpolate2(e[cE_000_010]->Point, c000, d000, c010, d010, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_000_010]->Normal, g000, d000, g010, d010,
I->Level);
}
active |= cM_000_010;
}
if(i000 != i011) {
if(!(I3(I->ActiveEdges, i, j, k) & cM_000_011)) {
I3(I->ActiveEdges, i, j, k) |= cM_000_011;
TetsurfInterpolate4(e[cE_000_011]->Point, c000, d000, c011, d011, d001,
d010, I->Level);
if(mode == 3)
TetsurfInterpolate4(e[cE_000_011]->Normal, g000, d000, g011, d011, d001,
d010, I->Level);
}
active |= cM_000_011;
}
if(i000 != i100) {
if(!(I3(I->ActiveEdges, i, j, k) & cM_000_100)) {
I3(I->ActiveEdges, i, j, k) |= cM_000_100;
TetsurfInterpolate2(e[cE_000_100]->Point, c000, d000, c100, d100, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_000_100]->Normal, g000, d000, g100, d100,
I->Level);
}
active |= cM_000_100;
}
if(i000 != i101) {
if(!(I3(I->ActiveEdges, i, j, k) & cM_000_101)) {
I3(I->ActiveEdges, i, j, k) |= cM_000_101;
TetsurfInterpolate4(e[cE_000_101]->Point, c000, d000, c101, d101, d100,
d001, I->Level);
if(mode == 3)
TetsurfInterpolate4(e[cE_000_101]->Normal, g000, d000, g101, d101, d100,
d001, I->Level);
}
active |= cM_000_101;
}
if(i000 != i110) {
if(!(I3(I->ActiveEdges, i, j, k) & cM_000_110)) {
I3(I->ActiveEdges, i, j, k) |= cM_000_110;
TetsurfInterpolate4(e[cE_000_110]->Point, c000, d000, c110, d110, d100,
d010, I->Level);
if(mode == 3)
TetsurfInterpolate4(e[cE_000_110]->Normal, g000, d000, g110, d110, d100,
d010, I->Level);
}
active |= cM_000_110;
}
if(i000 != i111) {
if(!(I3(I->ActiveEdges, i, j, k) & cM_000_111)) {
I3(I->ActiveEdges, i, j, k) |= cM_000_111;
TetsurfInterpolate8(e[cE_000_111]->Point,
c000, d000, c111, d111,
d001, d010, d011, d100, d101, d110, I->Level);
if(mode == 3)
TetsurfInterpolate8(e[cE_000_111]->Normal,
g000, d000, g111, d111,
d001, d010, d011, d100, d101, d110, I->Level);
}
active |= cM_000_111;
}
if(i001 != i011) {
if(!(I3(I->ActiveEdges, i, j, k + 1) & cM_000_010)) {
I3(I->ActiveEdges, i, j, k + 1) |= cM_000_010;
TetsurfInterpolate2(e[cE_001_011]->Point, c001, d001, c011, d011, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_001_011]->Normal, g001, d001, g011, d011,
I->Level);
}
active |= cM_001_011;
}
if(i001 != i101) {
if(!(I3(I->ActiveEdges, i, j, k + 1) & cM_000_100)) {
I3(I->ActiveEdges, i, j, k + 1) |= cM_000_100;
TetsurfInterpolate2(e[cE_001_101]->Point, c001, d001, c101, d101, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_001_101]->Normal, g001, d001, g101, d101,
I->Level);
}
active |= cM_001_101;
}
if(i001 != i111) {
if(!(I3(I->ActiveEdges, i, j, k + 1) & cM_000_110)) {
I3(I->ActiveEdges, i, j, k + 1) |= cM_000_110;
TetsurfInterpolate4(e[cE_001_111]->Point, c001, d001, c111, d111, d101,
d011, I->Level);
if(mode == 3)
TetsurfInterpolate4(e[cE_001_111]->Normal, g001, d001, g111, d111, d101,
d011, I->Level);
}
active |= cM_001_111;
}
if(i010 != i011) {
if(!(I3(I->ActiveEdges, i, j + 1, k) & cM_000_001)) {
I3(I->ActiveEdges, i, j + 1, k) |= cM_000_001;
TetsurfInterpolate2(e[cE_010_011]->Point, c010, d010, c011, d011, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_010_011]->Normal, g010, d010, g011, d011,
I->Level);
}
active |= cM_010_011;
}
if(i010 != i110) {
if(!(I3(I->ActiveEdges, i, j + 1, k) & cM_000_100)) {
I3(I->ActiveEdges, i, j + 1, k) |= cM_000_100;
TetsurfInterpolate2(e[cE_010_110]->Point, c010, d010, c110, d110, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_010_110]->Normal, g010, d010, g110, d110,
I->Level);
}
active |= cM_010_110;
}
if(i010 != i111) {
if(!(I3(I->ActiveEdges, i, j + 1, k) & cM_000_101)) {
I3(I->ActiveEdges, i, j + 1, k) |= cM_000_101;
TetsurfInterpolate4(e[cE_010_111]->Point, c010, d010, c111, d111, d110,
d011, I->Level);
if(mode == 3)
TetsurfInterpolate4(e[cE_010_111]->Normal, g010, d010, g111, d111, d110,
d011, I->Level);
}
active |= cM_010_111;
}
if(i100 != i101) {
if(!(I3(I->ActiveEdges, i + 1, j, k) & cM_000_001)) {
I3(I->ActiveEdges, i + 1, j, k) |= cM_000_001;
TetsurfInterpolate2(e[cE_100_101]->Point, c100, d100, c101, d101, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_100_101]->Normal, g100, d100, g101, d101,
I->Level);
}
active |= cM_100_101;
}
if(i100 != i110) {
if(!(I3(I->ActiveEdges, i + 1, j, k) & cM_000_010)) {
I3(I->ActiveEdges, i + 1, j, k) |= cM_000_010;
TetsurfInterpolate2(e[cE_100_110]->Point, c100, d100, c110, d110, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_100_110]->Normal, g100, d100, g110, d110,
I->Level);
}
active |= cM_100_110;
}
if(i100 != i111) {
if(!(I3(I->ActiveEdges, i + 1, j, k) & cM_000_011)) {
I3(I->ActiveEdges, i + 1, j, k) |= cM_000_011;
TetsurfInterpolate4(e[cE_100_111]->Point, c100, d100, c111, d111, d101,
d110, I->Level);
if(mode == 3)
TetsurfInterpolate4(e[cE_100_111]->Normal, g100, d100, g111, d111, d101,
d110, I->Level);
}
active |= cM_100_111;
}
if(i011 != i111) {
if(!(I3(I->ActiveEdges, i, j + 1, k + 1) & cM_000_100)) {
I3(I->ActiveEdges, i, j + 1, k + 1) |= cM_000_100;
TetsurfInterpolate2(e[cE_011_111]->Point, c011, d011, c111, d111, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_011_111]->Normal, g011, d011, g111, d111,
I->Level);
}
active |= cM_011_111;
}
if(i101 != i111) {
if(!(I3(I->ActiveEdges, i + 1, j, k + 1) & cM_000_010)) {
I3(I->ActiveEdges, i + 1, j, k + 1) |= cM_000_010;
TetsurfInterpolate2(e[cE_101_111]->Point, c101, d101, c111, d111, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_101_111]->Normal, g101, d101, g111, d111,
I->Level);
}
active |= cM_101_111;
}
if(i110 != i111) {
if(!(I3(I->ActiveEdges, i + 1, j + 1, k) & cM_000_001)) {
I3(I->ActiveEdges, i + 1, j + 1, k) |= cM_000_001;
TetsurfInterpolate2(e[cE_110_111]->Point, c110, d110, c111, d111, I->Level);
if(mode == 3)
TetsurfInterpolate2(e[cE_110_111]->Normal, g110, d110, g111, d111,
I->Level);
}
active |= cM_110_111;
}
if(active) {
switch (mode) {
case 2:
case 3:
code =
(i000 ? 0x01 : 0) |
(i001 ? 0x02 : 0) |
(i010 ? 0x04 : 0) |
(i011 ? 0x08 : 0) |
(i100 ? 0x10 : 0) |
(i101 ? 0x20 : 0) | (i110 ? 0x40 : 0) | (i111 ? 0x80 : 0);
eidx = I->EdgeStart[code];
while(1) {
idx = I->Edge[eidx];
if(idx < 0)
break;
/* assemble a triangle from these three points */
VLACheck(I->Tri, TriangleType, n_tri);
tt = I->Tri + n_tri;
tt->p[0] = e[idx];
tt->p[1] = e[I->Edge[eidx + 1]];
tt->p[2] = e[I->Edge[eidx + 2]];
VLACheck(I->PtLink, PointLinkType, n_link + 3);
/* link this triangle into the points */
I->PtLink[n_link].tri = n_tri;
I->PtLink[n_link].link = tt->p[0]->Link;
tt->p[0]->Link = n_link;
n_link++;
I->PtLink[n_link].tri = n_tri;
I->PtLink[n_link].link = tt->p[1]->Link;
tt->p[1]->Link = n_link;
n_link++;
I->PtLink[n_link].tri = n_tri;
I->PtLink[n_link].link = tt->p[2]->Link;
tt->p[2]->Link = n_link;
n_link++;
n_tri++;
eidx += 3;
}
break;
case 1: /* lines */
VLACheck(*vert, float, (n_vert * 3) + 200);
code =
(i000 ? 0x01 : 0) |
(i001 ? 0x02 : 0) |
(i010 ? 0x04 : 0) |
(i011 ? 0x08 : 0) |
(i100 ? 0x10 : 0) |
(i101 ? 0x20 : 0) | (i110 ? 0x40 : 0) | (i111 ? 0x80 : 0);
eidx = I->EdgeStart[code];
while(1) {
idx = I->Edge[eidx];
if(idx < 0)
break;
copy3fn(e[idx]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(e[I->Edge[eidx + 1]]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(e[I->Edge[eidx + 1]]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(e[I->Edge[eidx + 2]]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(e[I->Edge[eidx + 2]]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(e[idx]->Point, (*vert) + (n_vert * 3));
n_vert++;
eidx += 3;
}
break;
case 0:
default: /* dots */
VLACheck(*vert, float, (n_vert * 3) + 200);
if(active & cM_000_001) {
copy3fn(e[cE_000_001]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_000_010) {
copy3fn(e[cE_000_010]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_000_011) {
copy3fn(e[cE_000_011]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_000_100) {
copy3fn(e[cE_000_100]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_000_101) {
copy3fn(e[cE_000_101]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_000_110) {
copy3fn(e[cE_000_110]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_000_111) {
copy3fn(e[cE_000_111]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_001_011) {
copy3fn(e[cE_001_011]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_001_101) {
copy3fn(e[cE_001_101]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_001_111) {
copy3fn(e[cE_001_111]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_010_011) {
copy3fn(e[cE_010_011]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_010_110) {
copy3fn(e[cE_010_011]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_010_111) {
copy3fn(e[cE_010_111]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_100_101) {
copy3fn(e[cE_100_101]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_100_110) {
copy3fn(e[cE_100_110]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_100_111) {
copy3fn(e[cE_100_111]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_011_111) {
copy3fn(e[cE_011_111]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_101_111) {
copy3fn(e[cE_101_111]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
if(active & cM_110_111) {
copy3fn(e[cE_101_111]->Point, (*vert) + (n_vert * 3));
n_vert += 1;
}
break;
}
n_active++;
}
}
}
switch (mode) {
case 2:
case 3:
/* compute area-weighted normal */
for(a = 0; a < n_tri; a++) {
float *v0, *v1, *v2;
float vt1[3], vt2[3];
tt = I->Tri + a;
v0 = tt->p[0]->Point;
v1 = tt->p[1]->Point;
v2 = tt->p[2]->Point;
tt->done = false; /* init */
subtract3f(v0, v2, vt1);
subtract3f(v1, v2, vt2);
if(side >= 0) {
cross_product3f(vt2, vt1, tt->n);
} else {
cross_product3f(vt1, vt2, tt->n);
}
}
/* compute (or lookup) normals at active points */
for(a = 0; a < n_tri; a++) {
float v[3];
float dp;
tt = I->Tri + a;
for(b = 0; b < 3; b++) {
if(!tt->p[b]->NormalFlag) {
zero3f(v);
idx = tt->p[b]->Link;
while(idx > 0) {
add3f(I->Tri[I->PtLink[idx].tri].n, v, v);
idx = I->PtLink[idx].link;
}
if(mode == 3) { /* gradient-based normals */
dp = dot_product3f(v, tt->p[b]->Normal);
if(dp < 0.0F) {
invert3f(tt->p[b]->Normal);
normalize3f(tt->p[b]->Normal);
} else if(dp == 0.0F) { /* fall back on triangle normal */
normalize23f(v, tt->p[b]->Normal);
} else {
normalize3f(tt->p[b]->Normal);
}
} else { /* triangle-based normals */
normalize23f(v, tt->p[b]->Normal);
}
tt->p[b]->NormalFlag = true;
}
}
}
if(mode == 2) {
/* if we're using triangle normals, then
do an additional averaging cycle with no weighting */
for(a = 0; a < n_tri; a++) {
tt = I->Tri + a;
add3f(tt->p[0]->Normal, tt->p[1]->Normal, tt->n);
add3f(tt->p[2]->Normal, tt->n, tt->n);
normalize3f(tt->n);
tt->p[0]->NormalFlag = false;
tt->p[1]->NormalFlag = false;
tt->p[2]->NormalFlag = false;
}
/* compute normals at active points */
for(a = 0; a < n_tri; a++) {
float v[3];
tt = I->Tri + a;
for(b = 0; b < 3; b++) {
if(!tt->p[b]->NormalFlag) {
zero3f(v);
idx = tt->p[b]->Link;
while(idx > 0) {
add3f(I->Tri[I->PtLink[idx].tri].n, v, v);
idx = I->PtLink[idx].link;
}
normalize23f(v, tt->p[b]->Normal);
tt->p[b]->NormalFlag = true;
}
}
}
}
/* Need to move the points now, right? */
/* if we are carving, then exclude triangles outside region */
if(voxelmap) {
for(a = 0; a < n_tri; a++) {
float *v;
tt = I->Tri + a;
c = 0;
for(b = 0; b < 3; b++) {
v = tt->p[b]->Point;
MapLocus(voxelmap, v, &h, &k, &l);
i = *(MapEStart(voxelmap, h, k, l));
if(i) {
j = voxelmap->EList[i++];
while(j >= 0) {
if(within3f(a_vert + 3 * j, v, carvebuffer)) {
c++;
break;
}
j = voxelmap->EList[i++];
}
}
}
if(avoid_flag) {
if(c >= 3)
tt->done = true; /* exclude this triangle from the surface */
} else {
if(c < 3) /* exclude this triangle from the surface */
tt->done = true;
}
}
}
/* now create triangle strips (not yet optimal) */
for(a = 0; a < n_tri; a++) {
tt = I->Tri + a;
n_start = n_vert;
if(!tt->done) {
VLACheck(*vert, float, (n_vert * 3) + 200);
if(side >= 0) {
/* switch order around to get "correct" triangles */
copy3fn(tt->p[1]->Normal, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[1]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[0]->Normal, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[0]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[2]->Normal, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[2]->Point, (*vert) + (n_vert * 3));
n_vert++;
p0 = tt->p[0];
p1 = tt->p[2];
} else {
copy3fn(tt->p[0]->Normal, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[0]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[1]->Normal, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[1]->Point, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[2]->Normal, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(tt->p[2]->Point, (*vert) + (n_vert * 3));
n_vert++;
p0 = tt->p[1];
p1 = tt->p[2];
}
tt->done = true;
while(1) {
p2 = NULL;
idx = p1->Link;
while(idx > 0) {
tt = I->Tri + I->PtLink[idx].tri;
if(!tt->done) {
if((tt->p[0] == p0) && (tt->p[1] == p1)) {
p2 = tt->p[2];
break;
}
if((tt->p[1] == p0) && (tt->p[2] == p1)) {
p2 = tt->p[0];
break;
}
if((tt->p[2] == p0) && (tt->p[0] == p1)) {
p2 = tt->p[1];
break;
}
if((tt->p[1] == p0) && (tt->p[0] == p1)) {
p2 = tt->p[2];
break;
}
if((tt->p[2] == p0) && (tt->p[1] == p1)) {
p2 = tt->p[0];
break;
}
if((tt->p[0] == p0) && (tt->p[2] == p1)) {
p2 = tt->p[1];
break;
}
}
idx = I->PtLink[idx].link;
}
if(!p2)
break;
tt->done = true;
VLACheck(*vert, float, (n_vert * 3) + 200);
copy3fn(p2->Normal, (*vert) + (n_vert * 3));
n_vert++;
copy3fn(p2->Point, (*vert) + (n_vert * 3));
n_vert++;
p0 = p1;
p1 = p2;
}
}
if(n_vert > n_start) {
VLACheck(*strip_l, int, *n_strip);
(*strip_l)[*n_strip] = n_vert - n_start;
(*n_strip)++;
}
}
I->TotPrim += n_tri;
break;
case 1:
/* Need to move the points now, right? */
if(n_vert > n_start) {
VLACheck(*strip_l, int, *n_strip);
(*strip_l)[*n_strip] = n_vert - n_start;
(*n_strip)++;
}
break;
case 0: /* dots */
default:
/* Need to move the points now, right? */
if(n_vert > n_start) {
VLACheck(*strip_l, int, *n_strip);
(*strip_l)[*n_strip] = n_vert - n_start;
(*n_strip)++;
}
break;
}
/*
printf("n_strip %d\n",*n_strip);
printf("n_active %d\n",n_active);
printf("n_vert %d\n",n_vert);
printf("mode %d\n",mode);
*/
return (n_vert);
}
/*===========================================================================*/
static int TetsurfCodeVertices(CTetsurf * II)
{
CTetsurf *I = II;
int i, j, k;
int b0, b1;
int flag1 = false;
int flag2 = false;
b0 = 1;
if(I->Level < 0.0F)
b0 = 0;
b1 = 1 - b0;
for(i = 0; i < I->Max[0]; i++)
for(j = 0; j < I->Max[1]; j++)
for(k = 0; k < I->Max[2]; k++) {
if((O3(I->Data, i, j, k, I->CurOff) > I->Level)) {
I3(I->VertexCodes, i, j, k) = b0;
flag1 = true;
} else {
I3(I->VertexCodes, i, j, k) = b1;
flag2 = true;
}
}
return (flag1 && flag2);
}