1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
/*
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
*/
/*
*
* Routines for point definition, rotation, etc.
*
*/
#include "3d.h"
#include "globvars.h"
//code a point. fills in the p3_codes field of the point, and returns the codes
ubyte g3_code_point(g3s_point *p)
{
ubyte cc=0;
if (p->p3_x > p->p3_z)
cc |= CC_OFF_RIGHT;
if (p->p3_y > p->p3_z)
cc |= CC_OFF_TOP;
if (p->p3_x < -p->p3_z)
cc |= CC_OFF_LEFT;
if (p->p3_y < -p->p3_z)
cc |= CC_OFF_BOT;
if (p->p3_z < 0)
cc |= CC_BEHIND;
return p->p3_codes = cc;
}
//rotates a point. returns codes. does not check if already rotated
ubyte g3_rotate_point(g3s_point *dest,const vms_vector *src)
{
vms_vector tempv;
vm_vec_sub(&tempv,src,&View_position);
vm_vec_rotate(&dest->p3_vec,&tempv,&View_matrix);
dest->p3_flags = 0; //no projected
return g3_code_point(dest);
}
//checks for overflow & divides if ok, fillig in r
//returns true if div is ok, else false
int checkmuldiv(fix *r,fix a,fix b,fix c)
{
quadint q,qt;
q.low=q.high=0;
fixmulaccum(&q,a,b);
qt = q;
if (qt.high < 0)
fixquadnegate(&qt);
qt.high *= 2;
if (qt.low > 0x7fff)
qt.high++;
if (qt.high >= c)
return 0;
else {
*r = fixdivquadlong(q.low,q.high,c);
return 1;
}
}
//projects a point
void g3_project_point(g3s_point *p)
{
#ifndef __powerc
fix tx,ty;
if (p->p3_flags & PF_PROJECTED || p->p3_codes & CC_BEHIND)
return;
if (checkmuldiv(&tx,p->p3_x,Canv_w2,p->p3_z) && checkmuldiv(&ty,p->p3_y,Canv_h2,p->p3_z)) {
p->p3_sx = Canv_w2 + tx;
p->p3_sy = Canv_h2 - ty;
p->p3_flags |= PF_PROJECTED;
}
else
p->p3_flags |= PF_OVERFLOW;
#else
double fz;
if ((p->p3_flags & PF_PROJECTED) || (p->p3_codes & CC_BEHIND))
return;
if ( p->p3_z <= 0 ) {
p->p3_flags |= PF_OVERFLOW;
return;
}
fz = f2fl(p->p3_z);
p->p3_sx = fl2f(fCanv_w2 + (f2fl(p->p3_x)*fCanv_w2 / fz));
p->p3_sy = fl2f(fCanv_h2 - (f2fl(p->p3_y)*fCanv_h2 / fz));
p->p3_flags |= PF_PROJECTED;
#endif
}
//from a 2d point, compute the vector through that point
void g3_point_2_vec(vms_vector *v,short sx,short sy)
{
vms_vector tempv;
vms_matrix tempm;
tempv.x = fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.z,Matrix_scale.x);
tempv.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.z,Matrix_scale.y);
tempv.z = f1_0;
vm_vec_normalize(&tempv);
vm_copy_transpose_matrix(&tempm,&Unscaled_matrix);
vm_vec_rotate(v,&tempv,&tempm);
}
//delta rotation functions
vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx)
{
dest->x = fixmul(View_matrix.rvec.x,dx);
dest->y = fixmul(View_matrix.uvec.x,dx);
dest->z = fixmul(View_matrix.fvec.x,dx);
return dest;
}
vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy)
{
dest->x = fixmul(View_matrix.rvec.y,dy);
dest->y = fixmul(View_matrix.uvec.y,dy);
dest->z = fixmul(View_matrix.fvec.y,dy);
return dest;
}
vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz)
{
dest->x = fixmul(View_matrix.rvec.z,dz);
dest->y = fixmul(View_matrix.uvec.z,dz);
dest->z = fixmul(View_matrix.fvec.z,dz);
return dest;
}
vms_vector *g3_rotate_delta_vec(vms_vector *dest,vms_vector *src)
{
return vm_vec_rotate(dest,src,&View_matrix);
}
ubyte g3_add_delta_vec(g3s_point *dest,g3s_point *src,vms_vector *deltav)
{
vm_vec_add(&dest->p3_vec,&src->p3_vec,deltav);
dest->p3_flags = 0; //not projected
return g3_code_point(dest);
}
//calculate the depth of a point - returns the z coord of the rotated point
fix g3_calc_point_depth(vms_vector *pnt)
{
quadint q;
q.low=q.high=0;
fixmulaccum(&q,(pnt->x - View_position.x),View_matrix.fvec.x);
fixmulaccum(&q,(pnt->y - View_position.y),View_matrix.fvec.y);
fixmulaccum(&q,(pnt->z - View_position.z),View_matrix.fvec.z);
return fixquadadjust(&q);
}
|