open-axiom repository from github
/*1Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd.2All rights reserved.3Copyright (C) 2007-2011, Gabriel Dos Reis.4All rights reserved.56Redistribution and use in source and binary forms, with or without7modification, are permitted provided that the following conditions are8met:910- Redistributions of source code must retain the above copyright11notice, this list of conditions and the following disclaimer.1213- Redistributions in binary form must reproduce the above copyright14notice, this list of conditions and the following disclaimer in15the documentation and/or other materials provided with the16distribution.1718- Neither the name of The Numerical Algorithms Group Ltd. nor the19names of its contributors may be used to endorse or promote products20derived from this software without specific prior written permission.2122THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS23IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED24TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A25PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER26OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,27EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,28PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR29PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF30LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING31NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS32SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33*/3435#define _SURFACE3D_C36#include "openaxiom-c-macros.h"3738#include <string.h>39#include <math.h>40#include <stdlib.h>4142#include "sockio.h"43#include "header.h"44#include "draw.h"45#include "mode.h" /* for #define components */46#include "com.h"47#include "XSpadFill.h"48#include "XShade.h"49#include "util.H1"50#include "Gfun.H1"51#include "all_3d.H1"525354/**** useful defines ****/5556#define precisionFactor 10245758/* depthChecker turns on the extensive depth checking mechanisms59for the depth sort algorithm. Without it, the hidden surface60removal is just a sort by z which works remarkably well, but,61is insufficient and, at times, may end up being incorrect */62#define depthChecker636465pointInfo ptIA, ptIB, ptIC; /* global to this file */6667/************************************68* void drawLineComponent(p,dFlag) *69************************************/7071void72drawLineComponent (poly * p, int dFlag)73{74int i, hue;75int *anIndex;76RGB col_rgb;7778/* If the polygon is clipped against the hither plane (clipPz) then79it is not drawn...or...if the clipStuff is set to true, and80the polygon is clipped against the user defined clip volume, it81is also not drawn. */82if (!((p->partialClipPz) || (viewData.clipStuff && (p->partialClip)))) {83/* This routine will eventually only be skipped if84p->totalClip is true and another routine would85handle the partialClip. this routine would handle86only those polygons without any clipped points */87for (i=0, anIndex=p->indexPtr; i<p->numpts; i++,anIndex++) {88quadMesh[i].x = refPt3D(viewData,*anIndex)->px;89quadMesh[i].y = refPt3D(viewData,*anIndex)->py;90}9192if (dFlag==Xoption) {93if (mono || viewport->monoOn)94GSetForeground(opaqueGC, (float)foregroundColor, dFlag);95else {96hue = hueValue(p->color);97GSetForeground(opaqueGC, (float)XSolidColor(hue,2), dFlag);98}99} else100GSetForeground(opaqueGC, psBlack, dFlag);101102if (dFlag==PSoption && !mono && !viewport->monoOn) {103hue = getHue(p->color);104col_rgb = hlsTOrgb((float)hue,0.5,0.8);105PSDrawColor(col_rgb.r,col_rgb.g,col_rgb.b,quadMesh,p->numpts);106} else {107GDrawLines(opaqueGC, viewport->viewWindow, quadMesh, p->numpts,108CoordModeOrigin, dFlag);109}110if (dFlag == Xoption)111XMapWindow(dsply, viewport->viewWindow);112}113}114115116117/**************************************************118* void drawOpaquePolygon(p,aGC,anotherGC) *119**************************************************/120121void122drawOpaquePolygon (poly *p,GC aGC,GC anotherGC,int dFlag)123{124125int *anIndex, i, hue, isNaN = 0;126RGB col_rgb;127128if (mono || viewport->monoOn) {129GSetForeground(anotherGC, (float)foregroundColor, dFlag);130} else {131hue = hueValue(p->color);132GSetForeground(anotherGC, (float)XSolidColor(hue,2), dFlag);133}134135/* If the polygon is clipped against the hither plane (clipPz) then136it is not drawn, or if the clipStuff is set to true, and137the polygon is clipped against the user defined clip volume, it138is also not drawn. */139140if (!((p->partialClipPz) || (viewData.clipStuff && (p->partialClip)))) {141142/* This routine should eventually only be skipped if143p->totalClip is true and another routine would144handle the partialClip. This routine would handle145only those polygons without any clipped points. */146147for (i=0, anIndex=p->indexPtr; i<p->numpts; i++,anIndex++) {148quadMesh[i].x = refPt3D(viewData,*anIndex)->px;149quadMesh[i].y = refPt3D(viewData,*anIndex)->py;150if (eqNANQ(quadMesh[i].x) || eqNANQ(quadMesh[i].y)) isNaN = 1;151}152153quadMesh[i].x =refPt3D(viewData,*(p->indexPtr))->px;154quadMesh[i].y =refPt3D(viewData,*(p->indexPtr))->py;155if (eqNANQ(quadMesh[i].x) || eqNANQ(quadMesh[i].y)) isNaN = 1;156157if (dFlag==PSoption && !mono && !viewport->monoOn && !isNaN) {158GSetForeground(GC9991, (float)backgroundColor, PSoption);159PSFillPolygon(GC9991, quadMesh, p->numpts+1);160hue = getHue(p->color);161col_rgb = hlsTOrgb((float)hue,0.5,0.8);162if (viewport->diagonals)163PSDrawColor(col_rgb.r,col_rgb.g,col_rgb.b,quadMesh,p->numpts+1);164else165PSDrawColor(col_rgb.r,col_rgb.g,col_rgb.b,quadMesh,p->numpts);166} else {167if (mono || viewport->monoOn) {168GSetForeground(anotherGC, (float)foregroundColor, dFlag);169} else {170hue = hueValue(p->color);171GSetForeground(anotherGC, (float)XSolidColor(hue,2), dFlag);172}173GSetForeground(aGC,(float)backgroundColor,dFlag);174if (!isNaN) {175XFillPolygon(dsply, viewport->viewWindow, aGC, quadMesh, p->numpts,176Convex,CoordModeOrigin);177if (viewport->diagonals)178GDrawLines(anotherGC,viewport->viewWindow,quadMesh,p->numpts+1,179CoordModeOrigin, dFlag);180else181GDrawLines(anotherGC,viewport->viewWindow,quadMesh,p->numpts,182CoordModeOrigin, dFlag);183}184}185if (dFlag == Xoption) XMapWindow(dsply,viewport->viewWindow);186} /* if not totally clipped */187}188189190191/*************************************192* poly *copyPolygons(polygonList) *193* *194* copies the given list of polygons *195* into a newly allocated list *196*************************************/197198poly *199copyPolygons (poly *polygonList)200{201202int i;203poly *aPoly,*retval,*prev;204205prev = retval = aPoly = (poly *)saymem("surface.c",1,sizeof(poly));206aPoly->indexPtr = (int *)saymem("surface.c",207polygonList->numpts,sizeof(int));208aPoly->num = polygonList->num;209aPoly->sortNum = polygonList->sortNum;210aPoly->split = polygonList->split;211aPoly->numpts = polygonList->numpts;212for (i=0; i<aPoly->numpts; i++)213*((aPoly->indexPtr) + i) = *((polygonList->indexPtr) + i);214aPoly->N[0] = polygonList->N[0];215aPoly->N[1] = polygonList->N[1];216aPoly->N[2] = polygonList->N[2];217aPoly->planeConst = polygonList->planeConst;218aPoly->color = polygonList->color;219aPoly->moved = no;220aPoly->pxmin = polygonList->pxmin;221aPoly->pxmax = polygonList->pxmax;222aPoly->pymin = polygonList->pymin;223aPoly->pymax = polygonList->pymax;224aPoly->pzmin = polygonList->pzmin;225aPoly->pzmax = polygonList->pzmax;226aPoly->xmin = polygonList->xmin;227aPoly->xmax = polygonList->xmax;228aPoly->ymin = polygonList->ymin;229aPoly->ymax = polygonList->ymax;230aPoly->zmin = polygonList->zmin;231aPoly->zmax = polygonList->zmax;232aPoly->normalFacingOut = polygonList->normalFacingOut;233aPoly->primitiveType = polygonList->primitiveType;234for (polygonList = polygonList->next;235polygonList != NIL(poly);236polygonList = polygonList->next) {237prev->next = aPoly = (poly *)saymem("surface.c",1,sizeof(poly));238aPoly->indexPtr = (int *)saymem("surface.c",239polygonList->numpts,sizeof(int));240aPoly->num = polygonList->num;241aPoly->sortNum = polygonList->sortNum;242aPoly->numpts = polygonList->numpts;243aPoly->split = polygonList->split;244for (i=0; i<aPoly->numpts; i++)245*((aPoly->indexPtr) + i) = *((polygonList->indexPtr) + i);246aPoly->N[0] = polygonList->N[0];247aPoly->N[1] = polygonList->N[1];248aPoly->N[2] = polygonList->N[2];249aPoly->planeConst = polygonList->planeConst;250aPoly->color = polygonList->color;251aPoly->moved = no;252aPoly->pxmin = polygonList->pxmin;253aPoly->pxmax = polygonList->pxmax;254aPoly->pymin = polygonList->pymin;255aPoly->pymax = polygonList->pymax;256aPoly->pzmin = polygonList->pzmin;257aPoly->pzmax = polygonList->pzmax;258aPoly->xmin = polygonList->xmin;259aPoly->xmax = polygonList->xmax;260aPoly->ymin = polygonList->ymin;261aPoly->ymax = polygonList->ymax;262aPoly->zmin = polygonList->zmin;263aPoly->zmax = polygonList->zmax;264aPoly->normalFacingOut = polygonList->normalFacingOut;265aPoly->primitiveType = polygonList->primitiveType;266prev = aPoly;267}268aPoly->next = 0;269return(retval);270}271272273/******************************274* void minMaxPolygons(aPoly) *275* *276* sets up the xmin, *277* etc, for each polygon *278* for sorting and *279* extent checking. *280******************************/281282void283minMaxPolygons (poly *aPoly)284{285286int *anIndex;287int i;288289for (; aPoly != NIL(poly); aPoly = aPoly->next) {290anIndex = aPoly->indexPtr;291aPoly->pxmin = aPoly->pxmax = refPt3D(viewData,*anIndex)->px;292aPoly->pymin = aPoly->pymax = refPt3D(viewData,*anIndex)->py;293aPoly->pzmin = aPoly->pzmax = refPt3D(viewData,*anIndex)->pz;294aPoly->xmin = aPoly->xmax = refPt3D(viewData,*anIndex)->x;295aPoly->ymin = aPoly->ymax = refPt3D(viewData,*anIndex)->y;296aPoly->zmin = aPoly->zmax = refPt3D(viewData,*anIndex)->z;297for (i=1,anIndex++; i<aPoly->numpts; i++,anIndex++) {298if (refPt3D(viewData,*anIndex)->px < aPoly->pxmin)299aPoly->pxmin = refPt3D(viewData,*anIndex)->px;300else if (refPt3D(viewData,*anIndex)->px > aPoly->pxmax)301aPoly->pxmax = refPt3D(viewData,*anIndex)->px;302if (refPt3D(viewData,*anIndex)->py < aPoly->pymin)303aPoly->pymin = refPt3D(viewData,*anIndex)->py;304else if (refPt3D(viewData,*anIndex)->py > aPoly->pymax)305aPoly->pymax = refPt3D(viewData,*anIndex)->py;306if (refPt3D(viewData,*anIndex)->pz < aPoly->pzmin)307aPoly->pzmin = refPt3D(viewData,*anIndex)->pz;308else if (refPt3D(viewData,*anIndex)->pz > aPoly->pzmax)309aPoly->pzmax = refPt3D(viewData,*anIndex)->pz;310311if (refPt3D(viewData,*anIndex)->x < aPoly->xmin)312aPoly->xmin = refPt3D(viewData,*anIndex)->x;313else if (refPt3D(viewData,*anIndex)->x > aPoly->xmax)314aPoly->xmax = refPt3D(viewData,*anIndex)->x;315if (refPt3D(viewData,*anIndex)->y < aPoly->ymin)316aPoly->ymin = refPt3D(viewData,*anIndex)->y;317else if (refPt3D(viewData,*anIndex)->y > aPoly->ymax)318aPoly->ymax = refPt3D(viewData,*anIndex)->y;319if (refPt3D(viewData,*anIndex)->z < aPoly->zmin)320aPoly->zmin = refPt3D(viewData,*anIndex)->z;321else if (refPt3D(viewData,*anIndex)->z > aPoly->zmax)322aPoly->zmax = refPt3D(viewData,*anIndex)->z;323}324}325} /* minMaxPolygons */326327328329/***********************************330* int polyCompare (p1,p2) *331* *332* returns -1 if p1 < p2 *333* 0 if p1 = p2 *334* 1 if p1 > p2 *335* note that this is the reverse *336* of what the msort requested. *337* this is so that the list will *338* be sorted from max to min. *339***********************************/340341int342polyCompare (poly *p1,poly *p2)343{344345if (p1->pzmax > p2->pzmax) return(-1);346else if (p1->pzmax < p2->pzmax) return(1);347else return(0);348}349350/***********************351* void calcEyePoint() *352* *353* sets the global *354* variable eyePoint[] *355* to where the viewer *356* is pointed towards *357***********************/358359void360calcEyePoint (void)361{362363eyePoint[0] = sinPhi * (sinTheta);364eyePoint[1] = sinPhi * (-cosTheta);365eyePoint[2] = cosPhi;366367}368369370371/*372void drawPolygons()373A general routine for displaying a list of polygons374with the proper hidden surfaces removed. Assumes the375list of polygons is in viewData.polygons. Needs a376routine to split intersecting polygons in object space. *377*/378379380/**************************************381* void drawRenderedPolygon(p,dFlag) *382* *383* calculate the color for the *384* polygon p and draw it *385**************************************/386387void388drawRenderedPolygon (poly *p,int dFlag)389{390391int i,hue,shade, isNaN = 0;392float whichSide,H[3],P[3],LN,HN,diff,spec,tempLight,lumens,E[3],N[3];393int *anIndex, *indx;394RGB col_rgb;395396if (!((p->partialClipPz) || (viewData.clipStuff && (p->partialClip)))) {397/* This routine should eventually only be skipped if398p->totalClip is true and another routine would399handle the partialClip. This routine would handle400only those polygons without any clipped points. */401402for (i=0, anIndex=p->indexPtr; i<p->numpts; i++,anIndex++) {403quadMesh[i].x = refPt3D(viewData,*anIndex)->px;404quadMesh[i].y = refPt3D(viewData,*anIndex)->py;405if (eqNANQ(quadMesh[i].x) || eqNANQ(quadMesh[i].y)) isNaN = 1;406}407quadMesh[i].x = refPt3D(viewData,*(p->indexPtr))->px;408quadMesh[i].y = refPt3D(viewData,*(p->indexPtr))->py;409if (eqNANQ(quadMesh[i].x) || eqNANQ(quadMesh[i].y)) isNaN = 1;410411if (!isNaN) {412/* calculate polygon illumination */413indx = p->indexPtr;414P[0] = (refPt3D(viewData,*(indx))->wx +415refPt3D(viewData,*(indx+1))->wx +416refPt3D(viewData,*(indx+2))->wx);417P[1] = (refPt3D(viewData,*(indx))->wy +418refPt3D(viewData,*(indx+1))->wy +419refPt3D(viewData,*(indx+2))->wy);420P[2] = (refPt3D(viewData,*(indx))->wz +421refPt3D(viewData,*(indx+1))->wz +422refPt3D(viewData,*(indx+2))->wz);423normalizeVector(P);424425N[0] = p->N[0]; N[1] = p->N[1]; N[2] = p->N[2];426normalizeVector(eyePoint);427E[0] = 4.0*eyePoint[0] - P[0];428E[1] = 4.0*eyePoint[1] - P[1];429E[2] = 4.0*eyePoint[2] - P[2];430normalizeVector(E);431diff = 0.0; spec = 0.0;432LN = N[0]*viewport->lightVector[0] +433N[1]*viewport->lightVector[1] +434N[2]*viewport->lightVector[2];435if (LN < 0.0) LN = -LN;436diff = LN*Cdiff;437438if (LN > 0.0) {439H[0] = E[0] + viewport->lightVector[0];440H[1] = E[1] + viewport->lightVector[1];441H[2] = E[2] + viewport->lightVector[2];442normalizeVector(H);443HN = dotProduct(N,H,3);444if (HN < 0.0) HN = -HN;445spec = pow((double)absolute(HN),coeff);446if (spec > 1.0) spec = 1.0;447}448449lumens = ((Camb + 0.15) + diff + spec*Cspec);450if (lumens > 1.0) lumens = 1.0;451if (lumens < 0.0) lumens = 0.0;452if (dFlag==PSoption && !mono && !viewport->monoOn) {453hue = getHue(p->color);454col_rgb = hlsTOrgb((float)hue,lumens,0.8);455/* NTSC color to grey = .299 red + .587 green + .114 blue */456maxGreyShade = (int) psShadeMax;457whichSide = (.299*col_rgb.r + .587*col_rgb.g + .114*col_rgb.b) *458(maxGreyShade-1);459}460else {461if (mono || viewport->monoOn) {462hue = getHue(p->color);463col_rgb = hlsTOrgb((float)hue,lumens,0.8);464whichSide = (.299*col_rgb.r + .587*col_rgb.g + .114*col_rgb.b) *465(maxGreyShade-1);466} else467whichSide = lumens*(totalShades-1);468}469470tempLight = lightIntensity;471if (lightIntensity < Camb) lightIntensity = Camb;472473shade = floor(lightIntensity * absolute(whichSide));474lightIntensity = tempLight;475476if (shade < totalShades) {477/* shade < totalShades is (temporarily) necessary here478because, currently, parameterizations for things like479the sphere would produce triangular shaped polygons480close to the poles which get triangularized leaving a481triangle with coincidental points. the normal for this482would be undefined (since coincidental points would create483a zero vector) and the shade would be large, hence,484the conditional. */485486if (mono || viewport->monoOn) {487if (dFlag == Xoption) {488XChangeShade(dsply,maxGreyShade-shade-1);489XShadePolygon(dsply,viewport->viewWindow,quadMesh,p->numpts+1,490Convex,CoordModeOrigin);491}492else if (dFlag == PSoption) { /* renderGC has number 9991493(see main.c, header.h) */494GSetForeground(GC9991,4951.0-(float)(maxGreyShade-shade-1)*psShadeMul,PSoption);496PSFillPolygon(GC9991, quadMesh, p->numpts+1);497}498} else { /* not mono */499if (dFlag == Xoption) {500hue = hueValue(p->color);501XSpadFillPolygon(dsply, viewport->viewWindow, quadMesh,502p->numpts+1, Convex,CoordModeOrigin, hue, shade);503}504else if (dFlag == PSoption) /* draws it out in monochrome */505PSColorPolygon(col_rgb.r,col_rgb.g,col_rgb.b,quadMesh,p->numpts+1);506} /* if mono-else */507508if (viewData.outlineRenderOn) {509if (viewport->diagonals) {510if (dFlag == PSoption) {511GSetForeground(renderGC,psBlack, dFlag);512GDrawLines(renderGC,viewport->viewWindow,quadMesh,p->numpts+1,513CoordModeOrigin,dFlag);514} else515GDrawLines(renderGC,viewport->viewWindow,quadMesh,p->numpts+1,516CoordModeOrigin,dFlag);517} else {518if (dFlag == PSoption) {519GSetForeground(renderGC,psBlack,PSoption);520GDrawLines(renderGC,viewport->viewWindow,quadMesh,p->numpts,521CoordModeOrigin,PSoption);522} else523GDrawLines(renderGC,viewport->viewWindow,quadMesh,p->numpts,524CoordModeOrigin,dFlag);525}526}527}528} /* if not NaN */529if (dFlag == Xoption) XMapWindow(dsply,viewport->viewWindow);530} /* if not clipped */531532} /* drawRenderedPolygon */533534535void536freePointResevoir(void)537{538539viewTriple *v;540541while (splitPoints != NIL(viewTriple)) {542v = splitPoints;543splitPoints = splitPoints->next;544free(v);545}546547} /* freePointResevoir */548549/***********************************550* void freeListOfPolygons(pList); *551* *552* frees up a list of polygons. *553***********************************/554555void556freeListOfPolygons (poly *pList)557{558559poly *nextP;560561for (; pList != NIL(poly); pList=nextP) {562nextP=pList->next;563free(pList->indexPtr);564free(pList);565}566} /* freeListOfPolygons() */567568569570void571drawPolygons(int dFlag)572{573574poly *p,*head;575poly *tempQuick=NULL;576int quickFirst=yes;577578if (recalc) {579580/* To get around multiple X Expose events the server tends581to send upon startup, leave negation of firstTime to the end. */582rotated = no;583zoomed = no;584translated = no;585switchedPerspective = no;586changedEyeDistance = no;587redoSmooth = yes;588589if (keepDrawingViewport()) {590if (!firstTime) {591strcpy(control->message," Creating Polygons ");592writeControlMessage();593freeListOfPolygons(quickList);594freePointResevoir();595}596strcpy(control->message," Collecting Polygons ");597writeControlMessage();598quickList = copyPolygons(viewData.polygons);599600if (keepDrawingViewport()) {601/* to get normal facing outside info */602strcpy(control->message," Projecting Polygons ");603writeControlMessage();604projectAllPolys(quickList);605if (keepDrawingViewport()) {606strcpy(control->message," Setting Extreme Values ");607writeControlMessage();608minMaxPolygons(quickList);609if (keepDrawingViewport()) {610strcpy(control->message," Sorting Polygons ");611writeControlMessage();612quickList = msort(quickList,0,viewData.numPolygons,polyCompare);613if (keepDrawingViewport()) {614calcEyePoint();615head = p = quickList;616617clearControlMessage();618strcpy(control->message,viewport->title);619writeControlMessage();620621if (viewData.scaleDown) {622if (keepDrawingViewport()) {623for (p=quickList;624keepDrawingViewport() && (p != NIL(poly));625p=p->next) {626switch (p->primitiveType) {627case pointComponent:628if (dFlag==Xoption) {629if (mono || viewport->monoOn)630GSetForeground(componentGC,631(float)foregroundColor, dFlag);632else633GSetForeground(componentGC,634(float)meshOutline, dFlag);635} else {636GSetForeground(componentGC, psBlack, dFlag);637GFillArc(componentGC, viewport->viewWindow,638(int)refPt3D(viewData,*(p->indexPtr))->px,639(int)refPt3D(viewData,*(p->indexPtr))->py,640viewData.pointSize,viewData.pointSize,0,641360*64, dFlag);642}643break;644case lineComponent:645drawLineComponent(p,dFlag);646break;647default:648if (viewData.style == opaqueMesh) {649GSetForeground(globGC,(float)backgroundColor,dFlag);650drawOpaquePolygon(p,globGC,opaqueGC,dFlag);651} else {652drawRenderedPolygon(p,dFlag);653}654} /* switch */655}656}657}658659if (!quickFirst) {660/* append the rest of the polygons onto the list */661tempQuick->next = head;662/* but do not continue the drawing... */663if (head != NIL(poly)) head->doNotStopDraw = no;664} /* if !quickFirst */665finishedList = (p==NIL(poly));666} /* for various */667} /* steps */668} /* of */669} /* keepDrawingViewport() */670} /* *** */671/* May want to have a flag somewhere to stop the drawing yet672continue the freeing */673if (firstTime) firstTime = no;674} else { /* if recalc else if not recalc just draw stuff in list */675if (keepDrawingViewport()) {676for (p=quickList;677keepDrawingViewport() && p != NIL(poly) &&678(viewData.scaleDown || p->doNotStopDraw); p=p->next) {679projectAPoly(p);680switch (p->primitiveType) {681case pointComponent:682if (dFlag==Xoption) {683if (mono || viewport->monoOn)684GSetForeground(componentGC,(float)foregroundColor, dFlag);685else686GSetForeground(componentGC,(float)meshOutline, dFlag);687} else688GSetForeground(componentGC,psBlack, dFlag);689GFillArc(componentGC, viewport->viewWindow,690(int)refPt3D(viewData,*(p->indexPtr))->px,691(int)refPt3D(viewData,*(p->indexPtr))->py,692viewData.pointSize,viewData.pointSize,0,360*64,dFlag);693break;694case lineComponent:695drawLineComponent(p,dFlag);696break;697default:698if (viewData.style == opaqueMesh) {699GSetForeground(globGC,(float)backgroundColor,dFlag);700drawOpaquePolygon(p,globGC,opaqueGC,dFlag);701} else702drawRenderedPolygon(p,dFlag);703} /* switch */704}705}706}707} /* drawPolygons */708709710711712713714715/**************************716* int lessThan(x,y) *717* int greaterThan(x,y) *718* int equal(x,y) *719* *720* Compares two floating *721* point numbers for *722* precision of up to one *723* place in a thousand. *724* returns *725* 1 if true *726* o otherwise *727**************************/728729int730lessThan (float x,float y)731{732int xI,yI;733734xI = x*precisionFactor;735yI = y*precisionFactor;736return(xI<yI);737}738739int740greaterThan (float x,float y)741{742int xI,yI;743744xI = x*precisionFactor;745yI = y*precisionFactor;746return(xI>yI);747}748749int750isNaN (float v)751{752return (v != v);753}754755756int757isNaNPoint (float x,float y,float z)758{759return (isNaN(x) || isNaN(y) || isNaN(z));760}761762int763equal (float x,float y)764{765int xI,yI;766767xI = x*precisionFactor;768yI = y*precisionFactor;769return(xI==yI);770}771772773774