home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
vectoper.zip
/
RTIMOps.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-19
|
10KB
|
320 lines
#include <stdio.h>
#include <math.h>
#include "RTTypes.h"
#include "RTVecOps.h"
#include "RTScreen.h"
#include "RTObjOps.h"
#include "RTIMOps.h"
#include "RayTrace.h"
#include "RTIntOps.h"
/*
*******************************************************************************
*
* Name: Illumination_model
*
* Purpose: this routine implements the warn lighting model. It sums
* intensities through multiple light sources and ammends the
* the each intensity if it is specified to be a directed light
* source. In additions, shadows are handled through the use
* of a "light (shadow) feeler". It is extended to the light
* source and determines a filter value "Si" that is applied
* to each light source based on the objects that lie in the
* path between the point being illuminated and the illumina-
* tion source.
*
*
*
* Input Parameters
*
* pt - point to be illuminated
* N_vec - normal vector at point
* View_vec - view vector at point
*
* Od - diffuse color at point
* Os - specular color at point
*
* Ka - ambient reflection constant at point
* Kd - diffuse reflection constant at point
* Ks - specular reflection constant at point
*
* n - phong constant
*
*
* Output Parameters
*
* U - diffuse component of illumination
* V - specular component of illumination
*
*******************************************************************************
*/
void
Illumination_Model(Vector pt, Vector *N_vec, Vector *View_vec,
Vector *Od, Vector *Os,
float Ka, float Kd, float Ks,
Vector *U, Vector *V)
{
Vector L_vec, negL_vec, Lp;
Vector R_vec;
Vector U_vec, V_vec;
float N_dot_L;
float cos_theta, cos_alpha, cos_gama;
float Si;
float t, s;
int i;
/*
* initialize light component variables
*/
vset (U, (float) 0.0, (float) 0.0, (float) 0.0);
vset (V, (float) 0.0, (float) 0.0, (float) 0.0);
vset (&U_vec, (float) 0.0, (float) 0.0, (float) 0.0);
vset (&V_vec, (float) 0.0, (float) 0.0, (float) 0.0);
/*
*******************************************************************************
*
* loop through all light specifications & calculate intensity if they are on
*
*******************************************************************************
*/
for (i=0; i<LIGHTS_MAX; i++) {
if (shared->lights[i].on) {
/*
* initialize lighting model
*/
L_vec = Vector_Difference(&shared->lights[i].L_pt, &pt);
L_vec = VectorScaler_Division(&L_vec, vector_len(&L_vec) );
N_dot_L = Dot_Product(N_vec, &L_vec);
cos_theta = N_dot_L;
t = (float) 0.0;
s = (float) 0.0;
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* apply lighting model if light source is in front of obj
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
if (cos_theta > 0.0) {
/*
* apply basic lighting model
*/
R_vec = VectorScaler_Product(N_vec, ((float)2.0) * N_dot_L);
R_vec = Vector_Difference(&R_vec, &L_vec);
R_vec = VectorScaler_Division(&R_vec, vector_len(&R_vec) );
cos_alpha = Dot_Product(&R_vec, View_vec);
if (cos_alpha > 0)
cos_alpha = cos_alpha;
else
cos_alpha = (float) 0.0;
t = Ka + (Kd * cos_theta);
s = Ks * pow(cos_alpha, shared->PhongConst);
/*
* if light source directed -- modify result
*/
if (shared->lights[i].directed) {
vset (&negL_vec, -L_vec.x, -L_vec.y, -L_vec.z);
Lp = Vector_Difference(&shared->lights[i].L_a,
&shared->lights[i].L_pt);
Lp = VectorScaler_Division(&Lp, vector_len(&Lp) );
cos_gama = Dot_Product(&negL_vec, &Lp);
if (cos_gama > shared->lights[i].cos_delta) {
t = t * pow(cos_gama, shared->lights[i].ro);
s = s * pow(cos_gama, shared->lights[i].ro);
}
else {
t = (float) 0.0;
s = (float) 0.0;
}
} /* end - if (shared->lights[i].directed) */
} /* end - if (cos_theta > 0.0) */
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
/*
* extend light feeler if necessary
*/
if (t > 0.0 || s > 0.0)
Si = Light_Feeler(pt, shared->lights[i].L_pt);
/*
* calculate diffuse illumination
*/
if (t > 0.0) {
U_vec = vproduct(Od, &shared->lights[i].I);
U_vec = VectorScaler_Product(&U_vec, t);
U_vec = VectorScaler_Product(&U_vec, Si);
*U = Vector_Sum(U, &U_vec);
}
/*
* calculate specular illumination
*/
if (s > 0.0) {
V_vec = vproduct(Os, &shared->lights[i].I);
V_vec = VectorScaler_Product(&V_vec, s);
V_vec = VectorScaler_Product(&V_vec, Si);
*V = Vector_Sum(V, &V_vec);
}
} /* end -- if (shared->lights[i].on) */
} /* end -- for i */
}
/*
*******************************************************************************
*
* Name: Light_Feeler
*
* Purpose: this routine determines if a ray from a given point to a light
* source intersects any objects along its length. If intersec-
* tions are found, the transparency constant for each object
* intersected are multiplied into a running product. This value
* is returned as the filter value for that light source.
*
* NOTE: the ray is parameterized so that the ray parameter value
* 't' varies from 0.0 (point) to 1.0 (light source).
*
* NOTE: the function "poly_mesh_int" is called with the parameter
* "LF". This parameter is used to tell the function to
* return after the first intersection is found rather than
* the closest intersection. (an optimization)
*
*
*
* Input Parameters
*
* pt - specified point to be illuminated
* light_pt - specified origin of light source
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
float
Light_Feeler( Vector pt, Vector light_pt)
{
Vector int_pt;
Sphere_Obj *sphere_ptr;
Poly_Mesh_Obj *poly_ptr;
Rect_Obj *rec_ptr;
Ray ray;
Boolean norm_flg = FALSE;
Boolean int_flg = FALSE;
float S = (float) 1.0;
float t;
int i;
/*
* initialize ray from point to light source
*/
ray.origin = pt;
ray.dir = Vector_Difference(&light_pt, &pt);
ray.dir = VectorScaler_Division(&ray.dir, vector_len(&ray.dir));
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ determine if any objects intersect ray
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
for (i=0; i<shared->obj_num && S > 0.0; i++) {
int_flg = 0;
switch (shared->obj_list[i].label) {
/*
* handle sphere objects
*/
case SPHERE:
sphere_ptr = (Sphere_Obj *) shared->obj_list[i].ptr;
int_flg = sphere_int(ray, sphere_ptr, norm_flg, &int_pt,
NULL, NULL, &t);
break;
/*
* handle polygon mesh objects
*/
case POLY_MESH:
poly_ptr = (Poly_Mesh_Obj *) shared->obj_list[i].ptr;
int_flg = poly_mesh_int(ray, poly_ptr, norm_flg, LF, &t,
&int_pt, NULL, NULL);
break;
/*
* handle rectangle objects
*/
case RECTANGLE:
rec_ptr = (Rect_Obj *) shared->obj_list[i].ptr;
int_flg = rect_int(ray, rec_ptr, norm_flg, &t, &int_pt, NULL);
break;
}
/*
* multiply in Kt for intersected object if:
* - there was an intersection (int_flag)
* - the intersection is not at the ray origin (t > 0.01)
* - the intersection is not beyond light source (t < || P -Lf)
*/
Vector Lf_P_dist = Vector_Difference(&light_pt, &pt);
t = t / vector_len(&Lf_P_dist);;
if ( (int_flg) && (t > 0.001) && (t < 1.0) ) {
S = S * shared->obj_props[i].Kt;
}
}
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
return(S);
}