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 _VIEWPORT3D_C36#include "openaxiom-c-macros.h"3738#include <math.h>39#include <stdio.h>40#include <string.h>41#include <unistd.h>42#include <stdlib.h>4344#include "spadBitmap.bitmap"45#include "spadMask.mask"4647#include "header.h"48/*** definition for the axes and labels - this is the minimun that will be49drawn on the window - thus allowing the user some idea of the50orientation of the coordinate axes when rotating, etc. The51drawing of the mesh is aborted when an appropriate X event occurs.52The mesh should be scaled to the range of [-100..100] in all53directions. axisRange defines the range...change the stuff below54if that has changed. ***/55#include "static.h"56#include "draw.h"57#include "volume.h"58#include "mode.h"5960#include "util.H1"61#include "Gfun.H1"62#include "XSpadFill.h"63#include "all_3d.H1"6465#define axesOffset 56667Atom wm_delete_window;686970/***************************71*** void writeTitle() ***72***************************/7374void75writeTitle (void)76{7778int strlength;79XWindowAttributes twInfo;8081XGetWindowAttributes(dsply, viewport->titleWindow, &twInfo);82if (mono || viewport->monoOn)83GSetForeground(anotherGC, (float)foregroundColor, Xoption);84else85GSetForeground(anotherGC, (float)titleColor, Xoption);86XClearWindow(dsply, viewport->titleWindow);8788strlength = strlen(viewport->title);89GDrawImageString(anotherGC, viewport->titleWindow,90centerX(anotherGC, viewport->title, strlength,91twInfo.width), 15,92viewport->title, strlength, Xoption);9394}959697/****************************98* void drawPreViewport() *99* *100* draws the axes and boxes *101* before the actual stuff. *102* all incoming signals *103* should be block and no *104* check for pending X *105* events are made. *106* *107****************************/108109void110drawPreViewport (int dFlag)111{112113int i, j, vPx0, vPy0, vPx1, vPy1;114/* for drawing the box */115float vPz, absTransX, absTransY;116XPoint blackbox[3], line[2];117RGB axes_rgb, clipbox_rgb, boundbox_rgb;118119axes_rgb.r = 0.8; axes_rgb.g = 0.6; axes_rgb.b = 0.2;120clipbox_rgb.r = 0.4; clipbox_rgb.g = 0.5; clipbox_rgb.b = 0.9;121boundbox_rgb.r = 0.4; boundbox_rgb.g = 0.7; boundbox_rgb.b = 0.9;122123XGetWindowAttributes(dsply, viewport->viewWindow, &vwInfo);124graphWindowAttrib = vwInfo;125126/* Calculate various factors for use in projection */127/* Scale so that plot the scaling between the axes remains constant128and fits within the smaller of the two dimensions. */129130xCenter = vwInfo.width / 2;131yCenter = vwInfo.height / 2;132133if (vwInfo.height <= vwInfo.width) {134viewScale = viewport->scale * vwInfo.height / viewHeight;135}136else {137viewScale = viewport->scale * vwInfo.width / viewWidth;138}139140/* Draw the projected image */141/** draw the axes without heeding to X interrupts, first **/142143if (dFlag == Xoption) /* do this for X option only */144XClearWindow(dsply, viewport->viewWindow);145146sinTheta = sin(-viewport->axestheta);147cosTheta = cos(-viewport->axestheta);148sinPhi = sin(viewport->axesphi);149cosPhi = cos(viewport->axesphi);150151/* Create transformation matrices */152ROTATE(R); /* angles theta and phi are global */153SCALE(viewport->scaleX,viewport->scaleY,viewport->scaleZ,S);154TRANSLATE(-viewport->deltaX,-viewport->deltaY,0.0,T);155156/**** Pre Draw Routine ****/157158if ((dFlag == PSoption) && (foregroundColor == white)) {159GSetForeground(globGC,(float)backgroundColor,dFlag);160blackbox[0].x = vwInfo.width; blackbox[0].y = vwInfo.height;161blackbox[1].x = 0; blackbox[1].y = 0;162blackbox[2].x = 0; blackbox[2].y = vwInfo.height;163if (viewport->monoOn || mono) {164PSFillPolygon(globGC, blackbox, 3);165} else {166PSColorPolygon(0.0,0.0,0.0,blackbox,4);167}168blackbox[0].x = vwInfo.width; blackbox[0].y = 0;169blackbox[1].x = 0; blackbox[1].y = 0;170blackbox[2].x = vwInfo.width; blackbox[2].y = vwInfo.height;171if (viewport->monoOn || mono) {172PSFillPolygon(globGC, blackbox, 3);173} else {174PSColorPolygon(0.0,0.0,0.0,blackbox,4);175}176}177178/* axes */179180for (i=0; i < 3; i++) {181projectStuff(axes[i][0],axes[i][1],axes[i][2],&vPx0,&vPy0,&vPz);182axesXY[i][0] = vPx0; axesXY[i][1] = vPy0; axesZ[i][0] = vPz;183projectStuff(axes[i][3],axes[i][4],axes[i][5],&vPx1,&vPy1,&vPz);184axesXY[i][2] = vPx1; axesXY[i][3] = vPy1; axesZ[i][1] = vPz;185if (viewport->axesOn) {186if (viewport->monoOn || mono) {187GSetForeground(globalGC1,(float)foregroundColor,dFlag);188GSetForeground(globGC,(float)foregroundColor,dFlag);189GDrawLine(globalGC1,viewport->viewWindow,vPx0,vPy0,vPx1,vPy1,dFlag);190} else {191if (dFlag == PSoption) {192GSetForeground(globGC,(float)foregroundColor,dFlag);193line[0].x = vPx0; line[0].y = vPy0;194line[1].x = vPx1; line[1].y = vPy1;195PSDrawColor(axes_rgb.r,axes_rgb.g,axes_rgb.b,line,2);196} else {197GSetForeground(globalGC1,(float)monoColor(axesColor),dFlag);198GSetForeground(globGC,(float)monoColor(labelColor),dFlag);199GDrawLine(globalGC1,viewport->viewWindow,vPx0,vPy0,vPx1,vPy1,dFlag);200}201}202if (i == 0) {203if (axesXY[0][2] < axesXY[0][0]) vPx1 -= axesOffset;204else vPx1 += axesOffset;205if (axesXY[0][3] < axesXY[0][1]) vPy1 -= axesOffset;206else vPy1 += axesOffset;207if (!viewport->yzOn)208GDrawString(globGC,viewport->viewWindow,vPx1,vPy1,"X",1,dFlag);209} else {210if (i == 1) {211if (axesXY[1][2] < axesXY[1][0]) vPx1 -= axesOffset;212else vPx1 += axesOffset;213if (axesXY[1][3] < axesXY[1][1]) vPy1 -= axesOffset;214else vPy1 += axesOffset;215if (!viewport->xzOn)216GDrawString(globGC,viewport->viewWindow,vPx1,vPy1,"Y",1,dFlag);217} else {218if (axesXY[2][2] < axesXY[2][0]) vPx1 -= axesOffset;219else vPx1 += axesOffset;220if (axesXY[2][3] < axesXY[2][1]) vPy1 -= axesOffset;221else vPy1 += axesOffset;222if (!viewport->xyOn)223GDrawString(globGC,viewport->viewWindow,vPx1,vPy1,"Z",1,dFlag);224}225}226GSetForeground(globalGC1,(float)monoColor(buttonColor),dFlag);227GSetForeground(globGC,(float)monoColor(buttonColor),dFlag);228} /* if viewport->axesOn */229}230231viewport->transX = (viewData.xmax + viewData.xmin)/2.0;232viewport->transY = (viewData.ymax + viewData.ymin)/2.0;233viewport->transZ = (viewData.zmax + viewData.zmin)/2.0;234235absTransX = absolute(viewport->transX);236absTransY = absolute(viewport->transY);237if ((absTransX > 0.5) || (absTransY > 0.5)) {238if (absTransX > absTransY)239reScale = 50.0 * absTransX / viewData.scaleToView;240else241reScale = 50.0 * absTransY / viewData.scaleToView;242if (reScale < 100.0) reScale = 100.0;243} else {244reScale = 100.0;245}246247sinTheta = sin(-viewport->thetaObj);248cosTheta = cos(-viewport->thetaObj);249sinPhi = sin(viewport->phiObj);250cosPhi = cos(viewport->phiObj);251ROTATE1(R1);252253if (viewport->originFlag) viewport->originFlag = no;254sinTheta = sin(-viewport->axestheta);255cosTheta = cos(-viewport->axestheta);256sinPhi = sin(viewport->axesphi);257cosPhi = cos(viewport->axesphi);258ROTATE(R);259260/* region box */261if (viewData.clipbox) {262clipCorners[0].x = viewData.clipXmin;263clipCorners[0].y = viewData.clipYmin;264clipCorners[0].z = viewData.clipZmin;265clipCorners[1].x = viewData.clipXmax;266clipCorners[1].y = viewData.clipYmin;267clipCorners[1].z = viewData.clipZmin;268clipCorners[2].x = viewData.clipXmax;269clipCorners[2].y = viewData.clipYmin;270clipCorners[2].z = viewData.clipZmax;271clipCorners[3].x = viewData.clipXmin;272clipCorners[3].y = viewData.clipYmin;273clipCorners[3].z = viewData.clipZmax;274clipCorners[4].x = viewData.clipXmin;275clipCorners[4].y = viewData.clipYmax;276clipCorners[4].z = viewData.clipZmin;277clipCorners[5].x = viewData.clipXmax;278clipCorners[5].y = viewData.clipYmax;279clipCorners[5].z = viewData.clipZmin;280clipCorners[6].x = viewData.clipXmax;281clipCorners[6].y = viewData.clipYmax;282clipCorners[6].z = viewData.clipZmax;283clipCorners[7].x = viewData.clipXmin;284clipCorners[7].y = viewData.clipYmax;285clipCorners[7].z = viewData.clipZmax;286287GSetLineAttributes(trashGC,0,LineSolid,CapButt,JoinMiter,dFlag);288289/* project the 8 corners of the box */290for (i=0;i<8;i++) projectAPoint(&(clipCorners[i]));291292for (i=0;i<6;i++) {293clipBox[i].inside = ((clipBox[i].pointsPtr[2]->px -294clipBox[i].pointsPtr[1]->px) *295(clipBox[i].pointsPtr[1]->py -296clipBox[i].pointsPtr[0]->py) -297(clipBox[i].pointsPtr[2]->py -298clipBox[i].pointsPtr[1]->py) *299(clipBox[i].pointsPtr[1]->px -300clipBox[i].pointsPtr[0]->px)) < 0;301if (clipBox[i].inside) {302for (j=0; j<3; j++) {303quadMesh[j].x = clipBox[i].pointsPtr[j]->px;304quadMesh[j].y = clipBox[i].pointsPtr[j]->py;305}306if (viewport->monoOn || mono) {307GSetForeground(trashGC,(float)foregroundColor,dFlag);308GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,309CoordModeOrigin, dFlag);310} else {311if (dFlag == PSoption) {312GSetForeground(trashGC,(float)clipBoxInline, dFlag);313line[0].x = quadMesh[0].x; line[0].y = quadMesh[0].y;314line[1].x = quadMesh[1].x; line[1].y = quadMesh[1].y;315PSDrawColor(clipbox_rgb.r,clipbox_rgb.g,clipbox_rgb.b,line,2);316line[0].x = quadMesh[1].x; line[0].y = quadMesh[1].y;317line[1].x = quadMesh[2].x; line[1].y = quadMesh[2].y;318PSDrawColor(clipbox_rgb.r,clipbox_rgb.g,clipbox_rgb.b,line,2);319} else {320GSetForeground(trashGC,(float)clipBoxInline, dFlag);321GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,322CoordModeOrigin, dFlag);323}324}325}326}327} /* if viewData.clipbox */328329/* VOLUME panel stuff */330if ((doingPanel == VOLUMEpanel) || viewData.box) {331332GSetLineAttributes(trashGC,0,LineSolid,CapButt,JoinMiter,dFlag);333334for (i=0;i<8;i++) {335/* project the 8 corners of the box */336projectAPoint(&(corners[i]));337if (i) {338if (corners[i].pz > pzMax) pzMax = corners[i].pz;339else if (corners[i].pz < pzMin) pzMin = corners[i].pz;340} else341pzMax = pzMin = corners[i].pz;342}343344for (i=0;i<6;i++) {345/* Process the 6 sides of the boxes.346Here, we calculate, for each side (defined by two segments)347whether it is facing towards or away from the viewer. if348facing, away, we draw them first. later we draw the ones349facing the viewer. (this is a sort of backface removal350scheme. */351/* We define the normal vector for the box as vA X vB where352vA=p2-p0 and vB=p1-p0. All we really care about, though,353is what sign the normal is (whether it is towards or away354from the viewer - so we just take the triple product of355it against the eye vector, which is, conveniently enough,356simply [0 0 1]. Hence, only the Z component of the357cross product is calculated. (Actually, we are using the358projected normal - that's how we are able to use the359trick of just taking the Z component. */360box[i].inside = ((box[i].pointsPtr[2]->px -361box[i].pointsPtr[0]->px) * /* Ax * */362(box[i].pointsPtr[1]->py -363box[i].pointsPtr[0]->py) - /* By - */364(box[i].pointsPtr[2]->py -365box[i].pointsPtr[0]->py) * /* Ay * */366(box[i].pointsPtr[1]->px -367box[i].pointsPtr[0]->px)) /* Bx */368< 0;369if (box[i].inside) {370for (j=0; j<3; j++) {371quadMesh[j].x = box[i].pointsPtr[j]->px;372quadMesh[j].y = box[i].pointsPtr[j]->py;373}374if (viewport->monoOn || mono) {375GSetForeground(trashGC,(float)foregroundColor,dFlag);376GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,377CoordModeOrigin, dFlag);378} else {379if (dFlag == PSoption) {380GSetForeground(trashGC,(float)boxInline, dFlag );381line[0].x = quadMesh[0].x; line[0].y = quadMesh[0].y;382line[1].x = quadMesh[1].x; line[1].y = quadMesh[1].y;383PSDrawColor(boundbox_rgb.r,boundbox_rgb.g,boundbox_rgb.b,line,2);384line[0].x = quadMesh[1].x; line[0].y = quadMesh[1].y;385line[1].x = quadMesh[2].x; line[1].y = quadMesh[2].y;386PSDrawColor(boundbox_rgb.r,boundbox_rgb.g,boundbox_rgb.b,line,2);387} else {388GSetForeground(trashGC,(float)boxInline, dFlag );389GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,390CoordModeOrigin, dFlag);391}392}393}394}395} /* if viewData.box */396397/* Write out view data */398if (dFlag == Xoption) { /* do this only for X option */399writeControlMessage();400XFlush(dsply);401}402}403404405/********************************/406/*** void drawTheViewport() ***/407/********************************/408409void410drawTheViewport (int dFlag)411{412413int i,j;414XPoint line[2];415RGB clipbox_rgb, boundbox_rgb;416417clipbox_rgb.r = 0.4; clipbox_rgb.g = 0.5; clipbox_rgb.b = 0.9;418boundbox_rgb.r = 0.4; boundbox_rgb.g = 0.7; boundbox_rgb.b = 0.9;419420/**** Draw Routine ****/421422if (viewport->allowDraw && (doingPanel != VOLUMEpanel)) {423/* Do not draw the mesh stuff if we're in the process of changing424the viewing volume; we just want to see the volume */425426/* drawMore allows the drawing to continue if no relevant XEvent occurs */427drawMore = yes;428drawMore = keepDrawingViewport();429draw3DComponents(dFlag);430431} /*if viewport->allowDraw */432433/**** Post Draw Routine ****/434if (viewData.clipbox) { /* draw the front 3 lines of region box */435GSetLineAttributes(trashGC,0,LineSolid,CapButt,JoinMiter,dFlag);436for (i=0; i<6; i++) {437if (!(clipBox[i].inside)) {438for (j=0; j<4; j++) {439quadMesh[j].x = clipBox[i].pointsPtr[j]->px;440quadMesh[j].y = clipBox[i].pointsPtr[j]->py;441}442if (viewport->monoOn || mono) {443GSetForeground(trashGC,(float)foregroundColor,dFlag);444GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,445CoordModeOrigin, dFlag);446} else {447if (dFlag == PSoption) {448GSetForeground(trashGC,(float)boxInline, dFlag );449line[0].x = quadMesh[0].x; line[0].y = quadMesh[0].y;450line[1].x = quadMesh[1].x; line[1].y = quadMesh[1].y;451PSDrawColor(clipbox_rgb.r,clipbox_rgb.g,clipbox_rgb.b,line,2);452line[0].x = quadMesh[1].x; line[0].y = quadMesh[1].y;453line[1].x = quadMesh[2].x; line[1].y = quadMesh[2].y;454PSDrawColor(clipbox_rgb.r,clipbox_rgb.g,clipbox_rgb.b,line,2);455} else {456GSetForeground(trashGC,(float)boxInline, dFlag );457GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,458CoordModeOrigin, dFlag);459}460}461}462}463}464465if ((doingPanel==VOLUMEpanel) || viewData.box) {466GSetLineAttributes(trashGC,0,LineSolid,CapButt,JoinMiter,dFlag);467for (i=0; i<6; i++) {468if (!(box[i].inside)) {469for (j=0; j<4; j++) {470quadMesh[j].x = box[i].pointsPtr[j]->px;471quadMesh[j].y = box[i].pointsPtr[j]->py;472}473if (viewport->monoOn || mono) {474GSetForeground(trashGC,(float)foregroundColor,dFlag);475GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,476CoordModeOrigin, dFlag);477} else {478if (dFlag == PSoption) {479GSetForeground(trashGC,(float)boxInline, dFlag );480line[0].x = quadMesh[0].x; line[0].y = quadMesh[0].y;481line[1].x = quadMesh[1].x; line[1].y = quadMesh[1].y;482PSDrawColor(boundbox_rgb.r,boundbox_rgb.g,boundbox_rgb.b,line,2);483line[0].x = quadMesh[1].x; line[0].y = quadMesh[1].y;484line[1].x = quadMesh[2].x; line[1].y = quadMesh[2].y;485PSDrawColor(boundbox_rgb.r,boundbox_rgb.g,boundbox_rgb.b,line,2);486} else {487GSetForeground(trashGC,(float)boxInline, dFlag );488GDrawLines(trashGC, viewport->viewWindow, quadMesh, 3,489CoordModeOrigin, dFlag);490}491}492}493}494}495496if (dFlag == Xoption) /* do this for X option only */497XFlush(dsply);498499if (smoothError) {500strcpy(control->message,"Cannot alloc more smooth shades.");501writeControlMessage();502smoothError = no;503}504505} /* drawTheViewport */506507/************************************508*** viewPoints *makeViewport() ***509************************************/510511viewPoints *512makeViewport (void)513{514515Pixmap spadbits,spadmask;516XSetWindowAttributes viewAttrib;517XSizeHints titleSizeHints;518Window viewTitleWindow, viewGraphWindow;519XColor foreColor, backColor;520521/**** create a viewport ****/522523if (!(viewport = (viewPoints *)saymem("viewport3D.c",5241,sizeof(viewPoints)))) {525fprintf(stderr,"Ran out of memory trying to create a viewport.\n");526exitWithAck(RootWindow(dsply,scrn),Window,-1);527}528/* Definition of the 4x4 identity matrix. */529I[0][0] = 1.0; I[0][1] = 0.0; I[0][2] = 0.0; I[0][3] = 0.0;530I[1][0] = 0.0; I[1][1] = 1.0; I[1][2] = 0.0; I[1][3] = 0.0;531I[2][0] = 0.0; I[2][1] = 0.0; I[2][2] = 1.0; I[2][3] = 0.0;532I[3][0] = 0.0; I[3][1] = 0.0; I[3][2] = 0.0; I[3][3] = 1.0;533534viewport->viewportKey = viewportKeyNum++;535viewport->nextViewport = 0;536viewport->prevViewport = 0;537viewport->deltaX = viewport->deltaX0 = viewData.deltaX;538viewport->deltaY = viewport->deltaY0 = viewData.deltaY;539viewport->deltaZ = viewport->deltaZ0 = viewData.deltaZ;540viewport->scale = viewport->scale0 = viewData.scale;541viewport->scaleX = viewData.scaleX;542viewport->scaleY = viewData.scaleY;543viewport->scaleZ = viewData.scaleZ;544viewport->transX = (viewData.xmax + viewData.xmin)/2.0;545viewport->transY = (viewData.ymax + viewData.ymin)/2.0;546viewport->transZ = (viewData.zmax + viewData.zmin)/2.0;547548viewport->theta = viewport->axestheta = viewport->theta0 = viewData.theta;549viewport->phi = viewport->axesphi = viewport->phi0 = viewData.phi;550viewport->thetaObj = 0.0;551viewport->phiObj = 0.0;552553strcpy(viewport->title,viewData.title);554555viewport->axesOn = yes;556viewport->regionOn = no;557viewport->monoOn = no;558viewport->zoomXOn = yes;559viewport->zoomYOn = yes;560viewport->zoomZOn = yes;561562viewport->originrOn = yes;563viewport->objectrOn = no;564viewport->originFlag = no;565566viewport->xyOn = no;567viewport->xzOn = no;568viewport->yzOn = no;569570viewport->closing = no;571viewport->allowDraw = yes; /*if no, just draw axes the first time */572viewport->needNorm = yes;573574viewport->lightVector[0] = -0.5;575viewport->lightVector[1] = 0.5;576viewport->lightVector[2] = 0.5;577viewport->translucency = viewData.translucency;578579viewport->hueOffset = viewData.hueOff;580viewport->numberOfHues = viewData.numOfHues;581viewport->hueTop = viewData.hueOff + viewData.numOfHues;582if (viewport->hueTop > totalHues-1) viewport->hueTop = totalHues-1;583viewport->diagonals = viewData.diagonals;584585/* make theta in [0..2pi) and phi in (-pi..pi] */586while (viewport->theta >= two_pi) {587viewport->theta -= two_pi;588}589while (viewport->theta < 0.0) {590viewport->theta += two_pi;591}592while (viewport->phi > pi) {593viewport->phi -= two_pi;594}595while (viewport->phi <= -pi) {596viewport->phi += two_pi;597}598599while (viewport->axestheta >= two_pi) {600viewport->axestheta -= two_pi;601}602while (viewport->axestheta < 0.0) {603viewport->axestheta += two_pi;604}605while (viewport->axesphi > pi) {606viewport->axesphi -= two_pi;607}608while (viewport->axesphi <= -pi) {609viewport->axesphi += two_pi;610}611612/* Initialize the rotation matrix about the origin. */613sinTheta = sin(-viewport->theta);614cosTheta = cos(-viewport->theta);615sinPhi = sin(viewport->phi);616cosPhi = cos(viewport->phi);617ROTATE(R); /* angles theta and phi are global */618619/* Initialize the rotation matrix about the object's center of volume. */620sinTheta = sin(-viewport->thetaObj);621cosTheta = cos(-viewport->thetaObj);622sinPhi = sin(viewport->phiObj);623cosPhi = cos(viewport->phiObj);624ROTATE1(R1); /* angles theta and phi are global */625626627/* Initialize the non-uniform scaling matrix. */628SCALE(viewport->scaleX,viewport->scaleY,viewport->scaleZ,S);629/* Initialize the translation matrix. */630TRANSLATE(-viewport->deltaX,-viewport->deltaY,0.0,T);631/**** make the windows for the viewport ****/632spadbits = XCreateBitmapFromData(dsply,rtWindow,633(const char*) spadBitmap_bits,634spadBitmap_width,spadBitmap_height);635spadmask = XCreateBitmapFromData(dsply,rtWindow,636(const char*) spadMask_bits,637spadMask_width,spadMask_height);638viewAttrib.background_pixel = backgroundColor;639viewAttrib.border_pixel = foregroundColor;640641viewAttrib.override_redirect = overrideManager;642643viewAttrib.colormap = colorMap;644foreColor.pixel = foregroundColor;645backColor.pixel = backgroundColor;646/*647foreColor.pixel = viewCursorForeground;648backColor.pixel = viewCursorBackground;649*/650XQueryColor(dsply,colorMap,&foreColor);651XQueryColor(dsply,colorMap,&backColor);652viewAttrib.cursor = XCreatePixmapCursor(dsply,spadbits,spadmask,653&foreColor,&backColor,spadBitmap_x_hot,spadBitmap_y_hot);654viewAttrib.event_mask = titleMASK;655if (viewData.vW) {656titleSizeHints.flags = PPosition | PSize;657titleSizeHints.x = viewData.vX;658titleSizeHints.y = viewData.vY;659titleSizeHints.width = viewData.vW;660titleSizeHints.height = viewData.vH;661} else { /* ain't gonna allow this for now... */662titleSizeHints.flags = PSize;663titleSizeHints.width = viewWidth;664titleSizeHints.height = viewHeight;665}666667viewTitleWindow = XCreateWindow(dsply /* display */,668rtWindow, /* parent */669viewData.vX, /* x */670viewData.vY, /* y */671viewData.vW, /* width */672viewData.vH, /* height */673/* viewBorderWidth+3*/ 0, /* border width */674CopyFromParent, /* depth */675InputOutput, /* class */676CopyFromParent, /* visual */677viewportTitleCreateMASK,/* valuemask */678&viewAttrib /* attributes */);679680wm_delete_window = XInternAtom(dsply, "WM_DELETE_WINDOW", False);681(void) XSetWMProtocols(dsply, viewTitleWindow, &wm_delete_window, 1);682683XSetNormalHints(dsply,viewTitleWindow,&titleSizeHints);684if (strlen(viewport->title) < 30)685XSetStandardProperties(dsply,viewTitleWindow,"OpenAxiom 3D",viewport->title,686None,NULL,0,&titleSizeHints);687else688XSetStandardProperties(dsply,viewTitleWindow,"OpenAxiom 3D","3D OpenAxiom Graph",689None,NULL,0,&titleSizeHints);690viewport->titleWindow = viewTitleWindow;691692viewAttrib.event_mask = viewportMASK;693viewSizeHints.flags = PPosition | PSize;694viewSizeHints.x = -(viewBorderWidth+3);695viewSizeHints.x = 0; /* lose this */696viewSizeHints.y = titleHeight;697viewSizeHints.width = titleSizeHints.width;698viewSizeHints.height = titleSizeHints.height-(titleHeight+appendixHeight);699700viewGraphWindow = XCreateWindow(dsply, /* display */701viewTitleWindow, /* parent */702viewSizeHints.x, /* x */703viewSizeHints.y, /* y */704viewSizeHints.width, /* width */705viewSizeHints.height, /* height */706/* viewBorderWidth+3*/0, /* border width */707CopyFromParent, /* depth */708InputOutput, /* class */709CopyFromParent, /* visual */710viewportCreateMASK, /* valuemask */711&viewAttrib /* attributes */);712XSetNormalHints(dsply,viewGraphWindow,&viewSizeHints);713XSetStandardProperties(dsply,viewGraphWindow,"","",None,NULL,0,714&viewSizeHints);715viewport->viewWindow = viewGraphWindow;716graphWindowAttrib.width = viewSizeHints.width;717graphWindowAttrib.height = viewSizeHints.height;718719if (viewport->hueOffset != viewport->hueTop) {720multiColorFlag = yes;721redoColor = no;722} else {723if (viewport->hueTop < 11)724smoothHue = viewport->hueTop*6;725else {726if (viewport->hueTop > 10 && viewport->hueTop < 16)727smoothHue = viewport->hueTop*20 - 140;728else smoothHue = viewport->hueTop*12 - 12;729}730redoColor = yes;731}732733/**** Make the control panel for the viewport. ****/734735XSync(dsply,0);736737control = viewport->controlPanel = makeControlPanel();738makeLightingPanel();739makeVolumePanel();740makeSavePanel();741makeQuitPanel();742743if ((viewport->haveControl = viewData.showCP))744putControlPanelSomewhere(anywhere);745746firstTime = yes;747return(viewport);748749} /* makeViewport() */750751752/*****************************753* void postMakeViewport() *754* *755* post processing when *756* creating a viewport. *757* 1) assign min,max values *758* for the box volume *759*****************************/760761void762postMakeViewport (void)763{764765corners[0].x = viewData.xmin; corners[0].y = viewData.ymin;766corners[0].z = viewData.zmin;767corners[1].x = viewData.xmax; corners[1].y = viewData.ymin;768corners[1].z = viewData.zmin;769corners[2].x = viewData.xmax; corners[2].y = viewData.ymin;770corners[2].z = viewData.zmax;771corners[3].x = viewData.xmin; corners[3].y = viewData.ymin;772corners[3].z = viewData.zmax;773corners[4].x = viewData.xmin; corners[4].y = viewData.ymax;774corners[4].z = viewData.zmin;775corners[5].x = viewData.xmax; corners[5].y = viewData.ymax;776corners[5].z = viewData.zmin;777corners[6].x = viewData.xmax; corners[6].y = viewData.ymax;778corners[6].z = viewData.zmax;779corners[7].x = viewData.xmin; corners[7].y = viewData.ymax;780corners[7].z = viewData.zmax;781782box[2].pointsPtr[0] = &(corners[0]);783box[2].pointsPtr[1] = &(corners[1]);784box[2].pointsPtr[2] = &(corners[2]);785box[2].pointsPtr[3] = &(corners[3]);786787box[3].pointsPtr[0] = &(corners[1]);788box[3].pointsPtr[1] = &(corners[5]);789box[3].pointsPtr[2] = &(corners[6]);790box[3].pointsPtr[3] = &(corners[2]);791792box[0].pointsPtr[0] = &(corners[4]);793box[0].pointsPtr[1] = &(corners[7]);794box[0].pointsPtr[2] = &(corners[6]);795box[0].pointsPtr[3] = &(corners[5]);796797box[1].pointsPtr[0] = &(corners[0]);798box[1].pointsPtr[1] = &(corners[3]);799box[1].pointsPtr[2] = &(corners[7]);800box[1].pointsPtr[3] = &(corners[4]);801802box[5].pointsPtr[0] = &(corners[3]);803box[5].pointsPtr[1] = &(corners[2]);804box[5].pointsPtr[2] = &(corners[6]);805box[5].pointsPtr[3] = &(corners[7]);806807box[4].pointsPtr[0] = &(corners[0]);808box[4].pointsPtr[1] = &(corners[4]);809box[4].pointsPtr[2] = &(corners[5]);810box[4].pointsPtr[3] = &(corners[1]);811812/* clip box */813814clipBox[0].pointsPtr[0] = &(clipCorners[0]);815clipBox[0].pointsPtr[1] = &(clipCorners[1]);816clipBox[0].pointsPtr[2] = &(clipCorners[2]);817clipBox[0].pointsPtr[3] = &(clipCorners[3]);818819clipBox[1].pointsPtr[0] = &(clipCorners[1]);820clipBox[1].pointsPtr[1] = &(clipCorners[5]);821clipBox[1].pointsPtr[2] = &(clipCorners[6]);822clipBox[1].pointsPtr[3] = &(clipCorners[2]);823824clipBox[2].pointsPtr[0] = &(clipCorners[4]);825clipBox[2].pointsPtr[1] = &(clipCorners[7]);826clipBox[2].pointsPtr[2] = &(clipCorners[6]);827clipBox[2].pointsPtr[3] = &(clipCorners[5]);828829clipBox[3].pointsPtr[0] = &(clipCorners[0]);830clipBox[3].pointsPtr[1] = &(clipCorners[3]);831clipBox[3].pointsPtr[2] = &(clipCorners[7]);832clipBox[3].pointsPtr[3] = &(clipCorners[4]);833834clipBox[4].pointsPtr[0] = &(clipCorners[3]);835clipBox[4].pointsPtr[1] = &(clipCorners[2]);836clipBox[4].pointsPtr[2] = &(clipCorners[6]);837clipBox[4].pointsPtr[3] = &(clipCorners[7]);838839clipBox[5].pointsPtr[0] = &(clipCorners[0]);840clipBox[5].pointsPtr[1] = &(clipCorners[4]);841clipBox[5].pointsPtr[2] = &(clipCorners[5]);842clipBox[5].pointsPtr[3] = &(clipCorners[1]);843844845}846847848/*****************************************849*** int keepDrawingViewport() ***850*****************************************/851852853854855int856keepDrawingViewport(void)857{858859XEvent peekEvent;860int retVal;861862if (XPending(dsply)) {863XPeekEvent(dsply,&peekEvent);864if (((peekEvent.type == Expose) &&865((peekEvent.xany).window == viewport->viewWindow)) ||866((peekEvent.type == Expose) &&867((peekEvent.xany).window == viewport->titleWindow)) ||868((peekEvent.type == Expose) &&869((peekEvent.xany).window == control->controlWindow))) {870retVal = firstTime;871} else if ((peekEvent.xbutton.type == ButtonRelease) ||872((peekEvent.type == LeaveNotify) && !(followMouse)) ||873((peekEvent.type == MotionNotify) && !(followMouse)) ||874(peekEvent.type == ResizeRequest)) {875XNextEvent(dsply,&peekEvent);876followMouse = no;877retVal = yes;878} else if ((peekEvent.xany).window == (control->buttonQueue[hideControl]).self) {879viewport->haveControl = no;880XUnmapWindow(dsply,control->controlWindow);881retVal = yes;882} else {883retVal = no;884}885} else {886retVal = !followMouse;887}888889if (writeImage) retVal = yes;890drawMore = no;891return(retVal);892893}894895896