#include <math.h>
#include "PEXlib.h"
#include "PEXlibint.h"
#include "pl_util.h"
#include "pl_oc_util.h"
int
PEXRotate (axis, angle, matrix_return)
INPUT int axis;
INPUT double angle;
OUTPUT PEXMatrix matrix_return;
{
double sine;
double cosine;
sine = sin (angle);
cosine = cos (angle);
switch (axis)
{
case PEXXAxis:
matrix_return[0][0] = 1.0;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = 0.0;
matrix_return[0][3] = 0.0;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = cosine;
matrix_return[1][2] = -sine;
matrix_return[1][3] = 0.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = sine;
matrix_return[2][2] = cosine;
matrix_return[2][3] = 0.0;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
break;
case PEXYAxis:
matrix_return[0][0] = cosine;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = sine;
matrix_return[0][3] = 0.0;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = 1.0;
matrix_return[1][2] = 0.0;
matrix_return[1][3] = 0.0;
matrix_return[2][0] = -sine;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = cosine;
matrix_return[2][3] = 0.0;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
break;
case PEXZAxis:
matrix_return[0][0] = cosine;
matrix_return[0][1] = -sine;
matrix_return[0][2] = 0.0;
matrix_return[0][3] = 0.0;
matrix_return[1][0] = sine;
matrix_return[1][1] = cosine;
matrix_return[1][2] = 0.0;
matrix_return[1][3] = 0.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
matrix_return[2][3] = 0.0;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
break;
default:
return (PEXBadAxis);
}
return (0);
}
void
PEXRotate2D (angle, matrix_return)
INPUT double angle;
OUTPUT PEXMatrix3x3 matrix_return;
{
double sine;
double cosine;
sine = sin (angle);
cosine = cos (angle);
matrix_return[0][0] = cosine;
matrix_return[0][1] = -sine;
matrix_return[0][2] = 0.0;
matrix_return[1][0] = sine;
matrix_return[1][1] = cosine;
matrix_return[1][2] = 0.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
}
int
PEXRotateGeneral (point1, point2, angle, matrix_return)
INPUT PEXCoord *point1;
INPUT PEXCoord *point2;
INPUT double angle;
OUTPUT PEXMatrix matrix_return;
{
PEXMatrix preMatrix, calcMatrix, postMatrix, tempMatrix;
PEXCoord diff, rot;
float dist, temp, s;
double sine, cosine;
int i, j;
preMatrix[0][0] = 1.0;
preMatrix[0][1] = 0.0;
preMatrix[0][2] = 0.0;
preMatrix[0][3] = point1->x;
preMatrix[1][0] = 0.0;
preMatrix[1][1] = 1.0;
preMatrix[1][2] = 0.0;
preMatrix[1][3] = point1->y;
preMatrix[2][0] = 0.0;
preMatrix[2][1] = 0.0;
preMatrix[2][2] = 1.0;
preMatrix[2][3] = point1->z;
preMatrix[3][0] = 0.0;
preMatrix[3][1] = 0.0;
preMatrix[3][2] = 0.0;
preMatrix[3][3] = 1.0;
postMatrix[0][0] = 1.0;
postMatrix[0][1] = 0.0;
postMatrix[0][2] = 0.0;
postMatrix[0][3] = -(point1->x);
postMatrix[1][0] = 0.0;
postMatrix[1][1] = 1.0;
postMatrix[1][2] = 0.0;
postMatrix[1][3] = -(point1->y);
postMatrix[2][0] = 0.0;
postMatrix[2][1] = 0.0;
postMatrix[2][2] = 1.0;
postMatrix[2][3] = -(point1->z);
postMatrix[3][0] = 0.0;
postMatrix[3][1] = 0.0;
postMatrix[3][2] = 0.0;
postMatrix[3][3] = 1.0;
diff.x = point2->x - point1->x;
diff.y = point2->y - point1->y;
diff.z = point2->z - point1->z;
dist = sqrt (diff.x * diff.x + diff.y * diff.y + diff.z * diff.z);
if (NEAR_ZERO (dist))
return (PEXBadAxis);
rot.x = diff.x = diff.x / dist;
rot.y = diff.y = diff.y / dist;
rot.z = diff.z = diff.z / dist;
rot.x = rot.x * rot.x;
rot.y = rot.y * rot.y;
rot.z = rot.z * rot.z;
cosine = cos (angle);
sine = sin (angle);
calcMatrix[0][0] = rot.x + cosine * (1.0 - rot.x);
calcMatrix[1][1] = rot.y + cosine * (1.0 - rot.y);
calcMatrix[2][2] = rot.z + cosine * (1.0 - rot.z);
temp = diff.x * diff.y * (1.0 - cosine);
s = sine * diff.z;
calcMatrix[1][0] = temp - s;
calcMatrix[0][1] = temp + s;
temp = diff.x * diff.z * (1.0 - cosine);
s = sine * diff.y;
calcMatrix[2][0] = temp + s;
calcMatrix[0][2] = temp - s;
temp = diff.y * diff.z * (1.0 - cosine);
s = sine * diff.x;
calcMatrix[2][1] = temp - s;
calcMatrix[1][2] = temp + s;
calcMatrix[0][3] = 0.0;
calcMatrix[1][3] = 0.0;
calcMatrix[2][3] = 0.0;
calcMatrix[3][0] = 0.0;
calcMatrix[3][1] = 0.0;
calcMatrix[3][2] = 0.0;
calcMatrix[3][3] = 1.0;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
tempMatrix[i][j] = preMatrix[i][0] * calcMatrix[0][j] +
preMatrix[i][1] * calcMatrix[1][j] +
preMatrix[i][2] * calcMatrix[2][j] +
preMatrix[i][3] * calcMatrix[3][j];
}
}
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
matrix_return[i][j] = tempMatrix[i][0] * postMatrix[0][j] +
tempMatrix[i][1] * postMatrix[1][j] +
tempMatrix[i][2] * postMatrix[2][j] +
tempMatrix[i][3] * postMatrix[3][j];
}
}
return (0);
}
void
PEXScale (scale_vector, matrix_return)
INPUT PEXVector *scale_vector;
OUTPUT PEXMatrix matrix_return;
{
matrix_return[0][0] = scale_vector->x;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = 0.0;
matrix_return[0][3] = 0.0;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = scale_vector->y;
matrix_return[1][2] = 0.0;
matrix_return[1][3] = 0.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = scale_vector->z;
matrix_return[2][3] = 0.0;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
}
void
PEXScale2D (scale_vector, matrix_return)
INPUT PEXVector2D *scale_vector;
OUTPUT PEXMatrix3x3 matrix_return;
{
matrix_return[0][0] = scale_vector->x;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = 0.0;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = scale_vector->y;
matrix_return[1][2] = 0.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
}
void
PEXTranslate (trans_vector, matrix_return)
INPUT PEXVector *trans_vector;
OUTPUT PEXMatrix matrix_return;
{
matrix_return[0][0] = 1.0;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = 0.0;
matrix_return[0][3] = trans_vector->x;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = 1.0;
matrix_return[1][2] = 0.0;
matrix_return[1][3] = trans_vector->y;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
matrix_return[2][3] = trans_vector->z;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
}
void
PEXTranslate2D (trans_vector, matrix_return)
INPUT PEXVector2D *trans_vector;
OUTPUT PEXMatrix3x3 matrix_return;
{
matrix_return[0][0] = 1.0;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = trans_vector->x;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = 1.0;
matrix_return[1][2] = trans_vector->y;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
}
void
PEXMatrixMult (matrix1, matrix2, matrix_return)
INPUT PEXMatrix matrix1;
INPUT PEXMatrix matrix2;
OUTPUT PEXMatrix matrix_return;
{
register float *r;
register int i;
if ((matrix_return != matrix1) && (matrix_return != matrix2))
{
for (i = 0; i < 4; i++)
{
r = matrix1[i];
matrix_return[i][0] = r[0] * matrix2[0][0] + r[1] * matrix2[1][0] +
r[2] * matrix2[2][0] + r[3] * matrix2[3][0];
matrix_return[i][1] = r[0] * matrix2[0][1] + r[1] * matrix2[1][1] +
r[2] * matrix2[2][1] + r[3] * matrix2[3][1];
matrix_return[i][2] = r[0] * matrix2[0][2] + r[1] * matrix2[1][2] +
r[2] * matrix2[2][2] + r[3] * matrix2[3][2];
matrix_return[i][3] = r[0] * matrix2[0][3] + r[1] * matrix2[1][3] +
r[2] * matrix2[2][3] + r[3] * matrix2[3][3];
}
}
else
{
register float *src, *dst;
PEXMatrix temp;
for (i = 0; i < 4; i++)
{
r = matrix1[i];
temp[i][0] = r[0] * matrix2[0][0] + r[1] * matrix2[1][0] +
r[2] * matrix2[2][0] + r[3] * matrix2[3][0];
temp[i][1] = r[0] * matrix2[0][1] + r[1] * matrix2[1][1] +
r[2] * matrix2[2][1] + r[3] * matrix2[3][1];
temp[i][2] = r[0] * matrix2[0][2] + r[1] * matrix2[1][2] +
r[2] * matrix2[2][2] + r[3] * matrix2[3][2];
temp[i][3] = r[0] * matrix2[0][3] + r[1] * matrix2[1][3] +
r[2] * matrix2[2][3] + r[3] * matrix2[3][3];
}
src = (float *) temp;
dst = (float *) matrix_return;
for (i = 0; i < 16; i++)
*dst++ = *src++;
}
}
void
PEXMatrixMult2D (matrix1, matrix2, matrix_return)
INPUT PEXMatrix3x3 matrix1;
INPUT PEXMatrix3x3 matrix2;
OUTPUT PEXMatrix3x3 matrix_return;
{
register float *r;
register int i;
if ((matrix_return != matrix1) && (matrix_return != matrix2))
{
for (i = 0; i < 3; i++)
{
r = matrix1[i];
matrix_return[i][0] = r[0] * matrix2[0][0] + r[1] * matrix2[1][0] +
r[2] * matrix2[2][0];
matrix_return[i][1] = r[0] * matrix2[0][1] + r[1] * matrix2[1][1] +
r[2] * matrix2[2][1];
matrix_return[i][2] = r[0] * matrix2[0][2] + r[1] * matrix2[1][2] +
r[2] * matrix2[2][2];
}
}
else
{
register float *src, *dst;
PEXMatrix3x3 temp;
for (i = 0; i < 3; i++)
{
r = matrix1[i];
temp[i][0] = r[0] * matrix2[0][0] + r[1] * matrix2[1][0] +
r[2] * matrix2[2][0];
temp[i][1] = r[0] * matrix2[0][1] + r[1] * matrix2[1][1] +
r[2] * matrix2[2][1];
temp[i][2] = r[0] * matrix2[0][2] + r[1] * matrix2[1][2] +
r[2] * matrix2[2][2];
}
src = (float *) temp;
dst = (float *) matrix_return;
for (i = 0; i < 9; i++)
*dst++ = *src++;
}
}
void
PEXBuildTransform (fixed_point, trans_vector, angle_x, angle_y, angle_z,
scale_vector, matrix_return)
INPUT PEXCoord *fixed_point;
INPUT PEXVector *trans_vector;
INPUT double angle_x;
INPUT double angle_y;
INPUT double angle_z;
INPUT PEXVector *scale_vector;
OUTPUT PEXMatrix matrix_return;
{
register float cz, sz, cx, sx, cy, sy;
register float *r;
cx = cos (angle_x); sx = sin (angle_x);
cy = cos (angle_y); sy = sin (angle_y);
cz = cos (angle_z); sz = sin (angle_z);
r = matrix_return[0];
r[0] = cz * cy * scale_vector->x;
r[1] = (cz * sx * sy - sz * cx) * scale_vector->y;
r[2] = (cz * sy * cx + sz * sx) * scale_vector->z;
r[3] = trans_vector->x + fixed_point->x -
(r[0] * fixed_point->x + r[1] * fixed_point->y +
r[2] * fixed_point->z);
r = matrix_return[1];
r[0] = sz * cy * scale_vector->x;
r[1] = (sz * sx * sy + cz * cx) * scale_vector->y;
r[2] = (sz * sy * cx - cz * sx) * scale_vector->z;
r[3] = trans_vector->y + fixed_point->y -
(r[0] * fixed_point->x + r[1] * fixed_point->y +
r[2] * fixed_point->z);
r = matrix_return[2];
r[0] = -sy * scale_vector->x;
r[1] = cy * sx * scale_vector->y;
r[2] = cy * cx * scale_vector->z;
r[3] = trans_vector->z + fixed_point->z -
(r[0] * fixed_point->x + r[1] * fixed_point->y +
r[2] * fixed_point->z);
r = matrix_return[3];
r[0] = r[1] = r[2] = 0.0;
r[3] = 1.0;
}
void
PEXBuildTransform2D (fixed_point, trans_vector, angle_z,
scale_vector, matrix_return)
INPUT PEXCoord2D *fixed_point;
INPUT PEXVector2D *trans_vector;
INPUT double angle_z;
INPUT PEXVector2D *scale_vector;
OUTPUT PEXMatrix3x3 matrix_return;
{
register float *r;
register float c, s;
c = cos (angle_z);
s = sin (angle_z);
r = matrix_return[0];
r[0] = c * scale_vector->x;
r[1] = -s * scale_vector->y;
r[2] = trans_vector->x + fixed_point->x -
c * scale_vector->x * fixed_point->x +
s * scale_vector->y * fixed_point->y;
r = matrix_return[1];
r[0] = s * scale_vector->x;
r[1] = c * scale_vector->y;
r[2] = trans_vector->y + fixed_point->y -
(s * scale_vector->x * fixed_point->x +
c * scale_vector->y * fixed_point->y);
r = matrix_return[2];
r[0] = r[1] = 0.0;
r[2] = 1.0;
}
int
PEXViewOrientationMatrix (vrp, vpn, vup, matrix_return)
INPUT PEXCoord *vrp;
INPUT PEXVector *vpn;
INPUT PEXVector *vup;
OUTPUT PEXMatrix matrix_return;
{
float *e1 = matrix_return[0],
*e2 = matrix_return[1],
*e3 = matrix_return[2];
double s, mag_vpn;
if (ZERO_MAG (mag_vpn = MAG_V3 (vpn)))
{
return (PEXBadVector);
}
else if (ZERO_MAG (MAG_V3 (vup)))
{
return (PEXBadVector);
}
else
{
e1[0] = vup->y * vpn->z - vup->z * vpn->y;
e1[1] = vup->z * vpn->x - vup->x * vpn->z;
e1[2] = vup->x * vpn->y - vup->y * vpn->x;
s = sqrt (e1[0] * e1[0] + e1[1] * e1[1] + e1[2] * e1[2]);
if (ZERO_MAG (s))
return (PEXBadVectors);
}
s = 1.0 / s;
e1[0] *= s; e1[1] *= s; e1[2] *= s;
s = 1.0 / mag_vpn;
e3[0] = s * vpn->x; e3[1] = s * vpn->y; e3[2] = s * vpn->z;
e2[0] = e3[1] * e1[2] - e3[2] * e1[1];
e2[1] = e3[2] * e1[0] - e3[0] * e1[2];
e2[2] = e3[0] * e1[1] - e3[1] * e1[0];
e1[3] = -(e1[0] * vrp->x + e1[1] * vrp->y + e1[2] * vrp->z);
e2[3] = -(e2[0] * vrp->x + e2[1] * vrp->y + e2[2] * vrp->z);
e3[3] = -(e3[0] * vrp->x + e3[1] * vrp->y + e3[2] * vrp->z);
matrix_return[3][0] = matrix_return[3][1] = matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
return (0);
}
int
PEXViewOrientationMatrix2D (vrp, vup, matrix_return)
INPUT PEXCoord2D *vrp;
INPUT PEXVector2D *vup;
OUTPUT PEXMatrix3x3 matrix_return;
{
register double s;
if (ZERO_MAG (s = MAG_V2 (vup)))
{
return (PEXBadVector);
}
else
{
s = 1.0 / s;
matrix_return[0][0] = s * vup->y;
matrix_return[0][1] = s * -vup->x;
matrix_return[1][0] = s * vup->x;
matrix_return[1][1] = s * vup->y;
matrix_return[0][2] = -(matrix_return[0][0] * vrp->x +
matrix_return[0][1] * vrp->y);
matrix_return[1][2] = -(matrix_return[1][0] * vrp->x +
matrix_return[1][1] * vrp->y);
matrix_return[2][0] = matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
return (0);
}
}
int
PEXViewMappingMatrix (frame, viewport, perspective, prp, view_plane,
back_plane, front_plane, matrix_return)
INPUT PEXCoord2D *frame;
INPUT PEXNPCSubVolume *viewport;
INPUT int perspective;
INPUT PEXCoord *prp;
INPUT double view_plane;
INPUT double back_plane;
INPUT double front_plane;
OUTPUT PEXMatrix matrix_return;
{
double dx = viewport->max.x - viewport->min.x;
double dy = viewport->max.y - viewport->min.y;
double dz = viewport->max.z - viewport->min.z;
double vvz = front_plane - back_plane;
double sz, sx, sy;
double hx, hy;
double d;
double zf;
float *r;
if (!(frame[0].x < frame[1].x) || !(frame[0].y < frame[1].y))
{
return (PEXBadLimits);
}
else if (!(viewport->min.x < viewport->max.x) ||
!(viewport->min.y < viewport->max.y) ||
!(viewport->min.z <= viewport->max.z))
{
return (PEXBadViewport);
}
else if (NEAR_ZERO (vvz) && viewport->min.z != viewport->max.z)
{
return (PEXBadPlanes);
}
else if (perspective && prp->z < front_plane && prp->z > back_plane)
{
return (PEXBadPlanes);
}
else if (prp->z == view_plane)
{
return (PEXBadPRP);
}
else if (front_plane < back_plane)
{
return (PEXBadPlanes);
}
else if (!IN_RANGE (0.0, 1.0, viewport->min.x) ||
!IN_RANGE (0.0, 1.0, viewport->max.x) ||
!IN_RANGE (0.0, 1.0, viewport->min.y) ||
!IN_RANGE (0.0, 1.0, viewport->max.y) ||
!IN_RANGE (0.0, 1.0, viewport->min.z) ||
!IN_RANGE (0.0, 1.0, viewport->max.z))
{
return (PEXBadViewport);
}
if (perspective)
{
d = prp->z - view_plane;
sz = 1.0 / (prp->z - back_plane);
sx = sz * d * 2.0 / (frame[1].x - frame[0].x);
sy = sz * d * 2.0 / (frame[1].y - frame[0].y);
hx = (prp->x - 0.5 * (frame[0].x + frame[1].x)) / d;
hy = (prp->y - 0.5 * (frame[0].y + frame[1].y)) / d;
r = matrix_return[0];
r[0] = 0.5 * dx * sx;
r[1] = 0.0;
r[2] = -(0.5 * dx * (sx * hx + sz) + sz * viewport->min.x);
r[3] = -(0.5 * dx * sx * (prp->x - hx * prp->z) -
sz * prp->z * (0.5 * dx + viewport->min.x));
r = matrix_return[1];
r[0] = 0.0;
r[1] = 0.5 * dy * sy;
r[2] = -(0.5 * dy * (sy * hy + sz) + sz * viewport->min.y);
r[3] = -(0.5 * dy * sy * (prp->y - hy * prp->z) -
sz * prp->z * (0.5 * dy + viewport->min.y));
r = matrix_return[2];
r[0] = r[1] = 0.0;
zf = (prp->z - front_plane) / (prp->z - back_plane);
if (NEAR_ZERO (1.0 - zf))
{
r[2] = 0.0;
r[3] = sz * prp->z * viewport->max.z;
}
else
{
r[2] = sz * ((dz / (1.0 - zf)) - viewport->max.z);
r[3] = sz * prp->z * viewport->max.z -
(dz / (1.0 - zf)) * (sz * prp->z - zf);
}
r = matrix_return[3];
r[0] = r[1] = 0.0;
r[2] = -sz;
r[3] = sz * prp->z;
}
else
{
sx = dx / (frame[1].x - frame[0].x);
sy = dy / (frame[1].y - frame[0].y);
hx = (prp->x - 0.5 * (frame[0].x + frame[1].x)) /
(view_plane - prp->z);
hy = (prp->y - 0.5 * (frame[0].y + frame[1].y)) /
(view_plane - prp->z);
r = matrix_return[0];
r[0] = sx;
r[1] = 0.0;
r[2] = sx * hx;
r[3] = viewport->min.x - sx * (hx * view_plane + frame[0].x);
r = matrix_return[1];
r[0] = 0.0;
r[1] = sy;
r[2] = sy * hy;
r[3] = viewport->min.y - sy * (hy * view_plane + frame[0].y);
r = matrix_return[2];
r[0] = r[1] = 0.0;
if (NEAR_ZERO (vvz))
r[2] = 0.0;
else
r[2] = dz / vvz;
r[3] = viewport->min.z - r[2] * back_plane;
r = matrix_return[3];
r[0] = r[1] = r[2] = 0.0;
r[3] = 1.0;
}
return (0);
}
int
PEXViewMappingMatrix2D (frame, viewport, matrix_return)
INPUT PEXCoord2D *frame;
INPUT PEXCoord2D *viewport;
OUTPUT PEXMatrix3x3 matrix_return;
{
register float sx, sy;
if (!(frame[0].x < frame[1].x) || !(frame[0].y < frame[1].y))
{
return (PEXBadLimits);
}
else if (!(viewport[0].x < viewport[1].x) ||
!(viewport[0].y < viewport[1].y))
{
return (PEXBadViewport);
}
else if (!IN_RANGE (0.0, 1.0, viewport[0].x) ||
!IN_RANGE (0.0, 1.0, viewport[1].x) ||
!IN_RANGE (0.0, 1.0, viewport[0].y) ||
!IN_RANGE (0.0, 1.0, viewport[1].y))
{
return (PEXBadViewport);
}
sx = (viewport[1].x - viewport[0].x) / (frame[1].x - frame[0].x);
sy = (viewport[1].y - viewport[0].y) / (frame[1].y - frame[0].y);
matrix_return[0][0] = sx;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = sx * (-frame[0].x + viewport[0].x);
matrix_return[1][0] = 0.0;
matrix_return[1][1] = sy;
matrix_return[1][2] = sy * (-frame[0].y + viewport[0].y);
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
return (0);
}
int
PEXLookAtViewMatrix (from, to, up, matrix_return)
INPUT PEXCoord *from;
INPUT PEXCoord *to;
INPUT PEXVector *up;
OUTPUT PEXMatrix matrix_return;
{
PEXCoord a, b, c, d, e, f, t;
float magnitude;
float dot_product;
a.x = from->x - to->x;
a.y = from->y - to->y;
a.z = from->z - to->z;
magnitude = sqrt (a.x * a.x + a.y * a.y + a.z * a.z);
if (ZERO_MAG (magnitude))
{
return (PEXBadVectors);
}
b.x = a.x / magnitude;
b.y = a.y / magnitude;
b.z = a.z / magnitude;
c.x = up->x;
c.y = up->y;
c.z = up->z;
dot_product = (c.x * b.x) + (c.y * b.y) + (c.z * b.z);
d.x = c.x - (dot_product * b.x);
d.y = c.y - (dot_product * b.y);
d.z = c.z - (dot_product * b.z);
magnitude = sqrt (d.x * d.x + d.y * d.y + d.z * d.z);
if (ZERO_MAG (magnitude))
{
c.x = 0.0;
c.y = 1.0;
c.z = 0.0;
dot_product = b.y;
d.x = -(dot_product * b.x);
d.y = 1.0 - (dot_product * b.y);
d.z = -(dot_product * b.z);
magnitude = sqrt (d.x * d.x + d.y * d.y + d.z * d.z);
if (ZERO_MAG (magnitude))
{
c.x = 0.0;
c.y = 0.0;
c.z = 1.0;
dot_product = b.z;
d.x = -(dot_product * b.x);
d.y = -(dot_product * b.y);
d.z = 1.0 -(dot_product * b.z);
magnitude = sqrt (d.x * d.x + d.y * d.y + d.z * d.z);
}
}
e.x = d.x / magnitude;
e.y = d.y / magnitude;
e.z = d.z / magnitude;
f.x = (e.y * b.z) - (b.y * e.z);
f.y = (e.z * b.x) - (b.z * e.x);
f.z = (e.x * b.y) - (b.x * e.y);
matrix_return[0][0] = f.x;
matrix_return[0][1] = f.y;
matrix_return[0][2] = f.z;
matrix_return[1][0] = e.x;
matrix_return[1][1] = e.y;
matrix_return[1][2] = e.z;
matrix_return[2][0] = b.x;
matrix_return[2][1] = b.y;
matrix_return[2][2] = b.z;
t.x = (-to->x * f.x) + (-to->y * f.y) + (-to->z * f.z);
t.y = (-to->x * e.x) + (-to->y * e.y) + (-to->z * e.z);
t.z = (-to->x * b.x) + (-to->y * b.y) + (-to->z * b.z);
matrix_return[0][3] = t.x;
matrix_return[1][3] = t.y;
matrix_return[2][3] = t.z;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
return (0);
}
int
PEXPolarViewMatrix (from, distance, azimuth, altitude, twist, matrix_return)
INPUT PEXCoord *from;
INPUT double distance;
INPUT double azimuth;
INPUT double altitude;
INPUT double twist;
OUTPUT PEXMatrix matrix_return;
{
PEXCoord trans;
float cost;
float sint;
float cosaz;
float sinaz;
float cosalt;
float sinalt;
if (distance <= ZERO_TOLERANCE)
{
return (PEXBadDistance);
}
cost = cos (twist);
sint = sin (twist);
cosaz = cos (-azimuth);
sinaz = sin (-azimuth);
cosalt = cos (-altitude);
sinalt = sin (-altitude);
matrix_return[0][0] = cost * cosaz + (-sint) * (-sinalt) * (-sinaz);
matrix_return[0][1] = (-sint) * cosalt;
matrix_return[0][2] = cost * sinaz + (-sint) * (-sinalt) * cosaz;
matrix_return[1][0] = sint * cosaz + cost * (-sinalt) * (-sinaz);
matrix_return[1][1] = cost * cosalt;
matrix_return[1][2] = sint * sinaz + cost * (-sinalt) * cosaz;
matrix_return[2][0] = cosalt * (-sinaz);
matrix_return[2][1] = sinalt;
matrix_return[2][2] = cosalt * cosaz;
trans.x = -from->x * matrix_return[0][0] + -from->y * matrix_return[0][1] +
-from->z * matrix_return[0][2];
trans.y = -from->x * matrix_return[1][0] + -from->y * matrix_return[1][1] +
-from->z * matrix_return[1][2];
trans.z = -from->x * matrix_return[2][0] + -from->y * matrix_return[2][1] +
-from->z * matrix_return[2][2];
matrix_return[0][3] = trans.x;
matrix_return[1][3] = trans.y;
matrix_return[2][3] = trans.z + distance;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
return (0);
}
int
PEXOrthoProjMatrix (height, aspect, near_plane, far_plane, matrix_return)
INPUT double height;
INPUT double aspect;
INPUT double near_plane;
INPUT double far_plane;
OUTPUT PEXMatrix matrix_return;
{
float width;
float depth;
width = height * aspect;
depth = near_plane - far_plane;
if (NEAR_ZERO (depth) || NEAR_ZERO (width) || NEAR_ZERO (height))
{
return (PEXBadLimits);
}
matrix_return[0][0] = 1.0 / width;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = 0.0;
matrix_return[0][3] = 0.5;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = 1.0 / height;
matrix_return[1][2] = 0.0;
matrix_return[1][3] = 0.5;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0 / depth;
matrix_return[2][3] = 1.0 - (near_plane / depth);
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
return (0);
}
int
PEXPerspProjMatrix (fovy, distance, aspect, near_plane, far_plane, matrix_return)
INPUT double fovy;
INPUT double distance;
INPUT double aspect;
INPUT double near_plane;
INPUT double far_plane;
OUTPUT PEXMatrix matrix_return;
{
double fovy2;
double c_hy;
double s_hy;
float height;
float depth;
float width;
float eye_distance;
if (near_plane <= far_plane || NEAR_ZERO (fovy) ||
NEAR_ZERO (aspect) || distance <= near_plane)
{
return (PEXBadLimits);
}
if ((fovy > 3.140) || (fovy < -3.140))
{
fovy2 = 3.140 / 2.0;
}
else if (fovy < 0.0)
{
fovy2 = -fovy / 2.0;
}
else
{
fovy2 = fovy / 2.0;
}
c_hy = cos (fovy2);
s_hy = sin (fovy2);
eye_distance = distance - near_plane;
height = 2.0 * eye_distance * (s_hy / c_hy);
depth = near_plane - far_plane;
width = height * aspect;
matrix_return[0][0] = 1.0 / width;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = -1.0 / (2.0 * eye_distance);
matrix_return[0][3] = (1.0 + (near_plane / eye_distance)) / 2.0;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = 1.0 / height;
matrix_return[1][2] = -1.0 / (2.0 * eye_distance);
matrix_return[1][3] = (1.0 + (near_plane / eye_distance)) / 2.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0 / depth;
matrix_return[2][3] = -far_plane / depth;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = -1.0 / eye_distance;
matrix_return[3][3] = 1.0 + (near_plane / eye_distance);
return (0);
}
int
PEXTransformPoints (mat, count, points, points_return)
INPUT PEXMatrix mat;
INPUT int count;
INPUT PEXCoord *points;
OUTPUT PEXCoord *points_return;
{
register PEXCoord *point_in = points;
register PEXCoord *point_out = points_return;
register int i;
PEXCoord temp;
int status = 0;
if (NEAR_ZERO (mat[3][0]) && NEAR_ZERO (mat[3][1]) &&
NEAR_ZERO (mat[3][2]) && NEAR_ZERO (mat[3][3] - 1.0))
{
for (i = 0; i < count; i++, point_in++, point_out++)
{
temp.x = mat[0][0] * point_in->x +
mat[0][1] * point_in->y +
mat[0][2] * point_in->z + mat[0][3];
temp.y = mat[1][0] * point_in->x +
mat[1][1] * point_in->y +
mat[1][2] * point_in->z + mat[1][3];
temp.z = mat[2][0] * point_in->x +
mat[2][1] * point_in->y +
mat[2][2] * point_in->z + mat[2][3];
point_out->x = temp.x;
point_out->y = temp.y;
point_out->z = temp.z;
}
}
else
{
register float w;
for (i = 0; i < count; i++, point_in++, point_out++)
{
w = mat[3][0] * point_in->x + mat[3][1] * point_in->y +
mat[3][2] * point_in->z + mat[3][3];
if (NEAR_ZERO (w))
{
point_out->x = 0.0;
point_out->y = 0.0;
point_out->z = 0.0;
status = PEXBadHomoCoord;
}
else
{
temp.x = (mat[0][0] * point_in->x +
mat[0][1] * point_in->y +
mat[0][2] * point_in->z + mat[0][3]) / w;
temp.y = (mat[1][0] * point_in->x +
mat[1][1] * point_in->y +
mat[1][2] * point_in->z + mat[1][3]) / w;
temp.z = (mat[2][0] * point_in->x +
mat[2][1] * point_in->y +
mat[2][2] * point_in->z + mat[2][3]) / w;
point_out->x = temp.x;
point_out->y = temp.y;
point_out->z = temp.z;
}
}
}
return (status);
}
int
PEXTransformPoints2D (mat, count, points, points_return)
INPUT PEXMatrix3x3 mat;
INPUT int count;
INPUT PEXCoord2D *points;
OUTPUT PEXCoord2D *points_return;
{
register PEXCoord2D *point_in = points;
register PEXCoord2D *point_out = points_return;
register int i;
PEXCoord2D temp;
int status = 0;
if (NEAR_ZERO (mat[2][0]) && NEAR_ZERO (mat[2][1]) &&
NEAR_ZERO (mat[2][2] - 1.0))
{
for (i = 0; i < count; i++, point_in++, point_out++)
{
temp.x = mat[0][0] * point_in->x +
mat[0][1] * point_in->y + mat[0][2];
temp.y = mat[1][0] * point_in->x +
mat[1][1] * point_in->y + mat[1][2];
point_out->x = temp.x;
point_out->y = temp.y;
}
}
else
{
register float w;
for (i = 0; i < count; i++, point_in++, point_out++)
{
w = mat[2][0] * point_in->x + mat[2][1] * point_in->y + mat[2][2];
if (NEAR_ZERO (w))
{
point_out->x = 0.0;
point_out->y = 0.0;
status = PEXBadHomoCoord;
}
else
{
temp.x = (mat[0][0] * point_in->x +
mat[0][1] * point_in->y + mat[0][2]) / w;
temp.y = (mat[1][0] * point_in->x +
mat[1][1] * point_in->y + mat[1][2]) / w;
point_out->x = temp.x;
point_out->y = temp.y;
}
}
}
return (status);
}
void
PEXTransformPoints4D (mat, count, points, points_return)
INPUT PEXMatrix mat;
INPUT int count;
INPUT PEXCoord4D *points;
OUTPUT PEXCoord4D *points_return;
{
register PEXCoord4D *point_in = points;
register PEXCoord4D *point_out = points_return;
register int i;
PEXCoord4D temp;
for (i = 0; i < count; i++, point_in++, point_out++)
{
temp.x = mat[0][0] * point_in->x + mat[0][1] * point_in->y +
mat[0][2] * point_in->z + mat[0][3] * point_in->w;
temp.y = mat[1][0] * point_in->x + mat[1][1] * point_in->y +
mat[1][2] * point_in->z + mat[1][3] * point_in->w;
temp.z = mat[2][0] * point_in->x + mat[2][1] * point_in->y +
mat[2][2] * point_in->z + mat[2][3] * point_in->w;
temp.w = mat[3][0] * point_in->x + mat[3][1] * point_in->y +
mat[3][2] * point_in->z + mat[3][3] * point_in->w;
point_out->x = temp.x;
point_out->y = temp.y;
point_out->z = temp.z;
point_out->w = temp.w;
}
}
void
PEXTransformPoints2DH (mat, count, points, points_return)
INPUT PEXMatrix3x3 mat;
INPUT int count;
INPUT PEXCoord *points;
OUTPUT PEXCoord *points_return;
{
register PEXCoord *point_in = points;
register PEXCoord *point_out = points_return;
register int i;
PEXCoord temp;
for (i = 0; i < count; i++, point_in++, point_out++)
{
temp.x = mat[0][0] * point_in->x + mat[0][1] * point_in->y +
mat[0][2] * point_in->z;
temp.y = mat[1][0] * point_in->x + mat[1][1] * point_in->y +
mat[1][2] * point_in->z;
temp.z = mat[2][0] * point_in->x + mat[2][1] * point_in->y +
mat[2][2] * point_in->z;
point_out->x = temp.x;
point_out->y = temp.y;
point_out->z = temp.z;
}
}
void
PEXTransformVectors (mat, count, vectors, vectors_return)
INPUT PEXMatrix mat;
INPUT int count;
INPUT PEXVector *vectors;
OUTPUT PEXVector *vectors_return;
{
register PEXVector *vec_in = vectors;
register PEXVector *vec_out = vectors_return;
register int i;
PEXVector temp;
for (i = 0; i < count; i++, vec_in++, vec_out++)
{
temp.x = mat[0][0] * vec_in->x + mat[0][1] * vec_in->y +
mat[0][2] * vec_in->z;
temp.y = mat[1][0] * vec_in->x + mat[1][1] * vec_in->y +
mat[1][2] * vec_in->z;
temp.z = mat[2][0] * vec_in->x + mat[2][1] * vec_in->y +
mat[2][2] * vec_in->z;
vec_out->x = temp.x;
vec_out->y = temp.y;
vec_out->z = temp.z;
}
}
void
PEXTransformVectors2D (mat, count, vectors, vectors_return)
INPUT PEXMatrix3x3 mat;
INPUT int count;
INPUT PEXVector2D *vectors;
OUTPUT PEXVector2D *vectors_return;
{
register PEXVector2D *vec_in = vectors;
register PEXVector2D *vec_out = vectors_return;
register int i;
PEXVector2D temp;
for (i = 0; i < count; i++, vec_in++, vec_out++)
{
temp.x = mat[0][0] * vec_in->x + mat[0][1] * vec_in->y;
temp.y = mat[1][0] * vec_in->x + mat[1][1] * vec_in->y;
vec_out->x = temp.x;
vec_out->y = temp.y;
}
}
int
PEXNormalizeVectors (count, vectors, vectors_return)
INPUT int count;
INPUT PEXVector *vectors;
OUTPUT PEXVector *vectors_return;
{
register int i;
register PEXVector *vec_in = vectors;
register PEXVector *vec_out = vectors_return;
float sum, length;
int status = 0;
for (i = 0; i < count; i++, vec_in++, vec_out++)
{
sum = vec_in->x * vec_in->x +
vec_in->y * vec_in->y +
vec_in->z * vec_in->z;
if (NEAR_ZERO (sum))
{
vec_out->x = 0.0;
vec_out->y = 0.0;
vec_out->z = 0.0;
status = PEXBadVector;
}
else
{
length = sqrt (sum);
vec_out->x = vec_in->x / length;
vec_out->y = vec_in->y / length;
vec_out->z = vec_in->z / length;
}
}
return (status);
}
int
PEXNormalizeVectors2D (count, vectors, vectors_return)
INPUT int count;
INPUT PEXVector2D *vectors;
OUTPUT PEXVector2D *vectors_return;
{
register int i;
register PEXVector2D *vec_in = vectors;
register PEXVector2D *vec_out = vectors_return;
float sum, length;
int status = 0;
for (i = 0; i < count; i++, vec_in++, vec_out++)
{
sum = vec_in->x * vec_in->x +
vec_in->y * vec_in->y;
if (NEAR_ZERO (sum))
{
vec_out->x = 0.0;
vec_out->y = 0.0;
status = PEXBadVector;
}
else
{
length = sqrt (sum);
vec_out->x = vec_in->x / length;
vec_out->y = vec_in->y / length;
}
}
return (status);
}
int
PEXNPCToXCTransform (npc_sub_volume, viewport,
window_height, transform_return)
INPUT PEXNPCSubVolume *npc_sub_volume;
INPUT PEXDeviceCoord *viewport;
INPUT unsigned int window_height;
OUTPUT PEXMatrix transform_return;
{
float scale_x, scale_y, scale_z;
int dvx, dvy;
float dnx, dny;
float dvz, dnz;
PEXDeviceCoord new_viewport[2];
dvx = viewport[1].x - viewport[0].x;
dvy = viewport[1].y - viewport[0].y;
dvz = viewport[1].z - viewport[0].z;
if (dvx <= 0 || dvy <= 0 || !(viewport[0].z <= viewport[1].z))
return (PEXBadViewport);
if (BAD_SUBVOLUME (npc_sub_volume))
return (PEXBadSubVolume);
dnx = npc_sub_volume->max.x - npc_sub_volume->min.x;
dny = npc_sub_volume->max.y - npc_sub_volume->min.y;
dnz = npc_sub_volume->max.z - npc_sub_volume->min.z;
scale_x = (float) dvx / dnx;
scale_y = (float) dvy / dny;
scale_z = NEAR_ZERO (dnz) ? 1.0 : (dvz / dnz);
if (!NEAR_ZERO (scale_x - scale_y))
{
new_viewport[0].x = viewport[0].x;
new_viewport[0].y = viewport[0].y;
new_viewport[0].z = viewport[0].z;
if (scale_y < scale_x)
{
new_viewport[1].x = viewport[0].x + (float) dvy * dnx / dny;
new_viewport[1].y = viewport[1].y;
new_viewport[1].z = viewport[1].z;
}
else
{
new_viewport[1].x = viewport[1].x;
new_viewport[1].y = viewport[0].y + (float) dvx * dny / dnx;
new_viewport[1].z = viewport[1].z;
}
viewport = new_viewport;
}
transform_return[0][0] = scale_x;
transform_return[0][1] = 0.0;
transform_return[0][2] = 0.0;
transform_return[0][3] =
viewport[0].x - (scale_x * npc_sub_volume->min.x);
transform_return[1][0] = 0.0;
transform_return[1][1] = -scale_y;
transform_return[1][2] = 0.0;
transform_return[1][3] =
window_height - viewport[0].y + (scale_y * npc_sub_volume->min.y);
transform_return[2][0] = 0.0;
transform_return[2][1] = 0.0;
transform_return[2][2] = scale_z;
transform_return[2][3] =
viewport[0].z - (scale_z * npc_sub_volume->min.z);
transform_return[3][0] = 0.0;
transform_return[3][1] = 0.0;
transform_return[3][2] = 0.0;
transform_return[3][3] = 1.0;
return (0);
}
int
PEXNPCToXCTransform2D (npc_sub_volume, viewport,
window_height, transform_return)
INPUT PEXNPCSubVolume *npc_sub_volume;
INPUT PEXDeviceCoord2D *viewport;
INPUT unsigned int window_height;
OUTPUT PEXMatrix3x3 transform_return;
{
float scale_x, scale_y;
int dvx, dvy;
float dnx, dny;
PEXDeviceCoord2D new_viewport[2];
dvx = viewport[1].x - viewport[0].x;
dvy = viewport[1].y - viewport[0].y;
if (dvx <= 0 || dvy <= 0)
return (PEXBadViewport);
if (BAD_SUBVOLUME (npc_sub_volume))
return (PEXBadSubVolume);
dnx = npc_sub_volume->max.x - npc_sub_volume->min.x;
dny = npc_sub_volume->max.y - npc_sub_volume->min.y;
scale_x = (float) dvx / dnx;
scale_y = (float) dvy / dny;
if (!NEAR_ZERO (scale_x - scale_y))
{
new_viewport[0].x = viewport[0].x;
new_viewport[0].y = viewport[0].y;
if (scale_y < scale_x)
{
new_viewport[1].x = viewport[0].x + (float) dvy * dnx / dny;
new_viewport[1].y = viewport[1].y;
}
else
{
new_viewport[1].x = viewport[1].x;
new_viewport[1].y = viewport[0].y + (float) dvx * dny / dnx;
}
viewport = new_viewport;
}
transform_return[0][0] = scale_x;
transform_return[0][1] = 0.0;
transform_return[0][2] =
viewport[0].x - (scale_x * npc_sub_volume->min.x);
transform_return[1][0] = 0.0;
transform_return[1][1] = -scale_y;
transform_return[1][2] =
window_height - viewport[0].y + (scale_y * npc_sub_volume->min.y);
transform_return[2][0] = 0.0;
transform_return[2][1] = 0.0;
transform_return[2][2] = 1.0;
return (0);
}
int
PEXXCToNPCTransform (npc_sub_volume, viewport,
window_height, transform_return)
INPUT PEXNPCSubVolume *npc_sub_volume;
INPUT PEXDeviceCoord *viewport;
INPUT unsigned int window_height;
OUTPUT PEXMatrix transform_return;
{
float scale_x, scale_y, scale_z;
int dvx, dvy;
float dnx, dny;
float dvz, dnz;
PEXDeviceCoord new_viewport[2];
dvx = viewport[1].x - viewport[0].x;
dvy = viewport[1].y - viewport[0].y;
dvz = viewport[1].z - viewport[0].z;
if (dvx <= 0 || dvy <= 0 || !(viewport[0].z <= viewport[1].z))
return (PEXBadViewport);
if (BAD_SUBVOLUME (npc_sub_volume))
return (PEXBadSubVolume);
dnx = npc_sub_volume->max.x - npc_sub_volume->min.x;
dny = npc_sub_volume->max.y - npc_sub_volume->min.y;
dnz = npc_sub_volume->max.z - npc_sub_volume->min.z;
scale_x = dnx / (float) dvx;
scale_y = dny / (float) dvy;
scale_z = NEAR_ZERO (dvz) ? 1.0 : (dnz / dvz);
if (!NEAR_ZERO (scale_x - scale_y))
{
new_viewport[0].x = viewport[0].x;
new_viewport[0].y = viewport[0].y;
new_viewport[0].z = viewport[0].z;
if (scale_x < scale_y)
{
new_viewport[1].x = viewport[0].x + (float) dvy * dnx / dny;
new_viewport[1].y = viewport[1].y;
new_viewport[1].z = viewport[1].z;
}
else
{
new_viewport[1].x = viewport[1].x;
new_viewport[1].y = viewport[0].y + (float) dvx * dny / dnx;
new_viewport[1].z = viewport[1].z;
}
viewport = new_viewport;
}
transform_return[0][0] = scale_x;
transform_return[0][1] = 0.0;
transform_return[0][2] = 0.0;
transform_return[0][3] =
npc_sub_volume->min.x - (scale_x * viewport[0].x);
transform_return[1][0] = 0.0;
transform_return[1][1] = -scale_y;
transform_return[1][2] = 0.0;
transform_return[1][3] =
npc_sub_volume->min.y + scale_y * (window_height - viewport[0].y);
transform_return[2][0] = 0.0;
transform_return[2][1] = 0.0;
transform_return[2][2] = 1.0;
transform_return[2][3] =
npc_sub_volume->min.z - (scale_z * viewport[0].z);
transform_return[3][0] = 0.0;
transform_return[3][1] = 0.0;
transform_return[3][2] = 0.0;
transform_return[3][3] = 1.0;
return (0);
}
int
PEXXCToNPCTransform2D (npc_sub_volume, viewport,
window_height, transform_return)
INPUT PEXNPCSubVolume *npc_sub_volume;
INPUT PEXDeviceCoord2D *viewport;
INPUT unsigned int window_height;
INPUT PEXMatrix3x3 transform_return;
{
float scale_x, scale_y;
int dvx, dvy;
float dnx, dny;
PEXDeviceCoord2D new_viewport[2];
dvx = viewport[1].x - viewport[0].x;
dvy = viewport[1].y - viewport[0].y;
if (dvx <= 0 || dvy <= 0)
return (PEXBadViewport);
if (BAD_SUBVOLUME (npc_sub_volume))
return (PEXBadSubVolume);
dnx = npc_sub_volume->max.x - npc_sub_volume->min.x;
dny = npc_sub_volume->max.y - npc_sub_volume->min.y;
scale_x = dnx / (float) dvx;
scale_y = dny / (float) dvy;
if (!NEAR_ZERO (scale_x - scale_y))
{
new_viewport[0].x = viewport[0].x;
new_viewport[0].y = viewport[0].y;
if (scale_x < scale_y)
{
new_viewport[1].x = viewport[0].x + (float) dvy * dnx / dny;
new_viewport[1].y = viewport[1].y;
}
else
{
new_viewport[1].x = viewport[1].x;
new_viewport[1].y = viewport[0].y + (float) dvx * dny / dnx;
}
viewport = new_viewport;
}
transform_return[0][0] = scale_x;
transform_return[0][1] = 0.0;
transform_return[0][2] =
npc_sub_volume->min.x - (scale_x * viewport[0].x);
transform_return[1][0] = 0.0;
transform_return[1][1] = -scale_y;
transform_return[1][2] =
npc_sub_volume->min.y + scale_y * (window_height - viewport[0].y);
transform_return[2][0] = 0.0;
transform_return[2][1] = 0.0;
transform_return[2][2] = 1.0;
return (0);
}
int
PEXMapXCToNPC (point_count, points, window_height,
z_dc, viewport, npc_sub_volume, view_count, views,
view_return, count_return, points_return)
INPUT int point_count;
INPUT PEXDeviceCoord2D *points;
INPUT unsigned int window_height;
INPUT double z_dc;
INPUT PEXDeviceCoord *viewport;
INPUT PEXNPCSubVolume *npc_sub_volume;
INPUT int view_count;
INPUT PEXViewEntry *views;
OUTPUT int *view_return;
OUTPUT int *count_return;
OUTPUT PEXCoord *points_return;
{
PEXCoord *xc_wz_points;
PEXMatrix xform;
int pts_in_view;
int max_pts_in_view;
int max_pts_view;
int status, i, j;
xc_wz_points = (PEXCoord *) Xmalloc (
(unsigned) (point_count * sizeof (PEXCoord)));
for (i = 0; i < point_count; i++)
{
xc_wz_points[i].x = points[i].x;
xc_wz_points[i].y = points[i].y;
xc_wz_points[i].z = z_dc;
}
status = PEXXCToNPCTransform (npc_sub_volume, viewport,
window_height, xform);
if (status != 0)
return (status);
status = PEXTransformPoints (xform, point_count,
xc_wz_points, points_return);
Xfree ((char *) xc_wz_points);
if (status != 0)
return (status);
max_pts_view = -1;
max_pts_in_view = 0;
for (i = 0; i < view_count; i++)
{
for (j = pts_in_view = 0; j < point_count; j++)
{
if (POINT3D_IN_VIEW (points_return[j], views[i]))
pts_in_view++;
}
if (pts_in_view == point_count)
{
max_pts_in_view = point_count;
max_pts_view = i;
break;
}
else if (pts_in_view > max_pts_in_view)
{
max_pts_in_view = pts_in_view;
max_pts_view = i;
}
}
if (max_pts_in_view > 0 && max_pts_in_view != point_count)
{
int count = 0;
for (i = 0; i < point_count && count < max_pts_in_view; i++)
{
if (POINT3D_IN_VIEW (points_return[i], views[max_pts_view]))
{
points_return[count].x = points_return[i].x;
points_return[count].y = points_return[i].y;
points_return[count].z = points_return[i].z;
count++;
}
}
}
*view_return = max_pts_view;
*count_return = max_pts_in_view;
return (0);
}
int
PEXMapXCToNPC2D (point_count, points, window_height,
viewport, npc_sub_volume, view_count, views,
view_return, count_return, points_return)
INPUT int point_count;
INPUT PEXDeviceCoord2D *points;
INPUT unsigned int window_height;
INPUT PEXDeviceCoord2D *viewport;
INPUT PEXNPCSubVolume *npc_sub_volume;
INPUT int view_count;
INPUT PEXViewEntry *views;
OUTPUT int *view_return;
OUTPUT int *count_return;
OUTPUT PEXCoord2D *points_return;
{
PEXMatrix3x3 xform;
PEXCoord2D *xc_points;
int pts_in_view;
int max_pts_in_view;
int max_pts_view;
int status, i, j;
xc_points = (PEXCoord2D *) Xmalloc (
(unsigned) (point_count * sizeof (PEXCoord2D)));
for (i = 0; i < point_count; i++)
{
xc_points[i].x = points[i].x;
xc_points[i].y = points[i].y;
}
status = PEXXCToNPCTransform2D (npc_sub_volume, viewport,
window_height, xform);
if (status != 0)
return (status);
status = PEXTransformPoints2D (xform, point_count,
xc_points, points_return);
Xfree ((char *) xc_points);
if (status != 0)
return (status);
max_pts_view = -1;
max_pts_in_view = 0;
for (i = 0; i < view_count; i++)
{
for (j = pts_in_view = 0; j < point_count; j++)
{
if (POINT2D_IN_VIEW (points_return[j], views[i]))
pts_in_view++;
}
if (pts_in_view == point_count)
{
max_pts_in_view = point_count;
max_pts_view = i;
break;
}
else if (pts_in_view > max_pts_in_view)
{
max_pts_in_view = pts_in_view;
max_pts_view = i;
}
}
if (max_pts_in_view > 0 && max_pts_in_view != point_count)
{
int count = 0;
for (i = 0; i < point_count && count < max_pts_in_view; i++)
{
if (POINT2D_IN_VIEW (points_return[i], views[max_pts_view]))
{
points_return[count].x = points_return[i].x;
points_return[count].y = points_return[i].y;
count++;
}
}
}
*view_return = max_pts_view;
*count_return = max_pts_in_view;
return (0);
}
int
PEXInvertMatrix (matrix, inverseReturn)
INPUT PEXMatrix matrix;
OUTPUT PEXMatrix inverseReturn;
{
int ipivot, h, i, j, k;
float aug[4][5];
float pivot, temp, q;
for (h = 0; h < 4; h++)
{
for (i = 0; i < 4; i++)
{
aug[i][0] = matrix[i][0];
aug[i][1] = matrix[i][1];
aug[i][2] = matrix[i][2];
aug[i][3] = matrix[i][3];
aug[i][4] = (h == i) ? 1.0 : 0.0;
}
for (i = 0; i < 3; i++)
{
pivot = 0.0;
for (j = i; j < 4; j++)
{
temp = ABS (aug[j][i]);
if (pivot < temp)
{
pivot = temp;
ipivot = j;
}
}
if (NEAR_ZERO (pivot))
return (PEXBadMatrix);
if (ipivot != i)
{
for (k = i; k < 5; k++)
{
temp = aug[i][k];
aug[i][k] = aug[ipivot][k];
aug[ipivot][k] = temp;
}
}
for (k = i + 1; k < 4; k++)
{
q = -aug[k][i] / aug[i][i];
aug[k][i] = 0.0;
for (j = i + 1; j < 5; j++)
{
aug[k][j] = q * aug[i][j] + aug[k][j];
}
}
}
if (NEAR_ZERO (aug[3][3]))
return (PEXBadMatrix);
inverseReturn[3][h] = aug[3][4] / aug[3][3];
for (k = 1; k < 4; k++)
{
q = 0.0;
for (j = 1; j <= k; j++)
{
q = q + aug[3 - k][4 - j] * inverseReturn[4 - j][h];
}
inverseReturn[3 - k][h] = (aug[3 - k][4] - q) / aug[3 - k][3 - k];
}
}
return (0);
}
int
PEXInvertMatrix2D (matrix, inverseReturn)
PEXMatrix3x3 matrix;
PEXMatrix3x3 inverseReturn;
{
int ipivot, h, i, j, k;
float aug[3][4];
float pivot, temp, q;
for (h = 0; h < 3; h++)
{
for (i = 0; i < 3; i++)
{
aug[i][0] = matrix[i][0];
aug[i][1] = matrix[i][1];
aug[i][2] = matrix[i][2];
aug[i][3] = (h == i) ? 1.0 : 0.0;
}
for (i = 0; i < 2; i++)
{
pivot = 0.0;
for (j = i; j < 3; j++)
{
temp = ABS (aug[j][i]);
if (pivot < temp)
{
pivot = temp;
ipivot = j;
}
}
if (NEAR_ZERO (pivot))
return (PEXBadMatrix);
if (ipivot != i)
{
for (k = i; k < 4; k++)
{
temp = aug[i][k];
aug[i][k] = aug[ipivot][k];
aug[ipivot][k] = temp;
}
}
for (k = i + 1; k < 3; k++)
{
q = -aug[k][i] / aug[i][i];
aug[k][i] = 0.;
for (j = i + 1; j < 4; j++)
{
aug[k][j] = q * aug[i][j] + aug[k][j];
}
}
}
if (NEAR_ZERO (aug[2][2]))
return (PEXBadMatrix);
inverseReturn[2][h] = aug[2][3] / aug[2][2];
for (k = 1; k < 3; k++)
{
q = 0.0;
for (j = 1; j <= k; j++)
{
q = q + aug[2 - k][3 - j] * inverseReturn[3 - j][h];
}
inverseReturn[2 - k][h] = (aug[2 - k][3] - q) / aug[2 - k][2 - k];
}
}
return (0);
}
void
PEXIdentityMatrix (matrix_return)
OUTPUT PEXMatrix matrix_return;
{
matrix_return[0][0] = 1.0;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = 0.0;
matrix_return[0][3] = 0.0;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = 1.0;
matrix_return[1][2] = 0.0;
matrix_return[1][3] = 0.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
matrix_return[2][3] = 0.0;
matrix_return[3][0] = 0.0;
matrix_return[3][1] = 0.0;
matrix_return[3][2] = 0.0;
matrix_return[3][3] = 1.0;
}
void
PEXIdentityMatrix2D (matrix_return)
OUTPUT PEXMatrix3x3 matrix_return;
{
matrix_return[0][0] = 1.0;
matrix_return[0][1] = 0.0;
matrix_return[0][2] = 0.0;
matrix_return[1][0] = 0.0;
matrix_return[1][1] = 1.0;
matrix_return[1][2] = 0.0;
matrix_return[2][0] = 0.0;
matrix_return[2][1] = 0.0;
matrix_return[2][2] = 1.0;
}
int
PEXGeoNormFillArea (facet_attributes, vertex_attributes,
color_type, facet_data, count, vertices)
INPUT unsigned int facet_attributes;
INPUT unsigned int vertex_attributes;
INPUT int color_type;
INOUT PEXFacetData *facet_data;
INPUT unsigned int count;
INPUT PEXArrayOfVertex vertices;
{
PEXCoord *v1, *v2, *v3;
int found_v2, found_v3;
float dx, dy, dz, length;
int vert_size;
PEXVector *normal;
char *ptr;
if (!(facet_attributes & PEXGANormal))
return (0);
if (count < 3)
return (PEXBadPrimitive);
if (facet_attributes & PEXGAColor)
{
normal = (PEXVector *) ((char *) facet_data +
GetClientColorSize (color_type));
}
else
normal = (PEXVector *) facet_data;
vert_size = GetClientVertexSize (color_type, vertex_attributes);
ptr = (char *) vertices.no_data;
v1 = (PEXCoord *) ptr;
count--;
found_v2 = 0;
while (!found_v2 && count > 0)
{
ptr += vert_size;
v2 = (PEXCoord *) ptr;
count--;
dx = v2->x - v1->x;
dy = v2->y - v1->y;
dz = v2->z - v1->z;
if (!NEAR_ZERO (dx) || !NEAR_ZERO (dy) || !NEAR_ZERO (dz))
found_v2 = 1;
}
found_v3 = 0;
while (!found_v3 && count > 0)
{
ptr += vert_size;
v3 = (PEXCoord *) ptr;
count--;
CROSS_PRODUCT (v1, v2, v1, v3, normal);
NORMALIZE_VECTOR (normal, length);
if (!NEAR_ZERO (length))
found_v3 = 1;
}
if (found_v3)
return (0);
else
return (PEXBadPrimitive);
}
int
PEXGeoNormFillAreaSet (facet_attributes, vertex_attributes,
color_type, count, facet_data, vertex_lists)
INPUT unsigned int facet_attributes;
INPUT unsigned int vertex_attributes;
INPUT int color_type;
INPUT unsigned int count;
INOUT PEXFacetData *facet_data;
INPUT PEXListOfVertex *vertex_lists;
{
PEXCoord *v1, *v2, *v3;
int vert_size, vcount;
int found_v2, done, i;
float dx, dy, dz, length;
PEXVector *normal;
char *ptr;
if (!(facet_attributes & PEXGANormal))
return (0);
if (facet_attributes & PEXGAColor)
{
normal = (PEXVector *) ((char *) facet_data +
GetClientColorSize (color_type));
}
else
normal = (PEXVector *) facet_data;
vert_size = GetClientVertexSize (color_type, vertex_attributes);
for (i = done = 0; i < count && !done; i++)
{
if ((vcount = vertex_lists[i].count) > 2)
{
ptr = (char *) vertex_lists[i].vertices.no_data;
v1 = (PEXCoord *) ptr;
vcount--;
found_v2 = 0;
while (!found_v2 && vcount > 0)
{
ptr += vert_size;
v2 = (PEXCoord *) ptr;
vcount--;
dx = v2->x - v1->x;
dy = v2->y - v1->y;
dz = v2->z - v1->z;
if (!NEAR_ZERO (dx) || !NEAR_ZERO (dy) || !NEAR_ZERO (dz))
found_v2 = 1;
}
while (!done && vcount > 0)
{
ptr += vert_size;
v3 = (PEXCoord *) ptr;
vcount--;
CROSS_PRODUCT (v1, v2, v1, v3, normal);
NORMALIZE_VECTOR (normal, length);
if (!NEAR_ZERO (length))
done = 1;
}
}
}
if (done)
return (0);
else
return (PEXBadPrimitive);
}
int
PEXGeoNormTriangleStrip (facet_attributes, vertex_attributes,
color_type, facet_data, count, vertices)
INPUT unsigned int facet_attributes;
INPUT unsigned int vertex_attributes;
INPUT int color_type;
INOUT PEXArrayOfFacetData facet_data;
INPUT unsigned int count;
INPUT PEXArrayOfVertex vertices;
{
PEXCoord *v1, *v2, *v3;
int vert_size;
int facet_size, i;
PEXVector *normal;
float length;
char *ptr;
int status = 0;
if (!(facet_attributes & PEXGANormal))
return (0);
if (count < 3)
return (PEXBadPrimitive);
if (facet_attributes & PEXGAColor)
{
normal = (PEXVector *) ((char *) facet_data.index +
GetClientColorSize (color_type));
}
else
normal = (PEXVector *) facet_data.normal;
vert_size = GetClientVertexSize (color_type, vertex_attributes);
facet_size = GetClientFacetSize (color_type, facet_attributes);
ptr = (char *) vertices.no_data;
for (i = 0; i < count - 2; i++)
{
v1 = (PEXCoord *) ptr;
ptr += vert_size;
v2 = (PEXCoord *) ptr;
ptr += vert_size;
v3 = (PEXCoord *) ptr;
ptr -= vert_size;
if (i % 2)
{
CROSS_PRODUCT (v1, v3, v1, v2, normal);
}
else
{
CROSS_PRODUCT (v1, v2, v1, v3, normal);
}
NORMALIZE_VECTOR (normal, length);
if (NEAR_ZERO (length))
{
normal->x = normal->y = normal->z = 0.0;
status = PEXBadPrimitive;
}
normal = (PEXVector *) ((char *) normal + facet_size);
}
return (status);
}
int
PEXGeoNormQuadrilateralMesh (facet_attributes, vertex_attributes,
color_type, facet_data, col_count, row_count, vertices)
INPUT unsigned int facet_attributes;
INPUT unsigned int vertex_attributes;
INPUT int color_type;
INOUT PEXArrayOfFacetData facet_data;
INPUT unsigned int col_count;
INPUT unsigned int row_count;
INPUT PEXArrayOfVertex vertices;
{
PEXCoord *v1, *v2, *v3, *v4;
int vert_size, facet_size;
int row, col;
PEXVector *normal;
float length;
int status = 0;
if (!(facet_attributes & PEXGANormal))
return (0);
if (row_count < 2 || col_count < 2)
return (PEXBadPrimitive);
if (facet_attributes & PEXGAColor)
{
normal = (PEXVector *) ((char *) facet_data.index +
GetClientColorSize (color_type));
}
else
normal = (PEXVector *) facet_data.normal;
vert_size = GetClientVertexSize (color_type, vertex_attributes);
facet_size = GetClientFacetSize (color_type, facet_attributes);
for (row = 0; row < row_count - 1; row++)
for (col = 0; col < col_count - 1; col++)
{
v1 = (PEXCoord *) ((char *) vertices.no_data +
(row * col_count + col) * vert_size);
v4 = (PEXCoord *) ((char *) v1 + vert_size);
v3 = (PEXCoord *) ((char *) v1 + col_count * vert_size);
v2 = (PEXCoord *) ((char *) v3 + vert_size);
CROSS_PRODUCT (v1, v2, v3, v4, normal);
NORMALIZE_VECTOR (normal, length);
if (NEAR_ZERO (length))
{
normal->x = normal->y = normal->z = 0.0;
status = PEXBadPrimitive;
}
normal = (PEXVector *) ((char *) normal + facet_size);
}
return (status);
}
int
PEXGeoNormSetOfFillAreaSets (facet_attributes, vertex_attributes,
color_type, set_count, facet_data, vertex_count, vertices,
index_count, connectivity)
INPUT unsigned int facet_attributes;
INPUT unsigned int vertex_attributes;
INPUT int color_type;
INPUT unsigned int set_count;
INOUT PEXArrayOfFacetData facet_data;
INPUT unsigned int vertex_count;
INPUT PEXArrayOfVertex vertices;
INPUT unsigned int index_count;
INPUT PEXConnectivityData *connectivity;
{
PEXConnectivityData *pConnectivity;
PEXListOfUShort *pList;
PEXCoord *v1, *v2, *v3;
int vert_size, facet_size;
float dx, dy, dz, length;
int index, done;
int found_v2, i, j;
PEXVector *normal;
int status = 0;
if (!(facet_attributes & PEXGANormal))
return (0);
if (index_count < 3 || vertex_count < 3)
return (PEXBadPrimitive);
if (facet_attributes & PEXGAColor)
{
normal = (PEXVector *) ((char *) facet_data.index +
GetClientColorSize (color_type));
}
else
normal = (PEXVector *) facet_data.normal;
vert_size = GetClientVertexSize (color_type, vertex_attributes);
facet_size = GetClientFacetSize (color_type, facet_attributes);
pConnectivity = connectivity;
for (i = 0; i < set_count; i++)
{
pList = pConnectivity->lists;
done = 0;
for (j = 0; j < (int) pConnectivity->count && !done; j++, pList++)
{
if (pList->count > 2)
{
v1 = (PEXCoord *) ((char *) vertices.no_data +
vert_size * pList->shorts[0]);
index = 1;
found_v2 = 0;
while (!found_v2 && index < (int) pList->count)
{
v2 = (PEXCoord *) ((char *) vertices.no_data +
vert_size * pList->shorts[index]);
index++;
dx = v2->x - v1->x;
dy = v2->y - v1->y;
dz = v2->z - v1->z;
if (!NEAR_ZERO (dx) || !NEAR_ZERO (dy) || !NEAR_ZERO (dz))
found_v2 = 1;
}
while (!done && index < (int) pList->count)
{
v3 = (PEXCoord *) ((char *) vertices.no_data +
vert_size * pList->shorts[index]);
index++;
CROSS_PRODUCT (v1, v2, v1, v3, normal);
NORMALIZE_VECTOR (normal, length);
if (!NEAR_ZERO (length))
done = 1;
}
}
}
if (!done)
{
normal->x = normal->y = normal->z = 0.0;
status = PEXBadPrimitive;
}
normal = (PEXVector *) ((char *) normal + facet_size);
pConnectivity++;
}
return (status);
}