This is h3D.c in view mode; [Download] [Up]
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <string.h>
#include "h3D.h"
#include "hutil.h"
#define MARGINSIZE 0.035
#define PI 3.1415926536
#define TWOPI (2.0*PI)
#define HALFPI (PI/2.0)
#define QUARTERPI (HALFPI/2.0)
#define THREEHALFPI (PI + HALFPI)
#define THREEQUARTERPI (HALFPI+QUARTERPI)
#define RAD_TO_DEG 180.0/PI
#define DEG_TO_RAD PI/180.0
/*
* Internal C Functions
*/
static void h3D_genLegoPoints(display disp);
static void h3D_resetUserSpace(display disp);
static int h3D_setupTicks(display disp, binding_t axis);
/*
* Allocate and initialize a threeD struct
*/
int
h3D_init3D(display disp)
{
threeD_t *threeD;
int i;
/* allocate a threeD workarea */
if ((disp->threeDWorkArea = (void *)calloc(sizeof(threeD_t),1)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD = disp->threeDWorkArea; /* set local pointer */
threeD->cubeResults[0] = threeD->cubeU;
threeD->cubeResults[1] = threeD->cubeV;
threeD->xTickResults[0] = threeD->xTickU;
threeD->xTickResults[1] = threeD->xTickV;
threeD->yTickResults[0] = threeD->yTickU;
threeD->yTickResults[1] = threeD->yTickV;
threeD->zTickResults[0] = threeD->zTickU;
threeD->zTickResults[1] = threeD->zTickV;
/* bounding box used by DPSDoUserPath */
threeD->boundingBox[0] = -1.0;
threeD->boundingBox[1] = -1.0;
threeD->boundingBox[2] = 2.0;
threeD->boundingBox[3] = 2.0;
/* set arbitrary initial 'user space' for stand-alone cube */
for (i = 0; i < 3; i++) {
threeD->minval[i] = -1.0;
threeD->maxval[i] = 1.0;
}
h3D_resetUserSpace(disp);
return 0;
}
/*
* We have to reset the 'near face', every time theta changes
*/
void h3D_setNearFace(display disp)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
if (disp->theta < -THREEQUARTERPI) {
threeD->preferredFace = 2;
} else if (disp->theta < -HALFPI) {
threeD->preferredFace = 1;
} else if (disp->theta < -QUARTERPI) {
threeD->preferredFace = 1;
} else if (disp->theta < 0.0) {
threeD->preferredFace = 0;
} else if (disp->theta < QUARTERPI) {
threeD->preferredFace = 0;
} else if (disp->theta < HALFPI) {
threeD->preferredFace = 3;
} else if (disp->theta < THREEQUARTERPI) {
threeD->preferredFace = 3;
} else {
threeD->preferredFace = 2;
}
return;
}
/*
* Re-calculation is needed before display whenever angles, dist etc change
*/
void h3D_setDirty(display disp)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
threeD->reCalculateCube = 1;
threeD->reCalculateLegoPoints2D = 1;
threeD->reCalculateLegoPoints3D = 1;
threeD->reCalculateScatterPoints = 1;
threeD->reCalculateFill = 1;
return;
}
/*
* Go back to our initial rotation values
*/
void h3D_resetAngles(display disp)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
disp->theta = 0.0;
disp->phi = 0.0;
disp->dist = 2.0;
h3D_newTheta(disp);
h3D_newPhi(disp);
h3D_newDist(disp);
return;
}
/*
* Allocate space for lego plots If size hasn't changed, we just return. If
* space is allocated, we also generate the lego corner points from bins
*/
int
h3D_checkAllocLego(display disp)
{
threeD_t *threeD;
float *mem;
char *charmem;
struct block *blockmem, **ptrmem;
int sizeRequired, totBins, nPoints;
int alloc = 0, reAlloc = 0;
threeD = disp->threeDWorkArea; /* set local pointer */
totBins = disp->bins.xAxis.nBins * disp->bins.yAxis.nBins;
nPoints = totBins * 8;
if (threeD->legoPoints[0] == NULL) {
alloc = 1;
} else {
reAlloc = (threeD->nLegoPoints == nPoints) ? 0 : 1;
}
if (!alloc && !reAlloc) return 0;
sizeRequired = 3 * nPoints * sizeof(float);
/* alloc space for legoPoints */
if (alloc) {
if ((mem = (float *)malloc(sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->nLegoPoints = nPoints;
threeD->legoPoints[0] = &mem[0 * nPoints];
threeD->legoPoints[1] = &mem[1 * nPoints];
threeD->legoPoints[2] = &mem[2 * nPoints];
} else if (reAlloc) {
mem = threeD->legoPoints[0];
if ((mem = (float *)realloc(mem, sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->nLegoPoints = nPoints;
threeD->legoPoints[0] = &mem[0 * nPoints];
threeD->legoPoints[1] = &mem[1 * nPoints];
threeD->legoPoints[2] = &mem[2 * nPoints];
}
/* ditto for legoResults */
if (alloc) {
if ((mem = (float *)malloc(sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->legoResults[0] = &mem[0 * nPoints];
threeD->legoResults[1] = &mem[1 * nPoints];
threeD->legoResults[2] = &mem[2 * nPoints];
} else if (reAlloc) {
mem = threeD->legoResults[0];
if ((mem = (float *)realloc(mem, sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->legoResults[0] = &mem[0 * nPoints];
threeD->legoResults[1] = &mem[1 * nPoints];
threeD->legoResults[2] = &mem[2 * nPoints];
}
/* ditto for blockBank */
sizeRequired = totBins * sizeof(struct block);
if (alloc) {
if ((blockmem = (struct block *)malloc(sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->blockBank = blockmem;
threeD->numBlocks = totBins;
} else if (reAlloc) {
blockmem = threeD->blockBank;
if ((blockmem = (struct block *)realloc(blockmem, sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->blockBank = blockmem;
threeD->numBlocks = totBins;
}
/* and for block pointer array */
sizeRequired = totBins * sizeof(int);
if (alloc) {
if ((ptrmem = (struct block **)malloc(sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->blockPointer = ptrmem;
} else if (reAlloc) {
ptrmem = threeD->blockPointer;
if ((ptrmem = (struct block **)realloc(ptrmem, sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->blockPointer = ptrmem;
}
/* ditto for DPSDoUserPath cArray */
sizeRequired = 2 * MAXPSLINES * sizeof(float);
if (alloc) {
if ((mem = (float *)malloc(sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->cArray = mem;
}
/* and for DPSDoUserPath oArray */
sizeRequired = MAXPSLINES * sizeof(char);
if (alloc) {
if ((charmem = (char *)malloc(sizeRequired)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->oArray = charmem;
}
if (alloc || reAlloc) {
h3D_genLegoPoints(disp);
h3D_setDirty(disp);
}
return 0;
}
/*
* Allocate space for scatter results This is a series of (X,Y) pairs,
* terminated by a (0.0, 0.0) If size hasn't changed, we just return
*/
int
h3D_checkAllocScatterResults(display disp, int nCoords)
{
threeD_t *threeD;
float *mem;
char *charmem, plotChar='+';
int sizeRequired1, sizeRequired2;
int allocDone;
threeD = disp->threeDWorkArea; /* set local pointer */
allocDone = 0;
sizeRequired1 = (2 * nCoords + 2) * sizeof(float);
sizeRequired2 = (nCoords + 1) * sizeof(char);
/* alloc space for scatterResults and plotCharBuffer */
if (threeD->scatterResults == NULL) {
if ((mem = (float *)malloc(sizeRequired1)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
if ((charmem = (char *)malloc(sizeRequired2)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->scatterResults = mem;
threeD->nScatterPoints = nCoords;
threeD->plotCharBuffer = charmem;
allocDone = 1;
} else if (threeD->nScatterPoints != nCoords) {
mem = threeD->scatterResults;
if ((mem = (float *)realloc(mem, sizeRequired1)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
charmem = threeD->plotCharBuffer;
if ((charmem = (char *)realloc(charmem, sizeRequired2)) == NULL) {
printf("threeD - memory exceeded ");
return -1;
}
threeD->scatterResults = mem;
threeD->nScatterPoints = nCoords;
threeD->plotCharBuffer = charmem;
allocDone = 1;
}
if (allocDone) {
switch (disp->plotSymbol) {
case TRI1:
plotChar = 'a';
break;
case TRI2:
plotChar = 'b';
break;
case TRI3:
plotChar = 'c';
break;
case TRI4:
plotChar = 'd';
break;
case SQUARE:
plotChar = 'e';
break;
case SOLIDSQUARE:
plotChar = 'f';
break;
case DIA1:
plotChar = 'g';
break;
case DIA2:
plotChar = 'h';
break;
case CIRC1:
plotChar = 'i';
break;
case CIRC2:
plotChar = 'j';
break;
case TIMES:
plotChar = 'k';
break;
case PLUS:
plotChar = 'l';
break;
}
memset(threeD->plotCharBuffer,plotChar,threeD->nScatterPoints);
threeD->plotCharBuffer[threeD->nScatterPoints] = 0;
h3D_setDirty(disp); /* re-calculation will be neccessary */
}
return 0;
}
/*
* Convert tuple data to 3-d points needed for lego plots. Each 'lego' is
* described by 8 points in space.
*/
static void
h3D_genLegoPoints(display disp)
{
threeD_t *threeD;
int iBin, iYBin;
int totBins;
float xCoord, yCoord, xInit, yInit;
float deltaX, deltaY;
int i;
float *ptsx, *ptsy, *ptsz;
threeD = disp->threeDWorkArea; /* set local pointer */
totBins = disp->bins.xAxis.nBins * disp->bins.yAxis.nBins;
xInit = disp->xAxis.low;
yInit = disp->yAxis.low;
deltaX = (disp->xAxis.high - disp->xAxis.low) / disp->bins.xAxis.nBins;
deltaY = (disp->yAxis.high - disp->yAxis.low) / disp->bins.yAxis.nBins;
/* fill in the points */
xCoord = xInit;
yCoord = yInit;
iYBin = 0;
ptsx = threeD->legoPoints[0];
ptsy = threeD->legoPoints[1];
ptsz = threeD->legoPoints[2];
for (iBin = 0; iBin < totBins; iBin++) {
/* bins are arranged as bins[x][y] with y changing fastest */
for (i = 0; i < 2; i++) {
*ptsx++ = xCoord;
*ptsx++ = xCoord + deltaX;
*ptsx++ = xCoord + deltaX;
*ptsx++ = xCoord;
*ptsy++ = yCoord;
*ptsy++ = yCoord;
*ptsy++ = yCoord + deltaY;
*ptsy++ = yCoord + deltaY;
}
for (i = 0; i < 4; i++) {
*ptsz++ = disp->bins.binMin;
}
for (i = 0; i < 4; i++) {
*ptsz++ = disp->bins.data[iBin];
}
yCoord += deltaY;
iYBin++;
if (iYBin == disp->bins.yAxis.nBins) {
iYBin = 0;
yCoord = yInit;
xCoord += deltaX;
}
}
return;
}
/*
* See if bin max and mins have changed. If so, reset the user space.
*/
void
h3D_checkBinScale(display disp)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
if ((threeD->minval[0] != disp->xAxis.low)
|| (threeD->minval[1] != disp->yAxis.low)
|| (threeD->minval[2] != disp->bins.binMin)
|| (threeD->maxval[0] != disp->xAxis.high)
|| (threeD->maxval[1] != disp->yAxis.high)
|| (threeD->maxval[2] != disp->bins.binMax))
{
threeD->minval[0] = disp->xAxis.low;
threeD->minval[1] = disp->yAxis.low;
threeD->minval[2] = disp->bins.binMin;
threeD->maxval[0] = disp->xAxis.high;
threeD->maxval[1] = disp->yAxis.high;
threeD->maxval[2] = disp->bins.binMax;
disp->zAxis.low = disp->bins.binMin;
disp->zAxis.high = disp->bins.binMax;
h3D_checkAllocLego(disp);
h3D_genLegoPoints(disp);
h3D_resetUserSpace(disp);
}
return;
}
/*
* See if point max and mins etc have changed. If so, reset the user space.
*/
void
h3D_checkPointScale(display disp, int nCoords)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
if ((threeD->nScatterPoints != nCoords)
|| (threeD->tupleX != disp->binding.x)
|| (threeD->tupleY != disp->binding.y)
|| (threeD->tupleZ != disp->binding.z)
|| (threeD->minval[0] != disp->xAxis.low)
|| (threeD->minval[1] != disp->yAxis.low)
|| (threeD->minval[2] != disp->zAxis.low)
|| (threeD->maxval[0] != disp->xAxis.high)
|| (threeD->maxval[1] != disp->yAxis.high)
|| (threeD->maxval[2] != disp->zAxis.high))
{
threeD->tupleX = disp->binding.x;
threeD->tupleY = disp->binding.y;
threeD->tupleZ = disp->binding.z;
threeD->minval[0] = disp->xAxis.low;
threeD->minval[1] = disp->yAxis.low;
threeD->minval[2] = disp->zAxis.low;
threeD->maxval[0] = disp->xAxis.high;
threeD->maxval[1] = disp->yAxis.high;
threeD->maxval[2] = disp->zAxis.high;
h3D_resetUserSpace(disp);
}
return;
}
/*
* Given max and min data values, add a margin around them.
* Re-create the cube at outer limits.
* Finally re-scale the transformation matrix.
*/
static void
h3D_resetUserSpace(display disp)
{
threeD_t *threeD;
int i;
static int x_seq[] = {0, 3, 3, 0, 0, 3, 3, 0};
static int y_seq[] = {1, 1, 4, 4, 1, 1, 4, 4};
static int z_seq[] = {2, 2, 2, 2, 5, 5, 5, 5};
threeD = disp->threeDWorkArea; /* set local pointer */
/* add a margin around the data space and call it 'limits' */
for (i = 0; i < 3; i++) {
if (threeD->minval[i] >= threeD->maxval[i])
threeD->minval[i] = threeD->maxval[i] - 1;
threeD->limits[i] = threeD->minval[i] -
MARGINSIZE * (threeD->maxval[i] - threeD->minval[i]);
threeD->limits[i + 3] = threeD->maxval[i] +
MARGINSIZE * (threeD->maxval[i] - threeD->minval[i]);
}
/* create cube */
for (i = 0; i < 8; i++) {
threeD->cube[0][i] = threeD->limits[x_seq[i]];
threeD->cube[1][i] = threeD->limits[y_seq[i]];
threeD->cube[2][i] = threeD->limits[z_seq[i]];
}
/* re-generate tick marks */
h3D_setupTicks(disp, XAXIS);
h3D_setupTicks(disp, YAXIS);
h3D_setupTicks(disp, ZAXIS);
h3D_reScaleMatrix(disp);
/* impose previous rotations and distance */
h3D_newTheta(disp);
h3D_newPhi(disp);
h3D_newDist(disp);
/* Show that display re-calculation will be needed */
h3D_setDirty(disp);
return;
}
#define N__TICKS 20
static int h3D_setupTicks(display disp, binding_t axis)
{
threeD_t *threeD;
int nticks = 0, maxticks = N__TICKS;
int i;
float ticks[N__TICKS];
char labels[N__TICKS][10];
float pmag;
switch (axis)
{
case XAXIS:
genTicks(&disp->xAxis, maxticks, &nticks, ticks, labels, &pmag);
break;
case YAXIS:
genTicks(&disp->yAxis, maxticks, &nticks, ticks, labels, &pmag);
break;
case ZAXIS:
genTicks(&disp->zAxis, maxticks, &nticks, ticks, labels, &pmag);
break;
default:
return -1;
}
threeD = disp->threeDWorkArea; /* set local workarea pointer */
switch (axis)
{
case XAXIS:
threeD->nXTicks = nticks;
for (i = 0; i < nticks; i++) {
threeD->xTicks[0][i] = ticks[i];
threeD->xTicks[1][i] = threeD->limits[1];
threeD->xTicks[2][i] = threeD->limits[2];
threeD->xTicks[0][i + nticks] = ticks[i];
threeD->xTicks[1][i + nticks] = threeD->limits[4];
threeD->xTicks[2][i + nticks] = threeD->limits[2];
strcpy(threeD->xLabels[i], labels[i]);
}
break;
case YAXIS:
threeD->nYTicks = nticks;
for (i = 0; i < nticks; i++) {
threeD->yTicks[0][i] = threeD->limits[3];
threeD->yTicks[1][i] = ticks[i];
threeD->yTicks[2][i] = threeD->limits[2];
threeD->yTicks[0][i + threeD->nYTicks] = threeD->limits[0];
threeD->yTicks[1][i + threeD->nYTicks] = ticks[i];
threeD->yTicks[2][i + threeD->nYTicks] = threeD->limits[2];
strcpy(threeD->yLabels[i], labels[i]);
}
break;
case ZAXIS:
threeD->nZTicks = nticks;
for (i = 0; i < nticks; i++) {
threeD->zTicks[0][i] = threeD->limits[0];
threeD->zTicks[1][i] = threeD->limits[1];
threeD->zTicks[2][i] = ticks[i];
threeD->zTicks[0][i + threeD->nZTicks] = threeD->limits[3];
threeD->zTicks[1][i + threeD->nZTicks] = threeD->limits[1];
threeD->zTicks[2][i + threeD->nZTicks] = ticks[i];
threeD->zTicks[0][i + 2 * threeD->nZTicks] =
threeD->limits[3];
threeD->zTicks[1][i + 2 * threeD->nZTicks] =
threeD->limits[4];
threeD->zTicks[2][i + 2 * threeD->nZTicks] = ticks[i];
threeD->zTicks[0][i + 3 * threeD->nZTicks] =
threeD->limits[0];
threeD->zTicks[1][i + 3 * threeD->nZTicks] =
threeD->limits[4];
threeD->zTicks[2][i + 3 * threeD->nZTicks] = ticks[i];
strcpy(threeD->zLabels[i], labels[i]);
}
break;
default:
return -1;
}
return 0;
}
void h3D_transformCube(display disp)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
if (threeD->reCalculateCube) {
h3D_render2D(disp, 8, threeD->cube[0],
threeD->cube[1], threeD->cube[2],
threeD->cubeResults);
if (!disp->doSpeedy) {
h3D_render2D(disp, 2 * threeD->nXTicks,
threeD->xTicks[0], threeD->xTicks[1],
threeD->xTicks[2], threeD->xTickResults);
h3D_render2D(disp, 2 * threeD->nYTicks,
threeD->yTicks[0], threeD->yTicks[1],
threeD->yTicks[2], threeD->yTickResults);
h3D_render2D(disp, 4 * threeD->nZTicks,
threeD->zTicks[0], threeD->zTicks[1],
threeD->zTicks[2], threeD->zTickResults);
}
threeD->reCalculateCube = 0;
}
return;
}
int h3D_myCompare(const struct block ** ptr1, const struct block ** ptr2)
{
/* if minZs are unequal, arrange in ascending order */
if ((*ptr1)->minZ > (*ptr2)->minZ)
return 1;
/* if minZs are equal compare maxZs */
else if ((*ptr1)->minZ == (*ptr2)->minZ) {
if ((*ptr1)->maxZ > (*ptr2)->maxZ)
return 1;
}
return 0;
}
void h3D_transformLego(display disp)
{
threeD_t *threeD;
int i, j;
float *u, *v, *w;
float *p, *q, *r;
float zDist, zEye2, zMax=0.0, zMin=0.0;
int zMinCorner = 0;
struct block *thisBlock;
int blockBankIndex;
threeD = disp->threeDWorkArea; /* set local pointer */
if (threeD->reCalculateLegoPoints3D) {
h3D_checkAllocLego(disp);
h3D_render3D(disp, threeD->nLegoPoints, threeD->legoPoints[0],
threeD->legoPoints[1], threeD->legoPoints[2],
threeD->legoResults);
threeD->reCalculateLegoPoints3D = 0;
threeD->reCalculateLegoPoints2D = 0;
}
if (threeD->reCalculateFill) {
/* set up block bank */
blockBankIndex = 0;
thisBlock = threeD->blockBank;
u = threeD->legoResults[0];
v = threeD->legoResults[1];
w = threeD->legoResults[2];
for (i = 0; i < threeD->nLegoPoints; i += 8) {
p = &u[i];
q = &v[i];
r = &w[i];
/*
* find eye distances to base of each block, in x-z plane only
*/
zMax = -FLT_MAX;
zMin = FLT_MAX;
for (j = 0; j < 4; j++) {
if (disp->dist < FLT_MAX) {
zDist = disp->dist * r[j];
zEye2 = zDist * zDist + p[j] * p[j];
} else { /* if dist infinite, just sort according to y
* height */
zEye2 = v[i];
}
if (zEye2 > zMax)
zMax = zEye2;
if (zEye2 < zMin) {
zMin = zEye2;
zMinCorner = j;
}
}
thisBlock->xData = p;
thisBlock->yData = q;
thisBlock->maxZ = zMax;
thisBlock->minZ = zMin;
thisBlock->minZ = zMin;
thisBlock->nearCorner = zMinCorner;
threeD->blockPointer[blockBankIndex++] = thisBlock;
thisBlock++;
}
threeD->numBlocks = threeD->nLegoPoints / 8;
/*
* now sort the block pointers in increasing min distance
*/
qsort(threeD->blockPointer, threeD->numBlocks,
sizeof(struct block *), (int (*)
(const void *, const void *)) h3D_myCompare);
threeD->reCalculateFill = 0;
}
return;
}
void h3D_transformWireFrame(display disp)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
if (threeD->reCalculateLegoPoints2D) {
h3D_checkAllocLego(disp);
h3D_render2D(disp, threeD->nLegoPoints, threeD->legoPoints[0],
threeD->legoPoints[1], threeD->legoPoints[2],
threeD->legoResults);
threeD->reCalculateLegoPoints2D = 0;
}
return;
}
void h3D_transformMesh(display disp)
{
threeD_t *threeD;
threeD = disp->threeDWorkArea; /* set local pointer */
if (threeD->reCalculateLegoPoints2D) {
h3D_checkAllocLego(disp);
h3D_render2D(disp, threeD->nLegoPoints, threeD->legoPoints[0],
threeD->legoPoints[1], threeD->legoPoints[2],
threeD->legoResults);
threeD->reCalculateLegoPoints2D = 0;
}
return;
}
int h_set3DTheta( display disp, float angle)
{
disp->theta = angle * DEG_TO_RAD;
h3D_newTheta(disp);
return 0;
}
float h_get3DTheta( display disp)
{
return disp->theta * RAD_TO_DEG;
}
int h_set3DPhi(display disp, float angle)
{
disp->phi = -angle * DEG_TO_RAD;
h3D_newPhi(disp);
return 0;
}
float h_get3DPhi(display disp)
{
return -disp->phi * RAD_TO_DEG;
}
int h_set3DDist(display disp, float distance)
{
disp->dist = distance;
h3D_newDist(disp);
return 0;
}
float h_get3DDist(display disp)
{
return disp->dist;
}
/*
* Set/clear 3D plot type
*/
int h_set3DCube(display disp, int flag)
{
threeD_t *threeD;
if ((threeD = disp->threeDWorkArea) == NULL) return 1;
else {
disp->doCube = flag;
return 0;
}
}
int h_set3DWireFrame(display disp, int flag)
{
threeD_t *threeD;
if ((threeD = disp->threeDWorkArea) == NULL) return 1;
else {
disp->doWireFrame = flag;
return 0;
}
}
int h_set3DFill(display disp, int flag)
{
threeD_t *threeD;
if ((threeD = disp->threeDWorkArea) == NULL) return 1;
else {
disp->doFill = flag;
return 0;
}
}
int h_set3DMesh(display disp, int flag)
{
threeD_t *threeD;
if ((threeD = disp->threeDWorkArea) == NULL) return 1;
else {
disp->doMesh = flag;
return 0;
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.