751 lines
19 KiB
C
751 lines
19 KiB
C
/*
|
|
* Copyright (c) 1986, 1987, 1988, 1989 by Sun Microsystems, Inc.
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose and without fee is hereby granted, provided that the above
|
|
* copyright notice appear in all copies and that both that copyright
|
|
* notice and this permission notice are retained, and that the name
|
|
* of Sun Microsystems, Inc., not be used in advertising or publicity
|
|
* pertaining to this software without specific, written prior permission.
|
|
* Sun Microsystems, Inc., makes no representations about the suitability
|
|
* of this software or the interface defined in this software for any
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
|
*/
|
|
#ifndef lint
|
|
static char sccsid[] = "@(#)xformclip3.c 1.1 94/10/31 Copyr 1985 Sun Micro";
|
|
#endif
|
|
|
|
/*
|
|
* Copyright (c) 1985 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
/*
|
|
Operation:
|
|
Three-D viewing transform routines and clipping routines.
|
|
Usage:
|
|
typedef struct{ float x,y,z,w;
|
|
} pt_type; ' homogeneous point type
|
|
|
|
--- Transform utility operations ---
|
|
|
|
_core_tranpt( p1, p2) pt_type *p1, *p2;
|
|
' transform 3-D point using stack top,
|
|
' p2 gets transformed point.
|
|
_core_sizept( p1, p2) pt_type *p1, *p2;
|
|
' scale and rotate 3-D point, no
|
|
' translation.
|
|
_core_clipvec( p1,p2) ipt_type *p1, *p2;
|
|
' Clip 3-D vector to window, return true
|
|
' if visible.
|
|
_core_clippt3( x,y,z) int x,y,z;
|
|
' true if point is in view window
|
|
|
|
*/
|
|
/*--------------------------------------------------------------------*/
|
|
/* --- Transform Variables --- */
|
|
#include "coretypes.h"
|
|
#include "corevars.h"
|
|
#include <math.h>
|
|
#include <sys/types.h>
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/* --- Transform Operations --- */
|
|
/*--------------------------------------------------------------------*/
|
|
/*-----------------------------------*/
|
|
_core_tranpt( p1, p2) float *p1, *p2; /* transform pt using stack top */
|
|
{ /* p2[i] = Sum p1[k]*tran[k,i] */
|
|
register float *m, *q; /* k */
|
|
register int k,i;
|
|
float sum, *m1;
|
|
ddargtype ddstruct;
|
|
|
|
if (_core_xformvs) {
|
|
_core_critflag++; /* critical section since slight chance of
|
|
view surface termination via SIGCHILD
|
|
during the call to the dd */
|
|
ddstruct.instance = _core_xformvs->instance;
|
|
if (!_core_ddxformset) {
|
|
ddstruct.opcode = SETVWXFORM32K; /* send the matrix to the dd */
|
|
ddstruct.ptr1 = (char*)&_core_TStack[_core_TSp][0];
|
|
(*_core_xformvs->dd)(&ddstruct);
|
|
_core_ddxformset = TRUE;
|
|
}
|
|
ddstruct.opcode = VIEWXFORM3; /* transform a point */
|
|
ddstruct.ptr1 = (char*)p1;
|
|
ddstruct.ptr2 = (char*)p2;
|
|
(*_core_xformvs->dd)(&ddstruct);
|
|
if (--_core_critflag == 0 && _core_updatewin && _core_sighandle)
|
|
(*_core_sighandle)();
|
|
}
|
|
else {
|
|
m1 = &_core_TStack[_core_TSp][0];
|
|
for (i=0; i<4; i++) { /* for each output coord */
|
|
q = p1; m = m1 + i;
|
|
sum = 0.0;
|
|
for (k=0; k<4; k++) { /* point times matrix column*/
|
|
sum += *q++ * *m;
|
|
m += 4;
|
|
}
|
|
*p2++ = sum;
|
|
}
|
|
}
|
|
}
|
|
/*-----------------------------------*/
|
|
_core_sizept( p1, p2) float *p1, *p2; /* scale, rotate pt using stack top */
|
|
{ /* p2[i] = Sum p1[k]*tran[k,i] */
|
|
register float *m, *q; /* k */
|
|
register int k,i;
|
|
float sum, *m1;
|
|
|
|
m1 = &_core_TStack[_core_TSp][0];
|
|
for (i=0; i<3; i++) { /* for each output coord */
|
|
q = p1; m = m1 + i;
|
|
sum = 0.0;
|
|
for (k=0; k<3; k++) { /* point times matrix column*/
|
|
sum += *q++ * *m;
|
|
m += 4;
|
|
}
|
|
*p2++ = sum;
|
|
}
|
|
m = m1+3;
|
|
*p2 = 0.0;
|
|
for (k=0; k<4; k++) {
|
|
*p2 += *m;
|
|
m += 4;
|
|
}
|
|
}
|
|
/*---------------------------------------*/
|
|
_core_pt3cnvrt( fp, ip)
|
|
register float *fp;
|
|
register int *ip;
|
|
{ /* convert 3-D float point to int pt */
|
|
*ip++ = _core_roundf(fp);
|
|
fp++;
|
|
*ip++ = _core_roundf(fp);
|
|
fp++;
|
|
*ip++ = _core_roundf(fp);
|
|
fp++;
|
|
*ip = _core_roundf(fp);
|
|
}
|
|
/*--------------------------------------*/
|
|
_core_imxfrm3( segptr, p1, p2) register ipt_type *p1, *p2; segstruc *segptr;
|
|
{ /* image transform integer point in NDC coordinates */
|
|
int p1x, p1y, p1z, shiftx, shifty, shiftz;
|
|
|
|
if (segptr->type == XLATE2) {
|
|
p2->x = p1->x + segptr->imxform[3][0];
|
|
p2->y = p1->y + segptr->imxform[3][1];
|
|
p2->z = p1->z + segptr->imxform[3][2];
|
|
} else if(segptr->type == XFORM2) {
|
|
p1x = p1->x;
|
|
shiftx = 15;
|
|
while (p1x > 65535 || p1x < -65535)
|
|
{
|
|
p1x >>= 1;
|
|
shiftx--;
|
|
}
|
|
p1y = p1->y;
|
|
shifty = 15;
|
|
while (p1y > 65535 || p1y < -65535)
|
|
{
|
|
p1y >>= 1;
|
|
shifty--;
|
|
}
|
|
p1z = p1->z;
|
|
shiftz = 15;
|
|
while (p1z > 65535 || p1z < -65535)
|
|
{
|
|
p1z >>= 1;
|
|
shiftz--;
|
|
}
|
|
p2->x = p1->x * (segptr->imxform[0][0] >> 16) +
|
|
(p1x * (short)(segptr->imxform[0][0] & 0xFFFF) >> shiftx) +
|
|
p1->y * (segptr->imxform[1][0] >> 16) +
|
|
(p1y * (short)(segptr->imxform[1][0] & 0xFFFF) >> shifty) +
|
|
p1->z * (segptr->imxform[2][0] >> 16) +
|
|
(p1z * (short)(segptr->imxform[2][0] & 0xFFFF) >> shiftz) +
|
|
segptr->imxform[3][0];
|
|
p2->y = p1->x * (segptr->imxform[0][1] >> 16) +
|
|
(p1x * (short)(segptr->imxform[0][1] & 0xFFFF) >> shiftx) +
|
|
p1->y * (segptr->imxform[1][1] >> 16) +
|
|
(p1y * (short)(segptr->imxform[1][1] & 0xFFFF) >> shifty) +
|
|
p1->z * (segptr->imxform[2][1] >> 16) +
|
|
(p1z * (short)(segptr->imxform[2][1] & 0xFFFF) >> shiftz) +
|
|
segptr->imxform[3][1];
|
|
|
|
p2->z = p1->z;
|
|
/* We don't compute p2->z here since the only visible effect
|
|
would be for view surfaces doing hidden surface elimination
|
|
and our current z-buffer routines don't handle repainting
|
|
with dynamic image transformations. Note that this means
|
|
that even static image transformations may not yield a
|
|
correct result.
|
|
*/
|
|
}
|
|
}
|
|
/*--------------------------------------*/
|
|
_core_imszpt3( segptr, p1, p2) register ipt_type *p1, *p2; segstruc *segptr;
|
|
{ /* image transform integer point in NDC coordinates */
|
|
_core_imxfrm3(segptr, p1, p2);
|
|
p2->x -= segptr->imxform[3][0];
|
|
p2->y -= segptr->imxform[3][1];
|
|
}
|
|
|
|
/*---------------------------------------*/
|
|
|
|
static mkwec(v, wec, outcode)
|
|
ipt_type *v;
|
|
int wec[], *outcode;
|
|
{
|
|
*outcode = 0;
|
|
if ((wec[0] = v->w + v->x) < 0) *outcode |= 1;
|
|
if ((wec[1] = v->w - v->x) < 0) *outcode |= 2;
|
|
if ((wec[2] = v->w + v->y) < 0) *outcode |= 4;
|
|
if ((wec[3] = v->w - v->y) < 0) *outcode |= 8;
|
|
if ((wec[4] = v->z) < 0) *outcode |= 16;
|
|
if ((wec[5] = v->w - v->z) < 0) *outcode |= 32;
|
|
*outcode &= _core_wclipplanes;
|
|
}
|
|
|
|
|
|
int _core_clipvec(v1, v2)
|
|
ipt_type *v1, *v2;
|
|
{ /* 3-D Clipper. Clips vector from v1 to v2 to view
|
|
volume. Operates in homogeneous coordinates.
|
|
Cohen-Sutherland algorithm with window-edge
|
|
coordinates adapted from Newman & Sproull (2nd Ed.).
|
|
Lines with endpoints with negative w are not
|
|
treated properly. This can be changed later if
|
|
necessary. */
|
|
|
|
int wec1[6], wec2[6], outcodes, outcode1, outcode2;
|
|
u_int t1, t2, t;
|
|
int i, j, n, d;
|
|
int dx, dy, dz, dw;
|
|
int shiftx, shifty, shiftz, shiftw;
|
|
int clipcoord, clipcoord2;
|
|
short sdx, sdy, sdz, sdw;
|
|
|
|
mkwec(v1, wec1, &outcode1);
|
|
mkwec(v2, wec2, &outcode2);
|
|
if (!(outcodes = outcode1 | outcode2))
|
|
return(TRUE);
|
|
if (outcode1 & outcode2)
|
|
return(FALSE);
|
|
t1 = 0;
|
|
t2 = 65536;
|
|
j = 1;
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
if (outcodes & j)
|
|
{
|
|
/* The following several lines accomplish the
|
|
computation t = wec1[i] / (wec1[i] - wec2[i])
|
|
where t is a fixed-point number with the
|
|
bottom 16 bits the fractional part. Thus
|
|
the code maintains adequate precision and
|
|
guards against overflow.
|
|
Note that the numerator and denominator have
|
|
the same sign and that abs(n) <= abs(d).
|
|
*/
|
|
if ((n = wec1[i]) < 0)
|
|
{
|
|
n = -n;
|
|
d = wec2[i] - wec1[i];
|
|
}
|
|
else
|
|
d = wec1[i] - wec2[i];
|
|
while (n > 65535)
|
|
{
|
|
n >>= 1;
|
|
d >>= 1;
|
|
}
|
|
t = ((u_int) n * 65536) / (u_int) d;
|
|
if (outcode1 & j)
|
|
{
|
|
if (t > t1)
|
|
t1 = t;
|
|
}
|
|
else
|
|
{
|
|
if (t < t2)
|
|
t2 = t;
|
|
}
|
|
}
|
|
j <<= 1;
|
|
}
|
|
if (t2 < t1)
|
|
return(FALSE);
|
|
/* Compute magnitudes and signs of
|
|
deltas in preparation for computing
|
|
clipped endpoints below.
|
|
Also scale deltas to prevent overflow
|
|
below.
|
|
*/
|
|
if ((dx = v2->x - v1->x) < 0)
|
|
{
|
|
dx = -dx;
|
|
sdx = 1;
|
|
}
|
|
else
|
|
sdx = 0;
|
|
shiftx = 16;
|
|
while (dx > 65535)
|
|
{
|
|
dx >>= 1;
|
|
shiftx--;
|
|
}
|
|
if ((dy = v2->y - v1->y) < 0)
|
|
{
|
|
dy = -dy;
|
|
sdy = 1;
|
|
}
|
|
else
|
|
sdy = 0;
|
|
shifty = 16;
|
|
while (dy > 65535)
|
|
{
|
|
dy >>= 1;
|
|
shifty--;
|
|
}
|
|
if ((dz = v2->z - v1->z) < 0)
|
|
{
|
|
dz = -dz;
|
|
sdz = 1;
|
|
}
|
|
else
|
|
sdz = 0;
|
|
shiftz = 16;
|
|
while (dz > 65535)
|
|
{
|
|
dz >>= 1;
|
|
shiftz--;
|
|
}
|
|
if ((dw = v2->w - v1->w) < 0)
|
|
{
|
|
dw = -dw;
|
|
sdw = 1;
|
|
}
|
|
else
|
|
sdw = 0;
|
|
shiftw = 16;
|
|
while (dw > 65535)
|
|
{
|
|
dw >>= 1;
|
|
shiftw--;
|
|
}
|
|
if (t2 != 65536)
|
|
{
|
|
register int d;
|
|
/* The following lines compute
|
|
v2->x = v1->x + ((t2 * dx) >> 16)
|
|
The scaling done above prevents
|
|
overflow for large dx.
|
|
*/
|
|
(u_int) d = (t2 * (u_int) dx) >> shiftx;
|
|
if (sdx)
|
|
d = -d;
|
|
v2->x = v1->x + d;
|
|
|
|
/* v2->y = v1->y + ((t2 * dy) >> 16) */
|
|
(u_int) d = (t2 * (u_int) dy) >> shifty;
|
|
if (sdy)
|
|
d = -d;
|
|
v2->y = v1->y + d;
|
|
|
|
/* v2->z = v1->z + ((t2 * dz) >> 16) */
|
|
(u_int) d = (t2 * (u_int) dz) >> shiftz;
|
|
if (sdz)
|
|
d = -d;
|
|
v2->z = v1->z + d;
|
|
|
|
/* v2->w = v1->w + ((t2 * dw) >> 16) */
|
|
(u_int) d = (t2 * (u_int) dw) >> shiftw;
|
|
if (sdw)
|
|
d = -d;
|
|
v2->w = v1->w + d;
|
|
|
|
/* Now clamp clipped coords to view
|
|
volume to prevent horrible effects
|
|
from roundoff error.
|
|
*/
|
|
clipcoord = v2->w;
|
|
clipcoord2 = clipcoord << 1;
|
|
|
|
if ((_core_wclipplanes & 0x3) &&
|
|
((u_int) (v2->x + clipcoord) > clipcoord2))
|
|
if (v2->x < 0)
|
|
v2->x = -clipcoord;
|
|
else
|
|
v2->x = clipcoord;
|
|
|
|
if ((_core_wclipplanes & 0xC) &&
|
|
((u_int) (v2->y + clipcoord) > clipcoord2))
|
|
if (v2->y < 0)
|
|
v2->y = -clipcoord;
|
|
else
|
|
v2->y = clipcoord;
|
|
|
|
if ((_core_wclipplanes & 0x10) && (v2->z < 0))
|
|
v2->z = 0;
|
|
|
|
if ((_core_wclipplanes & 0x20) && (v2->z > clipcoord))
|
|
v2->z = clipcoord;
|
|
}
|
|
if (t1 != 0)
|
|
{
|
|
register int d;
|
|
|
|
/* v1->x += (t1 * dx) >> 16 */
|
|
(u_int) d = (t1 * (u_int) dx) >> shiftx;
|
|
if (sdx)
|
|
d = -d;
|
|
v1->x += d;
|
|
|
|
/* v1->y += (t1 * dy) >> 16 */
|
|
(u_int) d = (t1 * (u_int) dy) >> shifty;
|
|
if (sdy)
|
|
d = -d;
|
|
v1->y += d;
|
|
|
|
/* v1->z += (t1 * dz) >> 16 */
|
|
(u_int) d = (t1 * (u_int) dz) >> shiftz;
|
|
if (sdz)
|
|
d = -d;
|
|
v1->z += d;
|
|
|
|
/* v1->w += (t1 * dw) >> 16 */
|
|
(u_int) d = (t1 * (u_int) dw) >> shiftw;
|
|
if (sdw)
|
|
d = -d;
|
|
v1->w += d;
|
|
|
|
/* Now clamp clipped coords to view
|
|
volume to prevent horrible effects
|
|
from roundoff error.
|
|
*/
|
|
clipcoord = v1->w;
|
|
clipcoord2 = clipcoord << 1;
|
|
|
|
if ((_core_wclipplanes & 0x3) &&
|
|
((u_int) (v1->x + clipcoord) > clipcoord2))
|
|
if (v1->x < 0)
|
|
v1->x = -clipcoord;
|
|
else
|
|
v1->x = clipcoord;
|
|
|
|
if ((_core_wclipplanes & 0xC) &&
|
|
((u_int) (v1->y + clipcoord) > clipcoord2))
|
|
if (v1->y < 0)
|
|
v1->y = -clipcoord;
|
|
else
|
|
v1->y = clipcoord;
|
|
|
|
if ((_core_wclipplanes & 0x10) && (v1->z < 0))
|
|
v1->z = 0;
|
|
|
|
if ((_core_wclipplanes & 0x20) && (v1->z > clipcoord))
|
|
v1->z = clipcoord;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/*--------------------------------------*/
|
|
|
|
_core_clippt3(x,y,z) int x,y,z;
|
|
{ /* return true if point is in view window */
|
|
|
|
if ((_core_wndwclip &&
|
|
((x < -MAX_CLIP_COORD) || (x > MAX_CLIP_COORD) ||
|
|
(y < -MAX_CLIP_COORD) || (y > MAX_CLIP_COORD)))
|
|
|| (_core_frontclip && (z < 0))
|
|
|| (_core_backclip && (z > MAX_CLIP_COORD)))
|
|
|
|
return(FALSE);
|
|
|
|
else
|
|
return(TRUE);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------
|
|
Polygon clipper for 3-D polygons. Uses Sutherland Hodgeman algorithm
|
|
in 'Reentrant Polygon Clipping', CACM 17:1, January 1974.
|
|
Two function calls are included clipvertex( p) must be called for
|
|
each vertex of a polygon and clipend() is called to terminate the
|
|
polygon. Output vertices are written to the global array 'vtxlist'.
|
|
*/
|
|
|
|
/*------------globals---------------------*/
|
|
#define LEFTPLANE 0
|
|
#define RIGHTPLANE 1
|
|
#define BOTTOM 2
|
|
#define TOP 3
|
|
#define NEAR 4
|
|
#define FAR 5
|
|
#define VTXSIZE 7
|
|
|
|
static int procvtx(), polclos(), outvtx(), polout();
|
|
|
|
static struct clipplane {
|
|
struct clipplane *nextplane; /* ptr to data for next clip plane */
|
|
int (*procvtx)(); /* vertex processing routine */
|
|
int (*polclos)(); /* close-polygon-entry routine */
|
|
short firstvtx; /* TRUE if this is 1st vertex */
|
|
short planeno; /* clip plane number for this plane */
|
|
short nout; /* no. vtxs output by this stage */
|
|
vtxtype f, /* 1st vertex of polygon */
|
|
s, /* saved previous vtx of current pol */
|
|
i; /* intersect of edge with clip plane */
|
|
} planes[6] = { /* 6 clipping planes */
|
|
{&planes[1], procvtx, polclos, TRUE, LEFTPLANE},
|
|
{&planes[2], procvtx, polclos, TRUE, RIGHTPLANE},
|
|
{&planes[3], procvtx, polclos, TRUE, BOTTOM},
|
|
{&planes[4], procvtx, polclos, TRUE, TOP},
|
|
{&planes[5], procvtx, polclos, TRUE, NEAR},
|
|
{&planes[0], outvtx, polout, TRUE, FAR}
|
|
};
|
|
|
|
static int pclipplanes = 0x3F; /* Format of pclipplanes and _core_wclipplanes
|
|
is ...|F|N|T|B|R|L| */
|
|
|
|
/*-------------------------------------------
|
|
static printplanes()
|
|
{
|
|
int i;
|
|
for (i=0; i<6; i++) {
|
|
fprintf(stderr, " %d %d %d\n", planes[i].firstvtx, planes[i].planeno,
|
|
planes[i].nout);
|
|
fprintf(stderr, " %d %d %d %d\n", planes[i].f.x,planes[i].f.y,
|
|
planes[i].f.z,planes[i].f.w);
|
|
fprintf(stderr, " %d %d %d %d\n", planes[i].s.x,planes[i].s.y,
|
|
planes[i].s.z,planes[i].s.w);
|
|
fprintf(stderr, " %d %d %d %d\n", planes[i].i.x,planes[i].i.y,
|
|
planes[i].i.z,planes[i].i.w);
|
|
}
|
|
}
|
|
---------------------------------------------*/
|
|
/*------------------------------------*/
|
|
_core_clpvtx3( p) vtxtype *p;
|
|
{ /* hand this routine each vertex */
|
|
/* This routine assumes that
|
|
_core_wclipplanes != 0, so it should
|
|
never be called unless at least one
|
|
plane is being clipped against. */
|
|
int i, j;
|
|
|
|
if ( _core_wclipplanes != pclipplanes)
|
|
{
|
|
j = 0;
|
|
if (_core_wndwclip)
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
planes[i].nextplane = &planes[i + 1];
|
|
planes[i].procvtx = procvtx;
|
|
planes[i].polclos = polclos;
|
|
planes[i].firstvtx = TRUE;
|
|
planes[i].planeno = LEFTPLANE + i;
|
|
j++;
|
|
}
|
|
if (_core_frontclip)
|
|
{
|
|
planes[j].nextplane = &planes[j + 1];
|
|
planes[j].procvtx = procvtx;
|
|
planes[j].polclos = polclos;
|
|
planes[j].firstvtx = TRUE;
|
|
planes[j].planeno = NEAR;
|
|
j++;
|
|
}
|
|
if (_core_backclip)
|
|
{
|
|
planes[j].nextplane = &planes[0];
|
|
planes[j].procvtx = outvtx;
|
|
planes[j].polclos = polout;
|
|
planes[j].firstvtx = TRUE;
|
|
planes[j].planeno = FAR;
|
|
}
|
|
else
|
|
{
|
|
planes[--j].nextplane = &planes[0];
|
|
planes[j].procvtx = outvtx;
|
|
planes[j].polclos = polout;
|
|
}
|
|
pclipplanes = _core_wclipplanes;
|
|
}
|
|
if (_core_vwstate.projtype == PARALLEL) p->w = MAX_CLIP_COORD;
|
|
procvtx( p, &planes[0]);
|
|
}
|
|
/*------------------------------------*/
|
|
_core_clpend3() /* this routine terminates polygon */
|
|
{
|
|
polclos( &planes[0]);
|
|
}
|
|
|
|
/*------------------------------------*/
|
|
static procvtx( p, plane) vtxtype *p; struct clipplane *plane;
|
|
{
|
|
if (plane->firstvtx) {
|
|
plane->f = *p; /* f is first vertex of polygon */
|
|
plane->s = *p; /* s is previous 'saved' vertex */
|
|
}
|
|
else {
|
|
if (linecross( plane, p)) { /* if line sp crosses plane */
|
|
plane->s = *p; /* compute intersect vtx i */
|
|
(*(plane->procvtx))( &plane->i, plane->nextplane);
|
|
}
|
|
else plane->s = *p;
|
|
}
|
|
if ( visible( plane)) { /* if s on visible side of plane */
|
|
(*(plane->procvtx))( &plane->s, plane->nextplane);
|
|
plane->nout++;
|
|
}
|
|
plane->firstvtx = FALSE;
|
|
}
|
|
|
|
/*-----------------------------------------*/
|
|
static polclos( pl) register struct clipplane *pl;
|
|
{
|
|
if (pl->nout ) {
|
|
if (linecross( pl, &pl->f)) { /* handle last edge */
|
|
(*(pl->procvtx))( &pl->i, pl->nextplane);
|
|
}
|
|
}
|
|
pl->firstvtx = TRUE;
|
|
pl->nout = 0;
|
|
(*(pl->polclos))( pl->nextplane);
|
|
}
|
|
|
|
/*--------------------------------------------*/
|
|
static outvtx( p, pl) vtxtype *p; struct clipplane *pl;
|
|
{ /* output routine from last stage of clipper */
|
|
/* Now clamp clipped coords to view
|
|
volume to prevent horrible effects
|
|
from roundoff error.
|
|
*/
|
|
if ( (_core_wclipplanes & 0x3) && (u_int) (p->x + p->w) > (p->w << 1))
|
|
if (p->x < 0)
|
|
p->x = -p->w;
|
|
else
|
|
p->x = p->w;
|
|
|
|
if ( (_core_wclipplanes & 0xC) && (u_int) (p->y + p->w) > (p->w <<1))
|
|
if (p->y < 0)
|
|
p->y = -p->w;
|
|
else
|
|
p->y = p->w;
|
|
|
|
if ( (_core_wclipplanes &0x10) && p->z < 0) p->z = 0;
|
|
if ( (_core_wclipplanes &0x20) && p->z > p->w) p->z = p->w;
|
|
pl->nout++;
|
|
_core_vtxlist[_core_vtxcount++] = *p;
|
|
}
|
|
/*--------------------------------------------*/
|
|
static polout( pl) struct clipplane *pl;
|
|
{
|
|
if (pl->nout ) { /* later may want to notify about end of polygon */
|
|
}
|
|
pl->nout = 0;
|
|
}
|
|
|
|
/*----------------------------------------*/
|
|
static linecross( pl, p) struct clipplane *pl; vtxtype *p;
|
|
{
|
|
register int shift;
|
|
register u_int alpha, n, d;
|
|
int svis, pvis, i;
|
|
int *ptri, *ptrs, *ptrp;
|
|
short sd;
|
|
|
|
switch( pl->planeno) {
|
|
case LEFTPLANE:
|
|
svis = pl->s.x + pl->s.w; /* x-(-w) */
|
|
pvis = p->x + p->w;
|
|
break;
|
|
case RIGHTPLANE:
|
|
svis = pl->s.w - pl->s.x; /* -(x-w) */
|
|
pvis = p->w - p->x;
|
|
break;
|
|
case BOTTOM:
|
|
svis = pl->s.y + pl->s.w; /* y-(-w) */
|
|
pvis = p->y + p->w;
|
|
break;
|
|
case TOP:
|
|
svis = pl->s.w - pl->s.y; /* -(y-w) */
|
|
pvis = p->w - p->y;
|
|
break;
|
|
case NEAR:
|
|
svis = pl->s.z; /* (z-0) */
|
|
pvis = p->z;
|
|
break;
|
|
case FAR:
|
|
svis = pl->s.w - pl->s.z; /* -(z-w) */
|
|
pvis = p->w - p->z;
|
|
break;
|
|
}
|
|
if ((svis ^ pvis) & 0x80000000) { /* if opposite signs then on */
|
|
if (((int) n = svis) < 0) /* opposite sides of plane */
|
|
{
|
|
(int) n = - (int) n;
|
|
(int) d = pvis - svis;
|
|
}
|
|
else
|
|
(int) d = svis - pvis;
|
|
while (n > 65535)
|
|
{
|
|
n >>= 1;
|
|
d >>= 1;
|
|
}
|
|
alpha = (n << 16) / d;
|
|
ptri = &pl->i.x;
|
|
ptrs = &pl->s.x;
|
|
ptrp = &p->x;
|
|
for (i=0; i<VTXSIZE; i++){ /* compute intersection vrtx */
|
|
if (((int) d = *ptrp++ - *ptrs) < 0)
|
|
{
|
|
(int) d = - (int) d;
|
|
sd = 1;
|
|
}
|
|
else
|
|
sd = 0;
|
|
shift = 16;
|
|
while (d > 65535)
|
|
{
|
|
d >>= 1;
|
|
shift--;
|
|
}
|
|
d = (alpha * d) >> shift;
|
|
if (sd)
|
|
(int) d = - (int) d;
|
|
*ptri++ = *ptrs++ + (int) d;
|
|
}
|
|
return( TRUE);
|
|
}
|
|
else return( FALSE);
|
|
}
|
|
/*-------------------------------------*/
|
|
static visible( pl) struct clipplane *pl;
|
|
{
|
|
int svis;
|
|
|
|
switch( pl->planeno) {
|
|
case LEFTPLANE:
|
|
svis = pl->s.x + pl->s.w; /* x-(-w) */
|
|
break;
|
|
case RIGHTPLANE:
|
|
svis = pl->s.w - pl->s.x; /* -(x-w) */
|
|
break;
|
|
case BOTTOM:
|
|
svis = pl->s.y + pl->s.w; /* y-(-w) */
|
|
break;
|
|
case TOP:
|
|
svis = pl->s.w - pl->s.y; /* -(y-w) */
|
|
break;
|
|
case NEAR:
|
|
svis = pl->s.z; /* (z-0) */
|
|
break;
|
|
case FAR:
|
|
svis = pl->s.w - pl->s.z; /* -(z-w) */
|
|
break;
|
|
}
|
|
if (svis >= 0) return( TRUE);
|
|
else return( FALSE);
|
|
}
|