home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d polygonal solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Mar. 1990 *
- ******************************************************************************
- * Module to handle viewing of objects in the ViewWindow. *
- *****************************************************************************/
-
- #ifdef __MSDOS__
- #include <graphics.h>
- #include <conio.h>
- #endif /* __MSDOS__ */
-
- #include <stdio.h>
- #include <math.h>
- #include "program.h"
- #include "windowsl.h"
- #include "windowsg.h"
- #include "viewobjl.h"
- #include "viewobjg.h"
- #include "graphgng.h"
- #include "objects.h"
- #include "geomat3d.h"
-
- #ifdef __MSDOS__
- #include "mousedrv.h"
- #else
- #include "xgraphic.h"
- #endif /* __MSDOS__ */
-
- static int ViewNormals = FALSE, NormalsColor = 1, /* View normals to object. */
- QuitView = FALSE;
- static RealType NormalsSize = 0.1;
-
- /* Interactive mode menu set up structure is define below (See ViewObjL.H): */
- InteractWindowStruct InteractMenu = {
- { { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.2, RED, "Rotate" },
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.6, GREEN, "Translate" },
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 1.0, CYAN, "Scale" },
- },
- { { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.1, YELLOW, TRUE, "Screen Coords." },
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.3, RED, FALSE, "X" }, /* Rot */
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.4, RED, FALSE, "Y" },
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.5, RED, FALSE, "Z" },
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.7, GREEN, FALSE, "X" }, /* Trans */
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.8, GREEN, FALSE, "Y" },
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 0.9, GREEN, FALSE, "Z" },
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 1.1, CYAN, FALSE, "" }, /* Scale */
- { (SW_MIN_X + SW_MAX_X) / 2.0, SW_MAX_Y - 1.25, WHITE, TRUE, "Quit" },
- }
- };
-
- /*****************************************************************************
- * Routine to interactively display geometric object(s) PObjList on the View *
- * window enable rotating/translating/scaling it using the Input Device. *
- *****************************************************************************/
- void InteractGeomObject(ObjectStruct *PObjList, RealType *UpdateGlblMat)
- {
- struct ObjectStruct *ViewMat;
- MatrixType ViewMatCopy; /* Save original transformation to recover. */
-
- if (!IS_OLST_OBJ(PObjList))
- FatalError("InteractGeomObject: Not object list object!\n");
-
- if ((ViewMat = GetObject("VIEW_MAT")) == NULL) {
- WndwInputWindowPutStr(
- "No view transformation matrix VIEW_MAT!", RED);
- return;
- }
- else if (!IS_MAT_OBJ(ViewMat)) {
- WndwInputWindowPutStr(
- "VIEW_MAT object was modified (not matrix object)", RED);
- return;
- }
- MAT_COPY(ViewMatCopy, ViewMat -> U.Mat);
-
- #ifdef __MSDOS__
- WndwClaimStatus(); /* Gain control on status window - interac menu! */
- #endif /* __MSDOS__ */
-
- InteractDrawMenu(); /* Draw the transformation menu. */
- /* Get data from input device, interpret it, and display interactively: */
- InteractHandleInput(PObjList, ViewMat -> U.Mat);
-
- if (!APX_EQ(*UpdateGlblMat, 0.0))
- MAT_COPY(ViewMat -> U.Mat, ViewMatCopy); /* Recover. */
-
- #ifdef __MSDOS__
- WndwReclaimStatus(); /* Status window is not needed - free and recover. */
- WndwStatusWindowDraw();
- #endif /* __MSDOS__ */
- }
-
- /*****************************************************************************
- * Routine to draw the Interactive Menu in the Status window, using the *
- * InteractiveMenu structure defined above. *
- * It is assumed that string not inside of SubWindow will be of length 1. *
- *****************************************************************************/
- static void InteractDrawMenu(void)
- {
- int i;
- #ifdef __MSDOS__
- struct textsettingstype oldtext;
-
- gettextsettings(&oldtext);
- settextjustify(CENTER_TEXT, CENTER_TEXT); /* Draw strings centered. */
-
- WndwClearWindow(GlblStatusWindow); /* Clear the status window. */
- #endif /* __MSDOS__ */
-
- for (i=0; i<INTERACT_NUM_OF_STRINGS; i++) { /* Draw strings of struct. */
- GGMySetColor(InteractMenu.Strings[i].Color);
- GGXYPutStr(InteractMenu.Strings[i].X,
- InteractMenu.Strings[i].Y,
- InteractMenu.Strings[i].Str);
- }
-
- for (i=0; i<INTERACT_NUM_OF_SUB_WINDOWS; i++) { /* Draw sub windows. */
- GGMySetColor(InteractMenu.SubWindows[i].Color);
- /* Draw the frame of the SubWindow: */
- GGMyMove(InteractMenu.SubWindows[i].X - INTERACT_SUB_WINDOW_WIDTH,
- InteractMenu.SubWindows[i].Y - INTERACT_SUB_WINDOW_HEIGHT);
- GGMyDraw(InteractMenu.SubWindows[i].X + INTERACT_SUB_WINDOW_WIDTH,
- InteractMenu.SubWindows[i].Y - INTERACT_SUB_WINDOW_HEIGHT);
- GGMyDraw(InteractMenu.SubWindows[i].X + INTERACT_SUB_WINDOW_WIDTH,
- InteractMenu.SubWindows[i].Y + INTERACT_SUB_WINDOW_HEIGHT);
- GGMyDraw(InteractMenu.SubWindows[i].X - INTERACT_SUB_WINDOW_WIDTH,
- InteractMenu.SubWindows[i].Y + INTERACT_SUB_WINDOW_HEIGHT);
- GGMyDraw(InteractMenu.SubWindows[i].X - INTERACT_SUB_WINDOW_WIDTH,
- InteractMenu.SubWindows[i].Y - INTERACT_SUB_WINDOW_HEIGHT);
-
- /* Now the strings inside (and if outside, a middle vertical line): */
- if (InteractMenu.SubWindows[i].TextInside)
- GGXYPutStr(InteractMenu.SubWindows[i].X,
- InteractMenu.SubWindows[i].Y,
- InteractMenu.SubWindows[i].Str);
- else {
- GGXYPutStr(InteractMenu.SubWindows[i].X -
- INTERACT_SUB_WINDOW_WIDTH - 0.025,
- InteractMenu.SubWindows[i].Y,
- InteractMenu.SubWindows[i].Str);
- GGMyMove(InteractMenu.SubWindows[i].X,
- InteractMenu.SubWindows[i].Y -
- INTERACT_SUB_WINDOW_HEIGHT);
- GGMyDraw(InteractMenu.SubWindows[i].X,
- InteractMenu.SubWindows[i].Y +
- INTERACT_SUB_WINDOW_HEIGHT);
- }
- }
-
- #ifdef __MSDOS__
- settextjustify(oldtext.horiz, oldtext.vert);
- #endif /* __MSDOS__ */
- }
-
- /*****************************************************************************
- * Routine to handle data from the input device (keyboard, mouse etc.) - *
- * clip it against the sub windows of the interactive menu and perform the *
- * required transfomation, by updating the global view matrix object VIEW_MAT *
- * The input data in the Rotation/Translation/Scaling sub windows is used *
- * (horizontal distance from sub window center) to set amount of change. *
- *****************************************************************************/
- static void InteractHandleInput(ObjectStruct *PObjList, MatrixType GlblViewMat)
- {
- int i, UpdateView, ScreenCoord;
- double x, y, ChangeFactor;
- MatrixType Mat;
-
- ScreenCoord = (InteractMenu.SubWindows[0].Str[0] == 'S');
-
- WndwClearWindow(GlblViewWindow); /* Clear the view window. */
- QuitView = FALSE;
- ViewGeomObjectList(PObjList); /* Display it for the first time. */
-
- while (TRUE) {
- QuitView = FALSE;
- #ifdef __MSDOS__
- while (kbhit()) getch(); /* Flush out any keyboard key strokes. */
- #endif /* __MSDOS__ */
- MouseFlushBuffer(); /* Flush out any duplicated points picked. */
- GGGetPoint(&x, &y); /* Get coordinates from pick device. */
-
- for (i=0; i<INTERACT_NUM_OF_SUB_WINDOWS; i++)/* Test all sub windows.*/
- if (ABS(InteractMenu.SubWindows[i].Y - y) <
- INTERACT_SUB_WINDOW_HEIGHT &&
- ABS(InteractMenu.SubWindows[i].X - x) <
- INTERACT_SUB_WINDOW_WIDTH)
- break; /* The picked point is in this window! */
-
- ChangeFactor = (x - InteractMenu.SubWindows[i].X) / /* Between -1..1.*/
- INTERACT_SUB_WINDOW_WIDTH;
-
- if (i >= INTERACT_NUM_OF_SUB_WINDOWS) {
- GGTone(1000, 100);
- GGTone(1500, 100);
- GGTone(1000, 100);
- continue;
- }
-
- UpdateView = TRUE;
-
- switch (i) {
- case 0: /* Its Coordinate system - toggle it. */
- if (ScreenCoord) {
- InteractMenu.SubWindows[0].Str = "Object Coords.";
- ScreenCoord = FALSE;
- }
- else {
- InteractMenu.SubWindows[0].Str = "Screen Coords.";
- ScreenCoord = TRUE;
- }
- InteractDrawMenu(); /* Must update the menu on screen. */
- UpdateView = FALSE;
- break;
- case 1: /* Its rotation along the X axis. */
- MatGenMatRotX1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
- break;
- case 2: /* Its rotation along the Y axis. */
- MatGenMatRotY1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
- break;
- case 3: /* Its rotation along the Z axis. */
- MatGenMatRotZ1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
- break;
- case 4: /* Its translation along the X axis. */
- MatGenMatTrans(ChangeFactor * MAX_TRANSLATE_FACTOR, 0.0, 0.0,
- Mat);
- break;
- case 5: /* Its translation along the Y axis. */
- MatGenMatTrans(0.0, ChangeFactor * MAX_TRANSLATE_FACTOR, 0.0,
- Mat);
- break;
- case 6: /* Its translation along the Z axis. */
- MatGenMatTrans(0.0, 0.0, ChangeFactor * MAX_TRANSLATE_FACTOR,
- Mat);
- break;
- case 7: /* Its scaling along all axes. */
- if (ChangeFactor > 0.0) /* Make it around 1... */
- ChangeFactor = ChangeFactor * MAX_SCALE_FACTOR + 1.0;
- else ChangeFactor = 1.0 /
- (-ChangeFactor * MAX_SCALE_FACTOR + 1.0);
- MatGenMatScale(ChangeFactor, ChangeFactor, ChangeFactor, Mat);
- break;
- case 8:
- return; /* Its Quit. */
- default:
- FatalError("InteractHandleInput: Undefine input type, exit\n");
- }
- if (UpdateView) {
- if (ScreenCoord) /* Udpate the global viewing matrix. */
- MatMultTwo4by4(GlblViewMat, GlblViewMat, Mat);
- else MatMultTwo4by4(GlblViewMat, Mat, GlblViewMat);
- WndwClearWindow(GlblViewWindow); /* Clear the view window. */
- ViewGeomObjectList(PObjList); /* And display it... */
- }
- }
- }
-
- /*****************************************************************************
- * Routine to display the geometric objects in PObjList, by simply calling *
- * ViewGeomObject on all of them. PObjList must be of type OBJ_LIST_OBJ. *
- *****************************************************************************/
- static void ViewGeomObjectList(ObjectStruct *PObjList)
- {
- int Param = 0;
- struct ObjectStruct *PObj;
- char Line[LINE_LEN];
-
- while ((PObj = PObjList -> U.PObjList[Param]) != NULL &&
- Param++ < MAX_OBJ_LIST && !QuitView) {
- if (!IS_GEOM_OBJ(PObj)) {
- sprintf(Line, "Cannt display none geometric object %s, ignored",
- PObj -> Name);
- WndwInputWindowPutStr(Line, RED);
- continue;
- }
- ViewGeomObject(PObj);
- }
- }
-
- /*****************************************************************************
- * Routine to fetch the internal parameter from the INTERNAL object. *
- *****************************************************************************/
- static int GetInternal(void)
- {
- int Internal;
- struct ObjectStruct *PObj = GetObject("INTERNAL");
-
- if (PObj == NULL || !IS_NUM_OBJ(PObj)) {
- WndwInputWindowPutStr("No numeric object name INTERNAL is defined",
- RED);
- Internal = DEFAULT_INTERNAL;
- }
- else Internal = !APX_EQ((PObj -> U.R), 0.0);
-
- return Internal;
- }
-
- /*****************************************************************************
- * Routine to display the geometric object PObj on the View Window: *
- * Uses the global view transformation matrix ViewMat as view point. *
- *****************************************************************************/
- void ViewGeomObject(ObjectStruct *PObj)
- {
- int Color, ShowNormals, ViewInternal = GetInternal();
- struct PolygonStruct *Pl;
- struct ObjectStruct *ViewMat;
-
- QuitView = FALSE;
- #ifdef __MSDOS__
- while (kbhit()) getch(); /* Flush out any keyboard key strokes. */
- #endif /* __MSDOS__ */
- MouseFlushBuffer(); /* Flush out any duplicated points picked. */
-
- if (!IS_GEOM_OBJ(PObj))
- FatalError("ViewGeomObject: Not geometric object!\n");
-
- GGWindowViewPort(GlblViewWindow -> MinX, GlblViewWindow -> MinY,
- GlblViewWindow -> MaxX, GlblViewWindow -> MaxY,
- (int) VIEW_WINDOW_NAME);
-
- Pl = PObj -> U.Pl;
-
- if ((ViewMat = GetObject("VIEW_MAT")) == NULL) {
- WndwInputWindowPutStr(
- "No view transformation matrix VIEW_MAT!", RED);
- return;
- }
- else if (!IS_MAT_OBJ(ViewMat)) {
- WndwInputWindowPutStr(
- "VIEW_MAT object was modified (not matrix object)\n", RED);
- return;
- }
-
- Color = GET_OBJECT_COLOR(PObj);
- ShowNormals = (ViewNormals && !IS_POLYLINE_GEOM_OBJ(PObj));
-
- while (Pl && !QuitView) {
- ViewPolygon(Pl, Color, ShowNormals, ViewMat -> U.Mat, ViewInternal);
- Pl = Pl -> Pnext;
- TestQuitView(); /* if break display in the middle - Set QuitView. */
- }
- }
-
- /*****************************************************************************
- * Routine to test if quit display event - occured - SPACE was hit on *
- * keyboard or right button was clicked on mouse. *
- *****************************************************************************/
- static void TestQuitView(void)
- {
- int x, y, Buttons;
-
- #ifdef __MSDOS__
- if (kbhit() && getch() == ' ') QuitView = TRUE;
- #endif /* __MSDOS__ */
- if (MouseExists && MouseQueryBuffer()) {
- MouseGetBuffer(&x, &y, &Buttons);
- QuitView = (Buttons & 0x02);
- }
- }
-
- /*****************************************************************************
- * Routine to display one polygon on the view window using the matrix Mat as *
- * a transformation matrix. *
- *****************************************************************************/
- static void ViewPolygon(PolygonStruct *Pl, int Color, int ShowNormals,
- MatrixType Mat, int ViewInternal)
- {
- int NumOfPoints, DontDraw;
- RealType CenterX, CenterY;
- PointType P, CenterP;
- struct VertexStruct *V, *VStart;
-
- CenterX = (GlblViewWindow -> MinX + GlblViewWindow -> MaxX) / 2.0;
- CenterY = (GlblViewWindow -> MinY + GlblViewWindow -> MaxY) / 2.0;
-
- V = VStart = Pl -> V;
- if (V == NULL) FatalError("ViewPolygon: Empty polygon to view\n");
-
- MatMultVecby4by4(P, V -> Pt, Mat); /* Transform the first point. */
- GGMyMove(CenterX + P[0], CenterY + P[1]);
- DontDraw = IS_INTERNAL_EDGE(V) && !ViewInternal; /* Draw next edge? */
- GGMySetColor(Color);
-
- if (ShowNormals) { /* If display of normal is required. */
- NumOfPoints = 0;
- PT_CLEAR(CenterP);
- }
-
- do {
- V = V -> Pnext;
- if (ShowNormals) {
- NumOfPoints++;
- PT_ADD(CenterP, CenterP, V -> Pt);
- }
- MatMultVecby4by4(P, V -> Pt, Mat);
- /* If edge is INTERNAL (Irit.h) and not ViewInternal - dont draw: */
- if (DontDraw)
- GGMyMove(CenterX + P[0], CenterY + P[1]);
- else GGMyDraw(CenterX + P[0], CenterY + P[1]);
-
- DontDraw = IS_INTERNAL_EDGE(V) && !ViewInternal; /* Draw next edge? */
- } while (V != VStart && V -> Pnext != NULL);
-
- if (ShowNormals) {
- PT_SCALE(CenterP, 1.0/NumOfPoints); /* Estimate for normals. */
- MatMultVecby4by4(P, CenterP, Mat); /* Transform the first point. */
- GGMyMove(CenterX + P[0], CenterY + P[1]);
- PT_COPY(P, Pl -> Plane);
- PT_SCALE(P, NormalsSize);
- PT_ADD(CenterP, CenterP, P);
- MatMultVecby4by4(P, CenterP, Mat); /* Transform the second point. */
- GGMySetColor(NormalsColor);
- GGMyDraw(CenterX + P[0], CenterY + P[1]);
- }
- }
-
- /*****************************************************************************
- * Routine to set the normals default values: *
- *****************************************************************************/
- void ViewSetNormals(RealType *Active, RealType *Size, RealType *Color)
- {
- ViewNormals = !APX_EQ(*Active, 0.0);
- NormalsSize = *Size;
- NormalsColor = (int) *Color;
- }
-