home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
vectoper.zip
/
RTObjOps.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-19
|
17KB
|
621 lines
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "RTTypes.h"
#include "RTMatMac.h"
#include "RTVecOps.h"
#include "RTObjOps.h"
#include "RTIMOps.h"
#include "RayTrace.h"
char * Sh_malloc(unsigned size);
char * Sh_calloc(unsigned elem_count, unsigned size);
void build_sphere(FILE *fp);
void build_rect(FILE *fp);
void build_poly_mesh(FILE *fp);
void bound_sphere( Sphere_Obj *s_ptr, Vector min_vec, Vector max_vec);
void set_obj_defaults();
void clear_object(Poly_Mesh_Obj *obj_ptr);
int obj_label_to_type(char *object_label);
Vector ColorVecs_Out[10] = { (float)0.0, (float)0.0, (float)1.0, (float)0.0, (float)1.0, (float)0.0,
(float)1.0, (float)0.0, (float)1.0, (float)0.0, (float)1.0, (float)1.0};
Vector ColorVecs_In[10] = { (float)1.0, (float)0.0, (float)0.0, (float)0.0, (float)0.0, (float)1.0,
(float)0.0, (float)1.0, (float)1.0, (float)1.0, (float)1.0, (float)1.0};
int cvec_num = 4;
Obj_View obj_defaults;
/*
*******************************************************************************
*
* Name: build_object
*
* Purpose: this routine reads in data from a specified file and builds
* an object structure for the data.
*
*
*
* Input Parameters
*
* fp - file pointer
* new_obj - flag to indicate whether or not to reset object counter
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
void
build_object(FILE *fp, Boolean new_obj)
{
char object_label[50];
int object_type;
/*
* set object count & read object type
*/
shared->obj_num = (new_obj)? 1 : shared->obj_num + 1;
fscanf (fp, "%s\n", &object_label);
object_type = obj_label_to_type(object_label);
/*
* set default optical properties for object
*/
shared->obj_props[shared->obj_num-1].Od_out =
ColorVecs_Out[(shared->obj_num-1)%cvec_num];
shared->obj_props[shared->obj_num-1].Od_in =
ColorVecs_In[(shared->obj_num-1)%cvec_num];
vset(&shared->obj_props[shared->obj_num-1].Os, (float)1.0, (float)1.0, (float)1.0);
shared->obj_props[shared->obj_num-1].Ka = (float)0.2;
shared->obj_props[shared->obj_num-1].Kd = (float)0.7;
shared->obj_props[shared->obj_num-1].Ks = (float)0.6;
shared->obj_props[shared->obj_num-1].Kt = (float)0.0;
shared->obj_props[shared->obj_num-1].n = (float)1.5;
if (object_type == RECTANGLE)
shared->obj_props[shared->obj_num-1].txt_flg = TRUE;
else
shared->obj_props[shared->obj_num-1].txt_flg = FALSE;
switch(object_type) {
case SPHERE:
build_sphere(fp);
break;
case RECTANGLE:
build_rect(fp);
break;
case POLY_MESH:
build_poly_mesh(fp);
break;
}
}
/*
*******************************************************************************
*
* Name: obj_label_to_type
*
* Purpose: this routine examines the label identifying the type of object
* and returns the type associated with that object.
*
*
*
* Input Parameters
*
* object_label - label identifying object type
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
int
obj_label_to_type(char *object_label)
{
if (strcmp("SPHERE", object_label) == 0)
return(SPHERE);
else if (strcmp("RECTANGLE", object_label) == 0)
return(RECTANGLE);
else if (strcmp("POLY_MESH", object_label) == 0)
return(POLY_MESH);
else {
printf("***** Error: Illegal Object Type -- %s -- EXITING *****\n",
object_label);
exit(1);
}
exit(1);
return(1);
}
/*
*******************************************************************************
*
* Name: build_sphere
*
* Purpose:
*
*
*
* Input Parameters
*
* fp - file pointer
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
void
build_sphere(FILE *fp)
{
Sphere_Obj *curr_obj;
/*
* initialize object and read in header information from file
*/
shared->obj_list[shared->obj_num-1].label = SPHERE;
shared->obj_list[shared->obj_num-1].ptr = (char *) Sh_malloc( (unsigned)
sizeof(Sphere_Obj) );
curr_obj = (Sphere_Obj *) shared->obj_list[shared->obj_num-1].ptr;
fscanf (fp, "%f %f %f", &curr_obj->center_pt.x, &curr_obj->center_pt.y,
&curr_obj->center_pt.z);
fscanf (fp, "%f %f %f", &curr_obj->radius_pt.x, &curr_obj->radius_pt.y,
&curr_obj->radius_pt.z);
set_obj_defaults();
}
/*
*******************************************************************************
*
* Name: build_rect
*
* Purpose: .
*
*
*
* Input Parameters
*
* fp - file pointer
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
void
build_rect(FILE *fp)
{
Rect_Obj *curr_obj;
Vector max_vec, min_vec;
int i;
vset(&max_vec, (float)-9999.0, (float)-9999.0, (float)-9999.0);
vset(&min_vec, (float)9999.0, (float)9999.0, (float)9999.0);
/*
* initialize object and read in header information from file
*/
shared->obj_list[shared->obj_num-1].label = RECTANGLE;
shared->obj_list[shared->obj_num-1].ptr = (char *) Sh_malloc( (unsigned)
sizeof(Rect_Obj) );
curr_obj = (Rect_Obj *) shared->obj_list[shared->obj_num-1].ptr;
for (i=0; i<4; i++) {
fscanf (fp, "%f %f %f", &curr_obj->corners[i].x,
&curr_obj->corners[i].y,
&curr_obj->corners[i].z );
max_vec = vmax(&max_vec, &curr_obj->corners[i]);
min_vec = vmin(&min_vec, &curr_obj->corners[i]);
}
if (max_vec.x == min_vec.x)
curr_obj->normal = X_AXIS;
else if (max_vec.y == min_vec.y)
curr_obj->normal = Y_AXIS;
else if (max_vec.z == min_vec.z)
curr_obj->normal = Z_AXIS;
curr_obj->max_pt = max_vec;
curr_obj->min_pt = min_vec;
set_obj_defaults();
}
/*
*******************************************************************************
*
* Name: build_poly_mesh
*
* Purpose:
*
*
*
* Input Parameters
*
* fp - file pointer
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
void
build_poly_mesh(FILE *fp)
{
int surf_list[100];
Surface *sptr;
Triangle *tptr;
Poly_Mesh_Obj *curr_obj;
int no_obj, no_vert, no_faces, no_surf;
int conn_start, conn_stop, leng_conn;
int i,j;
/*
* initialize object and read in header information from file
*/
shared->obj_list[shared->obj_num-1].label = POLY_MESH;
shared->obj_list[shared->obj_num-1].ptr = (char *) Sh_malloc( (unsigned)
sizeof(Poly_Mesh_Obj) );
curr_obj = (Poly_Mesh_Obj *) shared->obj_list[shared->obj_num-1].ptr;
clear_object(curr_obj);
fscanf (fp, "%d", &no_obj);
fscanf (fp, "%d %d %d %d\n", &no_vert, &no_faces, &leng_conn, &no_surf);
fscanf (fp, "%d %d\n", &conn_start, &conn_stop);
/*
+++++++++++++++++++++++++++++++++++++++++++++++++
* read data points into object
+++++++++++++++++++++++++++++++++++++++++++++++++
*/
curr_obj->data = (Vector *) Sh_calloc( (unsigned)no_vert,
(unsigned)sizeof(Vector) );
curr_obj->num_vert = no_vert;
for (i=0; i<no_vert; i++)
fscanf (fp, "%f %f %f", &curr_obj->data[i].x, &curr_obj->data[i].y,
&curr_obj->data[i].z);
/*
+++++++++++++++++++++++++++++++++++++++++++++++++
* setup the surfaces in an object
+++++++++++++++++++++++++++++++++++++++++++++++++
*/
curr_obj->num_surf = no_surf;
/*
* malloc space in structure for normals
*/
curr_obj->surf_tnorm_flags = (Boolean *) Sh_calloc( (unsigned)no_surf,
(unsigned)sizeof(Boolean) );
curr_obj->surf_pnorm_flags = (Boolean *) Sh_calloc( (unsigned)no_surf,
(unsigned)sizeof(Boolean) );
for (i=0; i<no_surf; i++) {
curr_obj->surf_norms[i] = (Vector *) Sh_calloc((unsigned)no_vert,
(unsigned)sizeof(Vector));
fscanf (fp, "%d", &surf_list[i]);
}
/*
* malloc space in structure for surfaces
*/
curr_obj->surfs = (Surface *) Sh_calloc( (unsigned) curr_obj->num_surf,
(unsigned)sizeof(Surface) );
/*
+++++++++++++++++++++++++++++++++++++++++++++++++
* setup the triangles in a surface
+++++++++++++++++++++++++++++++++++++++++++++++++
*/
sptr = curr_obj->surfs;
for (i=0; i<no_surf; i++) {
/*
* malloc space in structure for current triangle
*/
sptr[i].triangs = (Triangle *)
Sh_calloc((unsigned) surf_list[i], (unsigned)sizeof(Triangle));
sptr[i].num_triang = surf_list[i];
tptr = sptr[i].triangs;
/*
* read in vertices for each triangle in surface
*/
for (j=0; j<surf_list[i]; j++) {
fscanf (fp, "%d %d %d *%d", &tptr[j].v[0], &tptr[j].v[1],
&tptr[j].v[2]);
tptr[j].v[0]--;
tptr[j].v[1]--;
tptr[j].v[2] = (-tptr[j].v[2]) - 1;
tptr[j].v[3] = tptr[j].v[0];
}
}
set_obj_defaults();
}
/*
*******************************************************************************
*
* Name: set_obj_defaults
*
* Purpose: this routine sets default viewing parameters for bounding box
* around object data extrema
*
*
*
* Input Parameters
*
* none
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
void
set_obj_defaults()
{
Obj *obj_ptr;
Poly_Mesh_Obj *poly_ptr;
Sphere_Obj *s_ptr;
Rect_Obj *r_ptr;
Vector min_vec, max_vec;
Vector min_s, max_s;
Vector min_r, max_r;
Vector min_p, max_p;
Vector range_vec;
float vrad, tanv2, delta;
float r;
int i, j;
vset(&min_vec, (float)9999.0, (float)9999.0, (float)9999.0);
vset(&max_vec, (float)-9999.0, (float)-9999.0, (float)-9999.0);
for (i=0; i<shared->obj_num; i++) {
obj_ptr = &shared->obj_list[i];
switch (obj_ptr->label) {
case POLY_MESH:
poly_ptr = (Poly_Mesh_Obj *) obj_ptr->ptr;
for (j=0; j<poly_ptr->num_vert; j++) {
min_p = vmin(&min_p, &poly_ptr->data[j]);
max_p = vmax(&max_p, &poly_ptr->data[j]);
}
bound_sphere(&poly_ptr->b_sph, min_p, max_p);
max_vec = vmax(&max_vec, &max_p);
min_vec = vmin(&min_vec, &min_p);
break;
case SPHERE:
s_ptr = (Sphere_Obj *) obj_ptr->ptr;
r = sqrt( SQR(s_ptr->center_pt.x - s_ptr->radius_pt.x) +
SQR(s_ptr->center_pt.y - s_ptr->radius_pt.y) +
SQR(s_ptr->center_pt.z - s_ptr->radius_pt.z) );
vset(&min_s, s_ptr->center_pt.x - r,
s_ptr->center_pt.y - r,
s_ptr->center_pt.z - r );
vset(&max_s, s_ptr->center_pt.x + r,
s_ptr->center_pt.y + r,
s_ptr->center_pt.z + r );
max_vec = vmax(&max_vec, &max_s);
min_vec = vmin(&min_vec, &min_s);
break;
case RECTANGLE:
r_ptr = (Rect_Obj *) obj_ptr->ptr;
max_r.x = MAX(r_ptr->corners[0].x, r_ptr->corners[2].x);
max_r.y = MAX(r_ptr->corners[0].y, r_ptr->corners[2].y);
max_r.z = MAX(r_ptr->corners[0].z, r_ptr->corners[2].z);
min_r.x = MIN(r_ptr->corners[0].x, r_ptr->corners[2].x);
min_r.y = MIN(r_ptr->corners[0].y, r_ptr->corners[2].y);
min_r.z = MIN(r_ptr->corners[0].z, r_ptr->corners[2].z);
bound_sphere(&r_ptr->b_sph, min_r, max_r);
max_vec = vmax(&max_vec, &max_r);
min_vec = vmin(&min_vec, &min_r);
break;
}
}
obj_defaults.zmax = max_vec;
obj_defaults.zmin = min_vec;
obj_defaults.v = (float)60.0;
vset( &obj_defaults.U, (float) 0.0, (float) 1.0, (float) 0.0);
obj_defaults.A.x = min_vec.x + (max_vec.x - min_vec.x) / ((float)2.0);
obj_defaults.A.y = min_vec.y + (max_vec.y - min_vec.y) / ((float)2.0);
obj_defaults.A.z = min_vec.z + (max_vec.z - min_vec.z) / ((float)2.0);
range_vec = Vector_Difference(&max_vec, &min_vec);
vrad = (obj_defaults.v/180) * M_PI;
tanv2 = 2 * tan(vrad/2);
/*
* delta = MAX(range_vec.z/tanv2, range_vec.x/tanv2);
*
*
* shared->obj_list->F.x = shared->obj_list->A.x;
*
* shared->obj_list->F.y = shared->obj_list->A.y - (range_vec.y/2 + delta);
* shared->obj_list->F.z = shared->obj_list->A.z;
*/
delta = MAX(range_vec.y/tanv2, range_vec.x/tanv2);
obj_defaults.F.x = obj_defaults.A.x;
obj_defaults.F.y = obj_defaults.A.y;
obj_defaults.F.z = obj_defaults.A.z + (range_vec.z/2 + delta);
for (i=0; i<LIGHTS_MAX; i++)
shared->lights[i].L_pt = obj_defaults.F;
}
/*
*******************************************************************************
*
* Name: clear_object
*
* Purpose: this routine nulls out the pointers in an object so that
* stray values will not fake other routines.
*
*
*
* Input Parameters
*
* obj_ptr - object to be cleared
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
void
clear_object(Poly_Mesh_Obj *obj_ptr)
{
int i;
obj_ptr->data = NULL;
obj_ptr->surfs = NULL;
obj_ptr->surf_tnorm_flags = NULL;
obj_ptr->surf_pnorm_flags = NULL;
for (i=0; i<100; i++)
obj_ptr->surf_norms[i] = NULL;
}
/*
*******************************************************************************
*
* Name: bound_sphere
*
* Purpose:
*
*
*
* Input Parameters
*
* fp - file pointer
*
*
* Output Parameters
*
* none
*
*******************************************************************************
*/
void
bound_sphere( Sphere_Obj *s_ptr, Vector min_vec, Vector max_vec)
{
Vector delta_vec;
delta_vec = Vector_Difference(&max_vec, &min_vec);
delta_vec = VectorScaler_Division(&delta_vec, (float)2.0);
s_ptr->center_pt = Vector_Sum(&min_vec, &delta_vec);
s_ptr->radius_pt = max_vec;
}