open-axiom repository from github
/*1Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.2All rights reserved.3Copyright (C) 2007-2010, 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 _MAIN3D_C36#include "openaxiom-c-macros.h"37#include <string.h>38#include <stdio.h>39#include <stdlib.h>40#include <unistd.h>41#include <signal.h>42#include <math.h>4344#include "header.h"45#include "cpanel.h"46#include "process.h"47#include "bsdsignal.h"4849#include "util.H1"50#include "Gfun.H1"51#include "XSpadFill.h"52#include "XShade.h"53#include "all_3d.H1"5455#include "spadBitmap.bitmap"56#include "spadMask.mask"5758viewPoints *viewport;59GCptr GChead=NULL; /* ptr to head of ps GC linked list */60char *PSfilename; /* output file name used in user directory */61int psInit=no; /* need to call globaInitPs() each run */62char *envAXIOM; /* used for ps file paths */63int maxGreyShade=0;64GC globalGC1, globalGC2, anotherGC, globGC, trashGC,65controlMessageGC, lightingGC, volumeGC, quitGC, processGC,66saveGC, graphGC, componentGC, opaqueGC, renderGC;67unsigned long foregroundColor, backgroundColor;68int Socket=1, ack=1;69Colormap colorMap;70viewTriple *splitPoints;71Display *dsply;72int scrn;73Window rtWindow;74HashTable *table;75int mono, totalColors, totalSolid, totalDithered, totalHues,76totalSolidShades, totalDitheredAndSolids,totalShades;77XFontStruct *globalFont, *buttonFont, *headerFont, *titleFont, *graphFont,78*lightingFont, *volumeFont, *quitFont, *saveFont,*serverFont;79XGCValues gcVals;80unsigned long * spadColors;81float transform[4][4], transform1[4][4],82R[4][4], R1[4][4], S[4][4], T[4][4], I[4][4];83float A[4][4], B[4][4], D[4], E[4][4], F[4], array[4][4];8485int followMouse=no,86viewportKeyNum=0;87/**********************/88/** global variables **/89/**********************/9091char scaleReport[5];92char deltaXReport[5], deltaYReport[5];93XSizeHints viewSizeHints;9495GC processGC;96viewPoints *viewport;97controlPanelStruct *control;98const char* s;99int someInt;100101/* check /usr/include/X11 for current implementation of102pixels (e.g. BlackPixel()) */103104/** totalShades is initially set to totalShadesConst.105If X cannot allocate 8 shades for each hue, total-106Shades is decremented. there is currently only a check for107this value to be positive. --> something to add: change over108to monochrome if totalShades=0. just modify the spadcolors.c109file. spadcolors.c has been modified so that it returns the110value for totalShades. since the return value had previously111been unused, a modification in this way ensures continued112support of other routines calling this function (e.g.113hypertex stuff). **/114115116int drawMore;117118int spadMode=no, /* yes if receiving OpenAxiom command and119calling drawViewport */120spadDraw=no; /* yes if drawing viewport for121an OpenAxiom command */122int spadSignalReceived=0; /* yes if current state is a result of123a signal from OpenAxiom */124int inNextEvent=no; /* true just before a call to125XNextEvent */126jmp_buf jumpFlag;127128char errorStr[80];129130view3DStruct viewData;131132Window quitWindow, saveWindow;133134/** variables below assume only one viewport per process **/135136Window lightingWindow, lightingAxes;137float lightPointer[3], tempLightPointer[3];138139int axesXY[3][4];140float axesZ[3][2];141142float lightIntensity=1.0, tempLightIntensity;143float backLightIntensity = 1.0;144145/** used for writing viewport info out to a file **/146char filename[256];147148149/** used for draw viewport routines */150float sinTheta, sinPhi, cosTheta, cosPhi, viewScale,151viewScaleX, viewScaleY, viewScaleZ, reScale;152int xCenter, yCenter;153154XWindowAttributes vwInfo;155XWindowAttributes graphWindowAttrib;156157XPoint *quadMesh;158XImage *imageX;159int *xPts; /* pointer to projected points (x followed by y) */160float transform[4][4], transform1[4][4],161R[4][4], R1[4][4], S[4][4], T[4][4], I[4][4];162float A[4][4], B[4][4], D[4], E[4][4], F[4], array[4][4];163164165int scanline, polyCount;166polyList *scanList[ARRAY_HEIGHT];167float xleft = (float)0 ,xright = (float)ARRAY_WIDTH;168169colorBuffer cBuffer[ARRAY_WIDTH];170float zBuffer[ARRAY_WIDTH];171172float zC, dzdx, lum, point_norm[3];173float intersectColor[2], dcolor;174triple dpt, dnorm;175176/** eyePoint **/177float eyePoint[3];178179/** tube stuff **/180XPoint polygonMesh[20];181182/* bypass the hidden surface algorithm if no rotations, etc */183int saveFlag=no;184int firstTime=yes, noTrans = yes, startup = yes;185int redrawView = no; /* set to yes when returning from186subpanels */187int redoColor = no, pixelSetFlag = no, redoDither = no;188int redoSmooth = no, multiColorFlag = no;189190/* In order to set recalc to true (see draw.h) */191int finishedList=no, zoomed=yes, translated = yes,192changedIntensity, movingLight = no, writeImage = no,193rotated=yes, switchedPerspective, changedEyeDistance,194gotToggle = no;195poly *quickList;196197/** if not connected to OpenAxiom **/198int viewAloned;199200/** for drawing the box **/201viewTriple corners[8], clipCorners[8];202boxSideStruct box[6], clipBox[6];203204/** for freeing up points created frrom split polygons **/205int resMax=0; /* number of points in the split point resevoir */206207/** view volume stuff **/208Window volumeWindow;209int frustrumVertex;210int doingPanel=CONTROLpanel; /* rewrite titles in proper panel */211int doingVolume;212213int screenX; /* global floating point indicating mouse position214on frustrum screen */215float xClipMinN, xClipMaxN, /* normalized values for216clip volume */217yClipMinN, yClipMaxN,218zClipMinN, zClipMaxN,219clipValue; /* mouse input */220float pzMin, pzMax; /* for a given (theta,phi): calculated in221drawViewport(), used in drawFrustrum() */222223/** B/W shades **/224/** events from the viewport manager **/225char propertyName[14];226char propertyBuffer[256];227228/* global ps variables */229230/** Resource database **/231XrmDatabase rDB;232233/** variables used for smooth shading **/234int smoothError = no;235Pixmap viewmap;236float Cspec = 0.30;237float Cdiff = 0.4;238float Camb = 0.3;239float coeff = 35.0;240float saturation = 0.8;241int smoothHue;242int smoothConst = 50;243244245246247void248main(void)249{250251XGCValues controlGCVals;252int i, code;253254char property[256];255char *prop = &property[0];256char *str_type[20];257XrmValue value;258259Atom wm_delete_window;260XColor foreColor, backColor;261XSizeHints titleSizeHints;262Window viewTitleWindow, viewGraphWindow;263XSetWindowAttributes viewAttrib;264Pixmap spadbits,spadmask;265266/**** Global inits ****/267splitPoints = NIL(viewTriple);268269/**** Set up display ****/270if ((dsply = XOpenDisplay(oa_getenv("DISPLAY"))) == NULL)271{fprintf(stderr,"Could not open display.\n");exit (-1);}272scrn = DefaultScreen(dsply);273rtWindow = RootWindow(dsply,scrn);274275/**** link Xwindows to viewports - X10 feature ****/276table = XCreateAssocTable(nbuckets);277278/**** Create OpenAxiom color map ****/279totalShades = 0;280totalColors = XInitSpadFill(dsply,scrn,&colorMap,281&totalHues,&totalSolidShades,282&totalDitheredAndSolids,&totalShades);283if (totalColors < 0) {284fprintf(stderr,"ERROR: Could not allocate all the necessary colors.\n");285exitWithAck(RootWindow(dsply,scrn),Window,-1);286}287288289290PSGlobalInit();291/* must initiate before using any G/PS functions */292/* need character name: used as postscript GC variable */293/* need to create ps GCs for all GCs used by drawing in viewWindow */294295/* globalGC1 */296controlGCVals.foreground = monoColor(axesColor);297controlGCVals.background = backgroundColor;298globalGC1 = XCreateGC(dsply,rtWindow,GCForeground |299GCBackground ,&controlGCVals);300carefullySetFont(globalGC1,globalFont);301PSCreateContext(globalGC1, "globalGC1", psNormalWidth, psButtCap,302psMiterJoin, psWhite, psBlack);303304/* controlMessageGC */305controlGCVals.foreground = controlMessageColor;306controlGCVals.background = backgroundColor;307controlMessageGC = XCreateGC(dsply,rtWindow,GCForeground |308GCBackground ,&controlGCVals);309carefullySetFont(controlMessageGC,globalFont);310311/* globalGC2 */312controlGCVals.foreground = monoColor(labelColor);313globalGC2 = XCreateGC(dsply,rtWindow,GCForeground,&controlGCVals);314carefullySetFont(globalGC2,buttonFont);315PSCreateContext(globalGC2, "globalGC2", psNormalWidth, psButtCap,316psMiterJoin, psWhite, psBlack);317318/* trashGC */319controlGCVals.function = GXcopy;320trashGC = XCreateGC(dsply,rtWindow,0 ,&controlGCVals);321carefullySetFont(trashGC,buttonFont);322PSCreateContext(trashGC, "trashGC", psNormalWidth, psButtCap,323psMiterJoin, psWhite, psBlack);324325/* componentGC */326componentGC = XCreateGC(dsply,rtWindow,0 ,&controlGCVals);327carefullySetFont(componentGC,buttonFont);328PSCreateContext(componentGC, "componentGC", psNormalWidth, psButtCap,329psMiterJoin, psWhite, psBlack);330331/* opaqueGC */332opaqueGC = XCreateGC(dsply,rtWindow,0 ,&controlGCVals);333carefullySetFont(opaqueGC,buttonFont);334PSCreateContext(opaqueGC, "opaqueGC", psNormalWidth, psButtCap,335psMiterJoin, psWhite, psBlack);336337/* renderGC */338renderGC = XCreateGC(dsply,rtWindow,0,&controlGCVals);339carefullySetFont(renderGC,buttonFont);340PSCreateContext(renderGC, "renderGC", psNormalWidth, psButtCap,341psMiterJoin, psWhite, psBlack);342343/* globGC */344globGC = XCreateGC(dsply,rtWindow,0,&controlGCVals);345carefullySetFont(globGC,headerFont);346PSCreateContext(globGC, "globGC", psNormalWidth, psButtCap,347psMiterJoin, psWhite, psBlack);348349/* anotherGC */350controlGCVals.line_width = colorWidth;351anotherGC = XCreateGC(dsply,rtWindow,GCBackground | GCLineWidth |352GCFunction ,&controlGCVals);353carefullySetFont(anotherGC,titleFont);354PSCreateContext(anotherGC, "anotherGC", psNormalWidth, psButtCap,355psMiterJoin, psWhite, psBlack);356357/* also create one for rendering (grayscale only for now) */358/* assign arbitrary number to renderGC as 9991 - see header.h */359PSCreateContext(GC9991, "renderGC", psNormalWidth, psButtCap,360psRoundJoin, psWhite, psBlack );361362363/* processGC */364gcVals.background = backgroundColor;365processGC = XCreateGC(dsply,rtWindow,GCBackground |366GCFillStyle,&gcVals);367carefullySetFont(processGC,buttonFont);368369/* lightingGC */370controlGCVals.foreground = monoColor(axesColor);371controlGCVals.background = backgroundColor;372lightingGC = XCreateGC(dsply,rtWindow,GCForeground | GCBackground373,&controlGCVals);374carefullySetFont(lightingGC,lightingFont);375376377/* volumeGC */378volumeGC = XCreateGC(dsply,rtWindow,GCForeground | GCBackground379,&controlGCVals);380carefullySetFont(volumeGC,volumeFont);381382/* quitGC */383quitGC = XCreateGC(dsply,rtWindow,GCForeground | GCBackground384,&controlGCVals);385carefullySetFont(quitGC,buttonFont);386387/* saveGC */388saveGC = XCreateGC(dsply,rtWindow,GCForeground | GCBackground389,&controlGCVals);390carefullySetFont(saveGC,buttonFont);391392393/* graphGC */394graphGC = XCreateGC(dsply,rtWindow,GCForeground | GCBackground395,&controlGCVals);396carefullySetFont(graphGC,buttonFont);397if (!(viewport = (viewPoints *)saymem("viewport3D.c",3981,sizeof(viewPoints)))) {399fprintf(stderr,"Ran out of memory trying to create a viewport.\n");400exitWithAck(RootWindow(dsply,scrn),Window,-1);401}402/* Definition of the 4x4 identity matrix. */403I[0][0] = 1.0; I[0][1] = 0.0; I[0][2] = 0.0; I[0][3] = 0.0;404I[1][0] = 0.0; I[1][1] = 1.0; I[1][2] = 0.0; I[1][3] = 0.0;405I[2][0] = 0.0; I[2][1] = 0.0; I[2][2] = 1.0; I[2][3] = 0.0;406I[3][0] = 0.0; I[3][1] = 0.0; I[3][2] = 0.0; I[3][3] = 1.0;407408viewport->viewportKey = viewportKeyNum++;409viewport->nextViewport = 0;410viewport->prevViewport = 0;411viewport->deltaX = viewport->deltaX0 = viewData.deltaX;412viewport->deltaY = viewport->deltaY0 = viewData.deltaY;413viewport->deltaZ = viewport->deltaZ0 = viewData.deltaZ;414viewport->scale = viewport->scale0 = viewData.scale;415viewport->scaleX = viewData.scaleX;416viewport->scaleY = viewData.scaleY;417viewport->scaleZ = viewData.scaleZ;418viewport->transX = (viewData.xmax + viewData.xmin)/2.0;419viewport->transY = (viewData.ymax + viewData.ymin)/2.0;420viewport->transZ = (viewData.zmax + viewData.zmin)/2.0;421422viewport->theta = viewport->axestheta = viewport->theta0 = viewData.theta;423viewport->phi = viewport->axesphi = viewport->phi0 = viewData.phi;424viewport->thetaObj = 0.0;425viewport->phiObj = 0.0;426427viewData.title = "untitled";428strcpy(viewport->title,viewData.title);429430viewport->axesOn = yes;431viewport->regionOn = no;432viewport->monoOn = no;433viewport->zoomXOn = yes;434viewport->zoomYOn = yes;435viewport->zoomZOn = yes;436437viewport->originrOn = yes;438viewport->objectrOn = no;439viewport->originFlag = no;440441viewport->xyOn = no;442viewport->xzOn = no;443viewport->yzOn = no;444445viewport->closing = no;446viewport->allowDraw = yes; /*if no, just draw axes the first time */447viewport->needNorm = yes;448449viewport->lightVector[0] = -0.5;450viewport->lightVector[1] = 0.5;451viewport->lightVector[2] = 0.5;452viewport->translucency = viewData.translucency;453454viewport->hueOffset = viewData.hueOff;455viewport->numberOfHues = viewData.numOfHues;456viewport->hueTop = viewData.hueOff + viewData.numOfHues;457if (viewport->hueTop > totalHues-1) viewport->hueTop = totalHues-1;458viewport->diagonals = viewData.diagonals;459460/* make theta in [0..2pi) and phi in (-pi..pi] */461while (viewport->theta >= two_pi) {462viewport->theta -= two_pi;463}464while (viewport->theta < 0.0) {465viewport->theta += two_pi;466}467while (viewport->phi > pi) {468viewport->phi -= two_pi;469}470while (viewport->phi <= -pi) {471viewport->phi += two_pi;472}473474while (viewport->axestheta >= two_pi) {475viewport->axestheta -= two_pi;476}477while (viewport->axestheta < 0.0) {478viewport->axestheta += two_pi;479}480while (viewport->axesphi > pi) {481viewport->axesphi -= two_pi;482}483while (viewport->axesphi <= -pi) {484viewport->axesphi += two_pi;485}486487/* Initialize the rotation matrix about the origin. */488sinTheta = sin(-viewport->theta);489cosTheta = cos(-viewport->theta);490sinPhi = sin(viewport->phi);491cosPhi = cos(viewport->phi);492ROTATE(R); /* angles theta and phi are global */493494/* Initialize the rotation matrix about the object's center of volume. */495sinTheta = sin(-viewport->thetaObj);496cosTheta = cos(-viewport->thetaObj);497sinPhi = sin(viewport->phiObj);498cosPhi = cos(viewport->phiObj);499ROTATE1(R1); /* angles theta and phi are global */500501502/* Initialize the non-uniform scaling matrix. */503SCALE(viewport->scaleX,viewport->scaleY,viewport->scaleZ,S);504/* Initialize the translation matrix. */505TRANSLATE(-viewport->deltaX,-viewport->deltaY,0.0,T);506/**** make the windows for the viewport ****/507spadbits = XCreateBitmapFromData(dsply,rtWindow,508spadBitmap_bits,509spadBitmap_width,spadBitmap_height);510spadmask = XCreateBitmapFromData(dsply,rtWindow,511spadMask_bits,512spadMask_width,spadMask_height);513viewAttrib.background_pixel = backgroundColor;514viewAttrib.border_pixel = foregroundColor;515516viewAttrib.override_redirect = overrideManager;517518viewAttrib.colormap = colorMap;519foreColor.pixel = foregroundColor;520backColor.pixel = backgroundColor;521/*522foreColor.pixel = viewCursorForeground;523backColor.pixel = viewCursorBackground;524*/525XQueryColor(dsply,colorMap,&foreColor);526XQueryColor(dsply,colorMap,&backColor);527viewAttrib.cursor = XCreatePixmapCursor(dsply,spadbits,spadmask,528&foreColor,&backColor,spadBitmap_x_hot,spadBitmap_y_hot);529viewAttrib.event_mask = titleMASK;530if (viewData.vW) {531titleSizeHints.flags = PPosition | PSize;532titleSizeHints.x = viewData.vX;533titleSizeHints.y = viewData.vY;534titleSizeHints.width = viewData.vW;535titleSizeHints.height = viewData.vH;536} else { /* ain't gonna allow this for now... */537titleSizeHints.flags = PSize;538titleSizeHints.width = viewWidth;539titleSizeHints.height = viewHeight;540}541542viewTitleWindow = XCreateWindow(dsply,rtWindow,viewData.vX,viewData.vY,543viewData.vW,viewData.vH,viewBorderWidth+3,544CopyFromParent,InputOutput,CopyFromParent,545viewportTitleCreateMASK,&viewAttrib);546547wm_delete_window = XInternAtom(dsply, "WM_DELETE_WINDOW", False);548(void) XSetWMProtocols(dsply, viewTitleWindow, &wm_delete_window, 1);549550XSetNormalHints(dsply,viewTitleWindow,&titleSizeHints);551if (strlen(viewport->title) < 30)552XSetStandardProperties(dsply,viewTitleWindow,"OpenAxiom 3D",viewport->title,553None,NULL,0,&titleSizeHints);554else555XSetStandardProperties(dsply,viewTitleWindow,"OpenAxiom 3D","3D OpenAxiom Graph",556None,NULL,0,&titleSizeHints);557viewport->titleWindow = viewTitleWindow;558559viewAttrib.event_mask = viewportMASK;560viewSizeHints.flags = PPosition | PSize;561viewSizeHints.x = -(viewBorderWidth+3);562viewSizeHints.y = titleHeight;563viewSizeHints.width = titleSizeHints.width;564viewSizeHints.height = titleSizeHints.height-(titleHeight+appendixHeight);565viewGraphWindow = XCreateWindow(dsply,viewTitleWindow,566viewSizeHints.x,viewSizeHints.y,567viewSizeHints.width,viewSizeHints.height,568viewBorderWidth+3,569CopyFromParent,InputOutput,CopyFromParent,570viewportCreateMASK,&viewAttrib);571XSetNormalHints(dsply,viewGraphWindow,&viewSizeHints);572XSetStandardProperties(dsply,viewGraphWindow,"","",None,NULL,0,573&viewSizeHints);574viewport->viewWindow = viewGraphWindow;575graphWindowAttrib.width = viewSizeHints.width;576graphWindowAttrib.height = viewSizeHints.height;577578if (viewport->hueOffset != viewport->hueTop) {579multiColorFlag = yes;580redoColor = no;581} else {582if (viewport->hueTop < 11)583smoothHue = viewport->hueTop*6;584else {585if (viewport->hueTop > 10 && viewport->hueTop < 16)586smoothHue = viewport->hueTop*20 - 140;587else smoothHue = viewport->hueTop*12 - 12;588}589redoColor = yes;590}591592593} /* main() */594595596597598599