home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
graphic
/
csg_rt
/
quad.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-09
|
12KB
|
450 lines
/*
QUAD.C Arbitrary quadratic logic
2 2 2
Defined solid for :- ax +by +cz +dxy+eyz+fzx+gx+hy+iz+j<=0
Ellisoids, spheres, infinitely long cylinders, double cones and planes are
all special case of this equation.
*/
/*...sincludes:0:*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <malloc.h>
#include <memory.h>
#include <math.h>
#include "standard.h"
#include "rt.h"
#include "vector.h"
#include "sil.h"
#define _QUAD_
#include "quad.h"
/*...vrt\46\h:0:*/
/*...vvector\46\h:0:*/
/*...vsil\46\h:0:*/
/*...vquad\46\h:0:*/
/*...e*/
/*...screate_quad \45\ create any general quadratic:0:*/
QUAD *create_quad(
double a, double b, double c,
double d, double e, double f,
double g, double h, double i,
double j
)
{
QUAD *quad;
if ( (quad = malloc(sizeof(QUAD))) == NULL )
return ( NULL );
quad -> a = a;
quad -> b = b;
quad -> c = c;
quad -> d = d;
quad -> e = e;
quad -> f = f;
quad -> g = g;
quad -> h = h;
quad -> i = i;
quad -> j = j;
return ( quad );
}
/*...e*/
/*...screate_ellipsoid \45\ create an ellipsoid of a given size at the origin:0:*/
QUAD *create_ellipsoid(double rx, double ry, double rz)
{
return ( create_quad(1.0 / (rx * rx), 1.0 / (ry * ry), 1.0 / (rz * rz),
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
-1.0) );
}
/*...e*/
/*...screate_x_ell_cyl \45\ create elliptical cylinder along x axis of given radii:0:*/
QUAD *create_x_ell_cyl(double ry, double rz)
{
return ( create_quad(0.0, 1.0 / (ry * ry), 1.0 / (rz * rz),
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
-1.0) );
}
/*...e*/
/*...screate_y_ell_cyl \45\ create elliptical cylinder along y axis of given radii:0:*/
QUAD *create_y_ell_cyl(double rx, double rz)
{
return ( create_quad(1.0 / (rx * rx), 0.0, 1.0 / (rz * rz),
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
-1.0) );
}
/*...e*/
/*...screate_z_ell_cyl \45\ create elliptical cylinder along z axis of given radii:0:*/
QUAD *create_z_ell_cyl(double rx, double ry)
{
return ( create_quad(1.0 / (rx * rx), 1.0 / (ry * ry), 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
-1.0) );
}
/*...e*/
/*...screate_x_cyl \45\ create cylinder along x axis of given radii:0:*/
QUAD *create_x_cyl(double r)
{
return ( create_x_ell_cyl(r, r) );
}
/*...e*/
/*...screate_y_cyl \45\ create cylinder along y axis of given radii:0:*/
QUAD *create_y_cyl(double r)
{
return ( create_y_ell_cyl(r, r) );
}
/*...e*/
/*...screate_z_cyl \45\ create cylinder along z axis of given radii:0:*/
QUAD *create_z_cyl(double r)
{
return ( create_z_ell_cyl(r, r) );
}
/*...e*/
/*...screate_x_ell_cone \45\ create elliptical cone along x axis of given radii:0:*/
QUAD *create_x_ell_cone(double ky, double kz)
{
return ( create_quad(-1.0, ky * ky, kz * kz,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0) );
}
/*...e*/
/*...screate_y_ell_cone \45\ create elliptical cone along y axis of given radii:0:*/
QUAD *create_y_ell_cone(double kx, double kz)
{
return ( create_quad(kx * kx, -1.0, kz * kz,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0) );
}
/*...e*/
/*...screate_z_ell_cone \45\ create elliptical cone along z axis of given radii:0:*/
QUAD *create_z_ell_cone(double kx, double ky)
{
return ( create_quad(kx * kx, ky * ky, -1.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
0.0) );
}
/*...e*/
/*...screate_x_cone \45\ create cone along x axis of given radii:0:*/
QUAD *create_x_cone(double k)
{
return ( create_x_ell_cone(k, k) );
}
/*...e*/
/*...screate_y_cone \45\ create cone along y axis of given radii:0:*/
QUAD *create_y_cone(double k)
{
return ( create_y_ell_cone(k, k) );
}
/*...e*/
/*...screate_z_cone \45\ create cone along z axis of given radii:0:*/
QUAD *create_z_cone(double k)
{
return ( create_z_ell_cone(k, k) );
}
/*...e*/
/*...scopy_quad \45\ make a copy of a quad:0:*/
QUAD *copy_quad(QUAD *quad)
{
QUAD *copy;
if ( (copy = malloc(sizeof(QUAD))) == NULL )
return ( NULL );
memcpy(copy, quad, sizeof(QUAD));
return ( copy );
}
/*...e*/
/*...sdestroy_quad \45\ destroy a quad:0:*/
void destroy_quad(QUAD *quad)
{
free(quad);
}
/*...e*/
/*...strans_x_quad \45\ translate by amount in x direction:0:*/
void trans_x_quad(QUAD *quad, double t)
{
quad -> j += (quad -> a * t * t - quad -> g * t);
quad -> i -= quad -> f * t;
quad -> h -= quad -> d * t;
quad -> g -= 2.0 * quad -> a * t;
}
/*...e*/
/*...strans_y_quad \45\ translate by amount in y direction:0:*/
void trans_y_quad(QUAD *quad, double t)
{
quad -> j += (quad -> b * t * t - quad -> h * t);
quad -> i -= quad -> e * t;
quad -> h -= 2.0 * quad -> b * t;
quad -> g -= quad -> d * t;
}
/*...e*/
/*...strans_z_quad \45\ translate by amount in z direction:0:*/
void trans_z_quad(QUAD *quad, double t)
{
quad -> j += (quad -> c * t * t - quad -> i * t);
quad -> i -= 2.0 * quad -> c * t;
quad -> h -= quad -> e * t;
quad -> g -= quad -> f * t;
}
/*...e*/
/*...sscale_x_quad \45\ scale by factor in x direction:0:*/
void scale_x_quad(QUAD *quad, double factor)
{
quad -> a /= (factor * factor);
quad -> d /= factor;
quad -> f /= factor;
quad -> g /= factor;
}
/*...e*/
/*...sscale_y_quad \45\ scale by factor in y direction:0:*/
void scale_y_quad(QUAD *quad, double factor)
{
quad -> b /= (factor * factor);
quad -> d /= factor;
quad -> e /= factor;
quad -> h /= factor;
}
/*...e*/
/*...sscale_z_quad \45\ scale by factor in z direction:0:*/
void scale_z_quad(QUAD *quad, double factor)
{
quad -> c /= (factor * factor);
quad -> e /= factor;
quad -> f /= factor;
quad -> i /= factor;
}
/*...e*/
/*...srot_x_quad \45\ rotate about x axis by given angle:0:*/
void rot_x_quad(QUAD *quad, double angle)
{
double b = quad -> b;
double c = quad -> c;
double d = quad -> d;
double e = quad -> e;
double f = quad -> f;
double h = quad -> h;
double i = quad -> i;
double ca = cos(angle);
double sa = sin(angle);
double caca = ca * ca;
double sasa = sa * sa;
double saca = sa * ca;
quad -> b = b * caca + c * sasa - e * saca;
quad -> c = b * sasa + c * caca + e * saca;
quad -> d = d * ca - f * sa;
quad -> e = 2.0 * (b - c) * saca + e * (caca - sasa);
quad -> f = d * sa + f * ca;
quad -> h = h * ca - i * sa;
quad -> i = h * sa + i * ca;
}
/*...e*/
/*...srot_y_quad \45\ rotate about y axis by given angle:0:*/
void rot_y_quad(QUAD *quad, double angle)
{
double a = quad -> a;
double c = quad -> c;
double d = quad -> d;
double e = quad -> e;
double f = quad -> f;
double g = quad -> g;
double i = quad -> i;
double ca = cos(angle);
double sa = sin(angle);
double caca = ca * ca;
double sasa = sa * sa;
double saca = sa * ca;
quad -> a = a * caca + c * sasa + f * saca;
quad -> c = a * sasa + c * caca - f * saca;
quad -> d = e * sa + d * ca;
quad -> e = e * ca - d * sa;
quad -> f = 2.0 * (c - a) * saca + f * (caca - sasa);
quad -> g = i * sa + g * ca;
quad -> i = i * ca - g * sa;
}
/*...e*/
/*...srot_z_quad \45\ rotate about z axis by given angle:0:*/
void rot_z_quad(QUAD *quad, double angle)
{
double a = quad -> a;
double b = quad -> b;
double d = quad -> d;
double e = quad -> e;
double f = quad -> f;
double g = quad -> g;
double h = quad -> h;
double ca = cos(angle);
double sa = sin(angle);
double caca = ca * ca;
double sasa = sa * sa;
double saca = sa * ca;
quad -> a = a * caca + b * sasa - d * saca;
quad -> b = a * sasa + b * caca + d * saca;
quad -> d = 2.0 * (a - b) * saca + d * (caca - sasa);
quad -> e = f * sa + e * ca;
quad -> f = f * ca - e * sa;
quad -> g = g * ca - h * sa;
quad -> h = g * sa + h * ca;
}
/*...e*/
/*...sisects_reqd_quad \45\ max number of isects we will generate:0:*/
int isects_reqd_quad(QUAD *quad)
{
quad=quad; /* Suppress 'unref arg' compiler warning */
return ( 4 );
}
/*...e*/
/*...sintersect_quad \45\ intersect quadratic:0:*/
/*
Those who don't like maths should page down a few times very rapidly!
Any point along the line we are interested in is of the form p + tq.
~ ~
2 2 2
Given: ax +by +cz +dxy+eyz+fzx+gx+hy+iz+j=0
Subs: x = x +tx y = y +ty z = z +tz
p q p q p q
2 2 2 2
Gives: (ax +by +cz +dx y +ey z +fz x )t +
q q q q q q q q q
(2[ax x +by y +cz z ]+d[x y +x y ]+e[y z +y z ]+f[z x +z x ]+gx +hy +iz )t +
p q p q p q p q q p p q q p p q q p q q q
2 2 2
(ax +by +cz +dx y +ey z +fz x +gx +hy +iz +j) = 0
p p p p p p p p p p p p
2 2 2
Opt: ax +by +cz +dx y +ey z +fz x costs 12x's and 5+'s
q q q q q q q q q
(ax +dy )x +(by +ez )y +(cz +fx )z costs 9x's and 5+'s
q q q q q q q q q
2 2 2
Opt: ax +by +cz +dx y +ey z +fz x +gx +hy +iz +j costs 15x's and 9+'s
p p p p p p p p p p p p
(ax +dy +g)x +(by +ez +h)y +(cz +fx +i)z +j costs 9x's and 9+'s
p p p p p p p p p
*/
/*...svalue_of_quad:0:*/
/*
Use this to determine value of quadratic at given point in space.
2 2 2
Opt: ax +by +cz +dxy+eyz+fzx+gx+hy+iz+j costs 15x's and 9+'s
(ax+dy+g)x+(by+ez+h)y+(cz+fx+i)z+j costs 9x's and 9+'s
*/
static double value_of_quad(void *shapeinfo, VECTOR v)
{
QUAD *quad = (QUAD *) shapeinfo;
double x = v.x, y = v.y, z = v.z;
return ( (quad -> a * x + quad -> d * y + quad -> g) * x +
(quad -> b * y + quad -> e * z + quad -> h) * y +
(quad -> c * z + quad -> f * x + quad -> i) * z +
quad -> j );
}
/*...e*/
void intersect_quad(QUAD *quad, VECTOR p, VECTOR q, SIL *sil)
{
double a = quad -> a;
double b = quad -> b;
double c = quad -> c;
double d = quad -> d;
double e = quad -> e;
double f = quad -> f;
double g = quad -> g;
double h = quad -> h;
double i = quad -> i;
double j = quad -> j;
double qa = (a * q.x + d * q.y) * q.x +
(b * q.y + e * q.z) * q.y +
(c * q.z + f * q.x) * q.z;
double xx = (a * p.x * q.x + b * p.y * q.y + c * p.z * q.z);
double qb = xx + xx +
d * (p.x * q.y + q.x * p.y) +
e * (p.y * q.z + q.y * p.z) +
f * (p.z * q.x + q.z * p.x) +
g * q.x + h * q.y + i * q.z;
double qc = (a * p.x + d * p.y + g) * p.x +
(b * p.y + e * p.z + h) * p.y +
(c * p.z + f * p.x + i) * p.z + j;
intersect_quadratic_t(qa, qb, qc, p, q,
(void *) quad, value_of_quad, sil);
}
/*...e*/
/*...snormal_to_quad \45\ find normal of surface at a given point:0:*/
/*
Use partial derivatives to find normal at a given point.
Given: 2 2 2
ax +by +cz +dxy+eyz+fzx+gx+hy+iz+j=0
d/dx: 2ax+dy+fz+g
d/dy: 2by+dx+ez+h
d/dz: 2cz+ey+fx+i
*/
VECTOR normal_to_quad(QUAD *quad, VECTOR p)
{
double a = quad -> a;
double b = quad -> b;
double c = quad -> c;
double d = quad -> d;
double e = quad -> e;
double f = quad -> f;
double g = quad -> g;
double h = quad -> h;
double i = quad -> i;
double x = p.x;
double y = p.y;
double z = p.z;
double ax = a * x;
double by = b * y;
double cz = c * z;
VECTOR normal;
normal.x = ax + ax + d * y + f * z + g;
normal.y = by + by + d * x + e * z + h;
normal.z = cz + cz + e * y + f * x + i;
return ( normal );
}
/*...e*/