home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * An implementation of the marching cube algorithm (test file). *
- * *
- * Gershon Elber, Dec 1992. *
- ******************************************************************************/
-
- #include <stdio.h>
- #include "irit_sm.h"
- #include "mrchcube.h"
- #include "iritprsr.h"
- #include "allocate.h"
-
- #define INPUT_ASCII 1
- #define INPUT_INTEGER 2
- #define INPUT_LONG 3
- #define INPUT_BYTE 4
- #define INPUT_FLOAT 5
- #define INPUT_DOUBLE 6
-
-
- static RealType
- CubeWidth = 0.1;
- static int
- DumpBinary = FALSE,
- DumpOneLayer = 0,
- DumpPolySkip = 1,
- SkipInputData = 1,
- DumpNormals = 1,
- DataWidth = 100,
- DataDepth = 100,
- DataHeight = 100,
- InputFormat = INPUT_ASCII;
-
- static RealType GetOneScalar(void);
- static MCCubeCornerScalarStruct *GetCube(CagdBType FirstTime);
- static void EstimateGradient(MCCubeCornerScalarStruct *CCS);
- static void DumpPolys(MCPolygonStruct *Polys);
- static void DumpPolysBinary(MCPolygonStruct *Polys);
-
- /******************************************************************************
- * Test routine of Marching Cubes. *
- * -t Threshold : the level (real number) to compute iso surface at. *
- * -d Width Depth Height : dimension of sampled data. *
- * -f [ascii | int | long | byte | float | double] : single datum format. *
- * -s n : dump out only every n polygons. 1 means dump all polygons. *
- * -S n : skip n rows/cols/planes in input data. 1 means skip nothing. *
- * -o n : process only layer number n. *
- * -n : do not do normals. *
- ******************************************************************************/
- void main(int argc, char **argv)
- {
- MCCubeCornerScalarStruct *CCS;
- RealType Threshold = 10.5;
-
- while (argc > 1) {
- if (argv[1][0] == '-') {
- switch (argv[1][1]) {
- case 't':
- sscanf(argv[2], "%lf", &Threshold);
- fprintf(stderr, "Threshold set at %lf\n", Threshold);
- argc -= 2;
- argv += 2;
- break;
- case 'd':
- sscanf(argv[2], "%d", &DataWidth);
- sscanf(argv[3], "%d", &DataDepth);
- sscanf(argv[4], "%d", &DataHeight);
- fprintf(stderr, "Dimensions %dx%dx%d\n",
- DataWidth, DataDepth, DataHeight);
- argc -= 4;
- argv += 4;
- break;
- case 'f':
- if (strncmp(argv[2], "ascii", 3) == 0)
- InputFormat = INPUT_ASCII;
- else if (strncmp(argv[2], "int", 3) == 0)
- InputFormat = INPUT_INTEGER;
- else if (strncmp(argv[2], "long", 3) == 0)
- InputFormat = INPUT_LONG;
- else if (strncmp(argv[2], "byte", 3) == 0)
- InputFormat = INPUT_BYTE;
- else if (strncmp(argv[2], "float", 3) == 0)
- InputFormat = INPUT_FLOAT;
- else if (strncmp(argv[2], "double", 3) == 0)
- InputFormat = INPUT_DOUBLE;
- else
- {
- fprintf(stderr, "Unknown input format \"%s\"\n",
- argv[2]);
- exit(1);
- }
- fprintf(stderr, "Input format is set to \"%s\"\n",
- argv[2]);
- argc -= 2;
- argv += 2;
- break;
- case 's':
- sscanf(argv[2], "%d", &DumpPolySkip);
- fprintf(stderr, "DumpPolySkip is %d\n", DumpPolySkip);
- argc -= 2;
- argv += 2;
- break;
- case 'S':
- sscanf(argv[2], "%d", &SkipInputData);
- fprintf(stderr, "SkipInputData is %d\n", SkipInputData);
- CubeWidth *= SkipInputData;
- argc -= 2;
- argv += 2;
- break;
- case 'n':
- DumpNormals = 0;
- fprintf(stderr, "Normal are not dumped\n");
- argc--;
- argv++;
- break;
- case 'b':
- DumpBinary = TRUE;
- fprintf(stderr, "Binary data is dumped out\n");
- argc--;
- argv++;
- break;
- case 'o':
- sscanf(argv[2], "%d", &DumpOneLayer);
- fprintf(stderr, "DumpOneLayer is %d\n", DumpOneLayer);
- argc -= 2;
- argv += 2;
- break;
- default:
- fprintf(stderr, "Unknown option %c\n", argv[1][1]);
- exit(1);
- }
- }
- else {
- fprintf(stderr, "Unknown command line %s\n", argv[1]);
- exit(1);
- }
- }
-
- GetCube(TRUE);
-
- if (DumpBinary) {
- MCPolygonStruct
- *AllPolys = NULL;
-
- while (CCS = GetCube(FALSE)) {
- MCPolygonStruct *PolyTmp,
- *Polys = MCThresholdCube(CCS, Threshold);
-
- if (Polys != NULL) {
- for (PolyTmp = Polys;
- PolyTmp -> Pnext != NULL;
- PolyTmp = PolyTmp -> Pnext);
- PolyTmp -> Pnext = AllPolys;
- AllPolys = Polys;
- }
- }
-
- DumpPolysBinary(AllPolys);
- }
- else {
- printf("[OBJECT MC\n");
- while (CCS = GetCube(FALSE)) {
- MCPolygonStruct
- *Polys = MCThresholdCube(CCS, Threshold);
-
- DumpPolys(Polys);
- }
- printf("]\n");
- }
-
- exit(0);
- }
-
- /******************************************************************************
- * Read stdin and returns one real at a time. *
- ******************************************************************************/
- static RealType GetOneScalar(void)
- {
- short i;
- long l;
- float f;
- double d;
- RealType r;
-
- switch (InputFormat) {
- case INPUT_ASCII:
- if (scanf("%lf", &r) != 1)
- return INFINITY;
- break;
- case INPUT_INTEGER:
- i = getchar();
- r = getchar() * 256 + i;
- break;
- case INPUT_LONG:
- if (read(0, &l, 4) != 4)
- return INFINITY;
- r = l;
- break;
- case INPUT_BYTE:
- if ((r = getchar()) == EOF)
- return INFINITY;
- break;
- case INPUT_FLOAT:
- if (read(0, &f, 4) != 4)
- return INFINITY;
- r = f;
- break;
- case INPUT_DOUBLE:
- if (read(0, &d, 8) != 8)
- return INFINITY;
- r = d;
- break;
- default:
- fprintf(stderr, "Input format requested not supported.\n");
- exit(1);
- break;
- }
-
- return r;
- }
-
- /******************************************************************************
- * Read stdin and returns one cube at a time. *
- ******************************************************************************/
- static MCCubeCornerScalarStruct *GetCube(CagdBType FirstTime)
- {
- static MCCubeCornerScalarStruct
- CCS;
- static int
- ProcessedOneLayer = FALSE,
- LayerCountX = -1,
- LayerCountY = 0,
- LayerNumber = -1;
- static RealType
- *LayerOne = NULL,
- *LayerTwo = NULL;
- int i, j;
- RealType *p;
-
- if (FirstTime) {
- /* Initialize the CCS constant data */
- CCS.CubeDim[0] = CubeWidth;
- CCS.CubeDim[1] = CubeWidth;
- CCS.CubeDim[2] = CubeWidth;
- LayerNumber = -SkipInputData;
- LayerCountX = -1;
- LayerCountY = 0;
-
- if (LayerOne == NULL) {
- LayerOne = (RealType *) IritMalloc(sizeof(RealType) * DataWidth *
- DataDepth);
- LayerTwo = (RealType *) IritMalloc(sizeof(RealType) * DataWidth *
- DataDepth);
- }
-
- for (p = LayerTwo, i = 0; i < DataWidth * DataDepth; i++)
- if ((*p++ = GetOneScalar()) == INFINITY)
- return NULL;
- return NULL;
- }
-
- if (LayerCountX == -1) { /* Read the next layer. */
- do {
- LayerNumber += SkipInputData;
- if ((DumpOneLayer > 0 && ProcessedOneLayer) ||
- LayerNumber >= DataHeight - 1) {
- IritFree((VoidPtr) LayerOne);
- IritFree((VoidPtr) LayerTwo);
- return NULL;
- }
-
- p = LayerOne;
- LayerOne = LayerTwo;
- LayerTwo = p;
-
- for (j = 0; j < SkipInputData; j++) {
- for (p = LayerTwo, i = 0; i < DataWidth * DataDepth; i++)
- if ((*p++ = GetOneScalar()) == INFINITY)
- return NULL;
- }
-
- LayerCountX = 0;
- LayerCountY = 0;
-
- fprintf(stderr, "Doing layer %d\n", LayerNumber);
- }
- while (DumpOneLayer > LayerNumber);
-
- ProcessedOneLayer = TRUE;
- }
-
-
- CCS.Vrtx0Lctn[0] = LayerCountX * CubeWidth / SkipInputData;
- CCS.Vrtx0Lctn[1] = LayerCountY * CubeWidth / SkipInputData;
- CCS.Vrtx0Lctn[2] = LayerNumber * CubeWidth / SkipInputData;
- CCS.Corners[0] = LayerOne[LayerCountY * DataWidth + LayerCountX];
- CCS.Corners[1] = LayerOne[LayerCountY * DataWidth +
- LayerCountX + SkipInputData];
- CCS.Corners[2] = LayerOne[(LayerCountY + SkipInputData) * DataWidth +
- LayerCountX + SkipInputData];
- CCS.Corners[3] = LayerOne[(LayerCountY + SkipInputData) * DataWidth +
- LayerCountX];
- CCS.Corners[4] = LayerTwo[LayerCountY * DataWidth + LayerCountX];
- CCS.Corners[5] = LayerTwo[LayerCountY * DataWidth +
- LayerCountX + SkipInputData];
- CCS.Corners[6] = LayerTwo[(LayerCountY + SkipInputData) * DataWidth +
- LayerCountX + SkipInputData];
- CCS.Corners[7] = LayerTwo[(LayerCountY + SkipInputData) * DataWidth +
- LayerCountX];
-
- EstimateGradient(&CCS);
-
- LayerCountX += SkipInputData;
- if (LayerCountX >= DataWidth - SkipInputData) {
- LayerCountY += SkipInputData;
- LayerCountX = 0;
- if (LayerCountY >= DataDepth - SkipInputData)
- LayerCountX = -1; /* No more data */
- }
-
- return &CCS;
- }
-
- /******************************************************************************
- * Estimate the gradient at the eight vertices, by first order difference. *
- * Note gradient is estimated from this cube's eight vertices only. *
- ******************************************************************************/
- static void EstimateGradient(MCCubeCornerScalarStruct *CCS)
- {
- CCS -> GradientX[0] =
- CCS -> GradientX[1] =
- CCS -> Corners[1] - CCS -> Corners[0];
- CCS -> GradientX[2] =
- CCS -> GradientX[3] =
- CCS -> Corners[2] - CCS -> Corners[3];
- CCS -> GradientX[4] =
- CCS -> GradientX[5] =
- CCS -> Corners[5] - CCS -> Corners[4];
- CCS -> GradientX[6] =
- CCS -> GradientX[7] =
- CCS -> Corners[6] - CCS -> Corners[7];
-
- CCS -> GradientY[0] =
- CCS -> GradientY[3] =
- CCS -> Corners[3] - CCS -> Corners[0];
- CCS -> GradientY[1] =
- CCS -> GradientY[2] =
- CCS -> Corners[2] - CCS -> Corners[1];
- CCS -> GradientY[4] =
- CCS -> GradientY[7] =
- CCS -> Corners[7] - CCS -> Corners[4];
- CCS -> GradientY[5] =
- CCS -> GradientY[6] =
- CCS -> Corners[6] - CCS -> Corners[5];
-
- CCS -> GradientZ[0] =
- CCS -> GradientZ[4] =
- CCS -> Corners[4] - CCS -> Corners[0];
- CCS -> GradientZ[1] =
- CCS -> GradientZ[5] =
- CCS -> Corners[5] - CCS -> Corners[1];
- CCS -> GradientZ[2] =
- CCS -> GradientZ[6] =
- CCS -> Corners[6] - CCS -> Corners[2];
- CCS -> GradientZ[3] =
- CCS -> GradientZ[7] =
- CCS -> Corners[7] - CCS -> Corners[3];
-
- CCS -> HasGradient = TRUE;
- }
-
- /******************************************************************************
- * Dumps the polygons to stdout (Only triangles). *
- ******************************************************************************/
- static void DumpPolys(MCPolygonStruct *Polys)
- {
- static int
- DumpPolySkipLcl = 1;
- char *VrtxFrmt;
-
- if (DumpNormals)
- VrtxFrmt = "\t[[NORMAL %9.6lg %9.6lg %9.6lg] %9.6lg %9.6lg %9.6lg]\n";
- else
- VrtxFrmt = "\t[%9.6lg %9.6lg %9.6lg]\n";
-
- while (Polys) {
- int i;
- MCPolygonStruct
- *Poly = Polys;
-
- Polys = Polys -> Pnext;
-
- /* Skip polygons in the output (so we can display them - they */
- /* are just too many of them. */
- if (--DumpPolySkipLcl <= 0) {
- DumpPolySkipLcl = DumpPolySkip;
-
- for (i = 2; i < Poly -> NumOfVertices - 1; i++) {
- printf(" [POLYGON 3\n");
- if (DumpNormals) {
- printf(VrtxFrmt,
- Poly -> N[0][0], Poly -> N[0][1], Poly -> N[0][2],
- Poly -> V[0][0], Poly -> V[0][1], Poly -> V[0][2]);
- printf(VrtxFrmt,
- Poly -> N[i-1][0], Poly -> N[i-1][1], Poly -> N[i-1][2],
- Poly -> V[i-1][0], Poly -> V[i-1][1], Poly -> V[i-1][2]);
- printf(VrtxFrmt,
- Poly -> N[i][0], Poly -> N[i][1], Poly -> N[i][2],
- Poly -> V[i][0], Poly -> V[i][1], Poly -> V[i][2]);
- }
- else {
- printf(VrtxFrmt,
- Poly -> V[0][0], Poly -> V[0][1], Poly -> V[0][2]);
- printf(VrtxFrmt,
- Poly -> V[i-1][0], Poly -> V[i-1][1], Poly -> V[i-1][2]);
- printf(VrtxFrmt,
- Poly -> V[i][0], Poly -> V[i][1], Poly -> V[i][2]);
- }
- printf(" ]\n");
- }
- }
-
- IritFree((VoidPtr) Poly);
- }
- }
-
- /******************************************************************************
- * Dumps triangles to stdout as binary file. *
- ******************************************************************************/
- static void DumpPolysBinary(MCPolygonStruct *Polys)
- {
- static int
- DumpPolySkipLcl = 1;
- int i, j, Handler;
- IPPolygonStruct *Pl,
- *PlHead = NULL;
- IPObjectStruct *PObj;
-
- while (Polys) {
- IPVertexStruct *V1, *V2, *V3;
- int i;
- MCPolygonStruct
- *Poly = Polys;
-
- Polys = Polys -> Pnext;
-
- /* Skip polygons in the output (so we can display them - they */
- /* are just too many of them. */
- if (--DumpPolySkipLcl <= 0) {
- DumpPolySkipLcl = DumpPolySkip;
-
- for (i = 2; i < Poly -> NumOfVertices - 1; i++) {
- V3 = IPAllocVertex(0, 0, NULL, NULL);
- V2 = IPAllocVertex(0, 0, NULL, V3);
- V1 = IPAllocVertex(0, 0, NULL, V2);
-
- Pl = IPAllocPolygon(0, 0, V1, PlHead);
- PlHead = Pl;
-
- for (j = 0; j < 3; j++) {
- V1 -> Coord[j] = Poly -> V[0][j];
- V2 -> Coord[j] = Poly -> V[i - 1][j];
- V3 -> Coord[j] = Poly -> V[i][j];
- }
-
- if (DumpNormals) {
- for (j = 0; j < 3; j++) {
- V1 -> Normal[j] = Poly -> N[0][j];
- V2 -> Normal[j] = Poly -> N[i - 1][j];
- V3 -> Normal[j] = Poly -> N[i][j];
- }
- IP_SET_NORMAL_VRTX(V1);
- IP_SET_NORMAL_VRTX(V2);
- IP_SET_NORMAL_VRTX(V3);
- }
- }
- }
-
- IritFree((VoidPtr) Poly);
- }
-
- PObj = IPAllocObject("MCH", IP_OBJ_POLY, NULL);
- PObj -> U.Pl = PlHead;
-
- Handler = IritPrsrOpenStreamFromFile(stdout, FALSE, TRUE, FALSE);
- IritPrsrPutObjectToHandler(Handler, PObj);
- IritPrsrCloseStream(Handler, TRUE);
-
- IPFreeObject(PObj);
- }
-
-