home *** CD-ROM | disk | FTP | other *** search
- #define LIBQDISPLAY_CORE
- #include "../include/libqdisplay.h"
-
- #define DOT_VEC_DBL(a1,a2,a3,b1,b2,b3) ((float)(a1*b1 + a2*b2 + a3*b3))
-
- float clipScaleX, clipScaleY, incSpeed, maxSpeed, decSpeed;
- vec3_t cameraLocation, currentSpeed;
- bool changedLocation, changedAngles, changedMatrix;
- angvec cameraAngles;
- struct extplane planes[4];
- float xCenter, yCenter;
-
- static float mainMatrix[3][3], viewMatrix[3][3], translate[3];
- static int clipXLow, clipXHigh, clipYLow, clipYHigh;
- static float projScaleX, projScaleY;
- static float nearClip = 0.01, nearCode = 16.0;
-
- void set_clip_values(int width, int height)
- {
- clipXLow = -32768;
- clipXHigh = (width << 16) - 32768;
- clipYLow = -32768;
- clipYHigh = (height << 16) - 32768;
- projScaleX = (width >> 1);
- projScaleY = (projScaleX * height) / (width * 0.75);
- xCenter = -0.5 + (width >> 1);
- yCenter = -0.5 + (height >> 1);
- clipScaleX = 1.0 / (width >> 1);
- clipScaleY = 1.0 / (height >> 1);
- incSpeed = width * (2 / 91.5);
- maxSpeed = width * (2 / 22.5);
- decSpeed = incSpeed * (2 / 1.5);
- }
-
- void set_view_info(void)
- {
- /* compute rotation matrix */
- if (changedAngles) {
- /*
- * the main matrix is the representation of the three vectors
- * that makes the lokal coordinate-system, called local-axis
- */
- if (!cameraAngles.ty) {
- mainMatrix[0][0] = cosTable[cameraAngles.tz];
- mainMatrix[0][1] = -sinTable[cameraAngles.tz];
- mainMatrix[0][2] = 0;
- mainMatrix[1][0] = sinTable[cameraAngles.tz] * sinTable[cameraAngles.tx];
- mainMatrix[1][1] = cosTable[cameraAngles.tz] * sinTable[cameraAngles.tx];
- mainMatrix[1][2] = cosTable[cameraAngles.tx];
- mainMatrix[2][0] = sinTable[cameraAngles.tz] * cosTable[cameraAngles.tx];
- mainMatrix[2][1] = cosTable[cameraAngles.tz] * cosTable[cameraAngles.tx];
- mainMatrix[2][2] = -sinTable[cameraAngles.tx];
-
- changedAngles = FALSE;
- }
- else {
- mainMatrix[0][0] = cosTable[cameraAngles.tz] * cosTable[cameraAngles.ty] + sinTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * sinTable[cameraAngles.ty];
- mainMatrix[0][1] = -sinTable[cameraAngles.tz] * cosTable[cameraAngles.ty] + cosTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * sinTable[cameraAngles.ty];
- mainMatrix[0][2] = cosTable[cameraAngles.tx] * sinTable[cameraAngles.ty];
- mainMatrix[1][0] = cosTable[cameraAngles.tz] * -sinTable[cameraAngles.ty] + sinTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * cosTable[cameraAngles.ty];
- mainMatrix[1][1] = -sinTable[cameraAngles.tz] * -sinTable[cameraAngles.ty] + cosTable[cameraAngles.tz] * sinTable[cameraAngles.tx] * cosTable[cameraAngles.ty];
- mainMatrix[1][2] = cosTable[cameraAngles.tx] * cosTable[cameraAngles.ty];
- mainMatrix[2][0] = sinTable[cameraAngles.tz] * cosTable[cameraAngles.tx];
- mainMatrix[2][1] = cosTable[cameraAngles.tz] * cosTable[cameraAngles.tx];
- mainMatrix[2][2] = -sinTable[cameraAngles.tx];
-
- if ((cameraAngles.ty > 1) && (cameraAngles.ty <= 45))
- cameraAngles.ty -= ((cameraAngles.ty - 0) / 6) + 1;
- else if ((cameraAngles.ty >= 315) && (cameraAngles.ty < 359))
- cameraAngles.ty += ((360 - cameraAngles.ty) / 6) + 1;
- else
- cameraAngles.ty = 0;
- }
- memcpy(viewMatrix, mainMatrix, sizeof(viewMatrix));
- /*
- * the view-matrix is the perspective correction of the main
- * matrix in advance of the screen-ratio
- */
- viewMatrix[0][0] *= projScaleX;
- viewMatrix[0][1] *= projScaleX;
- viewMatrix[0][2] *= projScaleX;
- viewMatrix[1][0] *= projScaleY;
- viewMatrix[1][1] *= projScaleY;
- viewMatrix[1][2] *= projScaleY;
- /*viewMatrix[2][0] *= projScaleZ; */
- /*viewMatrix[2][1] *= projScaleZ; */
- /*viewMatrix[2][2] *= projScaleZ; */
-
- changedMatrix = TRUE;
- }
-
- if (changedLocation) {
- /*
- * so (1,0,0) in camera space maps to viewMatrix[0] in world space.
- * thus we multiply on the right by a worldspace vector to transform
- * it to camera space.
- * now, to account for translation, we just subtract the camera
- * Center before multiplying
- */
- translate[0] = cameraLocation[0];
- translate[1] = cameraLocation[1];
- translate[2] = cameraLocation[2];
-
- if ((currentSpeed[0] != 0) || (currentSpeed[2] != 0)) {
- cameraLocation[0] += -mainMatrix[0][1] * currentSpeed[0];
- cameraLocation[1] += mainMatrix[0][0] * currentSpeed[0];
- cameraLocation[2] += mainMatrix[1][2] * currentSpeed[2];
-
- if (currentSpeed[0] > decSpeed)
- currentSpeed[0] -= decSpeed;
- else if (currentSpeed[0] < -decSpeed)
- currentSpeed[0] += decSpeed;
- else
- currentSpeed[0] = 0.0;
-
- if (currentSpeed[2] > decSpeed)
- currentSpeed[2] -= decSpeed;
- else if (currentSpeed[2] < -decSpeed)
- currentSpeed[2] += decSpeed;
- else
- currentSpeed[2] = 0.0;
- }
- else
- changedLocation = FALSE; /* release only if we really stop */
- }
- }
-
- float dist2_from_viewer(vec_t *in)
- {
- vec3_t temp;
-
- VectorSubtract(in, cameraLocation, temp);
-
- return VectorDist(temp);
- }
-
- #if 0 /* this works if IEEE and, sizeof(float) == sizeof(int) */
- #define FLOAT_POSITIVE(x) (*((int *)(&x)) >= 0)
- #else
- #define FLOAT_POSITIVE(x) ((x) >= 0)
- #endif
-
- /*
- * the view-frustum are four planes that shoot from the camera-point
- * in a direction that is the visible area
- * everything between the four planes (the frustum) is visible
- * this is called frustum-culling
- *
- * we form the four planes with four vectors (-1,0,1), (1,0,1), (0,1,1), (0,-1,1)
- * with the cameras position as origin
- * we use the hesse-normal-form
- *
- * in screen-space the z-coordinate is tht one that goes into the monitor
- * y- and x-coordinate are the same as the screens coordinate, (0,0,0) is exactly
- * in the middle of and on the screen
- */
- void compute_view_frustrum(void)
- {
- if (changedMatrix) {
- /*
- * why are the normals not normalized? (is the mainMatrix normalized?) the length are sqrt(2) instead of 1
- * what means the dists?
- * what is the direction of the normals (into the screen-space or out of?)?
- */
- planes[0].positive[0] = FLOAT_POSITIVE(
- planes[0].normal[0] = -mainMatrix[0][0] + mainMatrix[2][0]);
- planes[0].positive[1] = FLOAT_POSITIVE(
- planes[0].normal[1] = -mainMatrix[0][1] + mainMatrix[2][1]);
- planes[0].positive[2] = FLOAT_POSITIVE(
- planes[0].normal[2] = -mainMatrix[0][2] + mainMatrix[2][2]);
- planes[1].positive[0] = FLOAT_POSITIVE(
- planes[1].normal[0] = mainMatrix[0][0] + mainMatrix[2][0]);
- planes[1].positive[1] = FLOAT_POSITIVE(
- planes[1].normal[1] = mainMatrix[0][1] + mainMatrix[2][1]);
- planes[1].positive[2] = FLOAT_POSITIVE(
- planes[1].normal[2] = mainMatrix[0][2] + mainMatrix[2][2]);
- planes[2].positive[0] = FLOAT_POSITIVE(
- planes[2].normal[0] = mainMatrix[1][0] + mainMatrix[2][0]);
- planes[2].positive[1] = FLOAT_POSITIVE(
- planes[2].normal[1] = mainMatrix[1][1] + mainMatrix[2][1]);
- planes[2].positive[2] = FLOAT_POSITIVE(
- planes[2].normal[2] = mainMatrix[1][2] + mainMatrix[2][2]);
- planes[3].positive[0] = FLOAT_POSITIVE(
- planes[3].normal[0] = -mainMatrix[1][0] + mainMatrix[2][0]);
- planes[3].positive[1] = FLOAT_POSITIVE(
- planes[3].normal[1] = -mainMatrix[1][1] + mainMatrix[2][1]);
- planes[3].positive[2] = FLOAT_POSITIVE(
- planes[3].normal[2] = -mainMatrix[1][2] + mainMatrix[2][2]);
- }
-
- if (changedMatrix || changedLocation) {
- /*
- * we move the planes to the cameras position, up to now the distance to
- * the origin is 0 so
- * DotProduct(frustumNormal, point) + frustumDistance
- * gives
- * DotProduct(frustumNormal, point)
- *
- * why do we move it to cameras position?
- * why is the dist not -DotProduct(frustumNormal, point) as it should be?
- * is this correct??? I think the length of the cameras vector must
- * be the distance for all planes[?].dist, and for all equal
- * VectorLength(cameraLocation)
- */
- planes[0].dist = DotProduct(planes[0].normal, cameraLocation);
- planes[1].dist = DotProduct(planes[1].normal, cameraLocation);
- planes[2].dist = DotProduct(planes[2].normal, cameraLocation);
- planes[3].dist = DotProduct(planes[3].normal, cameraLocation);
- }
-
- changedMatrix = FALSE;
- }
-
- /*
- * we transform the world-axis-vector to the local-axis-vector
- * without take attention to the camera-position
- */
- void transform_vector(vec_t *out, vec_t *in)
- {
- out[0] = DotProduct(viewMatrix[0], in);
- out[1] = DotProduct(viewMatrix[1], in);
- out[2] = DotProduct(viewMatrix[2], in);
- }
-
- /*
- * we transform the world-axis-vector to the local-axis-vector
- * with previous camera-position correction
- */
- void transform_point_raw(vec_t *out, vec_t *in)
- {
- vec3_t temp;
-
- VectorSubtract(in, translate, temp);
- out[0] = DotProduct(viewMatrix[0], temp);
- out[1] = DotProduct(viewMatrix[1], temp);
- out[2] = DotProduct(viewMatrix[2], temp);
- }
-
- static void project_point(point_3d * p)
- {
- if (p->p[2] >= nearClip) {
- double div = 1.0 / p->p[2];
-
- p->sx = FLOAT_TO_FIX( p->p[0] * div + xCenter);
- p->sy = FLOAT_TO_FIX(-p->p[1] * div + yCenter);
- }
- }
-
- static void code_point(point_3d * p)
- {
- if (p->p[2] >= nearCode) {
- /* if point is far enough away, code in 2d from fixedpoint (faster) */
- if (p->sx < clipXLow)
- p->ccodes = CC_OFF_LEFT;
- else if (p->sx > clipXHigh)
- p->ccodes = CC_OFF_RIGHT;
- else
- p->ccodes = 0;
- if (p->sy < clipYLow)
- p->ccodes |= CC_OFF_TOP;
- else if (p->sy > clipYHigh)
- p->ccodes |= CC_OFF_BOT;
- }
- else {
- p->ccodes = (p->p[2] > 0) ? 0 : CC_BEHIND;
- if (p->p[0] * clipScaleX < -p->p[2])
- p->ccodes |= CC_OFF_LEFT;
- if (p->p[0] * clipScaleX > p->p[2])
- p->ccodes |= CC_OFF_RIGHT;
- if (p->p[1] * clipScaleY > p->p[2])
- p->ccodes |= CC_OFF_TOP;
- if (p->p[1] * clipScaleY < -p->p[2])
- p->ccodes |= CC_OFF_BOT;
- }
- }
-
- void transform_point(point_3d * p, vec_t *v)
- {
- transform_point_raw(p->p, v);
- project_point(p);
- code_point(p);
- }
-
- void transform_rotated_point(point_3d * p)
- {
- project_point(p);
- code_point(p);
- }
-