home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Programmation / c / QuakeC / qtools0.2-src.lha / src / libqdisplay / 3d.c next >
Encoding:
C/C++ Source or Header  |  1998-07-19  |  10.0 KB  |  289 lines

  1. #define    LIBQDISPLAY_CORE
  2. #include "../include/libqdisplay.h"
  3.  
  4. #define DOT_VEC_DBL(a1,a2,a3,b1,b2,b3) ((float)(a1*b1 + a2*b2 + a3*b3))
  5.  
  6. float clipScaleX, clipScaleY, incSpeed, maxSpeed, decSpeed;
  7. vec3_t cameraLocation, currentSpeed;
  8. bool changedLocation, changedAngles, changedMatrix;
  9. angvec cameraAngles;
  10. struct extplane planes[4];
  11. float xCenter, yCenter;
  12.  
  13. static float mainMatrix[3][3], viewMatrix[3][3], translate[3];
  14. static int clipXLow, clipXHigh, clipYLow, clipYHigh;
  15. static float projScaleX, projScaleY;
  16. static float nearClip = 0.01, nearCode = 16.0;
  17.  
  18. void set_clip_values(int width, int height)
  19. {
  20.   clipXLow = -32768;
  21.   clipXHigh = (width << 16) - 32768;
  22.   clipYLow = -32768;
  23.   clipYHigh = (height << 16) - 32768;
  24.   projScaleX = (width >> 1);
  25.   projScaleY = (projScaleX * height) / (width * 0.75);
  26.   xCenter = -0.5 + (width >> 1);
  27.   yCenter = -0.5 + (height >> 1);
  28.   clipScaleX = 1.0 / (width >> 1);
  29.   clipScaleY = 1.0 / (height >> 1);
  30.   incSpeed = width * (2 / 91.5);
  31.   maxSpeed = width * (2 / 22.5);
  32.   decSpeed = incSpeed * (2 / 1.5);
  33. }
  34.  
  35. void set_view_info(void)
  36. {
  37.   /* compute rotation matrix */
  38.   if (changedAngles) {
  39.     /*
  40.      * the main matrix is the representation of the three vectors
  41.      * that makes the lokal coordinate-system, called local-axis
  42.      */
  43.     if (!cameraAngles.ty) {
  44.       mainMatrix[0][0] =  cosTable[cameraAngles.tz];
  45.       mainMatrix[0][1] = -sinTable[cameraAngles.tz];
  46.       mainMatrix[0][2] =  0;
  47.       mainMatrix[1][0] =  sinTable[cameraAngles.tz] *  sinTable[cameraAngles.tx];
  48.       mainMatrix[1][1] =  cosTable[cameraAngles.tz] *  sinTable[cameraAngles.tx];
  49.       mainMatrix[1][2] =                    cosTable[cameraAngles.tx];
  50.       mainMatrix[2][0] =  sinTable[cameraAngles.tz] *  cosTable[cameraAngles.tx];
  51.       mainMatrix[2][1] =  cosTable[cameraAngles.tz] *  cosTable[cameraAngles.tx];
  52.       mainMatrix[2][2] =                   -sinTable[cameraAngles.tx];
  53.  
  54.       changedAngles = FALSE;
  55.     }
  56.     else {
  57.       mainMatrix[0][0] =  cosTable[cameraAngles.tz] *                     cosTable[cameraAngles.ty] + sinTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * sinTable[cameraAngles.ty];
  58.       mainMatrix[0][1] = -sinTable[cameraAngles.tz] *                     cosTable[cameraAngles.ty] + cosTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * sinTable[cameraAngles.ty];
  59.       mainMatrix[0][2] =                    cosTable[cameraAngles.tx] *  sinTable[cameraAngles.ty];
  60.       mainMatrix[1][0] =  cosTable[cameraAngles.tz] *                    -sinTable[cameraAngles.ty] + sinTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * cosTable[cameraAngles.ty];
  61.       mainMatrix[1][1] = -sinTable[cameraAngles.tz] *                    -sinTable[cameraAngles.ty] + cosTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * cosTable[cameraAngles.ty];
  62.       mainMatrix[1][2] =                    cosTable[cameraAngles.tx] *  cosTable[cameraAngles.ty];
  63.       mainMatrix[2][0] =  sinTable[cameraAngles.tz] *  cosTable[cameraAngles.tx];
  64.       mainMatrix[2][1] =  cosTable[cameraAngles.tz] *  cosTable[cameraAngles.tx];
  65.       mainMatrix[2][2] =                   -sinTable[cameraAngles.tx];
  66.  
  67.       if ((cameraAngles.ty > 1) && (cameraAngles.ty <= 45))
  68.     cameraAngles.ty -= ((cameraAngles.ty - 0) / 6) + 1;
  69.       else if ((cameraAngles.ty >= 315) && (cameraAngles.ty < 359))
  70.     cameraAngles.ty += ((360 - cameraAngles.ty) / 6) + 1;
  71.       else
  72.     cameraAngles.ty = 0;
  73.     }
  74.     memcpy(viewMatrix, mainMatrix, sizeof(viewMatrix));
  75.     /*
  76.      * the view-matrix is the perspective correction of the main
  77.      * matrix in advance of the screen-ratio
  78.      */
  79.     viewMatrix[0][0] *= projScaleX;
  80.     viewMatrix[0][1] *= projScaleX;
  81.     viewMatrix[0][2] *= projScaleX;
  82.     viewMatrix[1][0] *= projScaleY;
  83.     viewMatrix[1][1] *= projScaleY;
  84.     viewMatrix[1][2] *= projScaleY;
  85.     /*viewMatrix[2][0] *= projScaleZ; */
  86.     /*viewMatrix[2][1] *= projScaleZ; */
  87.     /*viewMatrix[2][2] *= projScaleZ; */
  88.  
  89.     changedMatrix = TRUE;
  90.   }
  91.  
  92.   if (changedLocation) {
  93.     /*
  94.      * so (1,0,0) in camera space maps to viewMatrix[0] in world space.
  95.      * thus we multiply on the right by a worldspace vector to transform
  96.      * it to camera space.
  97.      * now, to account for translation, we just subtract the camera
  98.      * Center before multiplying
  99.      */
  100.     translate[0] = cameraLocation[0];
  101.     translate[1] = cameraLocation[1];
  102.     translate[2] = cameraLocation[2];
  103.  
  104.     if ((currentSpeed[0] != 0) || (currentSpeed[2] != 0)) {
  105.       cameraLocation[0] += -mainMatrix[0][1] * currentSpeed[0];
  106.       cameraLocation[1] +=  mainMatrix[0][0] * currentSpeed[0];
  107.       cameraLocation[2] +=  mainMatrix[1][2] * currentSpeed[2];
  108.  
  109.       if (currentSpeed[0] > decSpeed)
  110.     currentSpeed[0] -= decSpeed;
  111.       else if (currentSpeed[0] < -decSpeed)
  112.     currentSpeed[0] += decSpeed;
  113.       else
  114.     currentSpeed[0] = 0.0;
  115.  
  116.       if (currentSpeed[2] > decSpeed)
  117.     currentSpeed[2] -= decSpeed;
  118.       else if (currentSpeed[2] < -decSpeed)
  119.     currentSpeed[2] += decSpeed;
  120.       else
  121.     currentSpeed[2] = 0.0;
  122.     }
  123.     else
  124.       changedLocation = FALSE;                    /* release only if we really stop */
  125.   }
  126. }
  127.  
  128. float dist2_from_viewer(vec_t *in)
  129. {
  130.   vec3_t temp;
  131.  
  132.   VectorSubtract(in, cameraLocation, temp);
  133.  
  134.   return VectorDist(temp);
  135. }
  136.  
  137. #if 0                                /* this works if IEEE and, sizeof(float) == sizeof(int) */
  138. #define FLOAT_POSITIVE(x)   (*((int *)(&x)) >= 0)
  139. #else
  140. #define FLOAT_POSITIVE(x)   ((x) >= 0)
  141. #endif
  142.  
  143. /*
  144.  * the view-frustum are four planes that shoot from the camera-point
  145.  * in a direction that is the visible area
  146.  * everything between the four planes (the frustum) is visible
  147.  * this is called frustum-culling
  148.  *
  149.  * we form the four planes with four vectors (-1,0,1), (1,0,1), (0,1,1), (0,-1,1)
  150.  * with the cameras position as origin
  151.  * we use the hesse-normal-form
  152.  *
  153.  * in screen-space the z-coordinate is tht one that goes into the monitor
  154.  * y- and x-coordinate are the same as the screens coordinate, (0,0,0) is exactly
  155.  * in the middle of and on the screen
  156.  */
  157. void compute_view_frustrum(void)
  158. {
  159.   if (changedMatrix) {
  160.     /*
  161.      * why are the normals not normalized? (is the mainMatrix normalized?) the length are sqrt(2) instead of 1
  162.      * what means the dists?
  163.      * what is the direction of the normals (into the screen-space or out of?)?
  164.      */
  165.     planes[0].positive[0] = FLOAT_POSITIVE(
  166.     planes[0].normal[0] = -mainMatrix[0][0]         + mainMatrix[2][0]);
  167.     planes[0].positive[1] = FLOAT_POSITIVE(
  168.     planes[0].normal[1] = -mainMatrix[0][1]         + mainMatrix[2][1]);
  169.     planes[0].positive[2] = FLOAT_POSITIVE(
  170.     planes[0].normal[2] = -mainMatrix[0][2]         + mainMatrix[2][2]);
  171.     planes[1].positive[0] = FLOAT_POSITIVE(
  172.     planes[1].normal[0] =  mainMatrix[0][0]         + mainMatrix[2][0]);
  173.     planes[1].positive[1] = FLOAT_POSITIVE(
  174.     planes[1].normal[1] =  mainMatrix[0][1]         + mainMatrix[2][1]);
  175.     planes[1].positive[2] = FLOAT_POSITIVE(
  176.     planes[1].normal[2] =  mainMatrix[0][2]         + mainMatrix[2][2]);
  177.     planes[2].positive[0] = FLOAT_POSITIVE(
  178.     planes[2].normal[0] =                mainMatrix[1][0] + mainMatrix[2][0]);
  179.     planes[2].positive[1] = FLOAT_POSITIVE(
  180.     planes[2].normal[1] =                mainMatrix[1][1] + mainMatrix[2][1]);
  181.     planes[2].positive[2] = FLOAT_POSITIVE(
  182.     planes[2].normal[2] =                mainMatrix[1][2] + mainMatrix[2][2]);
  183.     planes[3].positive[0] = FLOAT_POSITIVE(
  184.     planes[3].normal[0] =               -mainMatrix[1][0] + mainMatrix[2][0]);
  185.     planes[3].positive[1] = FLOAT_POSITIVE(
  186.     planes[3].normal[1] =               -mainMatrix[1][1] + mainMatrix[2][1]);
  187.     planes[3].positive[2] = FLOAT_POSITIVE(
  188.     planes[3].normal[2] =               -mainMatrix[1][2] + mainMatrix[2][2]);
  189.   }
  190.  
  191.   if (changedMatrix || changedLocation) {
  192.     /*
  193.      * we move the planes to the cameras position, up to now the distance to
  194.      * the origin is 0 so 
  195.      *  DotProduct(frustumNormal, point) + frustumDistance
  196.      * gives
  197.      *  DotProduct(frustumNormal, point)
  198.      *
  199.      * why do we move it to cameras position?
  200.      * why is the dist not -DotProduct(frustumNormal, point) as it should be?
  201.      * is this correct??? I think the length of the cameras vector must
  202.      * be the distance for all planes[?].dist, and for all equal
  203.      *  VectorLength(cameraLocation)
  204.      */
  205.     planes[0].dist = DotProduct(planes[0].normal, cameraLocation);
  206.     planes[1].dist = DotProduct(planes[1].normal, cameraLocation);
  207.     planes[2].dist = DotProduct(planes[2].normal, cameraLocation);
  208.     planes[3].dist = DotProduct(planes[3].normal, cameraLocation);
  209.   }
  210.  
  211.   changedMatrix = FALSE;
  212. }
  213.  
  214. /*
  215.  * we transform the world-axis-vector to the local-axis-vector
  216.  * without take attention to the camera-position
  217.  */
  218. void transform_vector(vec_t *out, vec_t *in)
  219. {
  220.   out[0] = DotProduct(viewMatrix[0], in);
  221.   out[1] = DotProduct(viewMatrix[1], in);
  222.   out[2] = DotProduct(viewMatrix[2], in);
  223. }
  224.  
  225. /*
  226.  * we transform the world-axis-vector to the local-axis-vector
  227.  * with previous camera-position correction
  228.  */
  229. void transform_point_raw(vec_t *out, vec_t *in)
  230. {
  231.   vec3_t temp;
  232.  
  233.   VectorSubtract(in, translate, temp);
  234.   out[0] = DotProduct(viewMatrix[0], temp);
  235.   out[1] = DotProduct(viewMatrix[1], temp);
  236.   out[2] = DotProduct(viewMatrix[2], temp);
  237. }
  238.  
  239. static void project_point(point_3d * p)
  240. {
  241.   if (p->p[2] >= nearClip) {
  242.     double div = 1.0 / p->p[2];
  243.  
  244.     p->sx = FLOAT_TO_FIX( p->p[0] * div + xCenter);
  245.     p->sy = FLOAT_TO_FIX(-p->p[1] * div + yCenter);
  246.   }
  247. }
  248.  
  249. static void code_point(point_3d * p)
  250. {
  251.   if (p->p[2] >= nearCode) {
  252.     /* if point is far enough away, code in 2d from fixedpoint (faster) */
  253.     if (p->sx < clipXLow)
  254.       p->ccodes = CC_OFF_LEFT;
  255.     else if (p->sx > clipXHigh)
  256.       p->ccodes = CC_OFF_RIGHT;
  257.     else
  258.       p->ccodes = 0;
  259.     if (p->sy < clipYLow)
  260.       p->ccodes |= CC_OFF_TOP;
  261.     else if (p->sy > clipYHigh)
  262.       p->ccodes |= CC_OFF_BOT;
  263.   }
  264.   else {
  265.     p->ccodes = (p->p[2] > 0) ? 0 : CC_BEHIND;
  266.     if (p->p[0] * clipScaleX < -p->p[2])
  267.       p->ccodes |= CC_OFF_LEFT;
  268.     if (p->p[0] * clipScaleX >  p->p[2])
  269.       p->ccodes |= CC_OFF_RIGHT;
  270.     if (p->p[1] * clipScaleY >  p->p[2])
  271.       p->ccodes |= CC_OFF_TOP;
  272.     if (p->p[1] * clipScaleY < -p->p[2])
  273.       p->ccodes |= CC_OFF_BOT;
  274.   }
  275. }
  276.  
  277. void transform_point(point_3d * p, vec_t *v)
  278. {
  279.   transform_point_raw(p->p, v);
  280.   project_point(p);
  281.   code_point(p);
  282. }
  283.  
  284. void transform_rotated_point(point_3d * p)
  285. {
  286.   project_point(p);
  287.   code_point(p);
  288. }
  289.