home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Programming / Warp3D_Devel / Source / WarpTest.c
Encoding:
C/C++ Source or Header  |  2001-02-08  |  47.3 KB  |  1,633 lines

  1. /*
  2.     WarpTest
  3.     This program is part of the Warp3D project.
  4.     Copyright © 1998 Thomas Frieden, Hans-Jörg Frieden, Sam Jordan
  5.     You may freely modify and/or use any part of this file. It
  6.     is considered an example for programming Warp3D.
  7.  
  8.     This is a small program that shows some effects that can be done
  9.     with Warp3D, and may also serve as an example for programming
  10.     with Warp3D. It demonstrates fog, alpha blending, texture mapping,
  11.     both linear and perspective corrected, gouraud shading, filtering,
  12.     light mapping, mipmapping, including automatic mipmap generation,
  13.     and double buffering. Here`s how to use it:
  14.     From shell, enter WarpTest <texture.ppm>. If the texture is omitted,
  15.     wall.ppm is taken as default.
  16.     The wall can be moved and rotated with the cursor keys. Pressing the
  17.     mouse button and moving the mouse also rotates the wall. You can also
  18.     use the following keys for switching different effects:
  19.  
  20.         f - Toggle fogging.
  21.         8 - Push back the fog end value (observe the second last text row)
  22.         5 - Push fog end towards viewer
  23.         9 - Push back fog start
  24.         6 - Push fog start towards viewer
  25.  
  26.         t - toggle texture mapping/gouraud shading
  27.         e - toggle light mapping
  28.         p - toggle linear/perspective corrected mapping
  29.  
  30.         l - turn on alpha blending
  31.         1 - set filtering to W3D_NEAREST (no texture filtering)
  32.         2 - set filtering to W3D_LINEAR (bilinear texture
  33.         3 - set filtering to W3D_NEAREST_MIP_NEAREST (mipmapping, no filtering)
  34.         4 - set filtering to W3D_LINEAR_MIP_LINEAR (trilinear filtering with
  35.                                                 mipmapping)
  36.  
  37.         a - show mipmaps (don`t mind the flickering, they are only drawn
  38.                                                 to the first buffer)
  39.         b - show vertex coordinates (not very useful)
  40.         c - slow motion
  41.         d - draw the background pattern
  42.  
  43.         Pressing 'a' shows the current texture, along with the mipmaps
  44.         that were automatically created. These mipmaps are created with
  45.         a simple median where four pixels are summed up and divided by
  46.         four to produce a new pixel.
  47.  
  48.     History
  49.     -------
  50.     6-Aug-98        First public developer release
  51.  
  52.     8-Aug-98        Added a background patter switch (red lines), plus a
  53.                     key ('d') to toggle it. Additionally, Opacity for
  54.                     textures was replaced with a gradient pattern running
  55.                     from top-left to bottom-right.
  56.  
  57.     13-Sep-98       ZBuffering now works
  58.     28-Sep-98       Pressing F not switches hinting about fogging (press twice,
  59.                     I wa too lazy to correct the bug :)
  60.      3-Oct-98       Added TEXTURE and ZBUFFER command line switches
  61.     12-Jan-99       Added Outline mode with W3D_DrawLineLoop
  62.                     Added V2 driver interface
  63.                     Increased library minimum version to 2.0
  64.                     Added information printing about drivers
  65.                     Added example for W3D_QueryDriver
  66.     20-Feb-99       ClearZBuffer is now executed inside a hardware lock,
  67.                     so this shouldn't cause anymore problems (fingers crossed)
  68.  
  69. */
  70. ;// Includes
  71. #include <exec/types.h>
  72. #include <exec/memory.h>
  73. #include <libraries/asl.h>
  74. #include <proto/exec.h>
  75. #include <proto/intuition.h>
  76. #include <proto/cybergraphics.h>
  77. #include <proto/dos.h>
  78. #include <proto/graphics.h>
  79. #include <proto/Warp3D.h>
  80. #include <cybergraphx/cybergraphics.h>
  81. #include <stdio.h>
  82. #include <stdlib.h>
  83. #include <string.h>
  84. #include <math.h>
  85.  
  86. ;;//
  87. ;// Stuff
  88.  
  89.  
  90.  
  91. #ifdef __STORM__
  92. char version[] = "$VER: WarpTest_StormC 2.0 (6-Aug-98)";
  93. #else
  94. char version[] = "$VER: WarpTest 2.0 (6-Aug-98)";
  95. #endif
  96.  
  97. #ifndef __STORM__
  98. #pragma msg 193 ignore
  99. #pragma msg  93 ignore
  100. #endif
  101.  
  102. #ifndef __PPC__
  103. struct Library *Warp3DBase;
  104. #else
  105. struct Library *Warp3DPPCBase;
  106. #endif
  107. struct Library *CyberGfxBase;
  108. struct IntuitionBase *IntuitionBase;
  109. struct GfxBase *GfxBase;
  110. struct DosLibrary *DOSBase;
  111. struct Screen *screen;
  112. struct Window *window;
  113. int bufnum = 0;
  114. BOOL outline = FALSE;
  115. BOOL zb = FALSE;
  116.  
  117. struct RDArgs *rda = NULL;
  118. #define TEMPLATE "TEXTURE,ZBUFFER/S,REPEAT/N,LIGHTMAP/K"
  119.  
  120. ULONG texturesize;
  121. UBYTE *texture;
  122. UBYTE *lightmap;
  123. LONG result[10];
  124.  
  125. W3D_Texture *tex, *lighttex = NULL;
  126. W3D_Triangle tri;
  127. //W3D_Point point;
  128. W3D_Color ccol = {0.0, 1.0, 0.0, 0.8};
  129. W3D_Double zdepth = 0.8;
  130. ULONG zmode = 0;
  131.  
  132. ULONG DLevel=0, DWrap=0;
  133. int persp = 0;
  134. int forcelin = 0;
  135. float divisor = 2048.0;
  136. float factor = 16.f;
  137. float tmax   = 256.f;
  138. float lastw  = 0.f;
  139. float lastd  = 0.f;
  140. ULONG CurrentBlend = 0;
  141. ULONG BlendModes[] = {W3D_REPLACE, W3D_DECAL, W3D_MODULATE, W3D_BLEND};
  142. ULONG CurrentFog = 0;
  143. ULONG FogModes[] = {0, W3D_FOG_LINEAR, W3D_FOG_EXP, W3D_FOG_EXP_2, W3D_FOG_INTERPOLATED};
  144. W3D_Double LastZ = 0.0;
  145. int curfilt = 1;
  146. int drag = 0;
  147. int push = 0;
  148. int second_wall = 0;
  149. int pixels = 1;
  150.  
  151. const float Back  = 40.0;
  152. const float Front = 0.5;
  153.  
  154. #define kzen (-65535.0*(Back*Front)/(Back-Front))
  155. #define z0   ( 65535.0*Back/(Back-Front))
  156. #define SCALE 240
  157.  
  158. typedef struct {
  159.     float x,y,z;
  160.     float u,v;
  161.     float iz;
  162. } Vector3;
  163.  
  164. typedef struct {
  165.     float m11, m12, m13;
  166.     float m21, m22, m23;
  167.     float m31, m32, m33;
  168. } Matrix3;
  169.  
  170. Vector3 Square[4] = {
  171.     // x     y    z      u      v
  172.     {-1.f,  1.f, 0.f,   0.f,   0.f},
  173.     { 1.f,  1.f, 0.f,   1.f,   0.f},
  174.     { 1.f, -1.f, 0.f,   1.f,   1.f},
  175.     {-1.f, -1.f, 0.f,   0.f,   1.f}
  176. };
  177.  
  178. Vector3 LSquare[4] = {
  179.     // x     y    z      u      v
  180.     {-1.f,  1.f, 0.f,   0.f,   0.f},
  181.     { 1.f,  1.f, 0.f,   1.f,   0.f},
  182.     { 1.f, -1.f, 0.f,   1.f,   1.f},
  183.     {-1.f, -1.f, 0.f,   0.f,   1.f}
  184. };
  185.  
  186.  
  187. Vector3 TempSquare[4];
  188.  
  189. Vector3 Pos = {0.f, 0.f, 3.f, 0.f, 0.f};    // Position of wall
  190. float theta = 0.0;                          // Wall Angle
  191.  
  192. int aflag=0, bflag=0, cflag=0, dflag=0;
  193.  
  194. ULONG FogQuality = W3D_H_NICE;
  195. W3D_Fog myFog = {
  196.     1.0,0.2,1.0,
  197.     {8.1/32.0, 8.1/32.0, 17.1/32.0}
  198. };
  199.  
  200.  
  201. void *texmap;
  202.  
  203. ;;//
  204. ;// Matrix/Vector stuff
  205. void MatVec(Matrix3 *M, Vector3 *v, Vector3 *r)
  206. {
  207.     // Calcuate r=Mv
  208.     r->x = M->m11*v->x + M->m12*v->y + M->m13*v->z;
  209.     r->y = M->m21*v->x + M->m22*v->y + M->m23*v->z;
  210.     r->z = M->m31*v->x + M->m32*v->y + M->m33*v->z;
  211. }
  212.  
  213. void RotYMat(Matrix3 *M, float theta)
  214. // Create a Y axis rotation matrix by angle theta (theta in degrees)
  215. {
  216.  
  217.     theta = theta/180.f * M_PI;
  218.  
  219.     M->m11 =  (float)cos(theta);
  220.     M->m13 = -(float)sin(theta);
  221.     M->m31 =  (float)sin(theta);
  222.     M->m33 =  (float)cos(theta);
  223.     M->m22 =  1.f;
  224.  
  225.     M->m12 =
  226.     M->m21 =
  227.     M->m23 =
  228.     M->m32 = 0.f;
  229. }
  230.  
  231. void Project(Vector3 *v)
  232. {
  233.     if (v->z == 0.f) v->z+=0.0001;
  234.     v->iz = 1.0/v->z;
  235.     v->x = 320+SCALE*v->x*(v->iz);
  236.     v->y = 240-SCALE*v->y*(v->iz);
  237.     v->z = ((kzen/v->z)+z0)/65536.f;
  238. }
  239.  
  240. void VecAdd(Vector3 *a, Vector3 *b, Vector3 *r)
  241. // Calcuate r=a+b;
  242. // I love C++!!!
  243. {
  244.     r->x = a->x + b->x;
  245.     r->y = a->y + b->y;
  246.     r->z = a->z + b->z;
  247. }
  248.  
  249. void Transform(Vector3 Pos, float theta)
  250. // Transform the wall to the desired orientation
  251. {
  252.     Matrix3 M;
  253.     Vector3 r;
  254.     int i;
  255.  
  256.     RotYMat(&M, theta);     // Create rotation matrix;
  257.     for (i=0; i<4; i++) {
  258.         MatVec(&M, &Square[i], &TempSquare[i]);
  259.         VecAdd(&TempSquare[i], &Pos, &TempSquare[i]);
  260.     //}
  261.     //for (i=0; i<4; i++) {
  262.         Project(&TempSquare[i]);
  263.     }
  264. }
  265. ;;//
  266. ;// "LoadTextureFromPPM"
  267. #define ARGB8888toARGB1555(ic) (0x8000 | ((ic&0xF8)>>3) | ((ic&0xF800)>>6) | ((ic&0xF80000)>>9))
  268. #define ARGB8888toARGB4444(ic) ((ic&0xF0000000)>>16 | \
  269.                                 (ic&0x00F00000)>>12 | \
  270.                                 (ic&0x0000F000)>>8  | \
  271.                                 (ic&0x000000F0)>>4)
  272. UBYTE *LoadTextureFromPPM(APTR where, char *filename, UBYTE Opacity, int *w, int *h)
  273. {
  274.     ULONG *map, *map2;
  275.     FILE *f;
  276.     int i,j;
  277.     UBYTE r,g,b;
  278.     UWORD a;
  279.     unsigned long x,y;
  280.     int opqy, opqx, o;
  281.  
  282.     f=fopen(filename, "r");
  283.  
  284.     if (!f) {
  285.         printf("Error: Unable to open file '%s'\n", filename);
  286.         return NULL;
  287.     }
  288.  
  289. #ifndef __STORM__
  290.     i=fscanf(f, "P6\n%ld %ld\n255\n", &x, &y);
  291. #else
  292.     i=fscanf(f, "P6\n%ld\n%ld\n255\n", &x, &y);
  293. #endif
  294.  
  295.     if (i!=2) {
  296.         printf("Error: This seems to be no PPM file\n");
  297.         fclose(f);
  298.         return NULL;
  299.     }
  300.  
  301.     *w = x;
  302.     *h = y;
  303.  
  304.     if (where==NULL) {
  305.         map2 = map = AllocVec(x*y*4, MEMF_PUBLIC);
  306.     } else {
  307.         map = map2 = where;
  308.     }
  309.     if (!map) {
  310.         fclose(f);
  311.         printf("Error: Out of memory\n");
  312.         return NULL;
  313.     }
  314.  
  315.     opqy = 256/y;
  316.     opqx = 256/x;
  317.     opqx = opqx>>1;
  318.     o=0;
  319.     for (i=0; i<y; i++) {
  320.         for(j=0; j<x; j++) {
  321.             if (o+j*opqy > 255)
  322.                 Opacity = 255;
  323.             else
  324.                 Opacity = (UBYTE)(o+j*opqy);
  325.  
  326.             r=(UBYTE)fgetc(f);
  327.             g=(UBYTE)fgetc(f);
  328.             b=(UBYTE)fgetc(f);
  329.             *map = (Opacity<<24) | ((r&0xFF)<<16) | ((g&0xFF)<<8) | (b&0xFF);
  330. //            *map = (Opacity<<8) | ((r&0xFF)) | ((g&0xFF)<<24) | (b&0xFF)<<16;
  331.             map++;
  332.         }
  333.         o += opqx;
  334.     }
  335.  
  336.     fclose(f);
  337.     return (UBYTE *)map2;
  338. }
  339. ;;//
  340. ;// GenTexture
  341. int log2(int x)
  342. {
  343.     // Kludgy but fast :)
  344.     // floats are too small for log(x)/log(2)...
  345.     switch(x) {
  346.     case 65536: return 16;
  347.     case 32768: return 15;
  348.     case 16384: return 14;
  349.     case 8192: return 13;
  350.     case 4096: return 12;
  351.     case 2048: return 11;
  352.     case 1024: return 10;
  353.     case 512: return 9;
  354.     case 256: return 8;
  355.     case 128: return 7;
  356.     case 64:  return 6;
  357.     case 32:  return 5;
  358.     case 16:  return 4;
  359.     case 8:   return 3;
  360.     case 4:   return 2;
  361.     case 2:   return 1;
  362.     case 1:   return 0;
  363.     }
  364. }
  365.  
  366. BOOL GenTexture(W3D_Context* context, char* name, LONG repeat)
  367. {
  368.     UBYTE *where;
  369.     int w, h;
  370.     ULONG error;
  371.     int maps,i;
  372.  
  373.     // This loads a ppm (24 bit) texture file from disk, and sets
  374.     // it to 50% transparency (0x7F)...
  375.     where = LoadTextureFromPPM(NULL, name, 0x7F, &w, &h);
  376.     if (!where) return FALSE;
  377.     printf("Size: %ld×%ld\n", w,h);
  378.  
  379.     // This sets the square's texture coordinates to the right pixel values
  380.     for (i=0;i<4; i++) {
  381.         Square[i].u *= (w-1);      //  -1
  382.         Square[i].v *= (h-1);      //  -1
  383.         if (repeat > 1) {
  384.             Square[i].u *= repeat;
  385.             Square[i].v *= repeat;
  386.         }
  387.     }
  388.  
  389.  
  390.     texmap = where;
  391.  
  392.     tex = W3D_AllocTexObjTags(context, &error,
  393.         W3D_ATO_IMAGE,      (ULONG)where,   // The image data
  394.         W3D_ATO_FORMAT,     W3D_A8R8G8B8,   // This is a 32 bit image
  395.         W3D_ATO_WIDTH,      w,              // Length of one side
  396.         W3D_ATO_HEIGHT,     h,
  397.         W3D_ATO_MIPMAP,     0xffff,         // Mipmap mask - see autodocs
  398.     TAG_DONE);
  399.  
  400.     printf("Texture created\n");
  401.  
  402.     if (!tex || error != W3D_SUCCESS) {
  403.         printf("Error generating texture: ");
  404.         switch(error) {
  405.         case W3D_ILLEGALINPUT:
  406.             printf("Illegal input\n");
  407.             break;
  408.         case W3D_NOMEMORY:
  409.             printf("Out of memory\n");
  410.             break;
  411.         case W3D_UNSUPPORTEDTEXSIZE:
  412.             printf("Unsupported texture size\n");
  413.             break;
  414.         case W3D_NOPALETTE:
  415.             printf("Chunky texture without palette specified\n");
  416.             break;
  417.         case W3D_UNSUPPORTEDTEXFMT:
  418.             printf("Texture format not supported\n");
  419.             break;
  420.         default:
  421.             printf("ahem... An error has occured\n");
  422.         }
  423.         return FALSE;
  424.     }
  425.  
  426.     W3D_UploadTexture(context, tex);
  427.  
  428.     return TRUE;
  429. }
  430. ;;//
  431. ;// GenLightmap
  432. // Ok, this is a cheap, but who cares :)
  433. // In a real application, you would have this code only once
  434. BOOL GenLightmap(W3D_Context* context, char* name, LONG repeat)
  435. {
  436. #define LEVEL a
  437.     UBYTE *where, *here;
  438.     int w, h;
  439.     ULONG error;
  440.     int maps,i;
  441.     int a;
  442.  
  443.     // This loads a ppm (24 bit) texture file from disk, and sets
  444.     // it to 50% transparency (0x7F)...
  445.     where = LoadTextureFromPPM(NULL, name, 0x7F, &w, &h);
  446.     if (!where) return FALSE;
  447.     printf("Size: %ld×%ld\n", w,h);
  448.  
  449.     // Convert it to pure alpha
  450.     // Should really use a W3D_A8 here, but I'm too lazy
  451.     here = where;
  452.     for (i = 0; i < w*h; i++) {
  453.         a = (here[1] + here[2] + here[3])/3;
  454.         here[0] = a;
  455.         here[1] = LEVEL;
  456.         here[2] = LEVEL;
  457.         here[3] = LEVEL;
  458.         here += 4;
  459.     }
  460.  
  461.  
  462.     // This sets the square's texture coordinates to the right pixel values
  463.     for (i=0;i<4; i++) {
  464.         LSquare[i].u *= (w-1);      //  -1
  465.         LSquare[i].v *= (h-1);      //  -1
  466.         if (repeat > 1) {
  467.             LSquare[i].u *= repeat;
  468.             LSquare[i].v *= repeat;
  469.         }
  470.     }
  471.  
  472.  
  473.     lightmap = where;
  474.  
  475.     lighttex = W3D_AllocTexObjTags(context, &error,
  476.         W3D_ATO_IMAGE,      (ULONG)where,   // The image data
  477.         W3D_ATO_FORMAT,     W3D_A8R8G8B8,   // This is a 32 bit image
  478.         W3D_ATO_WIDTH,      w,              // Length of one side
  479.         W3D_ATO_HEIGHT,     h,
  480.         W3D_ATO_MIPMAP,     0xffff,         // Mipmap mask - see autodocs
  481.     TAG_DONE);
  482.  
  483.     if (!tex || error != W3D_SUCCESS) {
  484.         printf("Error generating light texture: ");
  485.         switch(error) {
  486.         case W3D_ILLEGALINPUT:
  487.             printf("Illegal input\n");
  488.             break;
  489.         case W3D_NOMEMORY:
  490.             printf("Out of memory\n");
  491.             break;
  492.         case W3D_UNSUPPORTEDTEXSIZE:
  493.             printf("Unsupported texture size\n");
  494.             break;
  495.         case W3D_NOPALETTE:
  496.             printf("Chunky texture without palette specified\n");
  497.             break;
  498.         case W3D_UNSUPPORTEDTEXFMT:
  499.             printf("Texture format not supported\n");
  500.             break;
  501.         default:
  502.             printf("ahem... An error has occured\n");
  503.         }
  504.         return FALSE;
  505.     }
  506.     return TRUE;
  507. }
  508. ;;//
  509. ;// PrintInfo
  510. void PrintInfo(W3D_Context* context)
  511. {
  512.     int x,y;
  513.     static char buffer[256];
  514.  
  515.     SetAPen(window->RPort, 2);
  516.     SetDrMd(window->RPort, JAM1);
  517.     x=450; y=100;
  518.     if (bufnum == 0)    y += 480;
  519.  
  520.     if (W3D_GetState(context, W3D_FAST) == W3D_ENABLED)
  521.                        sprintf(buffer, "Fast mode");
  522.     else               sprintf(buffer, " ");
  523.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  524.  
  525.     if (outline)       sprintf(buffer, "Outline mode");
  526.     else               sprintf(buffer, " ");
  527.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  528.  
  529.     if (aflag)         sprintf(buffer, "Show MipMaps");
  530.     else               sprintf(buffer, " ");
  531.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  532.  
  533.     if (bflag)         sprintf(buffer, "Vertex coordinates");
  534.     else               sprintf(buffer, " ");
  535.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  536.  
  537.     if (cflag)         sprintf(buffer, "Slow motion");
  538.     else               sprintf(buffer, " ");
  539.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  540.  
  541.     if (W3D_GetState(context, W3D_PERSPECTIVE) == W3D_ENABLED)
  542.         sprintf(buffer, "Perspective");
  543.     else
  544.         sprintf(buffer, "Linear");
  545.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  546.  
  547.     if (W3D_GetState(context,W3D_TEXMAPPING) == W3D_ENABLED)
  548.         sprintf(buffer, "Texture Mapping");
  549.     else
  550.         sprintf(buffer, "Gouraud Shading");
  551.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  552.  
  553.     switch(CurrentBlend) {
  554.     case 0:
  555.         sprintf(buffer, "Blend REPLACE");
  556.         break;
  557.     case 1:
  558.         sprintf(buffer, "Blend DECAL");
  559.         break;
  560.     case 2:
  561.         sprintf(buffer, "Blend MODULATE");
  562.         break;
  563.     case 3:
  564.         sprintf(buffer, "Blend BLEND");
  565.         break;
  566.     default:
  567.         sprintf(buffer, "Blend UNKNOWN");
  568.     }
  569.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  570.  
  571.     sprintf(buffer, "theta=%3.1f", theta);
  572.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  573.  
  574.     sprintf(buffer, "pos=(%3.1f %3.1f %3.1f)", Pos.x, Pos.y, Pos.z);
  575.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  576.  
  577.     sprintf(buffer, "Z-Clipping Plane %3.2f", zdepth);
  578.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  579.     {
  580.         char *zm;
  581.         switch(zmode) {
  582.         case 0:             zm = "Z-Buffer disabled";   break;
  583.         case W3D_Z_NEVER:   zm = "Z-Buffer never pass"; break;
  584.         case W3D_Z_LESS:    zm = "Z-Buffer less";       break;
  585.         case W3D_Z_GEQUAL:  zm = "Z-Buffer greater/equal"; break;
  586.         case W3D_Z_LEQUAL:  zm = "Z-Buffer less/equal"; break;
  587.         case W3D_Z_GREATER: zm = "Z-Buffer greater";    break;
  588.         case W3D_Z_NOTEQUAL:zm = "Z-Buffer not equal";  break;
  589.         case W3D_Z_EQUAL:   zm = "Z-Buffer equal";      break;
  590.         case W3D_Z_ALWAYS:  zm = "Z-Buffer always pass";break;
  591.         default:            zm = "??? Unknown Z-Mode";  break;
  592.         }
  593.         Move(window->RPort, x,y); Text(window->RPort, zm, strlen(zm)); y+=14;
  594.     }
  595.  
  596.     sprintf(buffer, "Last Z: %3.2f", LastZ);
  597.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  598.  
  599.     if (W3D_GetState(context,W3D_BLENDING) == W3D_ENABLED)
  600.         sprintf(buffer, "Alpha Blending");
  601.     else
  602.         sprintf(buffer, "No Blending");
  603.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  604.  
  605.     switch (CurrentFog) {
  606.         case 0: sprintf(buffer, "Fog off");             break;
  607.         case 1: sprintf(buffer, "Fog linear");          break;
  608.         case 2: sprintf(buffer, "Fog exponential");     break;
  609.         case 3: sprintf(buffer, "Fog exponential 2");   break;
  610.         case 4: sprintf(buffer, "Fog interpolated");    break;
  611.     }
  612.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  613.  
  614.     sprintf(buffer, "(%3.2f - %3.2f)",
  615.         context->fog.fog_start, context->fog.fog_end);
  616.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  617.  
  618.     switch(curfilt) {
  619.         case 1: sprintf(buffer, "W3D_NEAREST"); break;
  620.         case 2: sprintf(buffer, "W3D_LINEAR"); break;
  621.         case 3: sprintf(buffer, "W3D_NEAREST_MIP_NEAREST"); break;
  622.         case 4: sprintf(buffer, "W3D_LINEAR_MIP_LINEAR"); break;
  623.     }
  624.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  625.  
  626.     y=430; if (bufnum == 0) y+=480;
  627.     x=10;
  628.  
  629.     sprintf(buffer, "A - Mipmap view  B - Vertex coords  C - Slow Motion  P - Perspective Mapping");
  630.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  631.     sprintf(buffer, "T - Texture Mapping  F - Fogging  L - Alpha  1..4 - Filter");
  632.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  633.     sprintf(buffer, "E - Blendmode  ESC - Quit");
  634.     Move(window->RPort, x,y); Text(window->RPort, buffer, strlen(buffer)); y+=14;
  635.  
  636. }
  637. ;;//
  638. ;// ClearWindow
  639. void ClearWindow(W3D_Context *context,struct Window *window)
  640. {
  641.     UWORD *t = tex->texdest;
  642.     int i,j,k;
  643.     int w = tex->texwidth;
  644.     int h = tex->texheight;
  645.  
  646.     EraseRect(window->RPort, 0, (1-bufnum) * 480, 639, (1-bufnum) * 480 + 479);
  647.  
  648.     if (dflag) {
  649.         int blah = (1-bufnum)*480;
  650.         SetAPen(window->RPort,10);
  651.         for (i=30; i<480; i+=30) {
  652.             Move(window->RPort, 0, i+blah);
  653.             Draw(window->RPort, 639, i+blah);
  654.         }
  655.         for (i=30; i<640; i+=30) {
  656.             Move(window->RPort, i, blah);
  657.             Draw(window->RPort, i, blah+479);
  658.         }
  659.     }
  660.     if (aflag) {
  661.         // If AFlag is set, draw the mipmap
  662.         WritePixelArray(tex->texsource, 0,0, w*4,
  663.             window->RPort, 0,(1-bufnum)*480, w,h, RECTFMT_ARGB);
  664.         if (w>h) {
  665.             j = w/2;
  666.             k = w;
  667.         } else{
  668.             j = h/2;
  669.             k = w;
  670.         }
  671.  
  672.         i=0;
  673.         while (j) {
  674.             WritePixelArray(tex->mipmaps[i++],0,0,w*2,
  675.                 window->RPort,
  676.                 k,(1-bufnum)*480, w/2,h/2, RECTFMT_ARGB);
  677.             k+=w/2;
  678.             j/=2;
  679.             w/=2; if (w == 0) w = 1;
  680.             h/=2; if (h == 0) h = 1;
  681.         }
  682.     }
  683.     PrintInfo(context);
  684. }
  685. ;;//
  686. ;// DrawWall
  687. void DrawWall(W3D_Context *context)
  688. {
  689.     static char buffer[512];
  690.     int i;
  691.  
  692.     Transform(Pos, theta);    // Do the perspective transformations
  693. #if 1
  694.     if (outline) {
  695.         static W3D_Color col[4] = {
  696.             {0.9, 0.9, 0.0, 1.0},
  697.             {0.9, 0.0, 0.1, 0.2},
  698.             {0.0, 0.0, 0.9, 0.5},
  699.             {0.9, 0.9, 0.9, 1.0}
  700.         };
  701.         static W3D_Lines temp;
  702.         static W3D_Vertex v[4];
  703.         for(i = 0; i < 4; i++) {
  704.             v[i].x = TempSquare[i].x;
  705.             v[i].y = TempSquare[i].y;
  706.             v[i].z = TempSquare[i].z;    //  Needed for zbuffer
  707.             v[i].w = TempSquare[i].iz;   //  Needed for fogging
  708.             v[i].color.r = col[i].r;
  709.             v[i].color.g = col[i].g;
  710.             v[i].color.b = col[i].b;
  711.             v[i].color.a = col[i].a;
  712.         }
  713.         temp.v = v;
  714.         temp.vertexcount = 4;
  715.         W3D_DrawLineLoop(context, &temp);
  716.     }
  717. #endif
  718.     tri.tex = tex;  // Set the texture handle
  719.  
  720.    /*
  721.     A few notes about the triangle structure:
  722.  
  723.     The "x" and "y" components are pretty obvious. They specify the screen
  724.     coordinates of the corresponding vertex (as a float; this gives you
  725.     sub-pixel accuracy, which is especially useful for small triangles).
  726.  
  727.     The "z" component is the depth of the vertex. 0.0 means this vertex
  728.     sticks to the glass of your monitor (i.e. is closest to the front
  729.     clipping plane), while 1.0 means that the vertex is far away. The "z"
  730.     component is used for Z-Buffering, and, depending on the driver, might
  731.     be used for fogging as well
  732.  
  733.     "u" and "v" are the texture coordinates on this vertex, expressed
  734.     as pixels on the map. Note that this conforms with the OpenGL notion
  735.     of "u" and "v". "u" and "v" are not to be confused with OpenGL's
  736.     "s" and "t", which are in the range [0..1].
  737.  
  738.     color is the vertex color if lighting is used. Note that the alpha
  739.     value might or might not be used, depending on the blending mode.
  740.     The ViRGE implementation ignores this value, since the vertex alpha
  741.     is required for fogging.
  742.  
  743.     Note however, that the texture alpha is always taken into account (if
  744.     the required blending mode is selected)
  745.     */
  746.  
  747.     tri.v1.x = TempSquare[3].x; tri.v1.y = TempSquare[3].y; tri.v1.z = TempSquare[3].z;
  748.     tri.v1.w = TempSquare[3].iz;        //1.f-tri.v1.z;
  749.     tri.v1.u = Square[3].u;     tri.v1.v = Square[3].v;
  750.     tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
  751.  
  752.     tri.v2.x = TempSquare[1].x; tri.v2.y = TempSquare[1].y; tri.v2.z = TempSquare[1].z;
  753.     tri.v2.w = TempSquare[1].iz;        //1.f-tri.v2.z;
  754.     tri.v2.u = Square[1].u;     tri.v2.v = Square[1].v;
  755.     tri.v2.color.r = 1.0; tri.v2.color.g = 0.0; tri.v2.color.b = 0.0; tri.v2.color.a = 0.5;
  756.  
  757.     tri.v3.x = TempSquare[0].x; tri.v3.y = TempSquare[0].y; tri.v3.z = TempSquare[0].z;
  758.     tri.v3.w = TempSquare[0].iz;        //1.f-tri.v3.z;
  759.     tri.v3.u = Square[0].u;     tri.v3.v = Square[0].v;
  760.     tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 0.1; tri.v3.color.a = 1.0;
  761.  
  762.     // You must lock the hardware prior to drawing anything.
  763.     // Note that AUTOLOCKING, if enabled, will do this for you,
  764.     // but it is strictly recommended that you do locking yourself,
  765.     // since performance will suffer if you lock the hardware for
  766.     // every triangle. It is more efficient to lock hardware once for
  767.     // a few triangles, for example, for one polygon.
  768.     //
  769.     // NOTE 2: The CyberGfx implementation of the graphic sub-system
  770.     // driver uses LockBitmap() for this, so you may not hold the
  771.     // lock longer than one display frame (i.e. for a short time)
  772.     if (W3D_SUCCESS != W3D_LockHardware(context)) {
  773. //        printf("Error: Can`t lock hardware\n");
  774.         return;
  775.     }
  776.  
  777.  
  778.     // Go ahead and fire off the first triangle.
  779.     W3D_DrawTriangle(context, &tri);
  780.  
  781.     // Fill in the triangle structure again.
  782.     tri.v1.x = TempSquare[1].x; tri.v1.y = TempSquare[1].y; tri.v1.z = TempSquare[1].z;
  783.     tri.v1.w = TempSquare[1].iz;        //1.f-tri.v1.z;
  784.     tri.v1.u = Square[1].u;     tri.v1.v = Square[1].v;
  785.  
  786.     tri.v2.x = TempSquare[2].x; tri.v2.y = TempSquare[2].y; tri.v2.z = TempSquare[2].z;
  787.     tri.v2.w = TempSquare[2].iz;        //1.f-tri.v2.z;
  788.     tri.v2.u = Square[2].u;     tri.v2.v = Square[2].v;
  789.  
  790.     tri.v3.x = TempSquare[3].x; tri.v3.y = TempSquare[3].y; tri.v3.z = TempSquare[3].z;
  791.     tri.v3.w = TempSquare[3].iz;        //1.f-tri.v3.z;
  792.     tri.v3.u = Square[3].u;     tri.v3.v = Square[3].v;
  793.  
  794.     tri.v1.color.r = 1.0; tri.v1.color.g = 0.0; tri.v1.color.b = 0.0; tri.v1.color.a = 0.5;
  795.     tri.v2.color.r = 0.0; tri.v2.color.g = 0.0; tri.v2.color.b = 1.0; tri.v2.color.a = 0.1;
  796.     tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
  797.  
  798.     // Fire off the second triangle. Note that the drawing routines
  799.     // will wait before writing the values to the registers, but
  800.     // if the W3D_SYNCHRON state is not set, it will return immediately
  801.     // and not wait for completion of the operation. In this case
  802.     // it is your duty to wait until the hardware is idle again.
  803.     W3D_DrawTriangle(context, &tri);
  804.  
  805.     if (result[3]) {
  806.         ULONG Blend;
  807.         W3D_SetBlendMode(context, W3D_SRC_ALPHA, W3D_ONE_MINUS_SRC_ALPHA);
  808.  
  809.         Blend = W3D_GetState(context, W3D_BLENDING);
  810.         W3D_SetState(context, W3D_BLENDING, W3D_ENABLE);
  811.  
  812.         tri.tex = lighttex;  // Set the texture handle
  813.         tri.v1.x = TempSquare[3].x; tri.v1.y = TempSquare[3].y; tri.v1.z = TempSquare[3].z;
  814.         tri.v1.w = TempSquare[3].iz;        //1.f-tri.v1.z;
  815.         tri.v1.u = LSquare[3].u;     tri.v1.v = LSquare[3].v;
  816.         tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
  817.  
  818.         tri.v2.x = TempSquare[1].x; tri.v2.y = TempSquare[1].y; tri.v2.z = TempSquare[1].z;
  819.         tri.v2.w = TempSquare[1].iz;        //1.f-tri.v2.z;
  820.         tri.v2.u = LSquare[1].u;     tri.v2.v = LSquare[1].v;
  821.         tri.v2.color.r = 1.0; tri.v2.color.g = 1.0; tri.v2.color.b = 1.0; tri.v2.color.a = 1.0;
  822.  
  823.         tri.v3.x = TempSquare[0].x; tri.v3.y = TempSquare[0].y; tri.v3.z = TempSquare[0].z;
  824.         tri.v3.w = TempSquare[0].iz;        //1.f-tri.v3.z;
  825.         tri.v3.u = LSquare[0].u;     tri.v3.v = LSquare[0].v;
  826.         tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
  827.  
  828.         W3D_DrawTriangle(context, &tri);
  829.  
  830.         tri.v1.x = TempSquare[1].x; tri.v1.y = TempSquare[1].y; tri.v1.z = TempSquare[1].z;
  831.         tri.v1.w = TempSquare[1].iz;        //1.f-tri.v1.z;
  832.         tri.v1.u = LSquare[1].u;     tri.v1.v = LSquare[1].v;
  833.  
  834.         tri.v2.x = TempSquare[2].x; tri.v2.y = TempSquare[2].y; tri.v2.z = TempSquare[2].z;
  835.         tri.v2.w = TempSquare[2].iz;        //1.f-tri.v2.z;
  836.         tri.v2.u = LSquare[2].u;     tri.v2.v = LSquare[2].v;
  837.  
  838.         tri.v3.x = TempSquare[3].x; tri.v3.y = TempSquare[3].y; tri.v3.z = TempSquare[3].z;
  839.         tri.v3.w = TempSquare[3].iz;        //1.f-tri.v3.z;
  840.         tri.v3.u = LSquare[3].u;     tri.v3.v = LSquare[3].v;
  841.  
  842.         tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
  843.         tri.v2.color.r = 1.0; tri.v2.color.g = 1.0; tri.v2.color.b = 1.0; tri.v2.color.a = 1.0;
  844.         tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
  845.  
  846.         W3D_DrawTriangle(context, &tri);
  847.         W3D_SetState(context, W3D_BLENDING, Blend);
  848.     }
  849.  
  850. #if 0
  851.     if (outline) {
  852.         static W3D_Color col[4] = {
  853.             {0.9, 0.9, 0.0, 1.0},
  854.             {0.9, 0.0, 0.1, 0.2},
  855.             {0.0, 0.0, 0.9, 0.5},
  856.             {0.9, 0.9, 0.9, 1.0}
  857.         };
  858.         static W3D_Lines temp;
  859.         static W3D_Vertex v[4];
  860.         for(i = 0; i < 4; i++) {
  861.             v[i].x = TempSquare[i].x;
  862.             v[i].y = TempSquare[i].y;
  863.             v[i].z = TempSquare[i].z;    //  Needed for zbuffer
  864.             v[i].w = TempSquare[i].iz;   //  Needed for fogging
  865.             v[i].color.r = col[i].r;
  866.             v[i].color.g = col[i].g;
  867.             v[i].color.b = col[i].b;
  868.             v[i].color.a = col[i].a;
  869.         }
  870.         temp.v = v;
  871.         temp.vertexcount = 4;
  872.         W3D_DrawLineLoop(context, &temp);
  873.     }
  874. #endif
  875.     if (second_wall) {
  876.         float t2;
  877.  
  878.         t2 = 360.0 - theta;
  879.         if (t2 < 0) t2 = 360.0 - t2;
  880.  
  881.         Transform(Pos, t2);    // Do the perspective transformations
  882.  
  883.         tri.tex = tex;  // Set the texture handle
  884.  
  885.         tri.v1.x = TempSquare[3].x; tri.v1.y = TempSquare[3].y; tri.v1.z = TempSquare[3].z;
  886.         tri.v1.w = TempSquare[3].iz;        //1.f-tri.v1.z;
  887.         tri.v1.u = Square[3].u;     tri.v1.v = Square[3].v;
  888.         tri.v1.color.r = 1.0; tri.v1.color.g = 1.0; tri.v1.color.b = 1.0; tri.v1.color.a = 1.0;
  889.  
  890.         tri.v2.x = TempSquare[1].x; tri.v2.y = TempSquare[1].y; tri.v2.z = TempSquare[1].z;
  891.         tri.v2.w = TempSquare[1].iz;        //1.f-tri.v2.z;
  892.         tri.v2.u = Square[1].u;     tri.v2.v = Square[1].v;
  893.         tri.v2.color.r = 1.0; tri.v2.color.g = 0.0; tri.v2.color.b = 0.0; tri.v2.color.a = 1.0;
  894.  
  895.         tri.v3.x = TempSquare[0].x; tri.v3.y = TempSquare[0].y; tri.v3.z = TempSquare[0].z;
  896.         tri.v3.w = TempSquare[0].iz;        //1.f-tri.v3.z;
  897.         tri.v3.u = Square[0].u;     tri.v3.v = Square[0].v;
  898.         tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 0.0; tri.v3.color.a = 1.0;
  899.  
  900.         // Go ahead and fire off the first triangle.
  901.         W3D_DrawTriangle(context, &tri);
  902.  
  903.         // Fill in the triangle structure again.
  904.         tri.v1.x = TempSquare[1].x; tri.v1.y = TempSquare[1].y; tri.v1.z = TempSquare[1].z;
  905.         tri.v1.w = TempSquare[1].iz;        //1.f-tri.v1.z;
  906.         tri.v1.u = Square[1].u;     tri.v1.v = Square[1].v;
  907.  
  908.         tri.v2.x = TempSquare[2].x; tri.v2.y = TempSquare[2].y; tri.v2.z = TempSquare[2].z;
  909.         tri.v2.w = TempSquare[2].iz;        //1.f-tri.v2.z;
  910.         tri.v2.u = Square[2].u;     tri.v2.v = Square[2].v;
  911.  
  912.         tri.v3.x = TempSquare[3].x; tri.v3.y = TempSquare[3].y; tri.v3.z = TempSquare[3].z;
  913.         tri.v3.w = TempSquare[3].iz;        //1.f-tri.v3.z;
  914.         tri.v3.u = Square[3].u;     tri.v3.v = Square[3].v;
  915.  
  916.         tri.v1.color.r = 1.0; tri.v1.color.g = 0.0; tri.v1.color.b = 0.0; tri.v1.color.a = 1.0;
  917.         tri.v2.color.r = 0.0; tri.v2.color.g = 0.0; tri.v2.color.b = 1.0; tri.v2.color.a = 1.0;
  918.         tri.v3.color.r = 1.0; tri.v3.color.g = 1.0; tri.v3.color.b = 1.0; tri.v3.color.a = 1.0;
  919.  
  920.         // Fire off the second triangle. Note that the drawing routines
  921.         // will wait before writing the values to the registers, but
  922.         // if the W3D_SYNCHRON state is not set, it will return immediately
  923.         // and not wait for completion of the operation. In this case
  924.         // it is your duty to wait until the hardware is idle again.
  925.         W3D_DrawTriangle(context, &tri);
  926.  
  927.         if (outline) {
  928.             W3D_Color col[4] = {
  929.                 {0.9, 0.9, 0.0, 1.0},
  930.                 {0.9, 0.0, 0.0, 1.0},
  931.                 {0.0, 0.0, 0.9, 1.0},
  932.                 {0.9, 0.9, 0.9, 1.0}
  933.             };
  934.             W3D_Line temp;
  935.             temp.v1.color.a = 1.0;
  936.             temp.v2.color.a = 0.2;
  937.  
  938.             for(i = 0; i < 4; i++) {
  939.                 temp.v1.x = TempSquare[i].x;
  940.                 temp.v1.y = TempSquare[i].y;
  941.                 temp.v1.z = TempSquare[i].z;    //  Needed for zbuffer
  942.                 temp.v1.w = TempSquare[i].iz;   //  Needed for fogging
  943.                 temp.v2.x = TempSquare[(i+1)%4].x;
  944.                 temp.v2.y = TempSquare[(i+1)%4].y;
  945.                 temp.v2.z = TempSquare[(i+1)%4].z;
  946.                 temp.v2.w = TempSquare[(i+1)%4].iz;
  947.                 temp.v1.color.r = col[i].r;
  948.                 temp.v1.color.g = col[i].g;
  949.                 temp.v1.color.b = col[i].b;
  950.                 temp.v2.color.r = col[(i+1)%4].r;
  951.                 temp.v2.color.g = col[(i+1)%4].g;
  952.                 temp.v2.color.b = col[(i+1)%4].b;
  953.                 W3D_DrawLine(context, &temp);
  954.             }
  955.         }
  956.     }
  957.  
  958.     W3D_UnLockHardware(context);
  959.  
  960.     SetAPen(window->RPort, 249);
  961.     RectFill(window->RPort, 638,0,639,1);
  962.  
  963.     // If the user flipped the bflag on, draw the coordinates at the
  964.     // polygon vertices
  965.     if (bflag) {
  966.         SetAPen(window->RPort, 255);
  967.         for (i=0; i<4; i++) {
  968. #ifndef __STORM__
  969.             Move(window->RPort,(long)TempSquare[i].x, (long)TempSquare[i].y+(1-bufnum)*480);
  970.             sprintf(buffer, "%3.2f,%3.2f", TempSquare[i].z, TempSquare[i].iz);
  971.             Text(window->RPort, buffer, strlen(buffer));
  972. #else           /* compiler bug workaround */
  973.             float temp, temp2;
  974.  
  975.             temp = TempSquare[i].iz;
  976.             temp2 = TempSquare[i].z;
  977.             Move(window->RPort,(long)TempSquare[i].x, (long)TempSquare[i].y+(1-bufnum)*480);
  978.             sprintf(buffer, "%3.2f,%3.2f", temp2, temp);
  979.             Text(window->RPort, buffer, strlen(buffer));
  980. #endif
  981.         }
  982.     }
  983. }
  984.  
  985. ;;//
  986. ;// dummy
  987. void dummy(void)
  988. {
  989.     volatile int dont_optimize_me_away;
  990.     return;
  991. }
  992. ;;//
  993. ;// SwitchBuffer
  994. void SwitchBuffer(W3D_Context *context, struct BitMap *bm, struct Screen *scr, BOOL clip)
  995. {
  996.     W3D_Scissor s = {0, 0, 640, 480};
  997.     struct ViewPort *vp = &(scr->ViewPort);
  998.  
  999.     if (clip) {
  1000.         s.left = 10;
  1001.         s.top = 20;
  1002.         s.width = 400;
  1003.         s.height = 300;
  1004.     }
  1005.  
  1006.     if (bufnum == 0) {
  1007.         W3D_SetDrawRegion(context, bm, 0, &s);
  1008.         vp->RasInfo->RyOffset = 480;
  1009.         ScrollVPort(vp);
  1010.         WaitBOVP(vp);
  1011.         bufnum = 1-bufnum;
  1012.         if (clip)   W3D_SetScissor(context, &s);
  1013.     } else {
  1014.         W3D_SetDrawRegion(context, bm, 480, &s);
  1015.         vp->RasInfo->RyOffset = 0;
  1016.         ScrollVPort(vp);
  1017.         WaitBOVP(vp);
  1018.         bufnum = 1-bufnum;
  1019.         if (clip)   W3D_SetScissor(context, &s);
  1020.     }
  1021.  
  1022. }
  1023. ;;//
  1024. ;// PrintDriverInfo
  1025. void PrintDriverInfo(void)
  1026. {
  1027.     ULONG res;
  1028.  
  1029.     W3D_Driver **drivers = W3D_GetDrivers();
  1030.  
  1031.     if (*drivers == NULL) {
  1032.         printf("Panic: No Drivers found\n");
  1033.         return;
  1034.     }
  1035.     printf("Available drivers:\n");
  1036.     while (*drivers) {
  1037.         printf("%s\n\tSupports format 0x%lX\n\t",
  1038.             drivers[0]->name, drivers[0]->formats);
  1039.         if (drivers[0]->swdriver) printf("CPU Driver\n");
  1040.         else                      printf("Hardware Driver\n");
  1041.  
  1042.         printf("\tPrimitives supported:\n\t");
  1043.         res = W3D_QueryDriver(drivers[0], W3D_Q_DRAW_POINT, W3D_FMT_R5G5B5);
  1044.         if (res != W3D_NOT_SUPPORTED) printf("[POINT] ");
  1045.  
  1046.         res = W3D_QueryDriver(drivers[0], W3D_Q_DRAW_LINE, W3D_FMT_R5G5B5);
  1047.         if (res != W3D_NOT_SUPPORTED) printf("[LINE] ");
  1048.  
  1049.         res = W3D_QueryDriver(drivers[0], W3D_Q_DRAW_TRIANGLE, W3D_FMT_R5G5B5);
  1050.         if (res != W3D_NOT_SUPPORTED) printf("[TRIANGLE] ");
  1051.  
  1052.         printf("\n\tFiltering:\n\t");
  1053.         res = W3D_QueryDriver(drivers[0], W3D_Q_BILINEARFILTER, W3D_FMT_R5G5B5);
  1054.         if (res != W3D_NOT_SUPPORTED) printf("[BI-FILTER] ");
  1055.  
  1056.         res = W3D_QueryDriver(drivers[0], W3D_Q_MMFILTER, W3D_FMT_R5G5B5);
  1057.         if (res != W3D_NOT_SUPPORTED) printf("[MM-FILTER] ");
  1058.         printf("\n");
  1059.  
  1060.         drivers++;
  1061.     }
  1062.     printf("\n\n");
  1063. }
  1064. ;;//
  1065. ;// main
  1066. void main(int argc, char **argv)
  1067. {
  1068.     ULONG ModeID, ID, format;
  1069.     ULONG OpenErr, CError, res, ret;
  1070.     struct BitMap *bm = NULL;
  1071.     W3D_Context *context = NULL;
  1072.     BOOL running=TRUE, clip = FALSE;
  1073.     struct IntuiMessage *imsg;
  1074.     int i,j,k;
  1075.     ULONG flags;
  1076.     int update;
  1077.     float f;
  1078.     UBYTE *newm;
  1079.     UBYTE *hit = 0;
  1080.     int si;
  1081.     LONG repeat = 1;
  1082.     W3D_Scissor s = {0, 0, 640, 480};
  1083.     W3D_Scissor sc = {32, 32, 64, 64};
  1084.  
  1085.     if (argc != 0)
  1086.     {
  1087.         rda = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL);
  1088.         bzero(result, 40);
  1089.         if (rda) {
  1090.             rda->RDA_Source.CS_Buffer = NULL;
  1091.             ReadArgs(TEMPLATE, result, rda);
  1092.             FreeDosObject(DOS_RDARGS, rda);
  1093.         }
  1094.         if (result[2]) repeat = *((LONG *)result[2]);
  1095.         else           repeat = 1;
  1096.     }
  1097.  
  1098.  
  1099.     // Initialize the required libraries (We assume intuition and graphics open OK
  1100.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0L);
  1101.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L);
  1102.  
  1103.  
  1104.     CyberGfxBase = OpenLibrary("cybergraphics.library", 0L);
  1105.     if (!CyberGfxBase) {
  1106.         printf("Error opening CyberGraphX library\n");
  1107.         goto panic;
  1108.     }
  1109.  
  1110. #ifndef __PPC__
  1111.     Warp3DBase = OpenLibrary("Warp3D.library", 2L);
  1112.     if (!Warp3DBase) {
  1113.         printf("Error opening Warp3D library\n");
  1114.         goto panic;
  1115. #else
  1116.     Warp3DPPCBase = OpenLibrary("Warp3DPPC.library", 2L);
  1117.     if (!Warp3DPPCBase) {
  1118.         printf("Error opening Warp3DPPC.library\n");
  1119. #endif
  1120.     }
  1121.  
  1122.     // Check for availability of drivers
  1123.     flags = W3D_CheckDriver();
  1124.     if (flags & W3D_DRIVER_3DHW) printf("Hardware driver available\n");
  1125.     if (flags & W3D_DRIVER_CPU)  printf("Software driver available\n");
  1126.     if (flags & W3D_DRIVER_UNAVAILABLE) {
  1127.         printf("PANIC: no driver available!!!\n");
  1128.         goto panic;
  1129.     }
  1130.  
  1131.     PrintDriverInfo();
  1132.  
  1133.     // Get a screen mode
  1134.     // Due to the current limitations of the virge, this
  1135.     // Screen must be 15 bit deep (NOT 16!)
  1136. #if 0
  1137.     ModeID = BestCModeIDTags(
  1138.         CYBRBIDTG_Depth,            15L,
  1139.         CYBRBIDTG_NominalWidth,     640,
  1140.         CYBRBIDTG_NominalHeight,    480,
  1141.         CYBRBIDTG_BoardName,        "CVision3D",
  1142.     TAG_DONE);
  1143. #else
  1144.     /*
  1145.     ** New in V2: The Screenmode requester
  1146.     ** This requester will ask for any screenmode the installed
  1147.     ** Hardware driver can handle, and also restrict the presented
  1148.     ** screen modes to 640x480 Modes...
  1149.     */
  1150.     ModeID = W3D_RequestModeTags(
  1151.         W3D_SMR_TYPE,       W3D_DRIVER_3DHW,
  1152.         W3D_SMR_SIZEFILTER, TRUE,
  1153.         W3D_SMR_DESTFMT,    ~W3D_FMT_CLUT,
  1154.         ASLSM_MinWidth,     640,
  1155.         ASLSM_MaxWidth,     641,
  1156.         ASLSM_MinHeight,    480,
  1157.         ASLSM_MaxHeight,    481,
  1158.     TAG_DONE);
  1159. #endif
  1160.  
  1161.     if (ModeID == INVALID_ID) {
  1162.         printf("Error: No ModeID found\n");
  1163.         goto panic;
  1164.     }
  1165.  
  1166.     // Open Screen
  1167.     screen = OpenScreenTags(NULL,
  1168.         SA_Height,    960,
  1169.         SA_DisplayID, ModeID,
  1170.         SA_Depth,     8,
  1171.         SA_ErrorCode, (ULONG)&OpenErr,
  1172.         SA_ShowTitle, FALSE,
  1173.         SA_Draggable, FALSE,
  1174.     TAG_DONE);
  1175.  
  1176.     if (!screen) {
  1177.         printf("Unable to open screen. Reason: Error code %d\n", OpenErr);
  1178.         goto panic;
  1179.     }
  1180.  
  1181.     // Open window
  1182.     // While this is not strictly nessessary, we use it because
  1183.     // we want to get IDCMP messages. You can also use the screen's
  1184.     // bitmap to render
  1185.     window = OpenWindowTags(NULL,
  1186.         WA_CustomScreen,    (ULONG)screen,
  1187.         WA_Activate,        TRUE,
  1188.         WA_Width,           screen->Width,
  1189.         WA_Height,          screen->Height,
  1190.         WA_Left,            0,
  1191.         WA_Top,             0,
  1192.         WA_Title,           NULL,
  1193.         WA_CloseGadget,     FALSE,
  1194.         WA_Backdrop,        TRUE,
  1195.         WA_Borderless,      TRUE,
  1196.         WA_IDCMP,           IDCMP_CLOSEWINDOW|IDCMP_VANILLAKEY|IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_DELTAMOVE,
  1197.         WA_Flags,           WFLG_REPORTMOUSE|WFLG_RMBTRAP,
  1198.     TAG_DONE);
  1199.  
  1200.     SetRGB32(&(screen->ViewPort), 0, 0x40ffffff, 0x40ffffff, 0x88ffffff);
  1201.     SetRGB32(&(screen->ViewPort), 10, 0xffffffff, 0x0, 0x0);
  1202.  
  1203.     if (!window) {
  1204.         printf("Unable to open window.\n");
  1205.         goto panic;
  1206.     }
  1207.  
  1208.     // We want to use this bitmap
  1209.     bm = window->RPort->BitMap;
  1210.  
  1211.     SetAPen(window->RPort, 249);
  1212.     RectFill(window->RPort, 0, 0, 639, 959);
  1213.  
  1214.     // Go ahead and create the context. We need a context for every drawing
  1215.     // operation, so this is done quite early in the program.
  1216.     // NOTE: Some functions, like W3D_Query, do work without a context.
  1217.     // The W3D_Query function without a context can be used to determine
  1218.     // what kind of display/texture format the chip driver prefers.
  1219.  
  1220.     context = W3D_CreateContextTags(&CError,
  1221.         W3D_CC_MODEID,      ModeID,             // Mandatory for non-pubscreen
  1222.         W3D_CC_BITMAP,      (ULONG)bm,          // The bitmap we'll use
  1223.         W3D_CC_YOFFSET,     0,                  // We don't do dbuffering
  1224.         W3D_CC_DRIVERTYPE,  W3D_DRIVER_BEST,    // Let Warp3D decide
  1225.         W3D_CC_DOUBLEHEIGHT,TRUE,               // Double height screen
  1226.         W3D_CC_FAST,        TRUE,               // Fast drawing
  1227.     TAG_DONE);
  1228.  
  1229.     if (!context || CError != W3D_SUCCESS) {
  1230.         printf("Error creating context. Reason:");
  1231.         switch(CError) {
  1232.         case W3D_ILLEGALINPUT:
  1233.             printf("Illegal input to CreateContext function\n");
  1234.             break;
  1235.         case W3D_NOMEMORY:
  1236.             printf("Out of memory\n");
  1237.             break;
  1238.         case W3D_NODRIVER:
  1239.             printf("No suitable driver found\n");
  1240.             break;
  1241.         case W3D_UNSUPPORTEDFMT:
  1242.             printf("Supplied bitmap cannot be handled by Warp3D\n");
  1243.             break;
  1244.         case W3D_ILLEGALBITMAP:
  1245.             printf("Supplied bitmap not properly initialized\n");
  1246.             break;
  1247.         default:
  1248.             printf("An error has occured... gosh\n");
  1249.         }
  1250.         goto panic;
  1251.     }
  1252.  
  1253.     if (result[0]) {
  1254.         if (FALSE == GenTexture(context, (char *)result[0], repeat)) {
  1255.             printf("Error loading/generating texture\n");
  1256.             goto panic;
  1257.         }
  1258.     } else {
  1259.         if (FALSE == GenTexture(context, "wall.ppm", repeat)) {
  1260.             printf("Error loading/generating default texture\n");
  1261.             goto panic;
  1262.         }
  1263.     }
  1264.  
  1265.     if (result[3]) {
  1266.         if (FALSE == GenLightmap(context, (char *)result[3], repeat)) {
  1267.             printf("Error loading/generating lightmap\n");
  1268.             goto panic;
  1269.         }
  1270.     }
  1271.  
  1272.  /* If you need to know the "success" of setting a state, you can
  1273.     find out by examining the return value of W3D_SetState. This should
  1274.     be done if your program depends heavily on this feature. If not, you
  1275.     may safely ignore the result. For example, the W3D_DITHERING state
  1276.     might not have a large impact on the performance of your engine, so
  1277.     you might ignore the outcome. On the other hand, it might be a severe
  1278.     problem if your driver does not support texture mapping.
  1279.  
  1280.     Things like this can be verified with W3D_Query after the context was
  1281.     created, or with W3D_QueryDriver if you didn't create a context yet.
  1282.  */
  1283.  
  1284.     printf("Setting states\n");
  1285.  
  1286.     // Set dithering. This will look considerably better on 15 bit displays.
  1287.     W3D_SetState(context, W3D_DITHERING, W3D_ENABLE);
  1288.     // Set Gouraud shading state
  1289.     W3D_SetState(context, W3D_GOURAUD, W3D_ENABLE);
  1290.     // Set texture wrapping mode to on.
  1291.     // Read the section about limitations of the Virge for this
  1292.     W3D_SetWrapMode(context, tex, W3D_REPEAT, W3D_REPEAT, NULL);
  1293.     // Set blending to CurrentBlend mode (defaults to no alpha blending)
  1294.     W3D_SetTexEnv(context, tex, BlendModes[CurrentBlend], NULL);
  1295.     // Set Fog parameters
  1296.     W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
  1297.     // Set Texture mapping
  1298.     W3D_SetState(context, W3D_TEXMAPPING, W3D_ENABLE);
  1299.     // Set Drawing region
  1300.     W3D_SetDrawRegion(context, bm, 0, &s);
  1301.     // Set current color
  1302.     W3D_SetCurrentColor(context, &ccol);
  1303.     if (result[1]) {
  1304.         // Set ZBuffer modes
  1305.         if (W3D_SUCCESS != W3D_AllocZBuffer(context)) {
  1306.             printf("Error: Can`t create ZBuffer\nZBuffering will not be available\n");
  1307.         } else {
  1308.             zb = TRUE;
  1309.             W3D_SetState(context, W3D_ZBUFFERUPDATE, W3D_ENABLE);
  1310.             if (W3D_SUCCESS == W3D_LockHardware(context)) {
  1311.                 W3D_ClearZBuffer(context, &zdepth);
  1312.                 W3D_UnLockHardware(context);
  1313.             }
  1314.         }
  1315.     }
  1316.  
  1317.     printf("Going into main loop\n");
  1318.  
  1319.     // Clear window, then draw our first wall.
  1320.     ClearWindow(context, window);
  1321.     DrawWall(context);
  1322.  
  1323.     running=TRUE;
  1324.  
  1325.     while (running) {
  1326. //        WaitPort(window->UserPort);
  1327.         while (imsg = (struct IntuiMessage *)GetMsg(window->UserPort)) {
  1328.             if (imsg == NULL) break;
  1329.             switch(imsg->Class) {
  1330.             case IDCMP_MOUSEBUTTONS:
  1331.                 if (imsg->Code == SELECTDOWN) {
  1332.                     drag = 1;
  1333.                 }
  1334.                 if (imsg->Code == SELECTUP) {
  1335.                     drag = 0;
  1336.                 }
  1337.                 if (imsg->Code == MENUDOWN) {
  1338.                     push = 1;
  1339.                 }
  1340.                 if (imsg->Code == MENUUP) {
  1341.                     push = 0;
  1342.                 }
  1343.                 break;
  1344.             case IDCMP_MOUSEMOVE:
  1345.                 if (drag) {
  1346.                     theta += (float)(imsg->MouseX);
  1347.                     if (theta < 0.0) theta += 360.f;
  1348.                     if (theta > 360.0) theta -= 360.f;
  1349.                 }
  1350.                 if (push) {
  1351.                     Pos.z += (float)(imsg->MouseY)/128.f;
  1352.                     if (Pos.z < Front+1.f) Pos.z = Front+1.f;
  1353.                     if (Pos.z > Back-1.f) Pos.z = Back-1.f;
  1354.                 }
  1355.                 update = 1;
  1356.                 break;
  1357.             case IDCMP_CLOSEWINDOW:
  1358.                 running=FALSE;
  1359.                 break;
  1360.             case IDCMP_RAWKEY:
  1361.                 update=1;
  1362.                 if (cflag == 0) {
  1363.                     switch(imsg->Code) {
  1364.                     case 0x4F:
  1365.                         theta -= 4.f;
  1366.                         if (theta < 0.0) theta += 360.f;
  1367.                         break;
  1368.                     case 0x4e:
  1369.                         theta += 4.f;
  1370.                         if (theta > 360.0) theta -= 360.f;
  1371.                         break;
  1372.                     case 0x4C:
  1373.                         Pos.z -= 1.f;
  1374.                         if (Pos.z < Front+1.f) Pos.z = Front+1.f;
  1375.                         break;
  1376.                     case 0x4D:
  1377.                         Pos.z += 1.f;
  1378.                         if (Pos.z > Back-1.f) Pos.z = Back-1.f;
  1379.                         break;
  1380.                     case 0x50:
  1381.                         W3D_SetWrapMode(context, tex, W3D_CLAMP, W3D_CLAMP, NULL);
  1382.                         break;
  1383.                     case 0x51:
  1384.                         W3D_SetWrapMode(context, tex, W3D_REPEAT, W3D_REPEAT, NULL);
  1385.                         break;
  1386.                     case 0x5f:      // Debug key
  1387.                         clip = !clip;
  1388.                         if (clip) W3D_SetState(context, W3D_SCISSOR, W3D_ENABLE);
  1389.                         else      W3D_SetState(context, W3D_SCISSOR, W3D_DISABLE);
  1390.                         break;
  1391.                     break;
  1392.                     }
  1393.                 } else {
  1394.                     switch(imsg->Code) {
  1395.                     case 0x4F:
  1396.                         theta -= 1.f;
  1397.                         if (theta < 0.0) theta += 360.f;
  1398.                         break;
  1399.                     case 0x4e:
  1400.                         theta += 1.f;
  1401.                         if (theta > 360.0) theta -= 360.f;
  1402.                         break;
  1403.                     case 0x4C:
  1404.                         Pos.z -= 0.25f;
  1405.                         if (Pos.z < Front+1.f) Pos.z = Front+1.f;
  1406.                         break;
  1407.                     case 0x4D:
  1408.                         Pos.z += 0.25f;
  1409.                         if (Pos.z > Back-1.f) Pos.z = Back-1.f;
  1410.                         break;
  1411.                     }
  1412.                 }
  1413.                 break;
  1414.             case IDCMP_VANILLAKEY:
  1415.                 update = 1;
  1416.                 switch(imsg->Code) {
  1417.                 case '|':
  1418.                     newm = LoadTextureFromPPM((APTR)NULL, (char *)"smallugly.ppm", 30, &si, &si);
  1419.                     W3D_UpdateTexSubImage(context, tex, (void *)newm, 0, NULL, &sc, 0);
  1420.                     FreeVec(newm);
  1421.                     break;
  1422.                 case 'S':
  1423.                     second_wall = 1 - second_wall;
  1424.                     break;
  1425.                 case '8':   // Move fog end further back
  1426.                     myFog.fog_end -= 0.01;
  1427.                     if (myFog.fog_end < 0.05) myFog.fog_end = 0.05;
  1428.                     W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
  1429.                     break;
  1430.                 case '5':   // Move fog end forward
  1431.                     myFog.fog_end += 0.01;
  1432.                     if (myFog.fog_end+0.05 > myFog.fog_start) myFog.fog_end = myFog.fog_start-0.05;
  1433.                     W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
  1434.                     break;
  1435.                 case '9':   // Move fog start further back
  1436.                     myFog.fog_start -= 0.01;
  1437.                     if (myFog.fog_start-0.05 < myFog.fog_end) myFog.fog_start = myFog.fog_end+0.05;
  1438.                     W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
  1439.                     break;
  1440.                 case '6':   // Move fog start forward
  1441.                     myFog.fog_start += 0.01;
  1442.                     if (myFog.fog_start > 1.0) myFog.fog_start = 1.0;
  1443.                     W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
  1444.                     break;
  1445.                 case 'F': // Toggle fog quality
  1446.                     if (FogQuality == W3D_H_NICE) FogQuality = W3D_H_FAST;
  1447.                     else                          FogQuality = W3D_H_NICE;
  1448.                     W3D_Hint(context, W3D_H_FOGGING, FogQuality);
  1449.                     break;
  1450.                 case 't':
  1451.                 case 'T':   // Toggle texture mapping
  1452.                     if (W3D_GetState(context, W3D_TEXMAPPING) == W3D_ENABLED)
  1453.                         W3D_SetState(context, W3D_TEXMAPPING, W3D_DISABLE);
  1454.                     else
  1455.                         W3D_SetState(context, W3D_TEXMAPPING, W3D_ENABLE);
  1456.                     break;
  1457.                 case 'p':
  1458.                 case 'P':   // Toggle perspective mapping
  1459.                     if (forcelin == 1) break; // Exit if forced to linear
  1460.                     if (persp==0) persp=1;
  1461.                     else          persp=0;
  1462.                     if (persp) W3D_SetState(context, W3D_PERSPECTIVE, W3D_ENABLE);
  1463.                     else       W3D_SetState(context, W3D_PERSPECTIVE, W3D_DISABLE);
  1464.                     break;
  1465.                 case '1':
  1466.                     curfilt = 1;
  1467.                     ret = W3D_SetFilter(context, tex, W3D_NEAREST, W3D_NEAREST);
  1468.                     if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
  1469.                     if (lighttex) W3D_SetFilter(context, tex, W3D_NEAREST, W3D_NEAREST);
  1470.                     break;
  1471.                 case '2':
  1472.                     curfilt = 2;
  1473.                     ret = W3D_SetFilter(context, tex, W3D_LINEAR, W3D_LINEAR);
  1474.                     if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
  1475.                     if (lighttex) W3D_SetFilter(context, tex, W3D_LINEAR, W3D_LINEAR);
  1476.                     break;
  1477.                 case '3':
  1478.                     curfilt = 3;
  1479.                     ret = W3D_SetFilter(context, tex, W3D_NEAREST_MIP_NEAREST, W3D_NEAREST);
  1480.                     if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
  1481.                     if (lighttex) W3D_SetFilter(context, tex, W3D_NEAREST_MIP_NEAREST, W3D_NEAREST);
  1482.                     break;
  1483.                 case '4':
  1484.                     curfilt = 4;
  1485.                     ret = W3D_SetFilter(context, tex, W3D_LINEAR_MIP_LINEAR, W3D_LINEAR);
  1486.                     if (ret != W3D_SUCCESS) printf("Warning: Unsupported Filter mode\n");
  1487.                     if (lighttex) W3D_SetFilter(context, tex, W3D_LINEAR_MIP_LINEAR, W3D_LINEAR);
  1488.                     break;
  1489.                 case 'a':
  1490.                 case 'A':   // Toggle "Show mipmaps" (A Flag)
  1491.                     pixels = 1-pixels;
  1492.                     break;
  1493.                 case 'b':
  1494.                 case 'B':   // Toggle "Show coordinates" (B Flag)
  1495.                     bflag = 1-bflag;
  1496.                     break;
  1497.                 case 'c':
  1498.                 case 'C':   // Toggle "Slowmotion" (C FLag)
  1499.                     cflag = 1-cflag;
  1500.                     break;
  1501.                 case 'D':   // Debug stuff. Don't look here, it's nasty
  1502.                     if (W3D_SUCCESS == W3D_LockHardware(context))
  1503.                     {
  1504.                         W3D_ClearDrawRegion(context, 0);
  1505.                         W3D_UnLockHardware(context);
  1506.                     }
  1507.                     break;
  1508.                 case 'd':
  1509.                     dflag = 1-dflag;
  1510.                     break;
  1511.                 case 'e':
  1512.                 case 'E':   // Toggle Lighting
  1513.                     do {
  1514.                         CurrentBlend = (CurrentBlend+1)%4;
  1515.                         res = W3D_SetTexEnv(context, tex, BlendModes[CurrentBlend], NULL);
  1516.                     } while (res != W3D_SUCCESS);
  1517.                     break;
  1518.                 case 'f': // Toggle fog. Note we ignore success/failure
  1519.                     do {
  1520.                         CurrentFog = (CurrentFog+1)%5;
  1521.                         if (CurrentFog == 0) {
  1522.                             res = W3D_SetState(context, W3D_FOGGING, W3D_DISABLE);
  1523.                         } else {
  1524.                             res = W3D_SetFogParams(context, &myFog, FogModes[CurrentFog]);
  1525.                             if (res == W3D_SUCCESS)
  1526.                                 W3D_SetState(context, W3D_FOGGING, W3D_ENABLE);
  1527.                         }
  1528.                     } while (res != W3D_SUCCESS);
  1529.                     break;
  1530.                 case 'o':
  1531.                 case 'O':
  1532.                     outline = ~outline;
  1533.                     break;
  1534.                 case 'z':
  1535.                 case 'Z':   // Toggle ZBuffer. Currently not supported
  1536.                     zmode++; if (zmode == 9) zmode=0;
  1537.                     if (zmode==0) {
  1538.                         W3D_SetState(context, W3D_ZBUFFER, W3D_DISABLE);
  1539.                     } else {
  1540.                         W3D_SetState(context, W3D_ZBUFFER, W3D_ENABLE);
  1541.                         if (W3D_DISABLED == W3D_GetState(context, W3D_ZBUFFER)) {
  1542.                             printf("Warning: Can`t enable ZBuffer\n");
  1543.                         }
  1544.                         W3D_SetZCompareMode(context, zmode);
  1545.                     }
  1546.                     break;
  1547.                 case 'L':
  1548.                     if (W3D_GetState(context, W3D_GOURAUD) == W3D_ENABLED)
  1549.                         W3D_SetState(context, W3D_GOURAUD, W3D_DISABLE);
  1550.                     else
  1551.                         W3D_SetState(context, W3D_GOURAUD, W3D_ENABLE);
  1552.                     break;
  1553.                 case 'l':   // Toggle Alpha Blending
  1554.                     W3D_SetBlendMode(context, W3D_SRC_ALPHA, W3D_ONE_MINUS_SRC_ALPHA);
  1555.                     if (W3D_GetState(context, W3D_BLENDING) == W3D_ENABLED)
  1556.                         W3D_SetState(context, W3D_BLENDING, W3D_DISABLE);
  1557.                     else
  1558.                         W3D_SetState(context, W3D_BLENDING, W3D_ENABLE);
  1559.                     break;
  1560.                 case 's':
  1561.                     if (W3D_GetState(context, W3D_FAST) == W3D_ENABLED)
  1562.                         W3D_SetState(context, W3D_FAST, W3D_DISABLE);
  1563.                     else
  1564.                         W3D_SetState(context, W3D_FAST, W3D_ENABLE);
  1565.                     break;
  1566.                 case '+':
  1567.                     zdepth+=0.05;
  1568.                     if (zdepth>1.0) zdepth=1.0;
  1569.                     if (W3D_SUCCESS == W3D_LockHardware(context)) {
  1570.                         W3D_ClearZBuffer(context, &zdepth);
  1571.                         W3D_UnLockHardware(context);
  1572.                     }
  1573.                     break;
  1574.                 case '-':
  1575.                     zdepth-=0.05;
  1576.                     if (zdepth<0.0) zdepth=0.0;
  1577.                     if (W3D_SUCCESS == W3D_LockHardware(context)) {
  1578.                         W3D_ClearZBuffer(context, &zdepth);
  1579.                         W3D_UnLockHardware(context);
  1580.                     }
  1581.                     break;
  1582.                 case 27:    // Esc or 'Q' quits
  1583.                 case 'Q':
  1584.                     running=FALSE;
  1585.                     break;
  1586.                 case 13:
  1587.                     {
  1588.                     W3D_Double test;
  1589.                     W3D_ReadZPixel(context, 10, 10, &test);
  1590.                     printf("Test: %g\n", (double)test);
  1591.                     }
  1592.                     break;
  1593.                 default:
  1594.                     break;
  1595.                 }
  1596.             break;
  1597.             }
  1598.  
  1599.             if (imsg) {
  1600.                 ReplyMsg((struct Message *)imsg);
  1601.                 imsg = NULL;
  1602.             }
  1603.         }
  1604.         SwitchBuffer(context, bm, screen, clip);
  1605.         ClearWindow(context, window);
  1606.         DrawWall(context);
  1607.         if (zb && W3D_SUCCESS == W3D_LockHardware(context)) {
  1608.             W3D_ClearZBuffer(context, &zdepth);
  1609.             W3D_UnLockHardware(context);
  1610.         }
  1611.     }
  1612.  
  1613. panic:
  1614.     printf("Closing down...\n");
  1615.     if (context)        W3D_FreeZBuffer(context);
  1616.     if (tex)            W3D_FreeTexObj(context, tex);
  1617.     if (lighttex)       W3D_FreeTexObj(context, lighttex);
  1618.     if (context)        W3D_DestroyContext(context);
  1619.     if (texmap)         FreeVec(texmap);
  1620.     if (window)         CloseWindow(window);
  1621.     if (screen)         CloseScreen(screen);
  1622. #ifndef __PPC__
  1623.     if (Warp3DBase)     CloseLibrary(Warp3DBase);
  1624. #else
  1625.     if (Warp3DPPCBase)  CloseLibrary(Warp3DPPCBase);
  1626. #endif
  1627.     if (CyberGfxBase)   CloseLibrary((struct Library *)CyberGfxBase);
  1628.     if (IntuitionBase)  CloseLibrary((struct Library *)IntuitionBase);
  1629.     if (GfxBase)        CloseLibrary((struct Library *)GfxBase);
  1630.     exit(0);
  1631. }
  1632. ;;//
  1633.