|
/*ScianVisIso.c
Routines for the isosurface visualization object
Eric Pepke
May 25, 1991
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianArrays.h"
#include "ScianWindows.h"
#include "ScianTextBoxes.h"
#include "ScianObjWindows.h"
#include "ScianIcons.h"
#include "ScianColors.h"
#include "ScianControls.h"
#include "ScianButtons.h"
#include "ScianTitleBoxes.h"
#include "ScianLists.h"
#include "ScianSpaces.h"
#include "ScianSliders.h"
#include "ScianIDs.h"
#include "ScianDatasets.h"
#include "ScianErrors.h"
#include "ScianVisObjects.h"
#include "ScianVisWindows.h"
#include "ScianStyle.h"
#include "ScianPictures.h"
#include "ScianDepend.h"
#include "ScianTimers.h"
#include "ScianScales.h"
#include "ScianTemplates.h"
#include "ScianTemplateHelper.h"
#include "ScianEvents.h"
#include "ScianScripts.h"
#include "ScianFixedClasses.h"
ObjPtr isoClass;
/*Specifier for a part of the hex, which can be linked into a list*/
typedef struct part
{
struct part *next; /*Next part in the list*/
int coords[3]; /*Coordinates of the part.
For a vertex, all three must be 0 or 1
For an edge, exactly one must be 2
For a face, two must be 2*/
} Part, *PartPtr;
/*Parts for using*/
#define NPARTS 1580
Part parts[NPARTS];
PartPtr freePart, tempFree;
#define MAXNPOLYS 4
PartPtr presetPolys[256][MAXNPOLYS];
/*Macros for allocating parts*/
#define NEWPART (freePart ? \
(tempFree = freePart, freePart = freePart -> next, tempFree) \
: newp(Part))
#define FREEPART(p) p -> next = freePart; freePart = p;
#ifdef HAVE_PROTOTYPES
Bool SectPart(PartPtr, PartPtr, PartPtr);
Bool IsoHex(real fieldHex[2][2][2], real surfVal, ObjPtr pic,
Bool lowInside);
#else
Bool SectPart();
Bool IsoHex();
#endif
/*Macro to insert a node after one node in the linked list*/
#define INSERTAFTER(list, node) \
{ \
node -> next = list -> next; \
list -> next = node; \
}
/*Macro to dispose of a node after the current node*/
#define DISPOSEAFTER(list) \
{ \
PartPtr next; \
next = list -> next -> next; \
FREEPART(list -> next); \
list -> next = next; \
}
/*Values for vertexState*/
#define WITHIN 0 /*Within the isosurface*/
#define WITHOUT 1 /*Outside the isosurface*/
#define USED 2 /*Already used in the polygon*/
Bool EdgeOnFace(e, f)
PartPtr e, f;
/*Returns true if edge e is on face f*/
{
register int k;
for (k = 0; k < 3; ++k)
{
if (e -> coords[k] == 2 && f -> coords[k] != 2)
{
return false;
}
}
return true;
}
Bool SectPart(s1, s2, d)
PartPtr s1, s2, d;
/*Returns true if s1 intersects s2 and, if so, puts the intersection in d
The intersection of two edges is a vertex; the intersection of two faces
is an edge*/
{
register int k;
for (k = 0; k < 3; ++k)
{
if (s1 -> coords[k] == 2)
{
d -> coords[k] = s2 -> coords[k];
}
else if (s2 -> coords[k] == 2)
{
d -> coords[k] = s1 -> coords[k];
}
else if (s1 -> coords[k] != s2 -> coords[k])
{
return false;
}
else
{
d -> coords[k] = s1 -> coords[k];
}
}
return true;
}
void UnionPart(s1, s2, d)
PartPtr s1, s2, d;
/*Puts in d the union of parts s1 and s2*/
{
register int k;
for (k = 0; k < 3; ++k)
{
if (s1 -> coords[k] == s2 -> coords[k])
{
d -> coords[k] = s1 -> coords[k];
}
else
{
d -> coords[k] = 2;
}
}
}
Bool ThirdEdge(s1, s2, d)
PartPtr s1, s2, d;
/*Given 2 edges, s1, and s2 which meet at a point, forms the third edge d*/
{
register int k;
for (k = 0; k < 3; ++k)
{
if (s1 -> coords[k] == 2)
{
d -> coords[k] = s2 -> coords[k];
}
else if (s2 -> coords[k] == 2)
{
d -> coords[k] = s1 -> coords[k];
}
else if (s1 -> coords[k] != s2 -> coords[k])
{
return false;
}
else
{
d -> coords[k] = 2;
}
}
return true;
}
void Other2Edges(e, v, e1, e2)
PartPtr e, v, e1, e2;
/*Given an edge e and a vertex v on that edge, puts in e1 and e2 the other
two edges which intersect that vertex*/
{
register int index; /*Index into which coordinate*/
for (index = 0; index < 3; ++index)
{
if (e -> coords[index] != 2)
{
e1 -> coords[0] = v -> coords[0];
e1 -> coords[1] = v -> coords[1];
e1 -> coords[2] = v -> coords[2];
e1 -> coords[index] = 2;
break;
}
}
for (index = 2; index >= 0; --index)
{
if (e -> coords[index] != 2)
{
e2 -> coords[0] = v -> coords[0];
e2 -> coords[1] = v -> coords[1];
e2 -> coords[2] = v -> coords[2];
e2 -> coords[index] = 2;
break;
}
}
}
#ifdef HAVE_PROTOTYPES
Bool CacheIso(int initState[2][2][2], int whichPreset, Bool lowInside)
#else
Bool CacheIso(initState, whichPreset, lowInside)
int initState[2][2][2];
int whichPreset;
Bool lowInside;
#endif
/*Calculates a series of polygons that make an isosurface through fieldHex
at surfVal, storing it in whichPreset. If lowInside, assumes
that what is lower than surfVal is inside, otherwise what is higher*/
{
int i, j, k; /*Counters*/
int vertexState[2][2][2]; /*State of each vertex in the hex*/
int verticesLeft; /*Number of within vertices left*/
Bool retVal = true; /*Return value*/
int whichPolygon; /*Which polygon of this polygon cache*/
/*Figure out what the state of the vertices is*/
verticesLeft = 0;
for (i = 0; i < 2; ++i)
{
for (j = 0; j < 2; ++j)
{
for(k = 0; k < 2; ++k)
{
if (initState[i][j][k])
{
vertexState[i][j][k] = lowInside ? WITHIN : WITHOUT;
}
else
{
vertexState[i][j][k] = lowInside ? WITHOUT : WITHIN;
}
if (vertexState[i][j][k] == WITHIN)
{
++verticesLeft;
}
}
}
}
/*If all vertices are within, don't bother trying*/
if (verticesLeft == 8)
{
return true;
}
whichPolygon = 0;
/*Create isosurfaces until no more are needed*/
while (verticesLeft)
{
int i0, j0, k0; /*Index of starting vertex*/
PartPtr polygon; /*The polygon around the isosurface,
circular linked list*/
register PartPtr oneEdge; /*Temporary edge*/
/*Pick an initial vertex around which to build the surface*/
for (i = 0; i < 2; ++i)
{
for (j = 0; j < 2; ++j)
{
for (k = 0; k < 2; ++k)
{
if (vertexState[i][j][k] == WITHIN)
{
i0 = i;
j0 = j;
k0 = k;
}
}
}
}
/*Now, i0, j0, and k0 are set to the initial vertex*/
/*Create the first polygon and account for that vertex*/
oneEdge = NEWPART;
oneEdge -> next = oneEdge;
oneEdge -> coords[0] = 2;
oneEdge -> coords[1] = j0;
oneEdge -> coords[2] = k0;
polygon = oneEdge;
/*Use checkerboard rule to determine initial order*/
if (i0 ^ j0 ^ k0)
{
oneEdge = NEWPART;
oneEdge -> coords[0] = i0;
oneEdge -> coords[1] = j0;
oneEdge -> coords[2] = 2;
INSERTAFTER(polygon, oneEdge);
oneEdge = NEWPART;
oneEdge -> coords[0] = i0;
oneEdge -> coords[1] = 2;
oneEdge -> coords[2] = k0;
INSERTAFTER(polygon, oneEdge);
}
else
{
oneEdge = NEWPART;
oneEdge -> coords[0] = i0;
oneEdge -> coords[1] = 2;
oneEdge -> coords[2] = k0;
INSERTAFTER(polygon, oneEdge);
oneEdge = NEWPART;
oneEdge -> coords[0] = i0;
oneEdge -> coords[1] = j0;
oneEdge -> coords[2] = 2;
INSERTAFTER(polygon, oneEdge);
}
vertexState[i0][j0][k0] = USED;
--verticesLeft;
/*Now go through and expand the polygon*/
for (;;)
{
PartPtr runner; /*Runner through the polygon*/
/*First see if there is any potential vertex, common to two
existing adjacent edges which can combine them into one*/
runner = polygon;
do
{
Part intersection; /*Intersection between two edges*/
if (SectPart(runner, runner -> next, &intersection))
{
/*intersection contains a vertex where two edges meet*/
if (vertexState[intersection . coords[0]]
[intersection . coords[1]]
[intersection . coords[2]] == WITHIN)
{
/*It's a valid candidate; gobble it up*/
ThirdEdge(runner, runner -> next, runner);
if (runner -> next == polygon)
{
polygon = runner;
}
DISPOSEAFTER(runner);
vertexState[intersection . coords[0]]
[intersection . coords[1]]
[intersection . coords[2]] = USED;
--verticesLeft;
goto tryAgain;
}
}
runner = runner -> next;
} while (runner != polygon);
/*Now see if an edge can be stretched over a neighboring vertex*/
runner = polygon;
do
{
int index; /*Index into which coord is Free*/
Part vertex;
/*Start off with vertex = edge*/
vertex . coords[0] = runner -> coords[0];
vertex . coords[1] = runner -> coords[1];
vertex . coords[2] = runner -> coords[2];
/*Figure out which coordinate is Free*/
for (index = 0; index < 3; ++index)
{
if (runner -> coords[index] == 2)
{
break;
}
}
/*Now try both vertices that share that edge*/
for (vertex . coords[index] = 0;
vertex . coords[index] < 2;
++(vertex . coords[index]))
{
if (vertexState[vertex . coords[0]]
[vertex . coords[1]]
[vertex . coords[2]] == WITHIN)
{
/*Yes, it's good! Snap it over it.*/
Part lastFace; /*Second face to climb over*/
Part temp; /*Temporary part*/
Part edge1, edge2; /*Candidate edges*/
/*Determine the last face the new line will climb over
to determine the order of edges*/
UnionPart(runner, runner -> next, &lastFace);
/*Start with the edge that does not intersect lastFace*/
Other2Edges(runner, &vertex, &edge1, &edge2);
oneEdge = NEWPART;
if (EdgeOnFace(&edge1, &lastFace))
{
/*Start with edge2*/
runner -> coords[0] = edge2 . coords[0];
runner -> coords[1] = edge2 . coords[1];
runner -> coords[2] = edge2 . coords[2];
oneEdge -> coords[0] = edge1 . coords[0];
oneEdge -> coords[1] = edge1 . coords[1];
oneEdge -> coords[2] = edge1 . coords[2];
}
else
{
/*Start with edge1*/
runner -> coords[0] = edge1 . coords[0];
runner -> coords[1] = edge1 . coords[1];
runner -> coords[2] = edge1 . coords[2];
oneEdge -> coords[0] = edge2 . coords[0];
oneEdge -> coords[1] = edge2 . coords[1];
oneEdge -> coords[2] = edge2 . coords[2];
}
INSERTAFTER(runner, oneEdge);
vertexState[vertex . coords[0]]
[vertex . coords[1]]
[vertex . coords[2]] = USED;
--verticesLeft;
goto tryAgain;
}
}
runner = runner -> next;
} while (runner != polygon);
#if 0
/*Failed the two tests. See if there are two identical intersections between two used
vertices to slide*/
runner = polygon;
do
{
int index; /*Index into which coord is Free*/
Part vertex;
/*Start off with vertex = edge*/
vertex . coords[0] = runner -> coords[0];
vertex . coords[1] = runner -> coords[1];
vertex . coords[2] = runner -> coords[2];
/*Figure out which coordinate is Free*/
for (index = 0; index < 3; ++index)
{
if (runner -> coords[index] == 2)
{
break;
}
}
/*Try both endpoints to see if they're both USED*/
vertex . coords[index] = 0;
if (vertexState[vertex . coords[0]]
[vertex . coords[1]]
[vertex . coords[2]] == USED)
{
/*Looks good so far*/
vertex . coords[index] = 1;
if (vertexState[vertex . coords[0]]
[vertex . coords[1]]
[vertex . coords[2]] == USED)
{
/*Excellent! Found one. Now search for the other one, if any*/
PartPtr other;
other = runner -> next;
do
{
if (runner -> coords[0] == other -> coords[0] &&
runner -> coords[1] == other -> coords[1] &&
runner -> coords[2] == other -> coords[2])
{
/*Hot diggity sclotos!*/
break;
}
other = other -> next;
} while (other != runner);
if (other != runner)
{
/*We found a mate! Slide the two*/
runner -> coords[0] = other -> next -> coords[0];
runner -> coords[1] = other -> next -> coords[1];
runner -> coords[2] = other -> next -> coords[2];
other -> coords[0] = runner -> next -> coords[0];
other -> coords[1] = runner -> next -> coords[1];
other -> coords[2] = runner -> next -> coords[2];
break;
}
}
}
runner = runner -> next;
} while (runner != polygon);
#endif
break;
tryAgain: ;
}
if (polygon)
{
PartPtr curNode; /*The current node in the polygon*/
PartPtr next; /*The next node in the polygon*/
int whichVertex; /*The current vertex*/
int k;
whichVertex = 0;
/*Test the polygon for sanity*/
curNode = polygon;
do
{
register int n; /*Dimension counters*/
register int ic, jc, kc;
int t1, t2;
/*Determine along which side this intersection lies*/
ic = curNode -> coords[0];
jc = curNode -> coords[1];
kc = curNode -> coords[2];
if (ic == 2)
{
/*i is Free*/
t1 = initState[0][jc][kc];
t2 = initState[1][jc][kc];
if (t1 == t2)
{
retVal = false;
goto zapPolygon;
}
}
else if (jc == 2)
{
/*j is Free*/
t1 = initState[ic][0][kc];
t2 = initState[ic][1][kc];
if (t1 == t2)
{
retVal = false;
goto zapPolygon;
}
}
else if (kc == 2)
{
/*k is Free*/
t1 = initState[ic][jc][0];
t2 = initState[ic][jc][1];
if (t1 == t2)
{
retVal = false;
goto zapPolygon;
}
}
else
{
ReportError("CacheIso", "Error, neither ic nor kc nor jc Free");
}
curNode = curNode -> next;
} while (curNode != polygon);
if (whichPolygon >= MAXNPOLYS) ReportError("CacheIso", "Too many polys");
presetPolys[whichPreset][whichPolygon] = polygon;
++whichPolygon;
continue;
zapPolygon:
/*Get rid of the polygon*/
curNode = polygon;
next = curNode -> next;
do
{
curNode = next;
next = curNode -> next;
FREEPART(curNode);
} while (curNode != polygon);
}
}
return retVal;
}
#ifdef HAVE_PROTOTYPES
Bool NewIsoHex(real *bottomField, real *topField,
VertexPtr *bottomVertices, VertexPtr *topVertices,
long index[], long dims[],
real surfVal, ObjPtr pic,
Bool lowInside)
#else
Bool NewIsoHex(bottomField, topField,
bottomVertices, topVertices,
index, dims,
surfVal, pic,
lowInside)
real *bottomField; real *topField;
VertexPtr *bottomVertices; VertexPtr *topVertices;
long index[]; long dims[];
real surfVal; ObjPtr pic;
Bool lowInside;
#endif
/*Calculates a series of polygons that make an isosurface.*/
{
int i, j, t; /*Counters*/
real sample;
int whichCase;
register long offset;
/*Calculate the case*/
whichCase = 0;
for (i = 0; i < 2; ++i)
{
for (j = 0; j < 2; ++j)
{
offset = (index[0] + i) * dims[1] + (index[1] + j);
whichCase = whichCase << 1;
sample = bottomField[offset];
if (sample == missingData) return true;
if (lowInside ? (sample <= surfVal) : (sample >= surfVal))
{
whichCase += 1;
}
whichCase = whichCase << 1;
sample = topField[offset];
if (sample == missingData) return true;
if (lowInside ? (sample <= surfVal) : (sample >= surfVal))
{
whichCase += 1;
}
}
}
i = index[0];
j = index[1];
for (t = 0; presetPolys[whichCase][t]; ++t)
{
PartPtr polygon;
polygon = presetPolys[whichCase][t];
if (polygon)
{
PartPtr curNode; /*The current node in the polygon*/
PartPtr next; /*The next node in the polygon*/
VertexPtr vertices[20]; /*The vertices into the polygon*/
int whichVertex; /*Which vertex of the poly looking at*/
whichVertex = 0;
/*Emit the polygon*/
curNode = polygon;
do
{
register int ic, jc, kc;
/*Determine along which side this intersection lies*/
ic = curNode -> coords[0];
jc = curNode -> coords[1];
kc = curNode -> coords[2];
if (ic == 2)
{
/*i is Free*/
offset = (i * dims[1] + (j + jc)) * 3;
}
else if (jc == 2)
{
/*j is Free*/
offset = ((i + ic) * dims[1] + j) * 3 + 1;
}
else if (kc == 2)
{
/*k is Free*/
offset = ((i + ic) * dims[1] + (j + jc)) * 3 + 2;
}
else
{
ReportError("NewIsoHex", "Error, neither ic nor kc nor jc Free");
return false;
}
vertices[whichVertex] = (kc == 1) ? topVertices[offset] : bottomVertices[offset];
if (vertices[whichVertex] == 0)
{
ReportError("NewIsoHex", "Vertex error");
return false;
}
++whichVertex;
curNode = curNode -> next;
} while (curNode != polygon);
/*Now the polygon has been assembled; spit it out.*/
TesselateSPolyToPicture(pic, whichVertex, vertices);
}
}
}
#define CALCDELTA(field, hc, pic, mic, pjc, mjc, pkc, mkc)
#undef NEXTFIELD
#undef PREVFIELD
#undef PLUSIC
#undef MINUSIC
#undef PLUSJC
#undef MINUSJC
#undef PLUSKC
#undef MINUSKC
#ifdef HAVE_PROTOTYPES
static void StuffIJKVertices(VertexPtr *elements, real *field, real *nextField, real deltas[], int fieldNum, int coord, long dims[3], long kVal, ObjPtr pic, real isoVal, Bool encloseLow)
#else
static void StuffIJKVertices(elements, field, nextField, deltas, fieldNum, coord, dims, kVal, pic, isoVal, encloseLow)
VertexPtr *elements;
real *field;
int fieldNum;
real *nextField;
real deltas[];
int coord;
long dims[3];
long kVal;
ObjPtr pic;
real isoVal;
Bool encloseLow;
#endif
/*Makes a group of IJK vertices for field at k = kVal, sticking them in pic
Coord is the coordinates. Stuffs the results into array. If deltas, uses
deltas as a holding place for the deltas to make normals*/
{
long index[3];
register long nElements;
register long i, j;
register long offset;
register real curVal, nextVal;
register real r;
/*Empty the array*/
nElements = dims[0] * dims[1] * 3;
for (offset = 0; offset < nElements; ++offset)
{
elements[offset] = 0;
}
/*Make I vertices*/
for (index[1] = 0; index[1] < dims[1]; ++index[1])
{
index[0] = 0;
index[2] = kVal;
offset = index[1];
curVal = field[offset];
for (index[0] = 1; index[0] < dims[0]; ++index[0])
{
nextVal = field[offset + dims[1]];
if (curVal != missingData && nextVal != missingData)
{
/*Maybe make some sort of a vertex*/
if (BETWEENP(isoVal, curVal, nextVal))
{
/*Yes! Vertex here!*/
register VertexPtr v;
register real location, location1;
real curCoord[3], nextCoord[3];
v = NewVertex(pic, 0);
location = (isoVal - curVal) / (nextVal - curVal);
location1 = 1.0 - location;
/*Get coordinates*/
--index[0];
curCoord[0] = SelectFieldComponent(coord, 0, index);
curCoord[1] = SelectFieldComponent(coord, 1, index);
curCoord[2] = SelectFieldComponent(coord, 2, index);
++index[0];
nextCoord[0] = SelectFieldComponent(coord, 0, index);
nextCoord[1] = SelectFieldComponent(coord, 1, index);
nextCoord[2] = SelectFieldComponent(coord, 2, index);
/*Set position*/
v -> position[0] = nextCoord[0] * location +
curCoord[0] * location1;
v -> position[1] = nextCoord[1] * location +
curCoord[1] * location1;
v -> position[2] = nextCoord[2] * location +
curCoord[2] * location1;
if (deltas)
{
/*Calculate normal from delta*/
--index[0];
#define FIELDHERE field
#define NEXTFIELD nextField
#define HEREC curCoord
#define HEREV curVal
#define PLUSIC nextCoord
#include "ScianIsoCalcDelta.h"
#undef FIELDHERE
#undef NEXTFIELD
#undef HEREC
#undef HEREV
#undef PLUSIC
++index[0];
#define FIELDHERE field
#define NEXTFIELD nextField
#define HEREC nextCoord
#define HEREV nextVal
#define MINUSIC curCoord
#include "ScianIsoCalcDelta.h"
#undef FIELDHERE
#undef NEXTFIELD
#undef HEREC
#undef HEREV
#undef MINUSIC
/*Now that we have two deltas, make the normal*/
offset += dims[1];
v -> normal[0] = location * deltas[offset * 3];
v -> normal[1] = location * deltas[offset * 3 + 1];
v -> normal[2] = location * deltas[offset * 3 + 2];
offset -= dims[1];
v -> normal[0] += location1 * deltas[offset * 3];
v -> normal[1] += location1 * deltas[offset * 3 + 1];
v -> normal[2] += location1 * deltas[offset * 3 + 2];
r = sqrt(SQUARE(v -> normal[0]) +
SQUARE(v -> normal[1]) +
SQUARE(v -> normal[2]));
if (r > 0.0)
{
r = 1.0 / r;
v -> normal[0] *= r;
v -> normal[1] *= r;
v -> normal[2] *= r;
if (!encloseLow)
{
v -> normal[0] = -(v -> normal[0]);
v -> normal[1] = -(v -> normal[1]);
v -> normal[2] = -(v -> normal[2]);
}
}
else
{
/*Just give it plus z normal*/
v -> normal[0] = 0.0;
v -> normal[1] = 0.0;
v -> normal[2] = 1.0;
}
}
else
{
/*Just give it plus z normal*/
v -> normal[0] = 0.0;
v -> normal[1] = 0.0;
v -> normal[2] = 1.0;
}
elements[offset * 3] = v;
}
}
curVal = nextVal;
offset += dims[1];
}
}
/*Make J vertices*/
for (index[0] = 0; index[0] < dims[0]; ++index[0])
{
index[1] = 0;
index[2] = kVal;
offset = index[0] * dims[1];
curVal = field[offset];
for (index[1] = 1; index[1] < dims[1]; ++index[1])
{
nextVal = field[offset + 1];
if (curVal != missingData && nextVal != missingData)
{
/*Maybe make some sort of a vertex*/
if (BETWEENP(isoVal, curVal, nextVal))
{
/*Yes! Vertex here!*/
register VertexPtr v;
register real location, location1;
real curCoord[3], nextCoord[3];
v = NewVertex(pic, 0);
location = (isoVal - curVal) / (nextVal - curVal);
location1 = 1.0 - location;
/*Get coordinates*/
--index[1];
curCoord[0] = SelectFieldComponent(coord, 0, index);
curCoord[1] = SelectFieldComponent(coord, 1, index);
curCoord[2] = SelectFieldComponent(coord, 2, index);
++index[1];
nextCoord[0] = SelectFieldComponent(coord, 0, index);
nextCoord[1] = SelectFieldComponent(coord, 1, index);
nextCoord[2] = SelectFieldComponent(coord, 2, index);
/*Set position*/
v -> position[0] = nextCoord[0] * location +
curCoord[0] * location1;
v -> position[1] = nextCoord[1] * location +
curCoord[1] * location1;
v -> position[2] = nextCoord[2] * location +
curCoord[2] * location1;
if (deltas)
{
/*Calculate normal from delta*/
--index[1];
#define FIELDHERE field
#define NEXTFIELD nextField
#define HEREC curCoord
#define HEREV curVal
#define PLUSJC nextCoord
#include "ScianIsoCalcDelta.h"
#undef FIELDHERE
#undef NEXTFIELD
#undef HEREC
#undef HEREV
#undef PLUSJC
++index[1];
#define FIELDHERE field
#define NEXTFIELD nextField
#define HEREC nextCoord
#define HEREV nextVal
#define MINUSJC curCoord
#include "ScianIsoCalcDelta.h"
#undef FIELDHERE
#undef NEXTFIELD
#undef HEREC
#undef HEREV
#undef MINUSJC
/*Now that we have two deltas, make the normal*/
++offset;
v -> normal[0] = location * deltas[offset * 3];
v -> normal[1] = location * deltas[offset * 3 + 1];
v -> normal[2] = location * deltas[offset * 3 + 2];
--offset;
v -> normal[0] += location1 * deltas[offset * 3];
v -> normal[1] += location1 * deltas[offset * 3 + 1];
v -> normal[2] += location1 * deltas[offset * 3 + 2];
r = sqrt(SQUARE(v -> normal[0]) +
SQUARE(v -> normal[1]) +
SQUARE(v -> normal[2]));
if (r > 0.0)
{
r = 1.0 / r;
v -> normal[0] *= r;
v -> normal[1] *= r;
v -> normal[2] *= r;
if (!encloseLow)
{
v -> normal[0] = -(v -> normal[0]);
v -> normal[1] = -(v -> normal[1]);
v -> normal[2] = -(v -> normal[2]);
}
}
else
{
/*Just give it plus z normal*/
v -> normal[0] = 0.0;
v -> normal[1] = 0.0;
v -> normal[2] = 1.0;
}
}
else
{
/*Just give it plus z normal*/
v -> normal[0] = 0.0;
v -> normal[1] = 0.0;
v -> normal[2] = 1.0;
}
elements[offset * 3 + 1] = v;
}
}
curVal = nextVal;
++offset;
}
}
/*Make K vertices*/
index[0] = 0;
index[1] = 0;
index[2] = kVal;
if (kVal < dims[2])
for (index[0] = 0; index[0] < dims[0]; ++index[0])
{
offset = index[0] * dims[1];
for (index[1] =0; index[1] < dims[1]; ++index[1])
{
index[2] = kVal;
curVal = field[offset];
index[2] = kVal + 1;
nextVal = nextField[offset];
if ((curVal != missingData) &&
(nextVal != missingData) &&
BETWEENP(isoVal, curVal, nextVal))
{
/*Yes! Vertex here!*/
register VertexPtr v;
register real location, location1;
real curCoord[3], nextCoord[3];
v = NewVertex(pic, 0);
location = (isoVal - curVal) / (nextVal - curVal);
location1 = 1.0 - location;
/*Get coordinates*/
--index[2];
curCoord[0] = SelectFieldComponent(coord, 0, index);
curCoord[1] = SelectFieldComponent(coord, 1, index);
curCoord[2] = SelectFieldComponent(coord, 2, index);
++index[2];
nextCoord[0] = SelectFieldComponent(coord, 0, index);
nextCoord[1] = SelectFieldComponent(coord, 1, index);
nextCoord[2] = SelectFieldComponent(coord, 2, index);
/*Set position*/
v -> position[0] = nextCoord[0] * location +
curCoord[0] * location1;
v -> position[1] = nextCoord[1] * location +
curCoord[1] * location1;
v -> position[2] = nextCoord[2] * location +
curCoord[2] * location1;
if (deltas)
{
/*Calculate normal from delta*/
--index[2];
#define FIELDHERE field
#define NEXTFIELD nextField
#define HEREC curCoord
#define PLUSKC nextCoord
#define HEREV curVal
#include "ScianIsoCalcDelta.h"
#undef FIELDHERE
#undef NEXTFIELD
#undef HEREC
#undef PLUSKC
#undef HEREV
v -> normal[0] = location1 * deltas[offset * 3];
v -> normal[1] = location1 * deltas[offset * 3 + 1];
v -> normal[2] = location1 * deltas[offset * 3 + 2];
deltas[offset * 3] = missingData;
deltas[offset * 3 + 1] = missingData;
deltas[offset * 3 + 2] = missingData;
++index[2];
#define FIELDHERE nextField
#define PREVFIELD field
#define HEREC nextCoord
#define MINUSKC curCoord
#define HEREV nextVal
#include "ScianIsoCalcDelta.h"
#undef FIELDHERE
#undef PREVFIELD
#undef HEREC
#undef MINUSKC
#undef HEREV
/*Now that we have two deltas, make the normal*/
v -> normal[0] += location * deltas[offset * 3];
v -> normal[1] += location * deltas[offset * 3 + 1];
v -> normal[2] += location * deltas[offset * 3 + 2];
r = sqrt(SQUARE(v -> normal[0]) +
SQUARE(v -> normal[1]) +
SQUARE(v -> normal[2]));
if (r > 0.0)
{
r = 1.0 / r;
v -> normal[0] *= r;
v -> normal[1] *= r;
v -> normal[2] *= r;
if (!encloseLow)
{
v -> normal[0] = -(v -> normal[0]);
v -> normal[1] = -(v -> normal[1]);
v -> normal[2] = -(v -> normal[2]);
}
}
else
{
/*Just give it plus z normal*/
v -> normal[0] = 0.0;
v -> normal[1] = 0.0;
v -> normal[2] = 1.0;
}
}
else
{
/*Just give it plus z normal*/
v -> normal[0] = 0.0;
v -> normal[1] = 0.0;
v -> normal[2] = 1.0;
}
elements[offset * 3 + 2] = v;
}
else
{
/*Haven't made deltas for next time, must kill them*/
if (deltas)
{
deltas[offset * 3] = missingData;
deltas[offset * 3 + 1] = missingData;
deltas[offset * 3 + 2] = missingData;
}
}
curVal = nextVal;
++offset;
}
}
}
static ObjPtr AddIsoVRControls(object, contents)
ObjPtr object, contents;
/*Adds controls appropriate to an isosurface to contents*/
{
ObjPtr button;
ObjPtr isoField, var;
real db[2];
real bc[3];
#ifdef GRAPHICS
Object o;
short c[3];
float v[3];
#endif
#ifdef GRAPHICS
/*Make the opaque button*/
o = genobj();
makeobj(o);
bgnpolygon();
c[0] = 255;
c[1] = 0;
c[2] = 0;
c3s(c);
v[0] = 0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0982890;
v[1] = -0.126105;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0931852;
v[1] = -0.151764;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0847759;
v[1] = -0.176537;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0732051;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0586707;
v[1] = -0.221752;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0414214;
v[1] = -0.241421;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0217523;
v[1] = -0.258671;
v[2] = 0.00000;
v3f(v);
v[0] = -4.47035e-08;
v[1] = -0.273205;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0234633;
v[1] = -0.284776;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0482361;
v[1] = -0.293185;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0738947;
v[1] = -0.298289;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0999999;
v[1] = -0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.126105;
v[1] = -0.298289;
v[2] = 0.00000;
v3f(v);
v[0] = 0.151764;
v[1] = -0.293185;
v[2] = 0.00000;
v3f(v);
v[0] = 0.176537;
v[1] = -0.284776;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.273205;
v[2] = 0.00000;
v3f(v);
v[0] = 0.221752;
v[1] = -0.258671;
v[2] = 0.00000;
v3f(v);
v[0] = 0.241421;
v[1] = -0.241421;
v[2] = 0.00000;
v3f(v);
v[0] = 0.258671;
v[1] = -0.221752;
v[2] = 0.00000;
v3f(v);
v[0] = 0.273205;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.284776;
v[1] = -0.176537;
v[2] = 0.00000;
v3f(v);
v[0] = 0.293185;
v[1] = -0.151764;
v[2] = 0.00000;
v3f(v);
v[0] = 0.298289;
v[1] = -0.126105;
v[2] = 0.00000;
v3f(v);
v[0] = 0.300000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.298289;
v[1] = -0.0738949;
v[2] = 0.00000;
v3f(v);
v[0] = 0.293185;
v[1] = -0.0482363;
v[2] = 0.00000;
v3f(v);
v[0] = 0.284776;
v[1] = -0.0234634;
v[2] = 0.00000;
v3f(v);
v[0] = 0.273205;
v[1] = -1.04308e-07;
v[2] = 0.00000;
v3f(v);
v[0] = 0.258671;
v[1] = 0.0217522;
v[2] = 0.00000;
v3f(v);
v[0] = 0.241421;
v[1] = 0.0414213;
v[2] = 0.00000;
v3f(v);
v[0] = 0.221752;
v[1] = 0.0586706;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = 0.0732050;
v[2] = 0.00000;
v3f(v);
v[0] = 0.176537;
v[1] = 0.0847759;
v[2] = 0.00000;
v3f(v);
v[0] = 0.151764;
v[1] = 0.0931851;
v[2] = 0.00000;
v3f(v);
v[0] = 0.126105;
v[1] = 0.0982890;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
c[0] = 0;
c[1] = 0;
c[2] = 255;
c3s(c);
v[0] = -0.300000;
v[1] = 0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.300000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.300000;
v[2] = 0.00000;
v3f(v);
endpolygon();
closeobj();
button = NewArenaButton("VR Opaque", o,
-AW_BUTTONSIZE * 0.6, -AW_BUTTONSIZE * 0.5, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
AssocConstVarControlWithVar(button, object, ISTRANSPARENT, ObjFalse);
o = genobj();
makeobj(o);
bgnpolygon();
c[0] = 255;
c[1] = 0;
c[2] = 0;
c3s(c);
v[0] = 0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0982890;
v[1] = -0.126105;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0931852;
v[1] = -0.151764;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0847759;
v[1] = -0.176537;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0732051;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0586707;
v[1] = -0.221752;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0414214;
v[1] = -0.241421;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0217523;
v[1] = -0.258671;
v[2] = 0.00000;
v3f(v);
v[0] = -4.47035e-08;
v[1] = -0.273205;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0234633;
v[1] = -0.284776;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0482361;
v[1] = -0.293185;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0738947;
v[1] = -0.298289;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0999999;
v[1] = -0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.126105;
v[1] = -0.298289;
v[2] = 0.00000;
v3f(v);
v[0] = 0.151764;
v[1] = -0.293185;
v[2] = 0.00000;
v3f(v);
v[0] = 0.176537;
v[1] = -0.284776;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.273205;
v[2] = 0.00000;
v3f(v);
v[0] = 0.221752;
v[1] = -0.258671;
v[2] = 0.00000;
v3f(v);
v[0] = 0.241421;
v[1] = -0.241421;
v[2] = 0.00000;
v3f(v);
v[0] = 0.258671;
v[1] = -0.221752;
v[2] = 0.00000;
v3f(v);
v[0] = 0.273205;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.284776;
v[1] = -0.176537;
v[2] = 0.00000;
v3f(v);
v[0] = 0.293185;
v[1] = -0.151764;
v[2] = 0.00000;
v3f(v);
v[0] = 0.298289;
v[1] = -0.126105;
v[2] = 0.00000;
v3f(v);
v[0] = 0.300000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.298289;
v[1] = -0.0738949;
v[2] = 0.00000;
v3f(v);
v[0] = 0.293185;
v[1] = -0.0482363;
v[2] = 0.00000;
v3f(v);
v[0] = 0.284776;
v[1] = -0.0234634;
v[2] = 0.00000;
v3f(v);
v[0] = 0.273205;
v[1] = -1.04308e-07;
v[2] = 0.00000;
v3f(v);
v[0] = 0.258671;
v[1] = 0.0217522;
v[2] = 0.00000;
v3f(v);
v[0] = 0.241421;
v[1] = 0.0414213;
v[2] = 0.00000;
v3f(v);
v[0] = 0.221752;
v[1] = 0.0586706;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = 0.0732050;
v[2] = 0.00000;
v3f(v);
v[0] = 0.176537;
v[1] = 0.0847759;
v[2] = 0.00000;
v3f(v);
v[0] = 0.151764;
v[1] = 0.0931851;
v[2] = 0.00000;
v3f(v);
v[0] = 0.126105;
v[1] = 0.0982890;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
c[0] = 0;
c[1] = 0;
c[2] = 255;
c3s(c);
v[0] = -0.300000;
v[1] = 0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.300000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0982890;
v[1] = -0.0738948;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0931852;
v[1] = -0.0482362;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0847759;
v[1] = -0.0234633;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0732051;
v[1] = -2.98023e-08;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0586707;
v[1] = 0.0217523;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0414214;
v[1] = 0.0414213;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0217523;
v[1] = 0.0586706;
v[2] = 0.00000;
v3f(v);
v[0] = -4.47035e-08;
v[1] = 0.0732051;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0234633;
v[1] = 0.0847759;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0482361;
v[1] = 0.0931851;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0738947;
v[1] = 0.0982890;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0999999;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.300000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
c[0] = 255;
c[1] = 0;
c[2] = 255;
c3s(c);
v[0] = 0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0738948;
v[1] = 0.0982890;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0482362;
v[1] = 0.0931852;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0234633;
v[1] = 0.0847759;
v[2] = 0.00000;
v3f(v);
v[0] = -1.49012e-08;
v[1] = 0.0732051;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0217523;
v[1] = 0.0586707;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0414214;
v[1] = 0.0414214;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0586707;
v[1] = 0.0217523;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0732051;
v[1] = 1.49012e-08;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0847759;
v[1] = -0.0234633;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0931852;
v[1] = -0.0482362;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0982890;
v[1] = -0.0738947;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
endpolygon();
closeobj();
button = NewArenaButton("VR Transparent", o,
AW_BUTTONSIZE * 0.6, -AW_BUTTONSIZE * 0.5, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
AssocConstVarControlWithVar(button, object, ISTRANSPARENT, ObjTrue);
o = genobj();
makeobj(o);
c[0] = 128;
c[1] = 128;
c[2] = 128;
c3s(c);
bgnpolygon();
v[0] = 0.00000;
v[1] = 0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.114805;
v[1] = 0.277164;
v[2] = 0.00000;
v3f(v);
v[0] = -0.212132;
v[1] = 0.212132;
v[2] = 0.00000;
v3f(v);
v[0] = -0.277164;
v[1] = 0.114805;
v[2] = 0.00000;
v3f(v);
v[0] = -0.300000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.277164;
v[1] = -0.114805;
v[2] = 0.00000;
v3f(v);
v[0] = -0.212132;
v[1] = -0.212132;
v[2] = 0.00000;
v3f(v);
v[0] = -0.114805;
v[1] = -0.277164;
v[2] = 0.00000;
v3f(v);
v[0] = 0.00000;
v[1] = -0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.114805;
v[1] = -0.277164;
v[2] = 0.00000;
v3f(v);
v[0] = 0.212132;
v[1] = -0.212132;
v[2] = 0.00000;
v3f(v);
v[0] = 0.277164;
v[1] = -0.114805;
v[2] = 0.00000;
v3f(v);
v[0] = 0.300000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.277164;
v[1] = 0.114805;
v[2] = 0.00000;
v3f(v);
v[0] = 0.212132;
v[1] = 0.212132;
v[2] = 0.00000;
v3f(v);
v[0] = 0.114805;
v[1] = 0.277164;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = 0.00000;
v[1] = 0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0500000;
v[1] = 0.350000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0500000;
v[1] = 0.350000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = 0.250000;
v[1] = 0.444000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.131000;
v[1] = 0.338000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.219000;
v[1] = 0.287000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = 0.438000;
v[1] = 0.256000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.281000;
v[1] = 0.225000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.331000;
v[1] = 0.144000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = 0.500000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.350000;
v[1] = 0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.350000;
v[1] = -0.0500000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = 0.450000;
v[1] = -0.256000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.331000;
v[1] = -0.138000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.281000;
v[1] = -0.219000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = 0.262000;
v[1] = -0.444000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.231000;
v[1] = -0.287000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.144000;
v[1] = -0.338000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = 0.00000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.0500000;
v[1] = -0.350000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0500000;
v[1] = -0.350000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = -0.256000;
v[1] = -0.438000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.138000;
v[1] = -0.338000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.225000;
v[1] = -0.281000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = -0.450000;
v[1] = -0.269000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.287000;
v[1] = -0.225000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.344000;
v[1] = -0.138000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = -0.500000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.350000;
v[1] = -0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.350000;
v[1] = 0.0500000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = -0.450000;
v[1] = 0.262000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.344000;
v[1] = 0.138000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.287000;
v[1] = 0.225000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
v[0] = -0.250000;
v[1] = 0.438000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.225000;
v[1] = 0.281000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.131000;
v[1] = 0.331000;
v[2] = 0.00000;
v3f(v);
endpolygon();
closeobj();
button = NewArenaSlider("Arena Brightness", o,
-AW_BUTTONSIZE * 0.6, -AW_BUTTONSIZE * 1.5, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
AssocDirectControlWithVar(button, object, BRIGHTNESS);
o = genobj();
makeobj(o);
bgnpolygon();
c[0] = 255;
c[1] = 255;
c[2] = 255;
c3s(c);
v[0] = 0.00000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.250000;
v[1] = -0.450000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.450000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.500000;
v[1] = -0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.500000;
v[1] = 0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.450000;
v[1] = 0.250000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.250000;
v[1] = 0.450000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.00000;
v[1] = 0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = 0.450000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.150000;
v[1] = 0.400000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.200000;
v[1] = 0.250000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.250000;
v[1] = 0.150000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.350000;
v[1] = 0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.450000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.500000;
v[1] = -0.150000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.500000;
v[1] = -0.250000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.450000;
v[1] = -0.350000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.300000;
v[1] = -0.350000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.350000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.350000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0500000;
v[1] = 0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.250000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.300000;
v[1] = 0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.400000;
v[1] = 0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.400000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.350000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.400000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.00000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
c[0] = 191;
c[1] = 191;
c[2] = 191;
c3s(c);
v[0] = 0.00000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.400000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.350000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.400000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.400000;
v[1] = 0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.300000;
v[1] = 0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.250000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0500000;
v[1] = 0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.350000;
v[1] = -0.100000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.350000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.300000;
v[1] = -0.350000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.200000;
v[1] = -0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.200000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.150000;
v[1] = -0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0500000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.150000;
v[1] = -0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.150000;
v[1] = -0.400000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.00000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
endpolygon();
bgnpolygon();
c[0] = 63;
c[1] = 63;
c[2] = 63;
c3s(c);
v[0] = 0.00000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.150000;
v[1] = -0.400000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.200000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.150000;
v[1] = -0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = 0.100000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.0500000;
v[1] = 0.00000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.150000;
v[1] = -0.0500000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.200000;
v[1] = -0.200000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.200000;
v[1] = -0.300000;
v[2] = 0.00000;
v3f(v);
v[0] = -0.100000;
v[1] = -0.500000;
v[2] = 0.00000;
v3f(v);
endpolygon();
closeobj();
isoField = GetObjectVar("AddIsoControls", object, MAINDATASET);
if (!isoField) return ObjFalse;
MakeVar(isoField, MINMAX);
var = GetVar(isoField, MINMAX);
if (!var) return ObjFalse;
Array2CArray(db, var);
ChooseGoodRange(&(db[0]), &(db[1]));
button = NewArenaSlider("Isovalue", o,
AW_BUTTONSIZE * 0.6, -AW_BUTTONSIZE * 1.5, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
AssocDirectControlWithVar(button, object, ISOVAL);
SetVar(button, HIVALUE, NewReal(db[1]));
SetVar(button, LOVALUE, NewReal(db[0]));
SetTrackNot(button, true);
c[0] = 255;
c[1] = 0;
c[2] = 0;
#include "ScianGeoBrush.h"
button = NewArenaButton("Red", o,
-AW_BUTTONSIZE, -AW_BUTTONSIZE * 3.2, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
bc[0] = 1.0;
bc[1] = 0.0;
bc[2] = 0.0;
var = NewRealArray(1, 3L);
CArray2Array(var, bc);
AssocConstVarControlWithVar(button, object, BASECOLOR, var);
c[0] = 0;
c[1] = 255;
c[2] = 0;
#include "ScianGeoBrush.h"
button = NewArenaButton("Green", o,
0.0, -AW_BUTTONSIZE * 3.2, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
bc[0] = 0.0;
bc[1] = 1.0;
bc[2] = 0.0;
var = NewRealArray(1, 3L);
CArray2Array(var, bc);
AssocConstVarControlWithVar(button, object, BASECOLOR, var);
c[0] = 0;
c[1] = 0;
c[2] = 255;
#include "ScianGeoBrush.h"
button = NewArenaButton("Blue", o,
AW_BUTTONSIZE, -AW_BUTTONSIZE * 3.2, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
bc[0] = 0.0;
bc[1] = 0.0;
bc[2] = 1.0;
var = NewRealArray(1, 3L);
CArray2Array(var, bc);
AssocConstVarControlWithVar(button, object, BASECOLOR, var);
c[0] = 0;
c[1] = 255;
c[2] = 255;
#include "ScianGeoBrush.h"
button = NewArenaButton("Cyan", o,
-AW_BUTTONSIZE, -AW_BUTTONSIZE * 4.2, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
bc[0] = 0.0;
bc[1] = 1.0;
bc[2] = 1.0;
var = NewRealArray(1, 3L);
CArray2Array(var, bc);
AssocConstVarControlWithVar(button, object, BASECOLOR, var);
c[0] = 255;
c[1] = 0;
c[2] = 255;
#include "ScianGeoBrush.h"
button = NewArenaButton("Magenta", o,
0.0, -AW_BUTTONSIZE * 4.2, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
bc[0] = 1.0;
bc[1] = 0.0;
bc[2] = 1.0;
var = NewRealArray(1, 3L);
CArray2Array(var, bc);
AssocConstVarControlWithVar(button, object, BASECOLOR, var);
c[0] = 255;
c[1] = 255;
c[2] = 255;
#include "ScianGeoBrush.h"
button = NewArenaButton("White", o,
AW_BUTTONSIZE, -AW_BUTTONSIZE * 4.2, AW_NUDGE,
AW_BUTTONSIZE, AW_BUTTONSIZE);
PrefixList(contents, button);
SetVar(button, PARENT, contents);
bc[0] = 1.0;
bc[1] = 1.0;
bc[2] = 1.0;
var = NewRealArray(1, 3L);
CArray2Array(var, bc);
AssocConstVarControlWithVar(button, object, BASECOLOR, var);
#endif
return ObjTrue;
}
static ObjPtr AddIsoControls(object, panelContents)
ObjPtr object, panelContents;
/*Adds controls appropriate to an isosurface to panelContents*/
{
int left, right, top;
real initValue; /*The initial value of a slider*/
ObjPtr var; /*A variable of some sort*/
ObjPtr slider; /*A slider*/
ObjPtr textBox; /*A text box*/
ObjPtr corral; /*An icon corral*/
int width; /*Width of the area we can use*/
ObjPtr name; /*The name of the field*/
ObjPtr icon; /*An icon that represents the field*/
ObjPtr isoField; /*The field of the isosurface.*/
ObjPtr defaultIcon; /*The default icon of the field*/
real db[2]; /*Bounds of the isosurface*/
ObjPtr minMax; /*Array containing min and max*/
ObjPtr checkBox; /*Temporary check box*/
ObjPtr titleBox; /*Temporary title box*/
ObjPtr radioGroup; /*Group of radio buttons*/
ObjPtr mainDataset; /*The main dataset of the field*/
ObjPtr scale; /*Scale for slider*/
width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
left = MAJORBORDER;
top = CWINHEIGHT - MAJORBORDER;
/*Put in the isosurface corral at the left*/
corral = NewIconCorral(NULLOBJ,
left, left + ONECORRALWIDTH,
top - ONECORRALHEIGHT,
top,
0);
SetVar(corral, SINGLECORRAL, ObjTrue);
SetVar(corral, TOPDOWN, ObjTrue);
SetVar(corral, NAME, NewString("Source Field"));
PrefixList(panelContents, corral);
SetVar(corral, HELPSTRING,
NewString("This corral shows the dataset that is being used to make \
the isosurface. To replace it with another dataset, drag the icon of the other \
dataset into this corral."));
SetVar(corral, PARENT, panelContents);
SetVar(corral, REPOBJ, object);
SetMethod(corral, DROPINCONTENTS, DropInMainDatasetCorral);
/*Create the iso source text box*/
textBox = NewTextBox(left, left + ONECORRALWIDTH,
top - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT,
top - ONECORRALHEIGHT - TEXTBOXSEP,
0, "Isosurface Field Text", "Source Field");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
SetTextAlign(textBox, CENTERALIGN);
top = top - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT - MAJORBORDER;
right = left + ONECORRALWIDTH;
/*Put in an icon that represents the field*/
isoField = GetObjectVar("AddIsoControls", object, MAINDATASET);
if (!isoField) return ObjFalse;
MakeVar(isoField, MINMAX);
minMax = GetVar(isoField, MINMAX);
if (!minMax) return ObjFalse;
Array2CArray(db, minMax);
while (mainDataset = GetVar(isoField, MAINDATASET))
{
isoField = mainDataset;
}
MakeVar(isoField, NAME);
name = GetVar(isoField, NAME);
MakeVar(isoField, DEFAULTICON);
defaultIcon = GetVar(isoField, DEFAULTICON);
if (defaultIcon)
{
icon = NewObject(defaultIcon, 0);
SetVar(icon, NAME, name);
SetVar(icon, REPOBJ, isoField);
}
else
{
icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
}
SetVar(icon, ICONLOC, NULLOBJ);
DropIconInCorral(corral, icon);
ChooseGoodRange(&(db[0]), &(db[1]));
/*Create the isovalue slider*/
slider = TemplateSlider(IsosurfaceTemplate, "Isovalue", SCALE);
if (!slider)
{
return ObjFalse;
}
PrefixList(panelContents, slider);
SetVar(slider, PARENT, panelContents);
SetVar(slider, HELPSTRING,
NewString("This slider controls the isosurface value shown by an \
isosurface visualization object. Move the indicator to a new desired isosurface value and \
and a new isosurface will be calculated. If you don't want the isosurface \
to be recalculated, you can turn off the icon representing the isosurface \
before you do this. You can get multiple isosurfaces by duplicating the \
isosurface icon."));
scale = TemplateScale(IsosurfaceTemplate, "Iso scale",
SO_LEFT, false);
PrefixList(panelContents, scale);
SetVar(scale, PARENT, panelContents);
LinkScale(scale, slider);
MakeVar(object, ISOVAL);
var = GetRealVar("AddIsoControls", object, ISOVAL);
if (var)
{
initValue = GetReal(var);
}
else
{
initValue = (db[0] + db[1]) * 0.5;
SetVar(object, ISOVAL, NewReal(initValue));
}
SetSliderRange(slider, db[1], db[0], 0.0);
AssocDirectControlWithVar(slider, object, ISOVAL);
SetTrackNot(slider, true);
/*Create the value legend box*/
textBox = TemplateTextBox(IsosurfaceTemplate, "Isovalue Text", ONE_LINE, "Isovalue:");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
top -= TEXTBOXHEIGHT + MINORBORDER;
/*Create the value text box*/
textBox = TemplateTextBox(IsosurfaceTemplate, "Isovalue Readout", EDITABLE + WITH_PIT + ONE_LINE, "Isovalue");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
SetTextAlign(textBox, RIGHTALIGN);
SliderReadout(slider, textBox);
/*Make radio buttons for enclosing*/
radioGroup = NewRadioButtonGroup("Enclose Data");
SetVar(radioGroup, HELPSTRING,
NewString("These radio buttons allow you to specify whether high or \
are to be enclosed within the isosurfaces. This information is used to determine \
the direction of surface normals and is also used to improve the behavior of the \
isosurface routine in ambiguous cases."));
checkBox = TemplateRadioButton(IsosurfaceTemplate, "High Values");
SetVar(checkBox, HELPSTRING,
NewString("This button specifies that the shapes of the isosurface \
enclose values higher than the isosurface value."));
AddRadioButton(radioGroup, checkBox);
checkBox = TemplateRadioButton(IsosurfaceTemplate, "Low Values");
SetVar(checkBox, HELPSTRING,
NewString("This button specifies that the shapes of the isosurface \
enclose values lower than the isosurface value."));
AddRadioButton(radioGroup, checkBox);
/*Title box around it*/
titleBox = TemplateTitleBox(IsosurfaceTemplate, "Enclose");
PrefixList(panelContents, titleBox);
SetVar(titleBox, PARENT, panelContents);
/*Add the radio button group*/
PrefixList(panelContents, radioGroup);
SetVar(radioGroup, PARENT, panelContents);
/*Set its value*/
if (!GetIntVar("AddIsoControls", object, ENCLOSELOW))
{
SetVar(object, ENCLOSELOW, NewInt(0));
}
AssocDirectControlWithVar(radioGroup, object, ENCLOSELOW);
/*Get Normals*/
titleBox = TemplateTitleBox(IsosurfaceTemplate, "Get Normals");
PrefixList(panelContents, titleBox);
SetVar(titleBox, PARENT, panelContents);
radioGroup = NewRadioButtonGroup("Normal Radio");
SetVar(radioGroup, HELPSTRING,
NewString("These radio buttons allow you to specify whether the \
vertex normals of the resulting surface are taken from the geometry or \
from the data. Taking the normals from the data is more accurate and \
produces a smoother surface. \
Taking the normals from the geometry is faster."));
checkBox = TemplateRadioButton(IsosurfaceTemplate, "From Data");
SetVar(checkBox, HELPSTRING,
NewString("This button specifies that the surface normals of the \
isosurface be taken from the gradient of the data, run through trilinear \
interpolation."));
AddRadioButton(radioGroup, checkBox);
checkBox = TemplateRadioButton(IsosurfaceTemplate, "From Geometry");
SetVar(checkBox, HELPSTRING,
NewString("This button specifies that the surface normals of the \
isosurface be calculated from the geometry using Phong lighting."));
AddRadioButton(radioGroup, checkBox);
/*Add the radio button group*/
PrefixList(panelContents, radioGroup);
SetVar(radioGroup, PARENT, panelContents);
AssocDirectControlWithVar(radioGroup, object, NORMALSFROM);
return ObjTrue;
}
#define NHIST 20
#define HISTFRACT 0.25
#define MAXDESIRABLE 2000
static ObjPtr MakeIsoVal(object)
ObjPtr object;
/*Makes the isoval of an object*/
{
real db[2];
real isoVal;
ObjPtr repObj;
ObjPtr minMax;
long histogram[NHIST];
int k;
int nTraversalDims;
long *traversalDims;
long *traversalSteps;
long *index;
real d;
long total;
long runningTotal;
int subDivision;
int advantage;
int whichDim;
repObj = GetObjectVar("MakeIsoVal", object, MAINDATASET);
if (!repObj)
{
return ObjFalse;
}
MakeVar(repObj, MINMAX);
minMax = GetFixedArrayVar("MakeIsoVal", repObj, MINMAX, 1, 2L);
if (!minMax)
{
return ObjFalse;
}
Array2CArray(db, minMax);
ChooseGoodRange(&(db[0]), &(db[1]));
/*Now we have the range, get the iso value*/
SetCurField(FIELD1, repObj);
/*Get the information on traversing the dataset*/
nTraversalDims = CountTraversalDims(FIELD1);
if (nTraversalDims)
{
traversalDims = (long *) Alloc(sizeof(long) * nTraversalDims);
traversalSteps = (long *) Alloc(sizeof(long) * nTraversalDims);
index = (long *) Alloc(sizeof(long) * nTraversalDims);
GetTraversalDims(FIELD1, traversalDims);
/*Figure out how coarsely to traverse dataset*/
runningTotal = 0;
advantage = 1;
for (k = 0; k < nTraversalDims; ++k)
{
runningTotal *= traversalDims[k];
advantage *= 2;
}
subDivision = 1;
while (runningTotal > MAXDESIRABLE)
{
++subDivision;
runningTotal /= advantage;
}
/*Zero the histogram*/
for (k = 0; k < NHIST; ++k)
{
histogram[k] = 0;
}
/*Zero the index*/
for (k = 0; k < nTraversalDims; ++k)
{
index[k] = 0;
}
/*Fill up the histogram*/
do
{
d = SelectFieldScalar(FIELD1, index);
if (d != missingData)
{
k = ((real) NHIST) * (d - db[0]) / (db[1] - db[0]);
if (k < 0) k = 0;
if (k >= NHIST) k = NHIST - 1;
++histogram[k];
}
/*Advance to next sample*/
for (whichDim = 0; whichDim < nTraversalDims; ++whichDim)
{
if (traversalDims[whichDim] > 0)
{
index[whichDim] += subDivision;
if (index[whichDim] >= traversalDims[whichDim])
{
index[whichDim] = 0;
}
else
{
break;
}
}
}
} while (whichDim < nTraversalDims); /*Break is based on advance*/
/*Now choose from histogram*/
total = 0;
for (k = 0; k < NHIST; ++k)
{
total += histogram[k];
}
runningTotal = 0;
for (k = NHIST - 1; k > 1; --k)
{
runningTotal += histogram[k];
if (runningTotal > HISTFRACT * total)
{
break;
}
}
++k;
if (k >= NHIST) --k;
isoVal = k * (db[1] - db[0]) / NHIST + db[0];
SAFEFREE(index);
SAFEFREE(traversalDims);
SAFEFREE(traversalSteps);
}
else
{
isoVal = (db[0] + db[1]) * 0.5;
}
SetVar(object, ISOVAL, NewReal(isoVal));
return ObjTrue;
}
Bool Escape()
{
int x, y;
if (runningScript)
{
return false;
}
else
{
return Mouse(&x, &y);
}
}
ObjPtr NewMakeIsoSurface(object)
ObjPtr object;
/*Makes a SURFACE in isosurface vis object*/
{
ObjPtr repObj;
long dims[3];
long index[3];
double time;
ObjPtr var;
real isoVal;
Bool encloseLow;
ObjPtr surface;
int isoLevel;
ObjPtr lastIJK, nextIJK;
ObjPtr lastData, nextData, nextPlusData;
Bool useDeltas;
ObjPtr deltas;
time = Clock();
repObj = GetObjectVar("MakeIsoSurface", object, MAINDATASET);
if (!repObj)
{
return ObjFalse;
}
/*Get the iso value*/
MakeVar(object, ISOVAL);
var = GetRealVar("MakeIsoSurface", object, ISOVAL);
if (!var)
{
return ObjFalse;
}
isoVal = GetReal(var);
encloseLow = GetPredicate(object, ENCLOSELOW);
useDeltas = GetPredicate(object, NORMALSFROM) ? false : true;
LongOperation();
/*Get the isolevel to start at*/
var = GetVar(object, ISOLEVEL);
if (var)
{
isoLevel = GetInt(var);
}
else
{
isoLevel = 0;
}
SetCurField(FIELD1, repObj);
SetCurForm(FORMFIELD, repObj);
if (CountTraversalDims(FIELD1) != 3)
{
ReportError("MakeIsoSurface", "Wrong number of traversal dimensions");
return ObjFalse;
}
GetTraversalDims(FIELD1, dims);
if (dims[0] <= 1 ||
dims[1] <= 1 ||
dims[2] <= 1)
{
SetVar(object, SURFACE, NULLOBJ);
return ObjTrue;
}
if (isoLevel)
{
/*This is just a continuation of a previous incarnation*/
if (isoLevel >= dims[2])
{
/*Escape clause; just return*/
return ObjTrue;
}
surface = GetVar(object, SURFACE);
if (!surface)
{
surface = NewPicture();
SetVar(object, SURFACE, surface);
}
lastIJK = GetVar(object, LASTIJKVERTICES);
if (!lastIJK)
{
ReportError("MakeIsoSurface", "No LASTIJKVERTICES");
return ObjFalse;
}
nextIJK = GetVar(object, NEXTIJKVERTICES);
if (!nextIJK)
{
ReportError("MakeIsoSurface", "No NEXTIJKVERTICES");
return ObjFalse;
}
lastData = GetVar(object, LASTDATA);
if (!lastData)
{
ReportError("MakeIsoSurface", "No LASTDATA");
return ObjFalse;
}
nextData = GetVar(object, NEXTDATA);
if (!nextData)
{
ReportError("MakeIsoSurface", "No NEXTDATA");
return ObjFalse;
}
deltas = GetVar(object, DELTAS);
}
else
{
long arrayDims[3];
real *elements;
long nElements;
surface = NewPicture();
SetVar(surface, REPOBJ, object);
SetVar(object, SURFACE, surface);
arrayDims[0] = dims[0];
arrayDims[1] = dims[1];
arrayDims[2] = 3;
/*Make data arrays*/
lastData = NewArray(AT_REAL, 2, arrayDims);
SetVar(object, LASTDATA, lastData);
nextData = NewArray(AT_REAL, 2, arrayDims);
SetVar(object, NEXTDATA, nextData);
if (useDeltas)
{
deltas = NewArray(AT_REAL, 3, arrayDims);
/*Make them all missing*/
nElements = arrayDims[0] * arrayDims[1] * arrayDims[2];
elements = ELEMENTS(deltas);
do
{
--nElements;
elements[nElements] = missingData;
} while (nElements);
}
else
{
deltas = NULLOBJ;
}
/*Fill in the data*/
index[0] = 0;
index[1] = 0;
index[2] = 0;
elements = ELEMENTS(lastData);
StuffIJPlane(elements, FIELD1, 0, index);
/*Get last data*/
index[0] = 0;
index[1] = 0;
index[2] = 0;
StuffIJPlane((real *) ELEMENTS(lastData), FIELD1, 0, index);
/*Get next data*/
index[0] = 0;
index[1] = 0;
index[2] = 1;
StuffIJPlane((real *) ELEMENTS(nextData), FIELD1, 0, index);
/*Make IJK arrays*/
lastIJK = NewArray(AT_POINTER, 3, arrayDims);
SetVar(object, LASTIJKVERTICES, lastIJK);
nextIJK = NewArray(AT_POINTER, 3, arrayDims);
SetVar(object, NEXTIJKVERTICES, nextIJK);
/*Fill in just the lastIJK*/
StuffIJKVertices(ELEMENTS(lastIJK), ELEMENTS(lastData), ELEMENTS(nextData), deltas ? ELEMENTS(deltas) : 0, FIELD1, FORMFIELD, dims, 0, surface, isoVal, encloseLow);
}
nextPlusData = NewArray(AT_REAL, 2, dims);
/*Go through and do the isosurface*/
while (isoLevel < dims[2] - 1)
{
index[0] = 0;
index[1] = 0;
index[2] = isoLevel + 2;
/*Get next plus data*/
if (isoLevel < dims[2] - 2)
{
StuffIJPlane((real *) ELEMENTS(nextPlusData), FIELD1, 0, index);
}
/*Get next IJK's*/
StuffIJKVertices(ELEMENTS(nextIJK), ELEMENTS(nextData), ELEMENTS(nextPlusData), deltas ? ELEMENTS(deltas) : 0, FIELD1, FORMFIELD, dims, isoLevel + 1, surface, isoVal, encloseLow);
/*Now go through and make the isosurface*/
for (index[0] = 0; index[0] < dims[0] - 1; ++index[0])
{
for (index[1] = 0; index[1] < dims[1] - 1; ++index[1])
{
NewIsoHex(ELEMENTS(lastData), ELEMENTS(nextData),
ELEMENTS(lastIJK), ELEMENTS(nextIJK),
index, dims,
isoVal, surface, encloseLow);
}
}
/*Shift down ijk vertices*/
var = lastIJK;
lastIJK = nextIJK;
nextIJK = var;
/*Shift down data*/
var = lastData;
lastData = nextData;
nextData = nextPlusData;
nextPlusData = var;
/*Go to next isoLevel*/
++isoLevel;
#if 0
/*Insert escape code here*/
if (Escape())
{
SetVar(object, LASTIJKVERTICES, lastIJK);
SetVar(object, NEXTIJKVERTICES, nextIJK);
SetVar(object, LASTDATA, lastData);
SetVar(object, NEXTDATA, nextData);
SetVar(object, ISOLEVEL, NewInt(isoLevel));
SetVar(object, DELTAS, deltas);
DeferMessage(object, MAKEISOSURFACE);
return ObjFalse;
}
#endif
}
if (!deltas)
{
CalcPictureNormals(surface);
}
SetVar(object, SURFACE, surface);
MakeVar(object, CPALETTE);
SetVar(surface, CPALETTE, GetVar(object, CPALETTE));
return ObjTrue;
}
static ObjPtr MakeIsoSurfaceLater(object)
ObjPtr object;
/*Sets up to make an isosurface later*/
{
FuncTyp method;
SetVar(object, ISOLEVEL, NewInt(0));
method = GetMethod(object, MAKEISOSURFACE);
if (method)
{
(*method)(object);
}
return ObjTrue;
}
static MakeMethod MakeIsoColors(object)
ObjPtr object;
/*Makes an isosurface's COLORS and COLOROBJ variable. By default,
it looks for the main dataset.*/
{
ObjPtr colorObj;
ObjPtr mainDataset;
ObjPtr var;
colorObj = GetVar(object, MAINDATASET);
while (var = GetVar(colorObj, MAINDATASET))
{
colorObj = var;
}
/*See if there's a color object within the main dataset*/
if (colorObj)
{
var = GetVar(colorObj, COLOROBJ);
if (var)
{
colorObj = var;
}
while (var = GetVar(colorObj, MAINDATASET))
{
colorObj = var;
}
}
SetVar(object, COLOROBJ, colorObj);
SetVar(object, COLORS, NewInt(0));
return ObjTrue;
}
void InitIsosurfaces()
{
ObjPtr icon;
int i, j, k;
int initState[2][2][2];
int *statePtr;
int stateFlags, tempFlags;
#ifdef GRAPHICS
Object o;
float n[3], v[3];
short c[3];
#endif
/*Initialize the Free space*/
parts[0] . next = 0;
for (k = 1; k < NPARTS; ++k)
{
parts[k] . next = &(parts[k - 1]);
}
freePart = &(parts[NPARTS - 1]);
/*Zero the polygons*/
for (i = 0; i < 256; ++i)
{
for (j = 0; j < MAXNPOLYS; ++j)
{
presetPolys[i][j] = 0;
}
}
/*Fill the polygons*/
for (stateFlags = 0; stateFlags < 256; ++stateFlags)
{
/*Fill initState based on stateFlag*/
tempFlags = stateFlags;
statePtr = &(initState[0][0][0]);
for (k = 0; k < 8; ++k)
{
*statePtr++ = (tempFlags & 128) ? 1 : 0;
tempFlags = tempFlags << 1;
}
if (!CacheIso(initState, stateFlags, false))
{
CacheIso(initState, stateFlags, true);
}
}
/*Class for an isosurface*/
isoClass = NewObject(visSurface, 0);
AddToReferenceList(isoClass);
DefineFixedClass(isoClass, CLASS_ISOSURFACE, "visIso");
SetVar(isoClass, NAME, NewString("Isosurface"));
SetMethod(isoClass, ADDCONTROLS, AddIsoControls);
SetVar(isoClass, DEFAULTICON, icon = NewObject(visIcon, 0));
SetVar(isoClass, NORMALSFROM, NewInt(0));
AddSnapVar(isoClass, NORMALSFROM);
#ifdef GRAPHICS
#include "ScianGeoIsosurface.h"
SetVar(icon, CACHEGRAPHICS, NewInt(o));
#endif
SetVar(icon, WHICHICON, NewInt(ICONISOSURFACE));
SetVar(icon, NAME, NewString("Isosurface"));
SetVar(icon, HELPSTRING,
NewString("This icon represents an isosurface. \
The isosurface object generates surfaces of constant value through 3-D \
scalar datasets defined over structured grids. Some day it will work with \
nonstructured grids, as well."));
icon = NewIcon(0, 0, ICONISOSURFACE, "Isosurface");
SetVar(icon, HELPSTRING,
NewString("Select this icon to show controls for the isosurface, such \
as the isosurface level and the treatment of missing data."));
SetVar(isoClass, CONTROLICON, icon);
SetVar(icon, PANELHELP, NewString("The isosurface object displays 3-D scalar \
fields as isosurfaces, or surfaces of constant value, in 3-space. This control panel \
lets you change the parameters of the isosurface."));
SetVar(isoClass, SAVEEXTENSION, NewString("isoSurface"));
SetVar(isoClass, HANDLEMISSING, NewInt(0));
AddSnapVar(isoClass, HANDLEMISSING);
SetMethod(isoClass, ISOVAL, MakeIsoVal);
AddSnapVar(isoClass, ISOVAL);
DeclareDependency(isoClass, SURFACE, ISOVAL);
DeclareDependency(isoClass, SURFACE, ENCLOSELOW);
AddSnapVar(isoClass, ENCLOSELOW);
SetVar(isoClass, ENCLOSELOW, NewInt(0));
DeclareIndirectDependency(isoClass, SURFACE, MAINDATASET, CHANGED);
DeclareDependency(isoClass, SURFACE, MAINDATASET);
DeclareDependency(isoClass, SURFACE, NORMALSFROM);
SetMethod(isoClass, MAKEISOSURFACE, NewMakeIsoSurface);
SetMethod(isoClass, SURFACE, MakeIsoSurfaceLater);
SetMethod(isoClass, COLORS, MakeIsoColors);
SetMethod(isoClass, ADDVRCONTROLS, AddIsoVRControls);
DefineVisMapping(DS_HASFORM | DS_HASFIELD, 3, 3, -1, isoClass);
DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_VECTOR, 3, 3, -1, isoClass);
}
void KillIsosurfaces()
{
DeleteThing(isoClass);
}
|