static void _dxf_BUFFER_RESTORE_CONFIG (void *ctx, int OrigDisplayMode, int OrigBufferMode, tdmInteractorRedrawMode redrawMode) { /* * Restore frame buffer configuration. */ ENTRY(("_dxf_BUFFER_RESTORE_CONFIG(0x%x, %d, %d, %d)", ctx, OrigDisplayMode, OrigBufferMode, redrawMode)); if (redrawMode == tdmBothBufferDraw || redrawMode == tdmFrontBufferDraw) { PRINT(("current interactor redraw mode is %s", redrawMode == tdmFrontBufferDraw ? "tdmFrontBufferDraw" : "tdmBothBufferDraw")); if (OrigBufferMode == BCKBUFFER) { PRINT(("restoring to original back buffer draw")); frontbuffer(FALSE) ; backbuffer(TRUE) ; } else PRINT(("remaining in original front buffer draw")); } else if (redrawMode == tdmBackBufferDraw || redrawMode == tdmViewEchoMode) { PRINT(("current interactor redraw mode is %s", redrawMode == tdmViewEchoMode ? "tdmViewEchoMode" : "tdmBackBufferDraw")); if (OrigBufferMode == FRNTBUFFER) { PRINT(("restoring to original front buffer draw")); frontbuffer(TRUE) ; backbuffer(FALSE) ; } else PRINT(("remaining in original back buffer draw")); } else PRINT(("\nignoring redraw mode")); EXIT(("")); }
static void _dxf_BUFFER_CONFIG (void *ctx, void *image, int llx, int lly, int urx, int ury, int *CurrentDisplayMode, int *CurrentBufferMode, tdmInteractorRedrawMode redrawMode) { /* * Direct interactor echos use this and following routine to manage * double buffering. */ ENTRY(("_dxf_BUFFER_CONFIG (0x%x, 0x%x, %d, %d, %d, %d, 0x%x, 0x%x, %d)", ctx, image, llx, lly, urx, ury, CurrentDisplayMode, CurrentBufferMode, redrawMode)); /* record current GL buffer mode */ *CurrentBufferMode = getbuffer() ; if (redrawMode == tdmBothBufferDraw || redrawMode == tdmFrontBufferDraw) { PRINT(("%s", redrawMode == tdmBothBufferDraw ? "tdmBothBufferDraw" : "tdmFrontBufferDraw")); /* * Interactor echos no longer double buffered, so don't bother * keeping front and back buffer contents identical. */ frontbuffer(TRUE) ; backbuffer(FALSE) ; } else if (redrawMode == tdmBackBufferDraw || redrawMode == tdmViewEchoMode) { PRINT(("%s", redrawMode == tdmViewEchoMode ? "tdmViewEchoMode" : "tdmBackBufferDraw")); frontbuffer(FALSE) ; backbuffer(TRUE) ; } else PRINT(("ignoring redraw mode")); EXIT(("")); }
setup_lcube() { window(-800.0, 800.0, -800.0, 800.0, -800.0, 800.0); lookat(0.0, 0.0, 1500.0, 0.0, 0.0, 0.0, 0); linewidth(3); /* * Start with a very ordinary filled cube like the old demo.. */ makecube(filledthing); makecube(outlinething); backbuffer(1); }
main() { char device[10], *p; float x, y, tdir = TRANS; int but, nplanes; int i, n; char buf[10][128]; fprintf(stderr,"Enter output device: "); gets(device); prefposition(50, 50); vinit(device); window(-800.0, 800.0, -800.0, 800.0, -800.0, 800.0); lookat(0.0, 0.0, 1500.0, 0.0, 0.0, 0.0, 0.0); makeobj(1); makepoly(); rect(-CUBE_SIZE, -CUBE_SIZE, CUBE_SIZE, CUBE_SIZE); closepoly(); closeobj(); if ((nplanes = getdepth()) == 1) makecubes(0); makecubes(1); backface(1); if (backbuffer() < 0) { vexit(); fprintf(stderr, "lcube: device doesn't support double buffering.\n"); exit(0); } while((but = slocator(&x, &y)) != 44) { pushmatrix(); rotate(100.0 * x, 'y'); rotate(100.0 * y, 'x'); color(BLACK); clear(); callobj(3); if (nplanes == 1) callobj(2); popmatrix(); swapbuffers(); switch (but = checkkey()) { case 'x': translate(tdir, 0.0, 0.0); break; case 'y': translate(0.0, tdir, 0.0); break; case 'z': translate(0.0, 0.0, tdir); break; case '-': tdir = -tdir; break; case '+': tdir = TRANS; break; case 27: /* ESC */ case 'q': vexit(); exit(0); default: ; } } vexit(); }
static void _dxf_DRAW_GNOMON (tdmInteractor I, void *udata, float rot[4][4], int draw) { /* * draw == 1 to draw gnomon, draw == 0 to undraw. This is done with * two separate calls in order to support explicit erasure of edges for * some implementations. A draw is always preceded by an undraw and * the pair of invocations is atomic. * * Computations are done in normalized screen coordinates in order to * render arrow heads correctly. */ DEFDATA(I,tdmRotateData) ; DEFPORT(I_PORT_HANDLE) ; int dummy = 0 ; float origin[2] ; float xaxis[2], yaxis[2], zaxis[2] ; float xlabel[2], ylabel[2], zlabel[2] ; ENTRY(("_dxf_DRAW_GNOMON (0x%x, 0x%x, 0x%x, %d)",I, udata, rot, draw)); if (PDATA(font) == -1) { /* font width for axes labels in normalized coordinates */ font(0) ; PDATA(font) = 0 ; PDATA(swidth) = (float)strwidth("Z")/(float)GNOMONRADIUS ; /* 1 pixel in normalized coordinates */ PDATA(nudge) = 1.0/(float)GNOMONRADIUS ; } else font(PDATA(font)) ; if (draw) { lmcolor(LMC_COLOR) ; cpack(0xffffffff) ; linewidth(1) ; } else { if (PDATA(redrawmode) != tdmViewEchoMode) { /* * In tdmViewEchoMode (DX's Execute On Change), we are drawing * the gnomon echo on top of a background image that is redrawn * with every frame of a direct interaction. * * If we're not in that mode, the background image is static * while the gnomon echo rotates in front of it, so erasing the * gnomon means we have to repair damage to the background. We * do this by blitting a portion of the static image to the * back buffer, drawing the gnomon over that, then blitting the * combined results back to the front buffer. */ /* force graphics output into back buffer */ frontbuffer(FALSE) ; backbuffer(TRUE) ; /* erase gnomon background */ lrectwrite (PDATA(illx), PDATA(illy), PDATA(iurx), PDATA(iury), PDATA(background)) ; } #ifndef NOSHADOW /* draw wide black lines to ensure visibility against background */ lmcolor(LMC_COLOR) ; cpack(0x0) ; linewidth(2) ; #else EXIT(("No shadow")); return ; #endif } origin[0] = 0 ; origin[1] = 0 ; xaxis[0] = 0.7 * rot[0][0] ; xaxis[1] = 0.7 * rot[0][1] ; yaxis[0] = 0.7 * rot[1][0] ; yaxis[1] = 0.7 * rot[1][1] ; zaxis[0] = 0.7 * rot[2][0] ; zaxis[1] = 0.7 * rot[2][1] ; xlabel[0] = 0.8 * rot[0][0] ; xlabel[1] = 0.8 * rot[0][1] ; ylabel[0] = 0.8 * rot[1][0] ; ylabel[1] = 0.8 * rot[1][1] ; zlabel[0] = 0.8 * rot[2][0] ; zlabel[1] = 0.8 * rot[2][1] ; pushmatrix() ; loadmatrix(identity) ; bgnline() ; v2f(origin) ; v2f(xaxis) ; endline() ; _dxf_DRAW_ARROWHEAD(PORT_CTX, xaxis[0], xaxis[1]) ; bgnline() ; v2f(origin) ; v2f(yaxis) ; endline() ; _dxf_DRAW_ARROWHEAD(PORT_CTX, yaxis[0], yaxis[1]) ; bgnline() ; v2f(origin) ; v2f(zaxis) ; endline() ; _dxf_DRAW_ARROWHEAD(PORT_CTX, zaxis[0], zaxis[1]) ; if (xlabel[0] <= 0) xlabel[0] -= PDATA(swidth) ; if (xlabel[1] <= 0) xlabel[1] -= PDATA(swidth) ; if (ylabel[0] <= 0) ylabel[0] -= PDATA(swidth) ; if (ylabel[1] <= 0) ylabel[1] -= PDATA(swidth) ; if (zlabel[0] <= 0) zlabel[0] -= PDATA(swidth) ; if (zlabel[1] <= 0) zlabel[1] -= PDATA(swidth) ; #ifndef NOSHADOW if (!draw) { /* offset text slightly for shadow */ xlabel[0] += PDATA(nudge) ; xlabel[1] -= PDATA(nudge) ; ylabel[0] += PDATA(nudge) ; ylabel[1] -= PDATA(nudge) ; zlabel[0] += PDATA(nudge) ; zlabel[1] -= PDATA(nudge) ; } #endif font(0) ; cmov2 (xlabel[0], xlabel[1]) ; charstr ("X") ; cmov2 (ylabel[0], ylabel[1]) ; charstr ("Y") ; cmov2 (zlabel[0], zlabel[1]) ; charstr ("Z") ; popmatrix() ; if (draw && PDATA(redrawmode) != tdmViewEchoMode) { /* copy rendered gnomon from back buffer to front buffer */ readsource(SRC_BACK) ; frontbuffer(TRUE) ; backbuffer(FALSE) ; rectcopy (PDATA(illx), PDATA(illy), PDATA(iurx), PDATA(iury), PDATA(illx), PDATA(illy)) ; /* restore original buffer config from current tdmFrontBufferDraw */ _dxf_BUFFER_RESTORE_CONFIG (PORT_CTX, dummy, PDATA(buffermode), tdmFrontBufferDraw) ; } EXIT(("")); }
static void _dxf_DRAW_GLOBE (tdmInteractor I, void *udata, float rot[4][4], int draw) { /* * draw == 1 to draw globe, draw == 0 to undraw. This is done with two * separate calls in order to support explicit erasure of edges for * some implementations. A draw is always preceded by an undraw and * the pair of invocations is atomic. */ DEFDATA(I,tdmRotateData) ; DEFPORT(I_PORT_HANDLE) ; int u, v, on, dummy = 0 ; /* globe edge visibility flags. all globe instance share this data. */ static struct { int latvis, longvis ; } edges[LATS][LONGS] ; /* globe and globeface defined in tdmGlobeEchoDef.h */ register const float (*Globe)[LONGS][3] = globe ; register const struct Face (*Globeface)[LONGS] = globeface ; /* view normal */ register float z0, z1, z2 ; z0 = rot[0][2] ; z1 = rot[1][2] ; z2 = rot[2][2] ; #define FACEVISIBLE(u,v,z0,z1,z2) \ (Globeface[u][v].norm[0] * z0 + \ Globeface[u][v].norm[1] * z1 + \ Globeface[u][v].norm[2] * z2 > 0.0) ENTRY(("_dxf_DRAW_GLOBE (0x%x, 0x%x, 0x%x, %d)",I, udata, rot, draw)); if (draw) { lmcolor(LMC_COLOR) ; cpack(0xffffffff) ; linewidth(1) ; } else { if (PDATA(redrawmode) != tdmViewEchoMode) { /* * In tdmViewEchoMode (DX's Execute On Change), we are drawing * the globe echo on top of a background image that is redrawn * with every frame of a direct interaction. * * If we're not in that mode, the background image is static * while the globe echo rotates in front of it, so erasing the * globe means we have to repair damage to the background. We * do this by blitting a portion of the static image to the * back buffer, drawing the globe over that, then blitting the * combined results back to the front buffer. */ /* force graphics output into back (draw) buffer */ frontbuffer(FALSE) ; backbuffer(TRUE) ; /* erase globe background */ lrectwrite (PDATA(illx), PDATA(illy), PDATA(iurx), PDATA(iury), PDATA(background)) ; } #ifndef NOSHADOW /* draw wide black lines to ensure visibility against background */ lmcolor(LMC_COLOR) ; cpack(0x0) ; linewidth(2) ; #else EXIT(("No shadow")); return ; #endif } #ifndef FACEVIS /* * Compute visible edges explicitly. This method might be faster and * works in XOR mode but as implemented here is applicable only for a * globe-type object rendered with latitude and longitude lines. */ #ifndef NOSHADOW if (!draw) #endif for (u=0 ; u<LATS-1 ; u++) { if (FACEVISIBLE(u, 0, z0, z1, z2)) { edges[u][LONGS-1].latvis++ ; edges[u+1][LONGS-1].latvis++ ; edges[u][0].longvis++ ; edges[u][LONGS-1].longvis++ ; } for (v=1 ; v<LONGS ; v++) if (FACEVISIBLE(u, v, z0, z1, z2)) { edges[u][v-1].latvis++ ; edges[u+1][v-1].latvis++ ; edges[u][v].longvis++ ; edges[u][v-1].longvis++ ; } } /* north pole */ if (z1 > 0.0) for (v=0 ; v<LONGS ; v++) edges[LATS-1][v].latvis++ ; /* south pole */ if (z1 < 0.0) for (v=0 ; v<LONGS ; v++) edges[0][v].latvis++ ; /* * Draw each visible edge exactly once. */ for (u=0 ; u<LATS ; u++) { for (v=0, on=0 ; v<LONGS-1 ; v++) if (edges[u][v].latvis) { if (!on) { on = 1 ; bgnline() ; v3f(Globe[u][v]) ; } v3f (Globe[u][v+1]) ; #ifndef NOSHADOW if (draw) #endif edges[u][v].latvis = 0 ; } else if (on) { on = 0 ; endline() ; } /* close latitude line if necessary */ if (edges[u][LONGS-1].latvis) { if (!on) { bgnline() ; v3f(Globe[u][LONGS-1]) ; } v3f (Globe[u][0]) ; endline() ; #ifndef NOSHADOW if (draw) #endif edges[u][LONGS-1].latvis = 0 ; } else if (on) endline() ; } /* longitude lines */ for (v=0 ; v<LONGS ; v++) { for (u=0, on=0 ; u<LATS-1 ; u++) if (edges[u][v].longvis) { if (!on) { on = 1 ; bgnline() ; v3f(Globe[u][v]) ; } v3f(Globe[u+1][v]) ; #ifndef NOSHADOW if (draw) #endif edges[u][v].longvis = 0 ; } else if (on) { on = 0 ; endline() ; } if (on) endline() ; } #else /* * Do it the easy way: draw all visible faces regardless of shared * edges. Most edges are drawn twice, so this is slower and not * compatible with XOR rendering. */ for (u=0 ; u<LATS-1 ; u++) for (v=0 ; v<LONGS ; v++) if (FACEVISIBLE(u, v, z0, z1, z2)) poly (4, Globeface[u][v].face) ; /* north pole */ if (z1 > 0.0) poly (LONGS, Globe[LATS-1]) ; /* south pole */ if (z1 < 0.0) poly (LONGS, Globe[0]) ; #endif /* ifndef FACEVIS */ if (draw && PDATA(redrawmode) != tdmViewEchoMode) { /* copy rendered globe from back buffer to front buffer */ readsource(SRC_BACK) ; frontbuffer(TRUE) ; backbuffer(FALSE) ; rectcopy (PDATA(illx), PDATA(illy), PDATA(iurx), PDATA(iury), PDATA(illx), PDATA(illy)) ; /* restore original buffer config from current tdmFrontBufferDraw */ _dxf_BUFFER_RESTORE_CONFIG (PORT_CTX, dummy, PDATA(buffermode), tdmFrontBufferDraw) ; } EXIT(("")); }