home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
back2roots/padua
/
padua.7z
/
padua
/
gfx
/
dkb212sr.lzh
/
quadrics.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-30
|
12KB
|
363 lines
/*****************************************************************************
*
* quadrics.c
*
* from DKBTrace (c) 1990 David Buck
*
* This module implements the code for the quadric shape primitive.
*
* This software is freely distributable. The source and/or object code may be
* copied or uploaded to communications services so long as this notice remains
* at the top of each file. If any changes are made to the program, you must
* clearly indicate in the documentation and in the programs startup message
* who it was who made the changes. The documentation should also describe what
* those changes were. This software may not be included in whole or in
* part into any commercial package without the express written consent of the
* author. It may, however, be included in other public domain or freely
* distributed software so long as the proper credit for the software is given.
*
* This software is provided as is without any guarantees or warranty. Although
* the author has attempted to find and correct any bugs in the software, he
* is not responsible for any damage caused by the use of the software. The
* author is under no obligation to provide service, corrections, or upgrades
* to this package.
*
* Despite all the legal stuff above, if you do find bugs, I would like to hear
* about them. Also, if you have any comments or questions, you may contact me
* at the following address:
*
* David Buck
* 22C Sonnet Cres.
* Nepean Ontario
* Canada, K2H 8W7
*
* I can also be reached on the following bulleton boards:
*
* OMX (613) 731-3419
* Mystic (613) 596-4249 or (613) 596-4772
*
* Fidonet: 1:163/109.9
* Internet: dbuck@ccs.carleton.ca
* The "You Can Call Me RAY" BBS (708) 358-5611
*
* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
*
* The "You Can Call Me RAY" BBS (708) 358-5611
* The Information Exchange BBS (708) 945-5575
*
*****************************************************************************/
#include "frame.h"
#include "vector.h"
#include "dkbproto.h"
METHODS Quadric_Methods =
{ Object_Intersect, All_Quadric_Intersections,
Inside_Quadric, Quadric_Normal,
Copy_Quadric,
Translate_Quadric, Rotate_Quadric,
Scale_Quadric, Invert_Quadric};
extern RAY *VP_Ray;
extern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
int All_Quadric_Intersections (Object, Ray, Depth_Queue)
OBJECT *Object;
RAY *Ray;
PRIOQ *Depth_Queue;
{
QUADRIC *Shape = (QUADRIC *) Object;
DBL Depth1, Depth2;
VECTOR Intersection_Point;
INTERSECTION Local_Element;
register int Intersection_Found;
Intersection_Found = FALSE;
if (Intersect_Quadric (Ray, Shape, &Depth1, &Depth2))
{
Local_Element.Depth = Depth1;
Local_Element.Object = Shape -> Parent_Object;
VScale (Intersection_Point, Ray -> Direction, Depth1);
VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
Local_Element.Point = Intersection_Point;
Local_Element.Shape = (SHAPE *)Shape;
pq_add (Depth_Queue, &Local_Element);
Intersection_Found = TRUE;
if (Depth2 != Depth1)
{
Local_Element.Depth = Depth2;
Local_Element.Object = Shape -> Parent_Object;
VScale (Intersection_Point, Ray -> Direction, Depth2);
VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
Local_Element.Point = Intersection_Point;
Local_Element.Shape = (SHAPE *) Shape;
pq_add (Depth_Queue, &Local_Element);
Intersection_Found = TRUE;
}
}
return (Intersection_Found);
}
int Intersect_Quadric (Ray, Shape, Depth1, Depth2)
RAY *Ray;
QUADRIC *Shape;
DBL *Depth1, *Depth2;
{
register DBL Square_Term, Linear_Term, Constant_Term, Temp_Term;
register DBL Determinant, Determinant_2, A2, BMinus;
Ray_Quadric_Tests++;
if (!Ray->Quadric_Constants_Cached)
Make_Ray(Ray);
if (Shape -> Non_Zero_Square_Term)
{
VDot (Square_Term, Shape -> Object_2_Terms, Ray -> Direction_2);
VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Dir_Dir);
Square_Term += Temp_Term;
}
else
Square_Term = 0.0;
VDot (Linear_Term, Shape -> Object_2_Terms, Ray -> Initial_Direction);
Linear_Term *= 2.0;
VDot (Temp_Term, Shape -> Object_Terms, Ray -> Direction);
Linear_Term += Temp_Term;
VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Init_Dir);
Linear_Term += Temp_Term;
if (Ray == VP_Ray)
if (!Shape -> Constant_Cached)
{
VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
Constant_Term += Temp_Term + Shape -> Object_Constant;
Shape -> Object_VP_Constant = Constant_Term;
Shape -> Constant_Cached = TRUE;
}
else
Constant_Term = Shape -> Object_VP_Constant;
else
{
VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
Constant_Term += Temp_Term + Shape -> Object_Constant;
}
VDot (Temp_Term, Shape -> Object_Mixed_Terms,
Ray -> Mixed_Initial_Initial);
Constant_Term += Temp_Term;
if (Square_Term != 0.0)
{
/* The equation is quadratic - find its roots */
Determinant_2 = Linear_Term * Linear_Term - 4.0 * Square_Term * Constant_Term;
if (Determinant_2 < 0.0)
return (FALSE);
Determinant = sqrt (Determinant_2);
A2 = Square_Term * 2.0;
BMinus = Linear_Term * -1.0;
*Depth1 = (BMinus + Determinant) / A2;
*Depth2 = (BMinus - Determinant) / A2;
}
else
{
/* There are no quadratic terms. Solve the linear equation instead. */
if (Linear_Term == 0.0)
return (FALSE);
*Depth1 = Constant_Term * -1.0 / Linear_Term;
*Depth2 = *Depth1;
}
if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
return (FALSE);
else
*Depth1 = *Depth2;
else
if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
*Depth2 = *Depth1;
Ray_Quadric_Tests_Succeeded++;
return (TRUE);
}
int Inside_Quadric (Test_Point, Object)
VECTOR *Test_Point;
OBJECT *Object;
{
QUADRIC *Shape = (QUADRIC *) Object;
VECTOR New_Point;
register DBL Result, Linear_Term, Square_Term;
VDot (Linear_Term, *Test_Point, Shape -> Object_Terms);
Result = Linear_Term + Shape -> Object_Constant;
VSquareTerms (New_Point, *Test_Point);
VDot (Square_Term, New_Point, Shape -> Object_2_Terms);
Result += Square_Term;
Result += Shape -> Object_Mixed_Terms.x * (Test_Point -> x) * (Test_Point -> y)
+ Shape -> Object_Mixed_Terms.y * (Test_Point -> x) * (Test_Point -> z)
+ Shape -> Object_Mixed_Terms.z * (Test_Point -> y) * (Test_Point -> z);
if (Result < Small_Tolerance)
return (TRUE);
return (FALSE);
}
void Quadric_Normal (Result, Object, Intersection_Point)
VECTOR *Result, *Intersection_Point;
OBJECT *Object;
{
QUADRIC *Intersection_Shape = (QUADRIC *) Object;
VECTOR Derivative_Linear;
DBL Len;
VScale (Derivative_Linear, Intersection_Shape -> Object_2_Terms, 2.0);
VEvaluate (*Result, Derivative_Linear, *Intersection_Point);
VAdd (*Result, *Result, Intersection_Shape -> Object_Terms);
Result -> x +=
Intersection_Shape->Object_Mixed_Terms.x * Intersection_Point->y +
Intersection_Shape->Object_Mixed_Terms.y * Intersection_Point->z;
Result -> y +=
Intersection_Shape->Object_Mixed_Terms.x * Intersection_Point->x +
Intersection_Shape->Object_Mixed_Terms.z * Intersection_Point->z;
Result -> z +=
Intersection_Shape->Object_Mixed_Terms.y * Intersection_Point->x +
Intersection_Shape->Object_Mixed_Terms.z * Intersection_Point->y;
Len = Result->x * Result->x + Result->y * Result->y + Result->z * Result->z;
Len = sqrt(Len);
if (Len == 0.0) {
/* The normal is not defined at this point of the surface. Set it
to any arbitrary direction. */
Result->x = 1.0;
Result->y = 0.0;
Result->z = 0.0;
}
else {
Result->x /= Len; /* normalize the normal */
Result->y /= Len;
Result->z /= Len;
}
}
void *Copy_Quadric (Object)
OBJECT *Object;
{
QUADRIC *New_Shape;
New_Shape = Get_Quadric_Shape ();
*New_Shape = *((QUADRIC *) Object);
New_Shape -> Next_Object = NULL;
if (New_Shape->Shape_Texture != NULL)
New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
return (New_Shape);
}
void Transform_Quadric (Shape, Transformation)
QUADRIC *Shape;
TRANSFORMATION *Transformation;
{
MATRIX Quadric_Matrix, Transform_Transposed;
Quadric_To_Matrix (Shape, (MATRIX *) &Quadric_Matrix[0][0]);
MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &(Transformation -> inverse[0][0]), (MATRIX *) &Quadric_Matrix[0][0]);
MTranspose ((MATRIX *) &Transform_Transposed[0][0], (MATRIX *) &(Transformation -> inverse[0][0]));
MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Transform_Transposed[0][0]);
Matrix_To_Quadric ((MATRIX *) &Quadric_Matrix[0][0], Shape);
}
void Quadric_To_Matrix (Quadric, Matrix)
QUADRIC *Quadric;
MATRIX *Matrix;
{
MZero (Matrix);
(*Matrix)[0][0] = Quadric -> Object_2_Terms.x;
(*Matrix)[1][1] = Quadric -> Object_2_Terms.y;
(*Matrix)[2][2] = Quadric -> Object_2_Terms.z;
(*Matrix)[0][1] = Quadric -> Object_Mixed_Terms.x;
(*Matrix)[0][2] = Quadric -> Object_Mixed_Terms.y;
(*Matrix)[0][3] = Quadric -> Object_Terms.x;
(*Matrix)[1][2] = Quadric -> Object_Mixed_Terms.z;
(*Matrix)[1][3] = Quadric -> Object_Terms.y;
(*Matrix)[2][3] = Quadric -> Object_Terms.z;
(*Matrix)[3][3] = Quadric -> Object_Constant;
}
void Matrix_To_Quadric (Matrix, Quadric)
MATRIX *Matrix;
QUADRIC *Quadric;
{
Quadric -> Object_2_Terms.x = (*Matrix)[0][0];
Quadric -> Object_2_Terms.y = (*Matrix)[1][1];
Quadric -> Object_2_Terms.z = (*Matrix)[2][2];
Quadric -> Object_Mixed_Terms.x = (*Matrix)[0][1] + (*Matrix)[1][0];
Quadric -> Object_Mixed_Terms.y = (*Matrix)[0][2] + (*Matrix)[2][0];
Quadric -> Object_Terms.x = (*Matrix)[0][3] + (*Matrix)[3][0];
Quadric -> Object_Mixed_Terms.z = (*Matrix)[1][2] + (*Matrix)[2][1];
Quadric -> Object_Terms.y = (*Matrix)[1][3] + (*Matrix)[3][1];
Quadric -> Object_Terms.z = (*Matrix)[2][3] + (*Matrix)[3][2];
Quadric -> Object_Constant = (*Matrix)[3][3];
}
void Translate_Quadric (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORMATION Transformation;
Get_Translation_Transformation (&Transformation, Vector);
Transform_Quadric ((QUADRIC *) Object, &Transformation);
Translate_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
}
void Rotate_Quadric (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORMATION Transformation;
Get_Rotation_Transformation (&Transformation, Vector);
Transform_Quadric ((QUADRIC *) Object, &Transformation);
Rotate_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
}
void Scale_Quadric (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORMATION Transformation;
Get_Scaling_Transformation (&Transformation, Vector);
Transform_Quadric ((QUADRIC *) Object, &Transformation);
Scale_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
}
void Invert_Quadric (Object)
OBJECT *Object;
{
QUADRIC *Shape = (QUADRIC *) Object;
VScale (Shape -> Object_2_Terms, Shape -> Object_2_Terms, -1.0);
VScale (Shape -> Object_Mixed_Terms, Shape -> Object_Mixed_Terms, -1.0);
VScale (Shape -> Object_Terms, Shape -> Object_Terms, -1.0);
Shape -> Object_Constant *= -1.0;
}