home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- morph.c - Use VGX texture mapping to do image metamorphosis.
-
- Tim Heidmann, Silicon Graphics
- Created May 1, 1991
- Last Edit November 25, 1991
- */
-
- /*
- Morph'ing is a technique and term first used in production by Industrial
- Light and Magic for the film "Willow". Real-time morph'ing using texture
- maps is from an idea by Michael Wahrman. Originally written for the
- George Coates Performance Works theatrical project "Invisible Site".
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <gl.h>
- #include <device.h>
- #include <gl/image.h>
-
- /* Window, mouse, and events */
- long xOrig, yOrig;
- long winWidth = 512, winHeight = 512;
- float winWidthFactor, winHeightFactor;
- long performXOrig, performYOrig, performXSize = -1, performYSize;
- float performAspect;
- #define MINDRAGDIST 0.01
- #define MAXHITDIST 0.02
- #define RGB_GRAY 0x00505050
- #define RGB_RED 0x000000a0
- #define RGB_GREEN 0x0000a000
- #define RGB_BLUE 0x00a00000
- #define RGB_YELLOW 0x0000a0a0
- #define RGB_CYAN 0x00a0a000
- #define RGB_MAGENTA 0x00a000a0
- #define RGB_WHITE 0x00ffffff
- #define RGB_BLACK 0x00000000
- #define RGB_BRIGHTER 0x00505050
- long colorList[] =
- {RGB_RED, RGB_GREEN, RGB_BLUE, RGB_YELLOW, RGB_CYAN, RGB_MAGENTA};
- long triColorList[] =
- {RGB_RED, RGB_GREEN, RGB_BLUE, RGB_YELLOW, RGB_CYAN, RGB_MAGENTA};
-
- float tev_val[] = {TV_NULL};
- float tex_val[] =
- {TX_MINFILTER, TX_BILINEAR, TX_MAGFILTER, TX_BILINEAR, TX_NULL};
- #define MINPADKEY PAD1
- #define MAXPADKEY PAD9
- /* Button numbers for numeric pad keys:
- 0 1 2 3 4 5 6 7 8 9 */
- int buttonNum[] = {59, 58, 64, 65, 63, 69, 70, 67, 68, 75};
-
-
- /* Program state */
- enum {selmoveVertices, addVertices, connectVertices}
- clickMode = selmoveVertices;
- int performFlag = TRUE;
- int fullScreen = FALSE;
- int shiftDown = 0;
- long mainMenu, vColorMenu, cColorMenu, targetGotoMenu, targetDeleteMenu;
- long performMenu;
- int dbxVertex = -1, nDbxEdges = 0, dbxEdges[10];
- long *bgImage = NULL;
- int bgXsize = -1, bgYsize = -1;
- int flushQueue = FALSE;
- int autoRun = FALSE;
- int showMesh = FALSE;
- int showTwins = FALSE;
-
-
- /* Working Mesh data structures */
- float crossArm = 0.008;
- #define MAXVERTICES 100
- struct vertlist_tag {
- float x, y;
- long color;
- int selected;
- } vertexList[MAXVERTICES];
- int nVertices = 0;
- long vColor = RGB_YELLOW;
-
- #define MAXCNX 600
- struct cnxlist_tag {
- int v0, v1;
- long color;
- int selected;
- } cnxList[MAXCNX];
- long nCnx = 0;
- long cColor = RGB_BLUE;
-
- #define MAXTRIANGLES 400
- struct tri_tag {
- int v0, v1, v2;
- } triangleList[MAXTRIANGLES];
- int nTriangles = 0;
-
-
- /* Collection of target images and meshes */
- #define MAXTARGETS 12
- struct target_tag {
- long *image;
- struct vertlist_tag *vertexList;
- struct cnxlist_tag *cnxList;
- struct tri_tag *triangleList;
- int xSize, ySize, nVertices, nCnx, nTriangles, textureIndex;
- } target[MAXTARGETS];
- int nTargets = 0;
- int thisTarget = -1, destTarget = -1;
- long thisTargetColor, destTargetColor;
- struct vertlist_tag tmpVertexList[MAXVERTICES];
- int nTmpVertices = 0;
-
- int currentSpeed = 5;
- /* Number of frames per transition for each numeric pad key:
- 0 1 2 3 4 5 6 7 8 9 */
- int frameCount[] = {1, 5, 10, 15, 20, 30, 45, 60, 90, 120};
-
- /* Temp structure for doing triangulation */
- #define MAXEDGESPERVERTEX 17
- struct {
- int nEdges;
- struct {
- int index; /* Index into edge (cnx) list */
- int marked; /* marked[i] TRUE => edge[i]-[i+1] angle tried. */
- } edge[MAXEDGESPERVERTEX];
- } vertexEdges[MAXVERTICES];
-
- /* Selected data structure */
- int selectedVList[MAXVERTICES];
- int nVSelected = 0;
- int selectedCList[MAXCNX];
- int nCSelected = 0;
-
- /* Prototypes */
- void
- ParseArgs(int c, char *v[]);
- void
- BadCommand(char *name);
- void
- DoClick(short mx, short my);
-
- int
- AddVertex(float x, float y);
- void
- DeleteVertex(int iVertex);
- int
- HitVertex(float x, float y);
-
- void
- AddSelectVertex(int iVertex);
- void
- SelectVertex(int iVertex);
- void
- DeleteVSelection(int iSelect);
- void
- MoveSelected(float dx, float dy);
- void
- DeleteSelectedVertices();
-
- int
- AddCnx(int v0, int v1);
- void
- DeleteCnx(int iCnx);
- int
- HitCnx(float x, float y);
-
- void
- AddSelectCnx(int iCnx);
- void
- SelectCnx(int iCnx);
- void
- DeleteCSelection(int iSelect);
- void
- DeleteSelectedCnx();
-
- int
- AddTriangle(int v0, int v1, int v2);
-
- int
- ReadLine(FILE *myf, char *buf);
- int
- ReadCnx(char *filename);
- int
- WriteCnx(char *filename);
-
- void
- CnxToTri();
-
-
- /*******************************************************************************
-
- Main
-
- *******************************************************************************/
-
- main(int argc, char *argv[]) {
- short dev, val;
- short initMouseX, initMouseY;
- int iNumPadKey, iTarget;
- int redrawFlag, doneFlag;
-
- printf("\n Loading data -- please wait ...\n");
-
- ParseArgs(argc, argv);
-
- printf(" Finished loading data!\n\n");
-
- InitGfx();
-
- for (doneFlag=FALSE; !doneFlag;) {
- if (performFlag) {
- /* Performance mode */
- if (flushQueue) {
- while (qtest()) qread(&val);
- flushQueue = FALSE;
- autoRun = FALSE;
- setbell(1); ringbell();
- }
-
- if (qtest()) switch (dev = qread(&val)) {
- case ESCKEY:
- doneFlag = TRUE;
- break;
- case RIGHTMOUSE:
- autoRun = FALSE;
- switch (dopup(performMenu)) {
- case 1: /* To Edit Mode */
- performFlag = FALSE;
- SetEditGfx();
- DrawWindow();
- break;
- case 2: /* Auto Run */
- autoRun = TRUE;
- break;
- case 3: /* Toggle Show Mesh */
- showMesh = !showMesh;
- DrawPerformWindow();
- break;
- case 4: /* Toggle Twin Images */
- showTwins = !showTwins;
- performAspect = (showTwins ? 2.0 : 1.0) *
- ((float)performYSize)/performXSize;
- DrawPerformWindow();
- break;
- case 99: /* Exit */
- doneFlag = TRUE;
- break;
- }
- break;
- case REDRAW:
- reshapeviewport();
- getorigin(&performXOrig, &performYOrig);
- getsize(&performXSize, &performYSize);
- performAspect = (showTwins ? 2.0 : 1.0) *
- ((float)performYSize)/performXSize;
- DrawPerformWindow();
- break;
- default:
- if (dev>=F1KEY && dev<=F12KEY) {
- /* Decode FKEY, or -1 for none. Initiate transition. */
- if (val) {
- autoRun = FALSE;
-
- thisTarget = destTarget;
- iTarget = dev - F1KEY;
- destTarget = iTarget<nTargets ? iTarget : -1;
- AnimateTransition();
-
- }
- }
- else if (dev>=MINPADKEY && dev<=MAXPADKEY) {
- /* Decode numeric pad button, set current speed */
- if (val) {
- autoRun = FALSE;
- for (iNumPadKey=0; iNumPadKey<=9; iNumPadKey++)
- if (buttonNum[iNumPadKey] == dev)
- {currentSpeed = iNumPadKey; break;}
- }
- }
- break;
- }
-
- if (autoRun && !qtest()) {
- thisTarget = destTarget;
- destTarget = (random() & 255) / 256.0 * nTargets;
- currentSpeed = random() % 7 + 3; /* Select speed 3-9 */
- AnimateTransition();
- }
-
- if (redrawFlag && !qtest()) {
- DrawPerformWindow();
- redrawFlag = FALSE;
- }
- }
- else
- /* Mesh editing mode */
- switch (dev = qread(&val)) {
- case LEFTMOUSE:
- qread(&initMouseX); qread(&initMouseY);
- if (val) DoClick(initMouseX, initMouseY);
- break;
- case RIGHTMOUSE:
- if (val) doneFlag = DoMenu();
- break;
- case LEFTSHIFTKEY:
- case RIGHTSHIFTKEY:
- shiftDown = val;
- break;
- case BACKSPACEKEY:
- /* Don't delete vertices in connect mode.
- Reset selection too. */
- if (clickMode == connectVertices) SelectVertex(-1);
- DeleteSelectedVertices();
- DeleteSelectedCnx();
- DrawWindow();
- break;
- case REDRAW:
- reshapeviewport();
- getorigin(&xOrig, &yOrig);
- DrawWindow();
- break;
- case ESCKEY:
- doneFlag = TRUE;
- break;
- default:
- break;
- }
- }
- }
-
- void
- ParseArgs(int c, char *v[]) {
- int i;
- FILE *f;
- char *cmdName, imgFile[100], cnxFile[100], buf[100];
- int fileRead;
-
- cmdName = v[0];
- fileRead = FALSE;
- for (c--, v++; c>0; c--, v++) {
- if (v[0][0] != '-') {
- if (fileRead) BadCommand(cmdName);
- if ((f = fopen(v[0], "r")) == NULL)
- fprintf(stderr, "Cannot open master file %s\n", v[0]);
- else {
- for (i=0; i<MAXTARGETS; i++) {
- if (!ReadLine(f, buf)) break;
- sscanf(buf, "%s %s", imgFile, cnxFile);
-
- if (!ReadImg(imgFile)) continue;
- if (ReadCnx(cnxFile) < 0) continue;
- AddTarget();
- }
- fclose(f);
- fileRead = TRUE;
- }
- } else /* v[0][0] == '-' */
- switch (v[0][1]) {
- case 'p': performFlag = TRUE; break;
- case 'f': fullScreen = TRUE; performFlag = TRUE; break;
- case 'e': performFlag = FALSE; break;
- default: BadCommand(cmdName);
- }
- }
- }
-
- void
- BadCommand(char *name) {
- fprintf(stderr, "usage: %s [-p] [-f] [-e] [<master file>]\n", name);
- exit(1);
- }
-
- InitGfx() {
- int i;
-
- /* Open the window */
- #ifdef DEBUG
- foreground();
- #endif
- if (performFlag) {
- if (fullScreen)
- prefposition(0, getgdesc(GD_XPMAX)-1, 0, getgdesc(GD_YPMAX)-1);
- winopen("Morph");
- getorigin(&performXOrig, &performYOrig);
- getsize(&performXSize, &performYSize);
- performAspect =
- (showTwins ? 2.0 : 1.0) * ((float)performYSize)/performXSize;
- /* Allow resizing the perform window */
- winconstraints();
- /* Position the edit window in the middle of the screen */
- xOrig = (getgdesc(GD_XPMAX) - 1 - winWidth) / 2;
- yOrig = (getgdesc(GD_YPMAX) - 1 - winHeight) / 2;
- thisTarget = destTarget = -1;
- tevdef(1, 0, tev_val);
- SetPerformGfx();
- } else {
- prefsize(winWidth, winHeight);
- winopen("Morph");
- getorigin(&xOrig, &yOrig);
- tevdef(1, 0, tev_val);
- SetEditGfx();
- }
- winWidthFactor = 1.0 / winWidth;
- winHeightFactor = 1.0 / winHeight;
-
- /* Check if texture mapping supported. */
- if( !getgdesc( GD_TEXTURE ) ) {
- printf("\n\nWARNING -- This machine does not support texture mapping,\n");
- printf(" which is required to perform the morphing.\n");
- }
-
- RGBmode();
- doublebuffer();
- gconfig();
-
- ortho2(0.0, 1.0, 0.0, 1.0);
- cpack(RGB_BLACK);
- clear();
- swapbuffers();
-
- /* Queue the devices */
- qdevice(LEFTMOUSE);
- tie(LEFTMOUSE, MOUSEX, MOUSEY);
- qdevice(RIGHTMOUSE);
- qdevice(LEFTSHIFTKEY);
- qdevice(RIGHTSHIFTKEY);
- qdevice(BACKSPACEKEY);
- for (i=F1KEY; i<=F12KEY; i++) qdevice(i);
- qdevice(ESCKEY);
- for (i=0; i<=9; i++) qdevice(buttonNum[i]);
-
- /* Set up the menus */
- mainMenu = defpup("");
- vColorMenu = defpup("Vertex Color %t");
- addtopup(vColorMenu,
- "Red%x31|Green%x32|Blue%x33|Yellow%x34|Cyan%x35|Magenta%x36");
- cColorMenu = defpup("Connection Color %t");
- addtopup(cColorMenu,
- "Red%x21|Green%x22|Blue%x23|Yellow%x24|Cyan%x25|Magenta%x26");
- targetGotoMenu = defpup("No Targets %t");
- targetDeleteMenu = defpup("No Targets %t");
- performMenu = defpup("Morph %t");
- addtopup(performMenu, "Edit Mode%x1%l|Auto Run%x2");
- addtopup(performMenu, "Toggle Mesh%x3|Toggle Twin Images%x4%l|Exit %x99");
-
- MakeTargetMenus();
- MakeMenu();
- }
-
- SetEditGfx() {
- int i;
-
- /* Set up graphics for mesh editing.
- Window to original size, border. Ortho projection. */
- /*
- winposition(xOrig, xOrig+winWidth-1, yOrig, yOrig+winHeight-1);
- */
- prefsize(winWidth, winHeight);
- winconstraints();
- reshapeviewport();
- ortho2(0.0, 1.0, 0.0, 1.0);
-
- /* No texture mapping, no alphablending */
- tevbind(TV_ENV0, 0);
- blendfunction(BF_ONE, BF_ZERO);
- }
-
- SetPerformGfx() {
- int i;
-
- /* Set up graphics for performance. */
- if (performXSize > 0)
- winposition(performXOrig, performXOrig+performXSize-1,
- performYOrig, performYOrig+performYSize-1);
- winconstraints();
- reshapeviewport();
-
- /* Turn texture mapping on, alphablending on */
- for (i=0; i<nTargets; i++)
- texdef2d(target[i].textureIndex, 4,
- target[i].xSize, target[i].ySize, target[i].image, 0, tex_val);
- tevbind(TV_ENV0, 1);
- blendfunction(BF_SA, BF_ONE);
- }
-
- void
- DoClick(short mx, short my) {
- int iVertex, iCnx;
- float xFirst, yFirst, xNew, yNew, xLast, yLast, dist;
- enum {starting, tracking, done} trackState;
-
- xFirst = (mx - xOrig) * winWidthFactor;
- yFirst = (my - yOrig) * winHeightFactor;
-
- switch (clickMode) {
- case selmoveVertices:
- /* Act on the hit to select new vertices */
- if ((iVertex = HitVertex(xFirst, yFirst)) >= 0)
- /* Vertex hit. Toggle selection or select just this */
- if (shiftDown) AddSelectVertex(iVertex);
- else {
- SelectVertex(iVertex);
- SelectCnx(-1);
- }
- else if ((iCnx = HitCnx(xFirst, yFirst)) >= 0)
- /* Connection hit. Toggle selection or select just this */
- if (shiftDown) AddSelectCnx(iCnx);
- else {
- SelectCnx(iCnx);
- SelectVertex(-1);
- }
- else {
- /* Nothing hit. Unless shiftkey is down, select nothing */
- if (!shiftDown) SelectVertex(-1); SelectCnx(-1);
- }
- DrawWindow();
-
- /* Now track any movement. Don't start moving until the mouse has been
- dragged a certain minimum amount. */
- xLast = xFirst; yLast = yFirst;
- for (trackState = starting;
- getbutton(LEFTMOUSE) && trackState != done; ) {
- xNew = (getvaluator(MOUSEX) - xOrig) * winWidthFactor;
- yNew = (getvaluator(MOUSEY) - yOrig) * winHeightFactor;
-
- switch (trackState) {
- case starting:
- dist = fabs(xFirst - xNew) + fabs(yFirst - yNew);
- if (dist > MINDRAGDIST) trackState = tracking;
- break;
- case tracking:
- MoveSelected(xNew - xLast, yNew - yLast);
- DrawWindow();
- xLast = xNew; yLast = yNew;
- break;
- }
- }
- break;
-
- case addVertices:
- AddVertex(xFirst, yFirst);
- DrawWindow();
- break;
- case connectVertices:
- /* If vertex already selected, connect new selection to old,
- update selection */
- iVertex = HitVertex(xFirst, yFirst);
- if (iVertex >= 0) {
- if (nVSelected)
- SelectCnx(AddCnx(selectedVList[0], iVertex));
- }
- SelectVertex(iVertex);
- DrawWindow();
- break;
- default:
- fprintf(stderr, "WHOA! Unknown mode!\n");
- break;
- }
- }
-
- int
- AddVertex(float x, float y) {
- vertexList[nVertices].x = x;
- vertexList[nVertices].y = y;
- vertexList[nVertices].color = vColor;
- vertexList[nVertices].selected = FALSE;
- nVertices++;
-
- return nVertices-1;
- }
-
- void
- DeleteVertex(int iVertex) {
- int i;
-
- /* Shift higher vertex records down */
- for (i=iVertex; i<nVertices-1; i++)
- vertexList[i] = vertexList[i+1];
- nVertices--;
-
- /* Renumber connections referencing higher vertices,
- Delete connections referencing this vertex */
- for (i=0; i<nCnx; ) {
- if (cnxList[i].v0 == iVertex || cnxList[i].v1 == iVertex) DeleteCnx(i);
- else {
- if (cnxList[i].v0 > iVertex) cnxList[i].v0--;
- if (cnxList[i].v1 > iVertex) cnxList[i].v1--;
- i++; /* We are keeping this connection, bump to next one */
- }
- }
-
- /* Delete or renumber selections referencing this vertex */
- for (i=0; i<nVSelected; )
- if (selectedVList[i] == iVertex) DeleteVSelection(i);
- else {
- if (selectedVList[i] > iVertex) selectedVList[i]--;
- i++;
- }
- }
-
- int
- HitVertex(float x, float y) {
- /* Return index of 1st vertex near given point, or -1 if none */
- int i;
-
- for (i=0; i<nVertices; i++) {
- if (fabs(x - vertexList[i].x) + fabs(y - vertexList[i].y) < MAXHITDIST)
- return i;
- }
-
- return -1;
- }
-
- void
- AddSelectVertex(int iVertex) {
- /* Toggle membership of iVertex in list of currently selected vertices */
- int i, j, found;
-
- /* Check selected list for iVertex. If there, remove it. */
- found = FALSE;
- for (i=0; i<nVSelected; i++)
- if (selectedVList[i] == iVertex) {
- DeleteVSelection(i);
- vertexList[iVertex].selected = FALSE;
- found = TRUE;
- break;
- }
-
- /* Otherwise, add it */
- if (!found) {
- selectedVList[nVSelected] = iVertex;
- nVSelected++;
- vertexList[iVertex].selected = TRUE;
- }
- }
-
- void
- SelectVertex(int iVertex) {
- /* Reset the selected vertex list to only this one (-1 => none) */
- int i;
-
- /* If already selected, do nothing */
- if (vertexList[iVertex].selected) return;
-
- /* Turn off selected flag in all entities but this one */
- for (i=0; i<nVSelected; i++)
- vertexList[selectedVList[i]].selected = FALSE;
-
- /* Reset the selected list */
- if (iVertex >= 0) {
- selectedVList[0] = iVertex;
- vertexList[iVertex].selected = TRUE;
- nVSelected = 1;
- } else {
- nVSelected = 0;
- }
- }
-
- void
- DeleteVSelection(int iSelect) {
- int i;
-
- for (i=iSelect; i<nVSelected-1; i++) selectedVList[i] = selectedVList[i+1];
- nVSelected--;
- }
-
- void
- MoveSelected(float dx, float dy) {
- /* Move all selected vertices by given increments */
- int i;
-
- for (i = 0; i < nVSelected; i++) {
- vertexList[selectedVList[i]].x += dx;
- vertexList[selectedVList[i]].y += dy;
- }
- }
-
- void
- DeleteSelectedVertices() {
- /* Delete all selected vertices */
- int i;
-
- /* Make changes to the vertex list */
- for (i=0; i<nVertices; )
- if (vertexList[i].selected) DeleteVertex(i);
- else i++;
- }
-
- int
- AddCnx(int v0, int v1) {
- int i;
-
- /* Check for degenerate edges */
- if (v0 == v1) return -1;
-
- /* Check for this edge already existing */
- for (i=0; i<nCnx; i++) {
- if (cnxList[i].v0 == v0)
- if (cnxList[i].v1 == v1) return i;
- else ;
- if (cnxList[i].v0 == v1)
- if (cnxList[i].v1 == v0) return i;
- else ;
- }
-
- /* Okay, add it */
- cnxList[nCnx].v0 = v0;
- cnxList[nCnx].v1 = v1;
- cnxList[nCnx].color = cColor;
- cnxList[nCnx].selected = FALSE;
- nCnx++;
-
- return nCnx-1;
- }
-
- void
- DeleteCnx(int iCnx) {
- /* Delete the given connection */
- int i;
-
- /* Shift higher records down */
- for (i=iCnx; i<nCnx-1; i++)
- cnxList[i] = cnxList[i+1];
- nCnx--;
-
- /* Delete or renumber selection info */
- for (i=0; i<nCSelected; )
- if (selectedCList[i] == iCnx) DeleteCSelection(i);
- else {
- if (selectedCList[i] > iCnx) selectedCList[i]--;
- i++;
- }
- }
-
- int
- HitCnx(float x, float y) {
- /* Return index of 1st connection near given point, or -1 if none */
- int i, v0, v1;
- float dx, dy, len, a, b, c, a2, b2, c2, dist;
-
- for (i=0; i<nCnx; i++) {
- v0 = cnxList[i].v0;
- v1 = cnxList[i].v1;
- dx = vertexList[v1].x - vertexList[v0].x;
- dy = vertexList[v1].y - vertexList[v0].y;
- len = fsqrt(dx*dx + dy*dy);
- a = dy / len; b = -dx / len;
- c = -(a*vertexList[v0].x + b*vertexList[v0].y);
- dist = a*x + b*y + c;
- if (fabs(dist) > MAXHITDIST) continue;
- a2 = -b/len; b2 = a/len;
- c2 = -(a2*vertexList[v0].x + b2*vertexList[v0].y);
- dist = a2*x + b2*y + c2;
- if (dist < 0.0 || dist > 1.0) continue;
-
- return i;
- }
-
- return -1;
- }
-
- void
- AddSelectCnx(int iCnx) {
- /* Toggle membership of iCnx in list of currently selected connections */
- int i, j, found;
-
- /* Check selected list for iCnx. If there, remove it. */
- found = FALSE;
- for (i=0; i<nCSelected; i++)
- if (selectedCList[i] == iCnx) {
- DeleteCSelection(i);
- cnxList[iCnx].selected = FALSE;
- found = TRUE;
- break;
- }
-
- /* Otherwise, add it */
- if (!found) {
- selectedCList[nCSelected] = iCnx;
- nCSelected++;
- cnxList[iCnx].selected = TRUE;
- }
- }
-
- void
- SelectCnx(int iCnx) {
- /* Reset the selected connection list to only this one (-1 => none) */
- int i;
-
- /* If already selected, do nothing */
- if (cnxList[iCnx].selected) return;
-
- /* Turn off selected flag in all connections but this one */
- for (i=0; i<nCSelected; i++)
- cnxList[selectedCList[i]].selected = FALSE;
-
- /* Reset the selected list */
- if (iCnx >= 0) {
- selectedCList[0] = iCnx;
- cnxList[iCnx].selected = TRUE;
- nCSelected = 1;
- } else {
- nCSelected = 0;
- }
- }
-
- void
- DeleteCSelection(int iSelect) {
- int i;
-
- for (i=iSelect; i<nCSelected-1; i++) selectedCList[i] = selectedCList[i+1];
- nCSelected--;
- }
-
- void
- DeleteSelectedCnx() {
- /* Delete all selected connections */
- int i;
- for (i=0; i<nCnx; )
- if (cnxList[i].selected) DeleteCnx(i);
- else i++;
- }
-
- PrintVSelected() {
- int i;
-
- fprintf(stdout, "%d Vertices Selected:", nVSelected);
- for (i=0; i<nVSelected; i++)
- fprintf(stdout, " %d", selectedVList[i]);
- fprintf(stdout, "\n");
- }
-
- int
- AddTriangle(int v0, int v1, int v2) {
- triangleList[nTriangles].v0 = v0;
- triangleList[nTriangles].v1 = v1;
- triangleList[nTriangles].v2 = v2;
- return nTriangles++;
- }
-
-
- /****************************************************************************
-
- File I/O
-
- ****************************************************************************/
- int
- ReadLine(FILE *myf, char *buf) {
- do {
- if (fgets(buf, 120, myf) == NULL) return FALSE;
- } while (buf[0] == '#');
- return TRUE;
- }
-
- int
- ReadCnx(char *filename) {
- int i;
- char line[120];
- FILE *f;
-
- /* Open the file and check the type */
- if ((f = fopen(filename, "r")) == NULL) {
- fprintf(stderr, "Cannot open file %s\n", filename);
- return -1;
- }
- fscanf(f, "%s\n", line);
- if (strcmp(line, "2DCnx") != 0) {
- fprintf(stderr, "File %s is not a connection file.\n", filename);
- return -1;
- }
-
- /* Reset the internal structures */
- nVertices = nCnx = 0;
- nVSelected = nCSelected = 0;
-
- /* Read the vertices, then the connections */
- if (!ReadLine(f, line)) goto oops;
- sscanf(line, "%d", &nVertices);
- for (i=0; i < nVertices; i++) {
- if (!ReadLine(f, line)) goto oops;
- if (sscanf(line, "%f %f %x",
- &vertexList[i].x, &vertexList[i].y, &vertexList[i].color) != 3)
- goto oops;
- }
-
- if (!ReadLine(f, line)) goto oops;
- sscanf(line, "%d", &nCnx);
- for (i=0; i < nCnx; i++) {
- if (!ReadLine(f, line)) goto oops;
- if (sscanf(line, "%d %d %x",
- &cnxList[i].v0, &cnxList[i].v1, &cnxList[i].color) != 3)
- goto oops;
- }
- fclose(f);
- return 0;
-
- oops:
- fclose(f);
- fprintf(stderr, "Error reading file %s.\n Input: %s\n", filename, line);
- nVertices = nCnx = 0;
- return -1;
- }
-
- int
- WriteCnx(char *filename) {
- int i;
- FILE *f;
-
- if ((f = fopen(filename, "w")) == NULL) {
- fprintf(stderr, "Cannot open output file %s\n", filename);
- return FALSE;
- }
- fprintf(f, "2DCnx\n");
- fprintf(f, "%d\n", nVertices);
- for (i=0; i<nVertices; i++)
- fprintf(f, "%f %f %x\n",
- vertexList[i].x, vertexList[i].y, vertexList[i].color);
- fprintf(f, "%d\n", nCnx);
- for (i=0; i<nCnx; i++)
- fprintf(f, "%d %d %x\n",
- cnxList[i].v0, cnxList[i].v1, cnxList[i].color);
- fclose(f);
- }
-
-
- int
- ReadImg(char *filename) {
- register IMAGE *image;
- register int x, y, xsize, ysize;
- register int z, zsize;
- short buf[4096];
-
- if ((image=iopen(filename, "r")) == NULL ) {
- fprintf(stderr,"readimg: can't open input file %s\n",filename);
- return FALSE;
- }
- xsize = image->xsize;
- ysize = image->ysize;
- zsize = image->zsize;
- if(zsize<3) {
- fprintf(stderr,"readimg: this is not an RGB image file\n");
- return FALSE;
- }
-
- if (bgXsize != xsize || bgYsize != ysize) {
- if (bgImage != NULL) free(bgImage);
- bgImage = (long *) malloc(xsize * ysize * sizeof(long));
- bgXsize = xsize; bgYsize = ysize;
- }
-
- for(y=0; y<ysize; y++) {
- getrow(image,buf,y,0); /* Red */
- for (x=0; x<xsize; x++) bgImage[y*xsize + x] = buf[x] | 0xff000000;
- getrow(image,buf,y,1); /* Green */
- for (x=0; x<xsize; x++) bgImage[y*xsize + x] |= buf[x] << 8;
- getrow(image,buf,y,2); /* Blue */
- for (x=0; x<xsize; x++) bgImage[y*xsize + x] |= buf[x] << 16;
- }
- return TRUE;
- }
-
- /******************************************************************************
-
- Menus
-
- ******************************************************************************/
- MakeMenu() {
- freepup(mainMenu);
- mainMenu = defpup("Morph Edit %t");
- addtopup(mainMenu, "Performance%x14%l");
- addtopup(mainMenu, clickMode==selmoveVertices ?
- "> Select/Move%x1" : " Select/Move%x1");
- addtopup(mainMenu, clickMode==addVertices ?
- "> Add Vertices%x2" : " Add Vertices%x2");
- addtopup(mainMenu, clickMode==connectVertices ?
- "> Add Connections%x3" : " Add Connections%x3");
- addtopup(mainMenu, " Draw Triangles%x10%l");
- addtopup(mainMenu, "Vertex Color %m", vColorMenu);
- addtopup(mainMenu, "Connection Color %m %l", cColorMenu);
- addtopup(mainMenu, "Read file blah.rgb%x6");
- addtopup(mainMenu, "Read file blah.cnx%x8");
- addtopup(mainMenu, "Save as blah.cnx%x7%l");
- addtopup(mainMenu, "Add to Target List%x12");
- addtopup(mainMenu, "Go to Target %m", targetGotoMenu);
- addtopup(mainMenu, "Delete Target from List %m%l", targetDeleteMenu);
- addtopup(mainMenu, "Exit%x99");
- }
-
- int
- DoMenu() {
- int item, myDoneFlag;
-
- myDoneFlag = FALSE;
- switch (item = dopup(mainMenu)) {
- case 1: /* Select/Move Vertices */
- clickMode = selmoveVertices;
- SelectVertex(-1);
- DrawWindow();
- MakeMenu();
- break;
- case 2: /* Add Vertices */
- clickMode = addVertices;
- SelectVertex(-1);
- DrawWindow();
- MakeMenu();
- break;
- case 3: /* Connect Vertices */
- clickMode = connectVertices;
- SelectVertex(-1);
- DrawWindow();
- MakeMenu();
- break;
- /* 4: Vertex Color */
- /* 5: Connection Color */
- case 6: /* Read Background image */
- ReadImg("blah.rgb");
- DrawWindow();
- break;
- case 7: /* Save connection file */
- WriteCnx("blah.cnx");
- break;
- case 8: /* Read connection file */
- ReadCnx("blah.cnx");
- DrawWindow();
- break;
- case 10: /* Draw Triangles */
- CnxToTri();
- DrawWindow();
- nTriangles = 0;
- break;
- /* 11: Goto Target */
- case 12: /* Add target to list */
- AddTarget();
- MakeTargetMenus();
- MakeMenu();
- break;
- /* 13: Delete target from list */
- case 14: /* Performance */
- performFlag = TRUE;
- autoRun = FALSE;
- thisTarget = destTarget = -1;
- SetPerformGfx();
- DrawPerformWindow();
- break;
- case 99: /* Exit */
- myDoneFlag = TRUE;
- break;
- default:
- /* Sub-menus... */
- if (item < 20) break;
- else if (item < 30)
- /* Set Connection Color (color 0 is menu #21) */
- cColor = colorList[item - 21];
- else if (item < 40)
- /* Set Vertex Color (color 0 is menu #31) */
- vColor = colorList[item - 31];
- else if (item < 60) {
- /* Go to a target in the list (target[0] is menu #40) */
- UseTarget(item - 40);
- SelectVertex(-1);
- DrawWindow();
- }
- else {
- /* Delete a target from list (target[0] is menu #60) */
- DeleteTarget(item - 60);
- MakeTargetMenus();
- MakeMenu();
- }
- break;
- }
-
- return myDoneFlag;
- }
-
- DrawWindow() {
- int i, v0, v1;
- long currentColor;
-
- /* Clear the screen */
- if (bgImage == NULL) {
- cpack(RGB_GRAY);
- clear();
- } else {
- rectzoom(2.0, 2.0);
- lrectwrite(0, 0, 255, 255, bgImage);
- }
-
- /* Draw the triangles */
- currentColor = 0;
- for (i=0; i<nTriangles; i++) {
- currentColor++;
- currentColor = currentColor % (sizeof(triColorList)/sizeof(long));
- cpack(triColorList[currentColor]);
- bgnpolygon();
- v2f(&vertexList[triangleList[i].v0].x);
- v2f(&vertexList[triangleList[i].v1].x);
- v2f(&vertexList[triangleList[i].v2].x);
- endpolygon();
- }
-
- /* Draw the Connections */
- for (i=0; i<nCnx; i++) {
- cpack(cnxList[i].color + (cnxList[i].selected ? RGB_BRIGHTER : 0));
- v0 = cnxList[i].v0;
- v1 = cnxList[i].v1;
- move2(vertexList[v0].x, vertexList[v0].y);
- draw2(vertexList[v1].x, vertexList[v1].y);
- }
-
- /* Draw the Vertices */
- for (i=0; i<nVertices; i++) {
- cpack(vertexList[i].color + (vertexList[i].selected?RGB_BRIGHTER:0));
- move2(vertexList[i].x, vertexList[i].y);
- rmv2(-crossArm, 0.0);
- rdr2(crossArm + crossArm, 0.0);
- rmv2(-crossArm, -crossArm);
- rdr2(0.0, crossArm + crossArm);
- }
-
- swapbuffers();
- }
-
- /*************************************************************************
-
- Connect to triangle rep routines
-
- *************************************************************************/
-
- void
- XRefEdge(int iVertex, int iCnx);
- int
- NextEdge(int iVertex, int iEdge);
- int
- OtherEnd(int iEdge, int iVertex);
-
- int
- CompareTheta(float *th0, float *th1) {
- return (*th0 > *th1) ? -1 : 1;
- }
-
- void
- CnxToTri() {
- /* My own vertex-edge list for sorting */
- struct mel_tag {
- float theta;
- int edge;
- } myEdgeList[MAXEDGESPERVERTEX];
-
- int i, j, k, myNEdges, myObtuse;
- int v0, v1, v2, v3, e0, e1, e2;
- float dTheta;
-
- /* Find all the edges connected to each vertex */
- for (i=0; i<nVertices; i++) vertexEdges[i].nEdges = 0;
- for (i=0; i<nCnx; i++) {
- XRefEdge(cnxList[i].v0, i);
- XRefEdge(cnxList[i].v1, i);
- }
-
- /* Measure and order edges at each vertex. */
- for (i=0; i<nVertices; i++) {
- /* Collect the edges, and sort them into clockwise order */
- if ((myNEdges = vertexEdges[i].nEdges) <= 0) continue;
- for (j=0; j<myNEdges; j++) {
- myEdgeList[j].edge = vertexEdges[i].edge[j].index;
- v0 = cnxList[myEdgeList[j].edge].v0;
- v1 = cnxList[myEdgeList[j].edge].v1;
- myEdgeList[j].theta = fatan2(
- vertexList[v0].y - vertexList[v1].y,
- vertexList[v0].x - vertexList[v1].x);
- if (v0 != i)
- if (myEdgeList[j].theta < 0.0)
- myEdgeList[j].theta += M_PI;
- else
- myEdgeList[j].theta -= M_PI;
- }
- qsort((char *) myEdgeList, myNEdges, sizeof(struct mel_tag),
- CompareTheta);
-
- /* Copy edges back into vertexEdge in clockwise order.
- Mark obtuse wedges radiating from vertex */
- for (j=0; j<myNEdges-1; j++) {
- dTheta = myEdgeList[j].theta - myEdgeList[j+1].theta;
- if (dTheta < 0.0) dTheta += M_PI + M_PI;
- vertexEdges[i].edge[j].marked = dTheta > M_PI;
- vertexEdges[i].edge[j].index = myEdgeList[j].edge;
- }
- dTheta = (myEdgeList[myNEdges-1].theta - myEdgeList[0].theta);
- if (dTheta < 0.0) dTheta += M_PI + M_PI;
- vertexEdges[i].edge[myNEdges-1].marked = dTheta > M_PI;
- vertexEdges[i].edge[myNEdges-1].index = myEdgeList[myNEdges-1].edge;
- }
-
- /* For each vertex, try to make triangles out of every edge */
- nTriangles = 0;
- for (i=0; i<nVertices; i++) {
- v0 = i;
- for (j=0; j<vertexEdges[i].nEdges; j++) {
- if ((e0 = NextEdge(v0, vertexEdges[i].edge[j].index)) < 0) continue;
- v1 = OtherEnd(e0, v0);
- if ((e1 = NextEdge(v1, e0)) < 0) continue;
- v2 = OtherEnd(e1, v1);
- if ((e2 = NextEdge(v2, e1)) < 0) continue;
- v3 = OtherEnd(e2, v2);
- if (v3 == v0) AddTriangle(v0, v1, v2);
- }
- }
- }
-
- void
- XRefEdge(int iVertex, int iCnx) {
- /* Add this vertex-edge pair to the per-vertex list */
- int n;
- n = vertexEdges[iVertex].nEdges;
- vertexEdges[iVertex].edge[n].index = iCnx;
- vertexEdges[iVertex].nEdges++;
- }
-
- int
- NextEdge(int iVertex, int iEdge) {
- /* Get the edge out if vertex iVertex which follows edge iEdge in
- clockwise order.
- Return false if that wedge is already marked. Otherwise, mark it. */
- int i;
-
- for (i=0; i<vertexEdges[iVertex].nEdges; i++) {
- if (vertexEdges[iVertex].edge[i].index == iEdge) {
- /* Found it. Marked already? */
- if (vertexEdges[iVertex].edge[i].marked)
- return -1;
- else {
- /* Not marked.
- Mark it, then return next one, or 0th one if we're at end */
- vertexEdges[iVertex].edge[i].marked = TRUE;
- if (i<vertexEdges[iVertex].nEdges-1)
- return vertexEdges[iVertex].edge[i+1].index;
- else
- return vertexEdges[iVertex].edge[0].index;
- }
- }
- }
-
- fprintf(stderr,
- "Data problems in NextEdge, vertex %d, edge %d\n", iVertex, iEdge);
- return -1;
- }
-
- int
- OtherEnd(int iEdge, int iVertex) {
- /* Find the vertex at the other end of edge iEdge from iVertex */
- if (cnxList[iEdge].v0 == iVertex) return cnxList[iEdge].v1;
- else return cnxList[iEdge].v0;
- }
-
- /*****************************************************************************
-
- Target management
-
- *****************************************************************************/
- AddTarget() {
- int i, j;
-
- if (nTargets >= MAXTARGETS) return;
-
- /* Make a copy of the Texture Image */
- target[nTargets].image = (long *) malloc(sizeof(long) * bgXsize * bgYsize);
- target[nTargets].xSize = bgXsize;
- target[nTargets].ySize = bgYsize;
- for (i=0; i<bgXsize*bgYsize; i++)
- target[nTargets].image[i] = bgImage[i];
-
- /* Make a copy of the vertex list */
- target[nTargets].vertexList =
- (struct vertlist_tag *) malloc(sizeof(struct vertlist_tag) * nVertices);
- target[nTargets].nVertices = nVertices;
- for (i=0; i<nVertices; i++)
- target[nTargets].vertexList[i] = vertexList[i];
-
- /* Make a copy of the connection list (just to keep around ) */
- target[nTargets].cnxList =
- (struct cnxlist_tag *) malloc(sizeof(struct cnxlist_tag) * nCnx);
- target[nTargets].nCnx = nCnx;
- for (i=0; i<nCnx; i++)
- target[nTargets].cnxList[i] = cnxList[i];
-
- /* Get a current triangulization and copy it too */
- CnxToTri();
- target[nTargets].triangleList =
- (struct tri_tag *) malloc(sizeof(struct tri_tag) * nTriangles);
- target[nTargets].nTriangles = nTriangles;
- for (i=0; i<nTriangles; i++)
- target[nTargets].triangleList[i] = triangleList[i];
- nTriangles = 0;
-
- /* Assign a texture id */
- for (i=1; i<=MAXTARGETS; i++) {
- for (j=0; j<nTargets; j++)
- if (target[j].textureIndex == i) break;
-
- if (j >= nTargets) {
- /* i is an unused index. Assign it. */
- target[nTargets].textureIndex = i;
- break;
- }
- }
-
- nTargets++;
- }
-
- UseTarget(int iTarget) {
- /* Make one of the existing targets the current working image/cnx combo */
- int i;
-
- /* Reallocate image array if the dimensions are different */
- if (target[iTarget].xSize != bgXsize || target[iTarget].ySize != bgYsize) {
- free(bgImage);
- bgXsize = target[iTarget].xSize;
- bgYsize = target[iTarget].ySize;
- bgImage = (long *) malloc(sizeof(long) * bgXsize * bgYsize);
- }
- for (i=0; i<bgXsize*bgYsize; i++)
- bgImage[i] = target[iTarget].image[i];
-
- /* Copy the vertex list back */
- nVertices = target[iTarget].nVertices;
- for (i=0; i<nVertices; i++) vertexList[i] = target[iTarget].vertexList[i];
-
- /* Copy the connection list back */
- nCnx = target[iTarget].nCnx;
- for (i=0; i<nCnx; i++) cnxList[i] = target[iTarget].cnxList[i];
- }
-
- DeleteTarget(int iTarget) {
- /* Free the memory for the indicated target, and collapse the list */
- int i;
-
- free(target[iTarget].image);
- free(target[iTarget].vertexList);
- free(target[iTarget].cnxList);
- free(target[iTarget].triangleList);
-
- for (i=iTarget; i<nTargets-1; i++) target[i] = target[i+1];
- nTargets--;
- }
-
- MakeTargetMenus() {
- int i;
- char buf[30];
-
- freepup(targetGotoMenu);
- targetGotoMenu = defpup("Go to Target:%t");
- for (i=0; i<nTargets; i++) {
- sprintf(buf, "Target %d %%x%d", i+1, 40+i);
- addtopup(targetGotoMenu, buf, 0);
- }
- freepup(targetDeleteMenu);
- targetDeleteMenu = defpup("Delete Target:%t");
- for (i=0; i<nTargets; i++) {
- sprintf(buf, "Target %d %%x%d", i+1, 60+i);
- addtopup(targetDeleteMenu, buf, 0);
- }
- }
-
- AnimateTransition() {
- int i, iVertex, iFrame, nFrames;
- float p, f, omf;
-
- /* Bob Drebin's workaround hack for 3.3.2 texture management bug */
- /* This code causes flashes on my PI, even resetting RGBmode & doublebuffer
- tevbind(TV_ENV0, 0);
- acsize(16);
- gconfig();
- acsize(0);
- gconfig();
- tevbind(TV_ENV0, 1);
- */
-
- /* Set up our vertices once if no morphing happens */
- if (thisTarget<0) {
- if (destTarget<0) return;
- nTmpVertices = target[destTarget].nVertices;
- for (iVertex=0; iVertex<nTmpVertices; iVertex++) {
- tmpVertexList[iVertex].x =
- target[destTarget].vertexList[iVertex].x;
- tmpVertexList[iVertex].y =
- target[destTarget].vertexList[iVertex].y;
- }
- }
-
-
- /* Loop through the frames */
- nFrames = frameCount[currentSpeed];
- if ((thisTarget<0 || destTarget<0) && showTwins) nFrames = 1;
- for (iFrame=1; !flushQueue && iFrame<=nFrames; iFrame++) {
- p = iFrame / (float) nFrames;
- f = (-p-p + 3.0)*p*p;
- if (flushQueue = getbutton(LEFTCTRLKEY)) f = 1.0;
- omf = 1.0 - f;
-
- /* Do a cross-dissolve with alpha values */
- thisTargetColor = destTargetColor = RGB_WHITE;
- if (!showTwins) {
- thisTargetColor |= ((int)(255*omf)) <<24;
- destTargetColor |= ((int)(255* f)) <<24;
- } else {
- thisTargetColor |= 255 << 24;
- destTargetColor |= 255 << 24;
- }
-
-
- /* Move the vertices */
- if (thisTarget>=0 && destTarget>=0) {
- for (iVertex=0; iVertex<nTmpVertices; iVertex++) {
- tmpVertexList[iVertex].x =
- (1.0-f) * target[thisTarget].vertexList[iVertex].x +
- ( f) * target[destTarget].vertexList[iVertex].x;
- tmpVertexList[iVertex].y =
- (1.0-f) * target[thisTarget].vertexList[iVertex].y +
- ( f) * target[destTarget].vertexList[iVertex].y;
- }
- }
-
- DrawPerformWindow();
- }
-
- }
-
- DrawPerformWindow() {
- struct vertlist_tag *vl, *tvl;
- struct tri_tag *tl;
- int nv, nt, iTri;
-
- /* Clear the screen */
- reshapeviewport();
- cpack(RGB_BLACK);
- clear();
-
- if (performAspect > 1.0)
- /* Higher than wide, fit image side-to-side */
- ortho2(0.0, 1.0,
- 0.0 - (performAspect-1.0)/2.0, 1.0 + (performAspect-1.0)/2.0);
- else
- /* Wider than high, fit top-to-bottom */
- ortho2(0.0 - (1.0/performAspect-1.0)/2.0,
- 1.0 + (1.0/performAspect-1.0)/2.0,
- 0.0, 1.0);
-
- /* Draw this target image */
- if (thisTarget>=0) {
- /* If showTwins is set, show this image in the left half of window */
- if (showTwins) viewport(0, performXSize/2, 0, performYSize);
-
- texbind(TX_TEXTURE_0, target[thisTarget].textureIndex);
- cpack(thisTargetColor);
- vl = tmpVertexList;
- nv = nTmpVertices;
- tvl = target[thisTarget].vertexList;
- tl = target[thisTarget].triangleList;
- nt = target[thisTarget].nTriangles;
- for (iTri=0; iTri<nt; iTri++) {
- bgnpolygon();
- t2f(&tvl[tl[iTri].v0].x);
- v2f( &vl[tl[iTri].v0].x);
- t2f(&tvl[tl[iTri].v1].x);
- v2f( &vl[tl[iTri].v1].x);
- t2f(&tvl[tl[iTri].v2].x);
- v2f( &vl[tl[iTri].v2].x);
- endpolygon();
- }
-
- if (showMesh && (showTwins || destTarget<0)) DrawMesh(thisTarget, vl);
- }
-
- /* Draw destination target image */
- if (destTarget>=0) {
- /* If showTwins is set, show this image in the right half of window */
- if (showTwins)
- viewport(performXSize/2+1, performXSize, 0, performYSize);
-
- texbind(TX_TEXTURE_0, target[destTarget].textureIndex);
- cpack(destTargetColor);
- vl = tmpVertexList;
- nv = nTmpVertices;
- tvl = target[destTarget].vertexList;
- tl = target[destTarget].triangleList;
- nt = target[destTarget].nTriangles;
- for (iTri=0; iTri<nt; iTri++) {
- bgnpolygon();
- t2f(&tvl[tl[iTri].v0].x);
- v2f( &vl[tl[iTri].v0].x);
- t2f(&tvl[tl[iTri].v1].x);
- v2f( &vl[tl[iTri].v1].x);
- t2f(&tvl[tl[iTri].v2].x);
- v2f( &vl[tl[iTri].v2].x);
- endpolygon();
- }
-
- if (showMesh) DrawMesh(destTarget, vl);
- }
-
- swapbuffers();
- }
-
- DrawMesh(int iTarget, struct vertlist_tag *vl) {
- int i, v0, v1;
- struct target_tag *t;
-
- t = &target[iTarget];
- texbind(TX_TEXTURE_0, 0);
-
- /* Draw the Connections */
- for (i=0; i<t->nCnx; i++) {
- cpack(t->cnxList[i].color | 255<<24);
- v0 = t->cnxList[i].v0;
- v1 = t->cnxList[i].v1;
- move2(vl[v0].x, vl[v0].y);
- draw2(vl[v1].x, vl[v1].y);
- }
-
- /* Draw the Vertices */
- for (i=0; i<t->nVertices; i++) {
- cpack(t->vertexList[i].color | 255<<24);
- move2(vl[i].x, vl[i].y);
- rmv2(-crossArm, 0.0);
- rdr2(crossArm + crossArm, 0.0);
- rmv2(-crossArm, -crossArm);
- rdr2(0.0, crossArm + crossArm);
- }
- }
-
-