Back to index

radiance  4R0+20100331
Classes | Defines | Typedefs | Functions | Variables
rayopt.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "vect.h"
#include "rayopt.h"

Go to the source code of this file.

Classes

struct  Palette
struct  Triangle
struct  TList
struct  TList2
struct  VList
struct  GTree

Defines

#define COOPERATE
#define HASHSIZE   1000 /* Size of hash table for vertex lookup */
#define DEGEN_TOL   (1e-8) /* float comparison tolerance for checking */
#define MAX_TEX   500 /* Maximum allowable number of texture */
#define POV10   0
#define POV20   1
#define VIVID   2
#define POLYRAY   3
#define MGF   4
#define MAXFLOAT   (1e37)
#define CIE_Y_r   0.265
#define CIE_Y_g   0.670
#define CIE_Y_b   0.065

Typedefs

typedef char * Texture
typedef struct TList TriList
typedef struct TList2 TriList2
typedef struct VList VertList
typedef struct GTree GroupTree

Functions

void init_object (void)
void cleanup_object (void)
float calc_tpr (GroupTree *gnode)
GroupTreecreate_group (void)
void delete_tree (GroupTree *gnode)
void optimize_tree (GroupTree *gnode)
void test_split (GroupTree *gnode, int axis, float *best_rtpr, TriList2 **best_loc)
void split_group (GroupTree *gnode, int axis, TriList2 *split_loc, GroupTree **group_a, GroupTree **group_b)
void write_file (void)
void write_box (Vector v1, Vector v2, Triangle *tri)
void write_pov10_tree (FILE *f, GroupTree *gnode, int level)
void write_pov10_texture (FILE *f, Triangle *tri)
void write_pov10_transform (FILE *f, Matrix matrix)
void write_pov10_header (FILE *f)
void write_pov10_triangle (FILE *f, Triangle *tri, int one_texture)
void write_pov10_bound (FILE *f, GroupTree *gnode)
void write_pov20_tree (FILE *f, GroupTree *gnode, int level)
void write_pov20_texture (FILE *f, Triangle *tri)
void write_pov20_transform (FILE *f, Matrix matrix)
void write_pov20_header (FILE *f)
void write_pov20_triangle (FILE *f, Triangle *tri, int one_texture)
void write_pov20_bound (FILE *f, GroupTree *gnode)
void write_vivid_tree (FILE *f, GroupTree *gnode)
void write_vivid_transform (FILE *f, Matrix matrix)
void write_vivid_texture (FILE *f, Triangle *tri)
void write_vivid_header (FILE *f)
void write_vivid_triangle (FILE *f, Triangle *tri)
void write_polyray_tree (FILE *f, GroupTree *gnode)
void write_polyray_transform (FILE *f, Matrix matrix)
void write_polyray_texture (FILE *f, Triangle *tri)
void write_polyray_header (FILE *f)
void write_polyray_triangle (FILE *f, Triangle *tri)
void write_mgf_tree (FILE *f, GroupTree *gnode, int level)
void write_mgf_texture (FILE *f, Triangle *tri)
void write_mgf_transform (FILE *f, Matrix matrix)
void write_mgf_header (FILE *f)
void write_mgf_triangle (FILE *f, Triangle *tri)
void update_node (GroupTree *gnode)
void sort_indexes (GroupTree *gnode)
void quick_sort (TriList2 *start, TriList2 *end, int axis)
float surf_area (float a, float b, float c)
float max_vertex (Triangle *tri, int axis)
float min_vertex (Triangle *tri, int axis)
float avg_vertex (Triangle *tri, int axis)
void build_tri_index (void)
void dump_tri_index (void)
void vert_normal (Triangle *t, Vector *norm)
void tri_normal (Triangle *t, Vector normal)
unsigned pal_lookup (float red, float green, float blue)
unsigned texture_lookup (char *texture_name)
unsigned vert_lookup (float x, float y, float z)
int degen_tri (float ax, float ay, float az, float bx, float by, float bz, float cx, float cy, float cz)
void abortmsg (char *msg, int exit_code)
float fltmin (float a, float b)
float fltmax (float a, float b)
void add_ext (char *fname, char *ext, int force)
void cleanup_name (char *name)
void opt_set_format (int format)
void opt_set_fname (char *out_name, char *inc_name)
void opt_set_quiet (int quiet)
void opt_set_bound (int bound)
void opt_set_smooth (float smooth)
void opt_set_vert (unsigned vert)
void opt_set_dec (int dec)
void opt_set_color (float red, float green, float blue)
void opt_set_texture (char *texture_name)
void opt_set_transform (Matrix mat)
void opt_clear_transform ()
int opt_add_tri (float ax, float ay, float az, float bx, float by, float bz, float cx, float cy, float cz)
void opt_write_pov (char *obj_name)
void opt_write_file (char *obj_name)
void opt_write_box (char *obj_name)
void opt_finish ()
void opt_get_limits (float *min_x, float *min_y, float *min_z, float *max_x, float *max_y, float *max_z)
void opt_get_glimits (float *min_x, float *min_y, float *min_z, float *max_x, float *max_y, float *max_z)
unsigned opt_get_vert_cnt ()
unsigned opt_get_tri_cnt ()
float opt_get_index ()
unsigned opt_get_bounds ()

Variables

static const char RCSid [] = "$Id: rayopt.c,v 1.4 2007/09/05 01:36:37 greg Exp $"
static Paletteptable
static unsigned pmax
static unsigned psize
static Texturettable
static unsigned tmax
static unsigned tsize
static Vectorvtable
static unsigned vmax
static unsigned vsize
static Vector gmin = {+MAXFLOAT, +MAXFLOAT, +MAXFLOAT}
static Vector gmax = {-MAXFLOAT, -MAXFLOAT, -MAXFLOAT}
static Matrix trans_matrix
static int use_transform = 0
static VertList ** vert_hash
static TriList ** tri_index
static GroupTreegroot
static int initialized = 0
static int quiet_mode = 0
static int bound_mode = 0
static float smooth_angle = 0.0
static unsigned vert_init = 0
static int dec_point = 4
static int out_format = POV10
static char out_file [64] = "rayopt.pov"
static char inc_file [64] = "rayopt.inc"
static unsigned tot_bounds = 0
static unsigned object_cnt = 0
static Vector last_vmin = {0.0, 0.0, 0.0}
static Vector last_vmax = {0.0, 0.0, 0.0}
static unsigned last_vert_cnt = 0
static unsigned last_tri_cnt = 0
static float last_index = 0.0
static unsigned last_bounds = 0
static Palette last_pal
static char last_texture [64] = ""
static unsigned texture_index
static char texture_type
static char object_name [64] = ""
static float orig_tpr
static float final_tpr
static float bound_cost

Class Documentation

struct Palette

Definition at line 55 of file rayopt.c.

Class Members
float blue
float green
float red
struct Triangle

Definition at line 63 of file rayopt.c.

Class Members
char flag
unsigned text_index
char text_type
unsigned vert
struct TList

Definition at line 72 of file rayopt.c.

Collaboration diagram for TList:
Class Members
struct TList * next
Triangle * tri
struct TList2

Definition at line 79 of file rayopt.c.

Collaboration diagram for TList2:
Class Members
struct TList2 * next
struct TList2 * prev
Triangle * tri
struct VList

Definition at line 87 of file rayopt.c.

Collaboration diagram for VList:
Class Members
struct VList * next
unsigned vert
struct GTree

Definition at line 94 of file rayopt.c.

Collaboration diagram for GTree:
Class Members
float area
struct GTree * child
int child_cnt
TriList2 * index
struct GTree * next
unsigned obj_cnt
struct GTree * parent
int split_cnt
Vector vmax
Vector vmin

Define Documentation

#define CIE_Y_b   0.065

Definition at line 53 of file rayopt.c.

#define CIE_Y_g   0.670

Definition at line 52 of file rayopt.c.

#define CIE_Y_r   0.265

Definition at line 51 of file rayopt.c.

#define COOPERATE

Definition at line 31 of file rayopt.c.

#define DEGEN_TOL   (1e-8) /* float comparison tolerance for checking */

Definition at line 35 of file rayopt.c.

#define HASHSIZE   1000 /* Size of hash table for vertex lookup */

Definition at line 34 of file rayopt.c.

#define MAX_TEX   500 /* Maximum allowable number of texture */

Definition at line 37 of file rayopt.c.

#define MAXFLOAT   (1e37)

Definition at line 47 of file rayopt.c.

#define MGF   4

Definition at line 44 of file rayopt.c.

#define POLYRAY   3

Definition at line 43 of file rayopt.c.

#define POV10   0

Definition at line 40 of file rayopt.c.

#define POV20   1

Definition at line 41 of file rayopt.c.

#define VIVID   2

Definition at line 42 of file rayopt.c.


Typedef Documentation

typedef struct GTree GroupTree
typedef char* Texture

Definition at line 61 of file rayopt.c.

typedef struct TList TriList
typedef struct TList2 TriList2
typedef struct VList VertList

Function Documentation

void abortmsg ( char *  msg,
int  exit_code 
)

Definition at line 2397 of file rayopt.c.

{
    printf ("\n%s\n", msg);
    exit (exit_code);
}

Here is the caller graph for this function:

void add_ext ( char *  fname,
char *  ext,
int  force 
)

Definition at line 2422 of file rayopt.c.

{
    int i;

    for (i = 0; i < strlen(fname); i++)
       if (fname[i] == '.') break;

    if (fname[i] == '\0' || force) {
       if (strlen(ext) > 0)
           fname[i++] = '.';

       strcpy (&fname[i], ext);
    }
}

Here is the caller graph for this function:

float avg_vertex ( Triangle tri,
int  axis 
)

Definition at line 2149 of file rayopt.c.

{
    float  avg;

    avg = (vtable[tri->vert[0]][axis] + vtable[tri->vert[1]][axis] +
          vtable[tri->vert[2]][axis])/3.0;

    return avg;
}

Here is the caller graph for this function:

void build_tri_index ( void  )

Definition at line 2162 of file rayopt.c.

{
    GroupTree *g;
    TriList   *temp;
    TriList2  *t;
    unsigned  i, vert_no;

    if (vsize == 0)
       return;

    tri_index = malloc (vsize * sizeof(TriList));
    if (tri_index == NULL)
       abortmsg ("Insufficient memory for smooth triangles.", 1);

    for (i = 0; i < vsize; i++)
       tri_index[i] = NULL;

    for (g = groot; g != NULL; g = g->next) {
       for (t = g->index[0]->next; t != g->index[0]; t = t->next) {
           for (i = 0; i < 3; i++) {
              vert_no = t->tri->vert[i];
              temp = tri_index[vert_no];
              tri_index[vert_no] = malloc (sizeof(TriList));
              if (tri_index[vert_no] == NULL)
                  abortmsg ("Insufficient memory for smooth triangles.\n", 1);

              tri_index[vert_no]->tri = t->tri;
              tri_index[vert_no]->next = temp;
           }
       }
    }

}

Here is the call graph for this function:

Here is the caller graph for this function:

float calc_tpr ( GroupTree gnode)

Definition at line 776 of file rayopt.c.

{
    GroupTree *g;
    float     tpr;

    if (gnode->child_cnt == 0)
       return gnode->obj_cnt;

    tpr = bound_cost * gnode->child_cnt;

    for (g = gnode->child; g != NULL; g = g->next)
       tpr = tpr + (g->area/gnode->area) * calc_tpr(g);

    return tpr;
}

Here is the caller graph for this function:

void cleanup_name ( char *  name)

Definition at line 2438 of file rayopt.c.

{
    char *tmp = malloc (strlen(name)+1);
    int  i;

    /* Remove any leading blanks or quotes */
    i = 0;
    while ((name[i] == ' ' || name[i] == '"') && name[i] != '\0')
       i++;

    strcpy (tmp, &name[i]);

    /* Remove any trailing blanks or quotes */
    for (i = strlen(tmp)-1; i >= 0; i--) {
       if (isprint(tmp[i]) && !isspace(tmp[i]) && tmp[i] != '"')
           break;
       else
           tmp[i] = '\0';
    }

    strcpy (name, tmp);

    /* Prefix the letter 'N' to materials that begin with a digit */
    if (!isdigit (name[0]))
       strcpy (tmp, name);
    else {
       tmp[0] = 'N';
       strcpy (&tmp[1], name);
    }

    /* Replace all illegal charaters in name with underscores */
    for (i = 0; tmp[i] != '\0'; i++) {
       if (!isalnum(tmp[i]))
          tmp[i] = '_';
    }

    strcpy (name, tmp);

    free (tmp);
}

Here is the caller graph for this function:

void cleanup_object ( void  )

Definition at line 698 of file rayopt.c.

{
    int i;
    Vector corners[8];  /* Corners of box */

    last_vert_cnt = vsize;
    last_tri_cnt  = groot->obj_cnt;
    last_index    = orig_tpr/final_tpr;
    last_bounds   = tot_bounds;

    vect_copy (last_vmin, groot->vmin);
    vect_copy (last_vmax, groot->vmax);

    /* Calculate the corners of the bounding box */
    corners[0][X] =  groot->vmin[X];
    corners[0][Y] =  groot->vmin[Y];
    corners[0][Z] =  groot->vmin[Z];

    corners[1][X] =  groot->vmin[X];
    corners[1][Y] =  groot->vmin[Y];
    corners[1][Z] =  groot->vmax[Z];

    corners[2][X] =  groot->vmax[X];
    corners[2][Y] =  groot->vmin[Y];
    corners[2][Z] =  groot->vmin[Z];

    corners[3][X] =  groot->vmax[X];
    corners[3][Y] =  groot->vmin[Y];
    corners[3][Z] =  groot->vmax[Z];

    corners[4][X] =  groot->vmin[X];
    corners[4][Y] =  groot->vmax[Y];
    corners[4][Z] =  groot->vmin[Z];

    corners[5][X] =  groot->vmax[X];
    corners[5][Y] =  groot->vmax[Y];
    corners[5][Z] =  groot->vmin[Z];

    corners[6][X] =  groot->vmin[X];
    corners[6][Y] =  groot->vmax[Y];
    corners[6][Z] =  groot->vmax[Z];

    corners[7][X] =  groot->vmax[X];
    corners[7][Y] =  groot->vmax[Y];
    corners[7][Z] =  groot->vmax[Z];

    /* Include any transformation in the box calcs */
    if (use_transform) {
       for (i = 0; i < 8; i++)
           vect_transform (corners[i], corners[i], trans_matrix);
    }

    for (i = 0; i < 8; i++) {
       gmin[X] = (corners[i][X] < gmin[X]) ? corners[i][X] : gmin[X];
       gmin[Y] = (corners[i][Y] < gmin[Y]) ? corners[i][Y] : gmin[Y];
       gmin[Z] = (corners[i][Z] < gmin[Z]) ? corners[i][Z] : gmin[Z];

       gmax[X] = (corners[i][X] > gmax[X]) ? corners[i][X] : gmax[X];
       gmax[Y] = (corners[i][Y] > gmax[Y]) ? corners[i][Y] : gmax[Y];
       gmax[Z] = (corners[i][Z] > gmax[Z]) ? corners[i][Z] : gmax[Z];
    }

    free (ptable);
    free (vtable);
    free (vert_hash);

    for (i = 0; i < tsize; i++)
       free (ttable[i]);

    free (ttable);

    delete_tree (groot);

    initialized = 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

GroupTree * create_group ( void  )

Definition at line 794 of file rayopt.c.

{
    GroupTree *new_group;
    int       i;

    new_group = malloc (sizeof(GroupTree));
    if (new_group == NULL)
       abortmsg ("Insufficient memory for group list.", 1);

    for (i = 0; i < 3; i++) {
       new_group->index[i] = malloc (sizeof(TriList2));
       if (new_group->index[i] == NULL)
           abortmsg ("Insufficient memory for tree.", 1);

       new_group->index[i]->tri = NULL;
       new_group->index[i]->prev = new_group->index[i];
       new_group->index[i]->next = new_group->index[i];
    }

    vect_init (new_group->vmin, +MAXFLOAT, +MAXFLOAT, +MAXFLOAT);
    vect_init (new_group->vmax, -MAXFLOAT, -MAXFLOAT, -MAXFLOAT);
    new_group->area      = 0.0;
    new_group->obj_cnt   = 0;
    new_group->child_cnt = 0;
    new_group->split_cnt = 0;
    new_group->parent    = NULL;
    new_group->next      = NULL;
    new_group->child     = NULL;

    return new_group;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int degen_tri ( float  ax,
float  ay,
float  az,
float  bx,
float  by,
float  bz,
float  cx,
float  cy,
float  cz 
)

Definition at line 2367 of file rayopt.c.

{
    Vector  ab, ac, norm;
    double  mag, fact;

    fact = pow (10.0, dec_point);

    /* Round the coords off to the output precision before checking */
    ax = floor((ax*fact) + 0.5)/fact;
    ay = floor((ay*fact) + 0.5)/fact;
    az = floor((az*fact) + 0.5)/fact;
    bx = floor((bx*fact) + 0.5)/fact;
    by = floor((by*fact) + 0.5)/fact;
    bz = floor((bz*fact) + 0.5)/fact;
    cx = floor((cx*fact) + 0.5)/fact;
    cy = floor((cy*fact) + 0.5)/fact;
    cz = floor((cz*fact) + 0.5)/fact;

    vect_init (ab, ax-bx, ay-by, az-bz);
    vect_init (ac, ax-cx, ay-cy, az-cz);
    vect_cross (norm, ab, ac);

    mag = vect_mag(norm);

    return (mag < DEGEN_TOL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void delete_tree ( GroupTree gnode)

Definition at line 828 of file rayopt.c.

{
    GroupTree *g, *g_temp;
    TriList2  *t, *t_temp;
    int       i;

    for (g = gnode->child; g != NULL; ) {
       g_temp = g->next;
       delete_tree (g);
       g = g_temp;
    }

    /* Free the indexes for this node (if any exist) */
    for (i = 0; i < 3; i++) {
       if ((gnode->index[i] != NULL) && (gnode->index[i]->prev != NULL)) {
           /* Drop a link so the list isn't circular any more */
           gnode->index[i]->prev->next = NULL;

           /* Delete the list */
           for (t = gnode->index[i]; t != NULL; ) {
              if (i == 0 && (t->tri != NULL))
                  free (t->tri);

              t_temp = t;
              t = t->next;
              free (t_temp);
           }
       }
    }

    /* And finally free the root node */
    free (gnode);
}

Here is the caller graph for this function:

void dump_tri_index ( void  )

Definition at line 2197 of file rayopt.c.

{
    TriList *temp;
    int     i;

    for (i = 0; i < vsize; i++) {
       while (tri_index[i] != NULL) {
           temp = tri_index[i];
           tri_index[i] = tri_index[i]->next;
           free (temp);
       }
    }

    free (tri_index);
}

Here is the caller graph for this function:

float fltmax ( float  a,
float  b 
)

Definition at line 2413 of file rayopt.c.

{
    if (a > b)
       return a;
    else
       return b;
}

Here is the caller graph for this function:

float fltmin ( float  a,
float  b 
)

Definition at line 2404 of file rayopt.c.

{
    if (a < b)
       return a;
    else
       return b;
}

Here is the caller graph for this function:

void init_object ( void  )

Definition at line 648 of file rayopt.c.

{
    int i;

    last_pal.red   = 0.0;
    last_pal.green = 0.0;
    last_pal.blue  = 0.0;

    strcpy (last_texture, "");

    bound_cost = 1.6;

    /* Allocate memory for palette lookup table */
    pmax   = 10;
    psize  = 0;
    ptable = malloc (pmax * sizeof(Palette));
    if (ptable == NULL)
       abortmsg ("Insufficient memory for palette.", 1);

    /* Allocate memory for texture table */
    tmax   = 10;
    tsize  = 0;
    ttable = malloc (tmax * sizeof(Texture));
    if (ttable == NULL)
       abortmsg ("Insufficient memory for textures.", 1);

    /* Allocate memory for vertex lookup table */
    vmax = (vert_init > 0) ? vert_init : 1000;
    vsize  = 0;
    vtable = malloc (vmax * sizeof(Vector));
    if (vtable == NULL)
       abortmsg ("Insufficient memory for vertices.", 1);

    /* Allocate memory for vertex hash table */
    vert_hash = malloc (sizeof(VertList*)*HASHSIZE);
    if (vert_hash == NULL)
       abortmsg ("Insufficient memory for vertex hash table.", 1);

    /* Initialize the vertex lookup hash table */
    for (i = 0; i < HASHSIZE; i++)
       vert_hash[i] = NULL;

    /* Start with an empty root node */
    groot = create_group();

    tot_bounds = 1;
    initialized = 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

float max_vertex ( Triangle tri,
int  axis 
)

Definition at line 2113 of file rayopt.c.

{
    float  max_v, val;
    int i;

    max_v = -MAXFLOAT;

    for (i = 0; i < 3; i++) {
       val = vtable[tri->vert[i]][axis];

       if (val > max_v)
           max_v = val;
    }

    return max_v;
}

Here is the caller graph for this function:

float min_vertex ( Triangle tri,
int  axis 
)

Definition at line 2131 of file rayopt.c.

{
    float  min_v, val;
    int i;

    min_v = +MAXFLOAT;

    for (i = 0; i < 3; i++) {
       val = vtable[tri->vert[i]][axis];

       if (val < min_v)
           min_v = val;
    }

    return min_v;
}

Here is the caller graph for this function:

int opt_add_tri ( float  ax,
float  ay,
float  az,
float  bx,
float  by,
float  bz,
float  cx,
float  cy,
float  cz 
)

Definition at line 379 of file rayopt.c.

{
    TriList2 *new_node;
    Triangle *new_tri;
    int      i;

    /* Check if the triangle is degenerate (zero area), if so return -1 */
    if (degen_tri (ax, ay, az, bx, by, bz, cx, cy, cz))
       return -1;

    if (!initialized)
       init_object();

    /* Allocate memory for the new triangle */
    new_tri = malloc (sizeof(Triangle));
    if (new_tri == NULL)
       abortmsg ("Insufficient memory for new triangles.", 1);

    /* Look up the vertex and texture indexes */
    new_tri->vert[0] = vert_lookup (ax, ay, az);
    new_tri->vert[1] = vert_lookup (bx, by, bz);
    new_tri->vert[2] = vert_lookup (cx, cy, cz);

    new_tri->text_index = texture_index;
    new_tri->text_type  = texture_type;

    new_tri->flag = 0;

    for (i = 0; i < 3; i++) {
       /* Create a new index node */
       new_node = malloc (sizeof(TriList2));
       if (new_node == NULL)
           abortmsg ("Insufficient memory for triangles.", 1);

       /* Point the index entry to the new triangle */
       new_node->tri = new_tri;

       /* Insert the new index node into the list */
       new_node->next = groot->index[i];
       new_node->prev = groot->index[i]->prev;
       groot->index[i]->prev->next = new_node;
       groot->index[i]->prev = new_node;
    }

    ++(groot->obj_cnt);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 372 of file rayopt.c.

{
    use_transform = 0;
}
void opt_finish ( void  )

Definition at line 539 of file rayopt.c.

{
    FILE *f;

    f = fopen (out_file, "a");

    switch (out_format) {
       case POV10:
            if (object_cnt > 2 && bound_mode == 0)
               fprintf (f, "composite {  /* All Objects */\n    ");

           fprintf (f, "#include \"%s\"\n", inc_file);

           if (object_cnt > 2 && bound_mode == 0) {
              fprintf (f, "\n");
              fprintf (f, "    bounded_by {\n");
              fprintf (f, "        box { <%.4f %.4f %.4f> <%.4f %.4f %.4f> }\n",
                                    gmin[X], gmin[Y], gmin[Z],
                                    gmax[X], gmax[Y], gmax[Z]);
              fprintf (f, "    }\n");
               fprintf (f, "}\n\n");
            }
           break;

       case POV20:
            if (object_cnt > 2 && bound_mode == 0)
                fprintf (f, "union {\n    ");

           fprintf (f, "#include \"%s\"\n", inc_file);

           if (object_cnt > 2 && bound_mode == 0) {
              fprintf (f, "\n");
              fprintf (f, "    bounded_by {\n");
              fprintf (f, "        box { <%.4f, %.4f, %.4f>, <%.4f, %.4f, %.4f> }\n",
                                    gmin[X], gmin[Y], gmin[Z],
                                    gmax[X], gmax[Y], gmax[Z]);
              fprintf (f, "    }\n");
                fprintf (f, "}\n\n");
            }
           break;

       case VIVID:
           fprintf (f, "#include %s\n\n", inc_file);
           break;

       case POLYRAY:
           fprintf (f, "include \"%s\"\n\n", inc_file);
           break;

       case MGF:
           fprintf (f, "i %s\n", inc_file);
           break;
    }

    fclose (f);
}

Here is the caller graph for this function:

unsigned opt_get_bounds ( void  )

Definition at line 642 of file rayopt.c.

{
    return last_bounds;
}
void opt_get_glimits ( float *  min_x,
float *  min_y,
float *  min_z,
float *  max_x,
float *  max_y,
float *  max_z 
)

Definition at line 611 of file rayopt.c.

{
    *min_x = gmin[X];
    *min_y = gmin[Y];
    *min_z = gmin[Z];

    *max_x = gmax[X];
    *max_y = gmax[Y];
    *max_z = gmax[Z];
}
float opt_get_index ( void  )

Definition at line 636 of file rayopt.c.

{
    return last_index;
}
void opt_get_limits ( float *  min_x,
float *  min_y,
float *  min_z,
float *  max_x,
float *  max_y,
float *  max_z 
)

Definition at line 598 of file rayopt.c.

{
    *min_x = last_vmin[X];
    *min_y = last_vmin[Y];
    *min_z = last_vmin[Z];

    *max_x = last_vmax[X];
    *max_y = last_vmax[Y];
    *max_z = last_vmax[Z];
}
unsigned opt_get_tri_cnt ( void  )

Definition at line 630 of file rayopt.c.

{
    return last_tri_cnt;
}
unsigned opt_get_vert_cnt ( void  )

Definition at line 624 of file rayopt.c.

{
    return last_vert_cnt;
}
void opt_set_bound ( int  bound)

Definition at line 287 of file rayopt.c.

{
    if (bound != 0 && bound != 1 && bound != 2)
       abortmsg ("ERROR: Invalid parameter passed to opt_set_bound.", 1);

    bound_mode = bound;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_set_color ( float  red,
float  green,
float  blue 
)

Definition at line 320 of file rayopt.c.

{
    if (!initialized)
       init_object();

    if (last_pal.red != red || last_pal.green != green ||
                            last_pal.blue != blue || psize == 0)
    {
       last_pal.red   = red;
       last_pal.green = green;
       last_pal.blue  = blue;

       texture_index = pal_lookup (red, green, blue);
    }

    texture_type = 0;   /* An RGB texture */
}

Here is the call graph for this function:

void opt_set_dec ( int  dec)

Definition at line 311 of file rayopt.c.

{
    if (dec < 0 || dec > 9)
       abortmsg ("ERROR: Invalid parameter passed to opt_set_dec.", 1);

    dec_point = dec;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_set_fname ( char *  out_name,
char *  inc_name 
)

Definition at line 235 of file rayopt.c.

{
    FILE *f;

    strcpy (out_file, out_name);

    if (strlen(inc_name) > 0)
       strcpy (inc_file, inc_name);
    else {
       strcpy (inc_file, out_file);

       switch (out_format) {
           case POV10:
           case POV20:   add_ext (inc_file, "inc", 1);
                       break;
           case VIVID:   add_ext (inc_file, "vo", 1);
                       break;
           case POLYRAY: add_ext (inc_file, "inc", 1);
                       break;
           case MGF:     add_ext (inc_file, "inc", 1);
                       break;
       }
    }

    if (strcmp (out_file, inc_file) == 0)
       abortmsg ("Main file and include file cannot have the same name", 1);

    if ((f = fopen (out_file, "w")) == NULL) {
       printf ("Cannot open output file %s\n", out_file);
       exit (1);
    }

    fclose (f);

    if ((f = fopen (inc_file, "w")) == NULL) {
       printf ("Cannot open output file %s\n", inc_file);
       exit (1);
    }

    fclose (f);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_set_format ( int  format)

Definition at line 225 of file rayopt.c.

{
    if (format != POV10 && format != POV20 && format != VIVID
              && format != POLYRAY && format != MGF)
       abortmsg ("ERROR: Invalid parameter passed to opt_set_format.", 1);

    out_format = format;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_set_quiet ( int  quiet)

Definition at line 278 of file rayopt.c.

{
    if (quiet != 0 && quiet != 1)
       abortmsg ("ERROR: Invalid parameter passed to opt_set_quiet.", 1);

    quiet_mode = quiet;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_set_smooth ( float  smooth)

Definition at line 296 of file rayopt.c.

{
    if (smooth < 0.0 || smooth > 180.0)
       abortmsg ("ERROR: Invalid parameter passed to opt_set_smooth.", 1);

    smooth_angle = smooth;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_set_texture ( char *  texture_name)

Definition at line 339 of file rayopt.c.

{
    char new_texture[64];

    if (!initialized)
       init_object();

    strcpy (new_texture, texture_name);
    cleanup_name (new_texture);

    if (strcmp (last_texture, new_texture) != 0) {
       strcpy (last_texture, new_texture);
       texture_index = texture_lookup (new_texture);
    }

    texture_type = 1;   /* A named texture */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_set_transform ( Matrix  mat)

Definition at line 359 of file rayopt.c.

{
    int i, j;

    for (i = 0; i < 4; i++) {
       for (j = 0; j < 3; j++)
           trans_matrix[i][j] = mat[i][j];
    }

    use_transform = 1;
}

Here is the caller graph for this function:

void opt_set_vert ( unsigned  vert)

Definition at line 305 of file rayopt.c.

{
    vert_init = vert;
}

Here is the caller graph for this function:

void opt_write_box ( char *  obj_name)

Definition at line 503 of file rayopt.c.

{
    VertList *temp;
    int i;

    if (!initialized || groot->obj_cnt == 0) {
       orig_tpr = 1.0;
       final_tpr = 0.0;
       tot_bounds = 0;
       return;   /* No triangles where ever added, nothing to write */
    }

    strcpy (object_name, obj_name);
    cleanup_name (object_name);

    ++object_cnt;

    /* Dump the hash table, don't need it any more */
    for (i = 0; i < HASHSIZE; i++) {
       while (vert_hash[i] != NULL) {
           temp = vert_hash[i];
           vert_hash[i] = vert_hash[i]->next;
           free (temp);
       }
    }

    orig_tpr = final_tpr = 1.0;

    update_node (groot);

    write_box (groot->vmin, groot->vmax, groot->index[0]->next->tri);

    cleanup_object();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_write_file ( char *  obj_name)

Definition at line 439 of file rayopt.c.

{
    VertList *temp;
    int      i;

    if (out_format != POV10 && out_format != POV20)
       bound_mode = 2;

    if (!initialized || groot->obj_cnt == 0) {
       orig_tpr = 1.0;
       final_tpr = 0.0;
       tot_bounds = 0;
       return;   /* No triangles where ever added, nothing to write */
    }

    strcpy (object_name, obj_name);
    cleanup_name (object_name);

    ++object_cnt;

    /* Dump the hash table, don't need it any more */
    for (i = 0; i < HASHSIZE; i++) {
       while (vert_hash[i] != NULL) {
           temp = vert_hash[i];
           vert_hash[i] = vert_hash[i]->next;
           free (temp);
       }
    }

    /* Build the vertice index */
    build_tri_index();

    if (bound_mode != 2) {
       if (!quiet_mode)
           printf ("Building indexes\n");

       sort_indexes (groot);
    }

    update_node (groot);

    if (!quiet_mode) {
       printf ("Adding bounds (1)\r");
       fflush(stdout);;
    }

    /* Optimize the tree */
    orig_tpr = calc_tpr (groot);

    if (bound_mode != 2)
       optimize_tree (groot);

    final_tpr = calc_tpr (groot);

    /* Write the file */
    write_file();

    /* Free up the vertex index */
    dump_tri_index();

    cleanup_object();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void opt_write_pov ( char *  obj_name)

Definition at line 432 of file rayopt.c.

Here is the call graph for this function:

void optimize_tree ( GroupTree gnode)

Definition at line 864 of file rayopt.c.

{
    GroupTree *group_a, *group_b;
    int axis, best_axis;
    float     best_rtpr, new_rtpr;
    TriList2  *best_loc, *new_loc;

    best_rtpr = 0.0;
    best_loc  = NULL;
    best_axis = -1;

    /* Try splitting the group in each of the three axis' (x,y,z) */
    for (axis = 0; axis < 3; axis++) {
       test_split (gnode, axis, &new_rtpr, &new_loc);

       if (new_rtpr < best_rtpr) {
           best_rtpr = new_rtpr;
           best_loc  = new_loc;
           best_axis = axis;
       }
    }

    if (best_axis != -1) {
       /* Split this node into two nodes */
       split_group (gnode, best_axis, best_loc, &group_a, &group_b);

       optimize_tree (group_a);
       optimize_tree (group_b);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned pal_lookup ( float  red,
float  green,
float  blue 
)

Definition at line 2258 of file rayopt.c.

{
    int i;

    /* The palette table is usually small so just do a simple linear search */
    for (i = psize-1; i >= 0; i--) {
       if (ptable[i].red   == red &&
           ptable[i].green == green &&
           ptable[i].blue  == blue)
         break;
    }

    if (i >= 0)
       return i;    /* found, return the table index */

    /* not found, insert the new palette into the table */
    ++psize;
    if (psize > pmax) {
       /* table not big enough, resize it */
       pmax = pmax + 10;
       ptable = realloc (ptable, pmax * sizeof(Palette));
       if (ptable == NULL)
           abortmsg ("Insufficient memory to expand palette table.", 1);
    }

    ptable[psize-1].red   = red;
    ptable[psize-1].green = green;
    ptable[psize-1].blue  = blue;

    return (psize-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void quick_sort ( TriList2 start,
TriList2 end,
int  axis 
)

Definition at line 2065 of file rayopt.c.

{
    TriList2 *a, *b;
    Triangle *temp;
    float  middle;

    if (start == end)
       return;

    a = start;
    b = end;
    middle = avg_vertex (a->tri, axis);

    do {
       while (avg_vertex (b->tri, axis) >= middle && a != b)
           b = b->prev;

       if (a != b) {
           temp   = a->tri;
           a->tri = b->tri;
           b->tri = temp;

           while (avg_vertex (a->tri, axis) <= middle && a != b)
              a = a->next;

           if (a != b) {
              temp   = a->tri;
              a->tri = b->tri;
              b->tri = temp;
           }
       }
    } while (a != b);

    if (a != start)
       quick_sort (start, a->prev, axis);

    if (b != end)
       quick_sort (b->next, end, axis);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sort_indexes ( GroupTree gnode)

Definition at line 2056 of file rayopt.c.

{
    int i;

    for (i = 0; i < 3; i++)
       quick_sort (gnode->index[i]->next, gnode->index[i]->prev, i);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void split_group ( GroupTree gnode,
int  axis,
TriList2 split_loc,
GroupTree **  group_a,
GroupTree **  group_b 
)

Definition at line 980 of file rayopt.c.

{
    GroupTree *new_a, *new_b;
    TriList2  *t, *next_t, *new_index;
    char      new_flag;
    int       i;

    COOPERATE /* support multitasking */

    /* Mark the triangles as to which group they will belong */
    new_flag = 0;
    for (t = gnode->index[axis]->next; t != gnode->index[axis]; t = t->next) {
       if (t == split_loc)
           new_flag = 1;

       t->tri->flag = new_flag;
    }

    new_a = create_group();
    new_b = create_group();

    for (i = 0; i < 3; i++) {
       t = gnode->index[i]->next;

       while (t != gnode->index[i]) {
           next_t = t->next;

           if (t->tri->flag == 0)
              new_index = new_a->index[i];
           else
              new_index = new_b->index[i];

           /* Remove this node from the list */
           t->prev->next = t->next;
           t->next->prev = t->prev;

           /* Insert node into its new group */
           t->prev = new_index->prev;
           t->next = new_index;
           new_index->prev->next = t;
           new_index->prev = t;

           t = next_t;
       }
    }

    for (i = 0; i < 3; i++) {
       free (gnode->index[i]);
       gnode->index[i] = NULL;
    }

    if (gnode->parent == NULL || gnode->split_cnt >= 2) {
       /* Add the new groups as children of original */
       gnode->child  = new_a;
       new_a->parent = gnode;
       new_a->next   = new_b;
       new_b->parent = gnode;

       new_a->split_cnt = 0;
       new_b->split_cnt = 0;

       tot_bounds = tot_bounds + 2;
    }
    else {
       /* Remove the original group and replace with the new groups */
       for (i = 0; i < 3; i++)
           gnode->index[i] = new_a->index[i];

       free (new_a);
       new_a = gnode;

       new_b->next = new_a->next;
       new_a->next = new_b;

       new_a->parent = gnode->parent;
       new_b->parent = gnode->parent;

       new_a->split_cnt = gnode->split_cnt + 1;
       new_b->split_cnt = gnode->split_cnt + 1;

       tot_bounds = tot_bounds + 1;
    }

    update_node (new_a);
    update_node (new_b);

    if (new_a->parent != NULL)
       update_node (new_a->parent);

    if (!quiet_mode) {
       printf ("Adding bounds (%d)\r", tot_bounds);
       fflush(stdout);
    }

    *group_a = new_a;
    *group_b = new_b;
}

Here is the call graph for this function:

Here is the caller graph for this function:

float surf_area ( float  a,
float  b,
float  c 
)

Definition at line 2107 of file rayopt.c.

{
    return 2.0*(a*b + b*c + c*a);
}

Here is the caller graph for this function:

void test_split ( GroupTree gnode,
int  axis,
float *  best_rtpr,
TriList2 **  best_loc 
)

Definition at line 898 of file rayopt.c.

{
    float    dim1, dim2;
    float    area1, area2, p_area;
    float    new_min1, new_max1, new_min2, new_max2;
    float    best_index, new_index;
    TriList2 *t;
    int      cnt, best_cnt;

    *best_loc  = NULL;
    best_index = +MAXFLOAT ;
    best_cnt   = 0;
    cnt = 0;

    dim1 = gnode->vmax[(axis+1) % 3] - gnode->vmin[(axis+1) % 3];
    dim2 = gnode->vmax[(axis+2) % 3] - gnode->vmin[(axis+2) % 3];

    for (t = gnode->index[axis]->next; t != gnode->index[axis]; t = t->next) {
       if (t->next == gnode->index[axis])
           break;

       ++cnt;

       /* Make an estimate of the new min/max limits, doing the full */
       /* calculation is just tooooo slooowww. */
       new_min1 = gnode->vmin[axis];
       new_max1 = max_vertex (t->tri, axis);
       new_min2 = min_vertex (t->next->tri, axis);
       new_max2 = gnode->vmax[axis];

       /* Calculate the surface area of the new groups */
       area1 = surf_area (dim1, dim2, new_max1 - new_min1);
       area2 = surf_area (dim1, dim2, new_max2 - new_min2);

       new_index = (cnt * area1) + ((gnode->obj_cnt - cnt) * area2);

       /* Keep track of the best one */
       if (new_index < best_index) {
           best_index = new_index;
           *best_loc  = t->next;
           best_cnt   = cnt;
       }
    }

    /* The former was just an estimate, verify the numbers */
    if (*best_loc != NULL) {
       new_min1 = gnode->vmin[axis];
       new_max1 = -MAXFLOAT;
       new_min2 = +MAXFLOAT;
       new_max2 = gnode->vmax[axis];

       for (t = gnode->index[axis]->next; t != *best_loc; t = t->next)
           new_max1 = fltmax (new_max1, max_vertex (t->tri, axis));

       for (t = *best_loc; t != gnode->index[axis]; t = t->next)
           new_min2 = fltmin (new_min2, min_vertex (t->tri, axis));

       area1 = surf_area (dim1, dim2, new_max1 - new_min1);
       area2 = surf_area (dim1, dim2, new_max2 - new_min2);

       best_index = (best_cnt * area1) +
                   ((gnode->obj_cnt - best_cnt) * area2);
    }

    if (gnode->parent == NULL || gnode->split_cnt >= 2) {
       p_area = gnode->area;

       *best_rtpr = -1.0*((gnode->area/p_area) * gnode->obj_cnt) +
                   (gnode->area/p_area) * ((best_index/p_area) +
                   2.0*bound_cost);
    }
    else {
       p_area = gnode->parent->area;

       *best_rtpr = -1.0*((gnode->area/p_area) * gnode->obj_cnt) +
                   (best_index/p_area) + bound_cost;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned texture_lookup ( char *  texture_name)

Definition at line 2292 of file rayopt.c.

{
    int i;

    /* The texture table is usually small so just do a simple linear search */
    for (i = tsize-1; i >= 0; i--) {
       if (strcmp (ttable[i], texture_name) == 0)
           break;
    }

    if (i >= 0)
       return i;    /* found, return the table index */

    /* not found, insert the new texture into the table */
    ++tsize;
    if (tsize > tmax) {
       /* table not big enough, resize it */
       tmax = tmax + 10;
       ttable = realloc (ttable, tmax * sizeof(Texture));
       if (ttable == NULL)
           abortmsg ("Insufficient memory to expand palette table.", 1);
    }

    ttable[tsize-1] = malloc (strlen(texture_name) + 1);
    if (ttable[tsize-1] == NULL)
       abortmsg ("Insufficient memory for texture name.", 1);

    strcpy (ttable[tsize-1], texture_name);

    return (tsize-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tri_normal ( Triangle t,
Vector  normal 
)

Definition at line 2245 of file rayopt.c.

{
    Vector ab, ac;

    vect_sub (ab, vtable[t->vert[1]], vtable[t->vert[0]]);
    vect_sub (ac, vtable[t->vert[2]], vtable[t->vert[0]]);
    vect_cross (normal, ac, ab);

    vect_normalize (normal);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void update_node ( GroupTree gnode)

Definition at line 2010 of file rayopt.c.

{
    GroupTree *g;
    TriList2  *t;
    int       i;

    vect_init (gnode->vmin, +MAXFLOAT, +MAXFLOAT, +MAXFLOAT);
    vect_init (gnode->vmax, -MAXFLOAT, -MAXFLOAT, -MAXFLOAT);

    gnode->obj_cnt   = 0;
    gnode->child_cnt = 0;

    if (gnode->index[0] == NULL) {
       /* Not a leaf node, calc the info from the child nodes */

       for (g = gnode->child; g != NULL; g = g->next) {
           ++(gnode->child_cnt);

           gnode->obj_cnt += g->obj_cnt;

           for (i = 0; i < 3; i++) {
              gnode->vmin[i] = fltmin (gnode->vmin[i], g->vmin[i]);
              gnode->vmax[i] = fltmax (gnode->vmax[i], g->vmax[i]);
           }
       }
    }
    else {
       /* A leaf node, calc the info from the triangle list */

       for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next) {
           ++(gnode->obj_cnt);

           for (i = 0; i < 3; i++) {
              gnode->vmin[i] = fltmin (gnode->vmin[i], min_vertex (t->tri, i));
              gnode->vmax[i] = fltmax (gnode->vmax[i], max_vertex (t->tri, i));
           }
       }
    }

    /* Update total surface area of region */
    gnode->area = surf_area (gnode->vmax[X] - gnode->vmin[X],
                          gnode->vmax[Y] - gnode->vmin[Y],
                          gnode->vmax[Z] - gnode->vmin[Z]);
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned vert_lookup ( float  x,
float  y,
float  z 
)

Definition at line 2326 of file rayopt.c.

{
    VertList *p, *new_node;
    unsigned hash;

    /* Vertex table is usually very large, use hash lookup */
    hash = (unsigned)((int)(326.4*x) ^ (int)(694.7*y) ^ (int)(1423.6*z)) % HASHSIZE;

    for (p = vert_hash[hash]; p != NULL; p = p->next) {
       if (vtable[p->vert][0] == x && vtable[p->vert][1] == y &&
           vtable[p->vert][2] == z) break;
    }

    if (p != NULL)
       return (p->vert);   /* found, return the table index */

    /* not found, insert the new vertex into the table */
    ++vsize;
    if (vsize > vmax) {
       /* table not big enough, expand it */
       vmax = vmax + 100;
       vtable = realloc (vtable, vmax * sizeof(Vector));
       if (vtable == NULL)
           abortmsg ("Insufficient memory for vertices.\n", 1);
    }

    vect_init (vtable[vsize-1], x, y, z);

    new_node = malloc (sizeof(VertList));
    if (new_node == NULL)
       abortmsg ("Insufficient memory for hash table.", 1);

    new_node->vert  = vsize-1;
    new_node->next  = vert_hash[hash];
    vert_hash[hash] = new_node;

    return (vsize-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void vert_normal ( Triangle t,
Vector norm 
)

Definition at line 2215 of file rayopt.c.

{
    Vector  curr_norm, new_norm;
    TriList *p;
    int     i;

    tri_normal (t, curr_norm);

    if (smooth_angle <= 0.0) {
       for (i = 0; i < 3; i++)
           vect_copy (norm[i], curr_norm);

       return;
    }

    for (i = 0; i < 3; i++) {
       vect_init (norm[i], 0.0, 0.0, 0.0);

       for (p = tri_index[t->vert[i]]; p != NULL; p = p->next) {
           tri_normal (p->tri, new_norm);
           if (vect_angle (curr_norm, new_norm) < smooth_angle)
              vect_add (norm[i], norm[i], new_norm);
       }

       vect_normalize (norm[i]);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_box ( Vector  v1,
Vector  v2,
Triangle tri 
)

Definition at line 1134 of file rayopt.c.

{
    FILE  *f;

    if (!quiet_mode)
       printf ("\nWriting files %s and %s\n", out_file, inc_file);

    f = fopen (inc_file, "a");
    if (f == NULL)
       abortmsg ("Error opening output file.", 1);

    switch (out_format) {
       case POV10:
           fprintf (f, "\n/* Object '%s' */\n", object_name);
           fprintf (f, "object {\n");
           fprintf (f, "\tbox { <%.4f %.4f %.4f> <%.4f %.4f %.4f> }\n",
                     v1[X], v1[Y], v1[Z], v2[X], v2[Y], v2[Z]);
           fprintf (f, "\t");
           write_pov10_texture (f, tri);
           fprintf (f, "\n");

           if (use_transform)
              write_pov10_transform (f, trans_matrix);

           fprintf (f, "}\n\n");
           break;

       case POV20:
           fprintf (f, "\n/* Object '%s' */\n", object_name);
           fprintf (f, "box {\n");
           fprintf (f, "\t<%.4f, %.4f, %.4f>, <%.4f, %.4f, %.4f>\n",
                     v1[X], v1[Y], v1[Z], v2[X], v2[Y], v2[Z]);
           fprintf (f, "\t");
           write_pov20_texture (f, tri);
           fprintf (f, "\n");

           if (use_transform)
              write_pov20_transform (f, trans_matrix);

           fprintf (f, "}\n\n");
           break;

       case VIVID:
           fprintf (f, "\n/* Object '%s' */\n", object_name);

           if (use_transform)
              write_vivid_transform (f, trans_matrix);

           write_vivid_texture (f, tri);

           fprintf (f, "polygon { points 4 vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f }\n",
                      v1[X], v1[Y], v1[Z], v2[X], v1[Y], v1[Z], v2[X], v2[Y], v1[Z], v1[X], v2[Y], v1[Z]);
           fprintf (f, "polygon { points 4 vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f }\n",
                      v1[X], v1[Y], v1[Z], v1[X], v2[Y], v1[Z], v1[X], v2[Y], v2[Z], v1[X], v1[Y], v2[Z]);
           fprintf (f, "polygon { points 4 vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f }\n",
                      v1[X], v2[Y], v1[Z], v2[X], v2[Y], v1[Z], v2[X], v2[Y], v2[Z], v1[X], v2[Y], v2[Z]);
           fprintf (f, "polygon { points 4 vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f }\n",
                      v2[X], v2[Y], v1[Z], v2[X], v1[Y], v1[Z], v2[X], v1[Y], v2[Z], v2[X], v2[Y], v2[Z]);
           fprintf (f, "polygon { points 4 vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f }\n",
                      v2[X], v1[Y], v1[Z], v1[X], v1[Y], v1[Z], v1[X], v1[Y], v2[Z], v2[X], v1[Y], v2[Z]);
           fprintf (f, "polygon { points 4 vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f vertex %.4f %.4f %.4f }\n",
                      v1[X], v1[Y], v2[Z], v1[X], v2[Y], v2[Z], v2[X], v2[Y], v2[Z], v2[X], v1[Y], v2[Z]);

           if (use_transform)
              fprintf (f, "transform_pop\n\n");
           break;

       case POLYRAY:
           fprintf (f, "\n// Object '%s'\n", object_name);
           fprintf (f, "object {\n");
           fprintf (f, "\tbox <%.4f, %.4f, %.4f>, <%.4f, %.4f, %.4f>\n",
                     v1[X], v1[Y], v1[Z], v2[X], v2[Y], v2[Z]);
           fprintf (f, "\t");
           write_polyray_texture (f, tri);
           fprintf (f, "\n");

           if (use_transform)
              write_polyray_transform (f, trans_matrix);

           fprintf (f, "}\n\n");
           break;

       case MGF:
           if (object_name[0]) fprintf (f, "o %s\n", object_name);
           write_mgf_texture (f, tri);
           fprintf (f, "v v1 =\n\tp %.4f %.4f %.4f\n", v1[X], v1[Y], v1[Z]);
           fprintf (f, "v v2 =\n\tp %.4f %.4f %.4f\n", v1[X], v2[Y], v1[Z]);
           fprintf (f, "v v3 =\n\tp %.4f %.4f %.4f\n", v2[X], v2[Y], v1[Z]);
           fprintf (f, "v v4 =\n\tp %.4f %.4f %.4f\n", v2[X], v1[Y], v1[Z]);
           fprintf (f, "prism v1 v2 v3 v4 %.4f\n", v2[Z]-v1[Z]);
           if (object_name[0]) fprintf (f, "o\n");
           fprintf (f, "\n");
    }

    fclose (f);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_file ( void  )

Definition at line 1081 of file rayopt.c.

{
    FILE  *f;

    if (!quiet_mode)
       printf ("\nWriting files %s and %s\n", out_file, inc_file);

    f = fopen (out_file, "a");
    if (f == NULL)
       abortmsg ("Error opening output file.", 1);

    switch (out_format) {
       case POV10:   write_pov10_header (f);
                    break;
       case POV20:   write_pov20_header (f);
                    break;
       case VIVID:   write_vivid_header (f);
                    break;
       case POLYRAY: write_polyray_header (f);
                    break;
       case MGF:     write_mgf_header (f);
                    break;
    }

    fclose (f);

    f = fopen (inc_file, "a");
    if (f == NULL)
       abortmsg ("Error opening output file.", 1);

    switch (out_format) {
       case POV10:   write_pov10_tree (f, groot, 1);
                    break;
       case POV20:   write_pov20_tree (f, groot, 1);
                    break;
       case VIVID:   write_vivid_tree (f, groot);
                    break;
       case POLYRAY: write_polyray_tree (f, groot);
                    break;
       case MGF:     write_mgf_tree (f, groot, 1);
                    break;
    }

    fclose (f);

    if (!quiet_mode) {
       printf ("Triangles: %u, ", groot->obj_cnt);
       printf ("Vertices: %u, ", vsize);
       printf ("Bounding index: %.2f\n\n", orig_tpr/final_tpr);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_mgf_header ( FILE *  f)

Definition at line 1952 of file rayopt.c.

{
    int i;

    if (psize >= MAX_TEX) {
       fprintf (f, "# Too many materials, materials generated in-line\n\n");
    }
    else {
       if (psize > 0)
           fprintf (f, "# Material definitions for object '%s'\n", object_name);

       for (i = 0; i < psize; i++) {
           fprintf (f, "m %s_%u =\n", object_name, i + 1);
           fprintf (f, "\tc\n\t\tcmix %.3f R %.3f G %.3f B\n\trd %.3f\n",
                   CIE_Y_r*ptable[i].red,
                   CIE_Y_g*ptable[i].green,
                   CIE_Y_b*ptable[i].blue,
                   CIE_Y_r*ptable[i].red +
                   CIE_Y_g*ptable[i].green +
                   CIE_Y_b*ptable[i].blue);
       }
    }
}

Here is the caller graph for this function:

void write_mgf_texture ( FILE *  f,
Triangle tri 
)

Definition at line 1896 of file rayopt.c.

{
    if (tri->text_type == 1)
       fprintf (f, "m %s\n", ttable[tri->text_index]);
    else if (psize < MAX_TEX)
       fprintf (f, "m %s_%u\n", object_name, tri->text_index + 1);
    else
       fprintf (f, "m\n\tc\n\t\tcmix %.3f R %.3f G %.3f B\n\trd %.3f\n",
               CIE_Y_r*ptable[tri->text_index].red,
               CIE_Y_g*ptable[tri->text_index].green,
               CIE_Y_b*ptable[tri->text_index].blue,
               CIE_Y_r*ptable[tri->text_index].red +
               CIE_Y_g*ptable[tri->text_index].green +
               CIE_Y_b*ptable[tri->text_index].blue);
}

Here is the caller graph for this function:

void write_mgf_transform ( FILE *  f,
Matrix  matrix 
)

Definition at line 1916 of file rayopt.c.

{
    Vector scale, shear, rotate, transl;
    float ascale;

    /* Decode the matrix into separate operations */
    mat_decode (matrix, scale, shear, rotate, transl);

    fprintf (f, "xf");
                                          /* print scaling */
    if (fabs(scale[X] - 1.0) > 0.001 || fabs(scale[Y] - 1.0) > 0.001 ||
              fabs(scale[Z] - 1.0) > 0.001) {
       if (fabs(scale[X] - scale[Y]) > 0.001 ||
                     fabs(scale[Y] - scale[Z]) > 0.001)
           printf("Warning: Non-linear scaling in transformation (ignored)\n");
       ascale = sqrt((scale[X]*scale[X] + scale[Y]*scale[Y] +
                     scale[Z]*scale[Z])/3.0);
       fprintf (f, " -s %.3f\n", ascale);
    }
                                          /* add rotation */
    if (fabs(rotate[X]) > 0.01)
       fprintf (f, " -rx %.2f", rotate[X]);
    if (fabs(rotate[Y]) > 0.01)
       fprintf (f, " -ry %.2f", rotate[Y]);
    if (fabs(rotate[Z]) > 0.01)
       fprintf (f, " -rz %.2f", rotate[Z]);
                                          /* final translation */
    fprintf (f, " -t %.4f, %.4f, %.4f\n", transl[X], transl[Y], transl[Z]);

    /* Can't handle shear but warn if it's there */
    if (fabs(shear[X]) > 0.01 || fabs(shear[Y]) > 0.01 || fabs(shear[Z]) > 0.01)
       printf ("Warning: Significant shear in transformation (ignored)\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_mgf_tree ( FILE *  f,
GroupTree gnode,
int  level 
)

Definition at line 1865 of file rayopt.c.

{
    GroupTree *g;
    TriList2  *t;

    if (level == 1) {
       fprintf (f, "\no %s\n", object_name);
       if (use_transform)
           write_mgf_transform (f, trans_matrix);
    }

    if (gnode->child != NULL) {
       for (g = gnode->child; g != NULL; g = g->next)
           write_mgf_tree (f, g, level+1);
    }
    else {
       for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next)
           write_mgf_triangle (f, t->tri);
    }

    fprintf (f, "\n");

    if (level == 1) {
       if (use_transform)
           fprintf (f, "xf\n");
       fprintf (f, "\no\n");
    }
    fprintf (f, "\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_mgf_triangle ( FILE *  f,
Triangle tri 
)

Definition at line 1978 of file rayopt.c.

{
    Vector norm[3];
    int    i;
    int    smooth;

    COOPERATE /* support multitasking */

    write_mgf_texture (f, tri);

    if (smooth_angle > 0.0) {
       vert_normal (tri, norm);

       smooth = !vect_equal (norm[0], norm[1]) ||
               !vect_equal (norm[1], norm[2]);
    } else
       smooth = 0;

    for (i = 0; i < 3; i++) {
       fprintf (f, "v v%d =\n\tp ", i+1);
       vect_print (f, vtable[tri->vert[i]], dec_point, ' ');
       if (smooth) {
           fprintf (f, "\n\tn ");
           vect_print (f, norm[i], 3, ' ');
       }
       fprintf (f, "\n");
    }
    fprintf (f, "f v1 v2 v3\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_polyray_header ( FILE *  f)

Definition at line 1810 of file rayopt.c.

{
    int i;

    if (psize > 0)
       fprintf (f, "// Texture declarations for object '%s'\n", object_name);

    for (i = 0; i < psize; i++) {
       fprintf (f, "define %s_%u\n", object_name, i + 1);
       fprintf (f, "texture {\n");
       fprintf (f, "    surface {\n");
       fprintf (f, "        ambient <%.3f, %.3f, %.3f>, 0.1\n",
                  ptable[i].red, ptable[i].green, ptable[i].blue);
       fprintf (f, "        diffuse <%.3f, %.3f, %.3f>, 0.7\n",
                  ptable[i].red, ptable[i].green, ptable[i].blue);
       fprintf (f, "        specular white, 1.0\n");
       fprintf (f, "        microfacet Reitz 10\n");
       fprintf (f, "    }\n");
       fprintf (f, "}\n\n");
    }
}

Here is the caller graph for this function:

void write_polyray_texture ( FILE *  f,
Triangle tri 
)

Definition at line 1799 of file rayopt.c.

{
    if (tri->text_type == 1)
       fprintf (f, "%s", ttable[tri->text_index]);
    else
       fprintf (f, "%s_%u",
               object_name, tri->text_index + 1);
}

Here is the caller graph for this function:

void write_polyray_transform ( FILE *  f,
Matrix  matrix 
)

Definition at line 1775 of file rayopt.c.

{
    Vector scale, shear, rotate, transl;

    /* Decode the matrix into separate operations */
    mat_decode (matrix, scale, shear, rotate, transl);

    fprintf (f, "\n\t// Object transformation\n");

    if (fabs(scale[X] - 1.0) > 0.001 || fabs(scale[Y] - 1.0) > 0.001 || fabs(scale[Z] - 1.0) > 0.001)
       fprintf (f, "\tscale <%.3f, %.3f, %.3f>\n", scale[X], scale[Y], scale[Z]);

    if (fabs(rotate[X]) > 0.01 || fabs(rotate[Y]) > 0.01 || fabs(rotate[Z]) > 0.01)
       fprintf (f, "\trotate <%.2f, %.2f, %.2f>\n", rotate[X], rotate[Y], rotate[Z]);

    if (fabs(transl[X]) > 0.0001 || fabs(transl[Y]) > 0.0001 || fabs(transl[Z]) > 0.0001)
       fprintf (f, "\ttranslate <%.4f, %.4f, %.4f>\n", transl[X], transl[Y], transl[Z]);

    /* Can't handle shear but warn if it's there */
    if (fabs(shear[X]) > 0.01 || fabs(shear[Y]) > 0.01 || fabs(shear[Z]) > 0.01)
       printf ("Warning: Significant shear in transformation (ignored)\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_polyray_tree ( FILE *  f,
GroupTree gnode 
)

Definition at line 1742 of file rayopt.c.

{
    TriList2  *t;

    fprintf (f, "\n// Object '%s'\n\n", object_name);

    fprintf (f, "object {\n");

    if (gnode->child != NULL)
       abortmsg ("Internal error", 1);

    for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next) {
       if (t != gnode->index[0]->next)
           fprintf (f, "\t+\n");

       write_polyray_triangle (f, t->tri);

       fprintf (f, "\t\t");
       write_polyray_texture (f, t->tri);
       fprintf (f, "\n\t}\n\n");
    }

    if (use_transform)
       write_polyray_transform (f, trans_matrix);

    fprintf (f, "}\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_polyray_triangle ( FILE *  f,
Triangle tri 
)

Definition at line 1834 of file rayopt.c.

{
    Vector norm[3];

    COOPERATE /* support multitasking */

    vert_normal (tri, norm);

    fprintf (f, "\tobject {\n");

    fprintf (f, "\t\tpatch\t <");
    vect_print (f, vtable[tri->vert[0]], dec_point, ',');
    fprintf (f, ">, <");
    vect_print (f, norm[0], 3, ',');
    fprintf (f, ">,\n");

    fprintf (f, "\t\t\t <");
    vect_print (f, vtable[tri->vert[1]], dec_point, ',');
    fprintf (f, ">, <");
    vect_print (f, norm[1], 3, ',');
    fprintf (f, ">,\n");

    fprintf (f, "\t\t\t <");
    vect_print (f, vtable[tri->vert[2]], dec_point, ',');
    fprintf (f, ">, <");
    vect_print (f, norm[2], 3, ',');
    fprintf (f, ">\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov10_bound ( FILE *  f,
GroupTree gnode 
)

Definition at line 1416 of file rayopt.c.

{
    if (gnode->obj_cnt > 1) {
       fprintf (f, "\n\tbounded_by { box { <");
       vect_print (f, gnode->vmin, dec_point + 1, ' ');
       fprintf (f, "> <");
       vect_print (f, gnode->vmax, dec_point + 1, ' ');
       fprintf (f, "> } }\n");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov10_header ( FILE *  f)

Definition at line 1329 of file rayopt.c.

{
    int i;

    if (psize >= MAX_TEX) {
       fprintf (f, "/* Too many textures, textures generated in-line */\n\n");
       fprintf (f, "#declare %s = texture {\n", object_name);
       fprintf (f, "    ambient 0.1\n");
       fprintf (f, "    diffuse 0.7\n");
       fprintf (f, "    phong 1.0\n");
       fprintf (f, "    phong_size 70.0\n");
       fprintf (f, "}\n\n");
    }
    else {
       if (psize > 0)
           fprintf (f, "/* Texture declarations for object '%s' */\n", object_name);

       for (i = 0; i < psize; i++) {
           fprintf (f, "#declare %s_%u = texture {\n", object_name, i + 1);
           fprintf (f, "    ambient 0.1\n");
           fprintf (f, "    diffuse 0.7\n");
           fprintf (f, "    phong 1.0\n");
           fprintf (f, "    phong_size 70.0\n");
           fprintf (f, "    color red %.3f green %.3f blue %.3f\n",
                   ptable[i].red, ptable[i].green, ptable[i].blue);
           fprintf (f, "}\n\n");
       }
    }
}

Here is the caller graph for this function:

void write_pov10_texture ( FILE *  f,
Triangle tri 
)

Definition at line 1286 of file rayopt.c.

{
    if (tri->text_type == 1)
       fprintf (f, "texture { %s }", ttable[tri->text_index]);
    else if (psize < MAX_TEX)
       fprintf (f, "texture { %s_%u }",
               object_name, tri->text_index + 1);
    else
       fprintf (f, "texture { %s color red %.3f green %.3f blue %.3f }",
               object_name, ptable[tri->text_index].red,
               ptable[tri->text_index].green, ptable[tri->text_index].blue);
}

Here is the caller graph for this function:

void write_pov10_transform ( FILE *  f,
Matrix  matrix 
)

Definition at line 1304 of file rayopt.c.

{
    Vector scale, shear, rotate, transl;

    /* Decode the matrix into separate operations */
    mat_decode (matrix, scale, shear, rotate, transl);

    fprintf (f, "\n\t/* Object transformation */\n");

    if (fabs(scale[X] - 1.0) > 0.001 || fabs(scale[Y] - 1.0) > 0.001 || fabs(scale[Z] - 1.0) > 0.001)
       fprintf (f, "\tscale <%.3f %.3f %.3f>\n", scale[X], scale[Y], scale[Z]);

    if (fabs(rotate[X]) > 0.01 || fabs(rotate[Y]) > 0.01 || fabs(rotate[Z]) > 0.01)
       fprintf (f, "\trotate <%.2f %.2f %.2f>\n", rotate[X], rotate[Y], rotate[Z]);

    if (fabs(transl[X]) > 0.0001 || fabs(transl[Y]) > 0.0001 || fabs(transl[Z]) > 0.0001)
       fprintf (f, "\ttranslate <%.4f %.4f %.4f>\n", transl[X], transl[Y], transl[Z]);

    /* Can't handle shear but warn if it's there */
    if (fabs(shear[X]) > 0.01 || fabs(shear[Y]) > 0.01 || fabs(shear[Z]) > 0.01)
       printf ("Warning: Significant shear in transformation (ignored)\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov10_tree ( FILE *  f,
GroupTree gnode,
int  level 
)

Definition at line 1233 of file rayopt.c.

{
    GroupTree *g;
    TriList2  *t;
    Triangle  *first_tri;
    int       one_texture;

    if (level == 1)
       fprintf (f, "\n/* Object '%s' */\n", object_name);

    fprintf (f, "composite {\n");

    if (gnode->child != NULL) {
       for (g = gnode->child; g != NULL; g = g->next)
           write_pov10_tree (f, g, level+1);
    }
    else {
       first_tri = gnode->index[0]->next->tri;
       one_texture = 1;

       for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next) {
           if (t->tri->text_index != first_tri->text_index ||
              t->tri->text_type  != first_tri->text_type) {
                 one_texture = 0;
                 break;
           }
       }

       if (one_texture) {
           fprintf (f, "\tobject {\n");
           fprintf (f, "\t\tunion {\n");
       }

       for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next)
           write_pov10_triangle (f, t->tri, one_texture);

       if (one_texture) {
           fprintf (f, "\t\t}\n\n\t\t");
           write_pov10_texture (f, first_tri);
           fprintf (f, "\n\t}\n");
       }
    }

    if (bound_mode == 0)
        write_pov10_bound (f, gnode);

    if (level == 1 && use_transform)
       write_pov10_transform (f, trans_matrix);

    fprintf (f, "}\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov10_triangle ( FILE *  f,
Triangle tri,
int  one_texture 
)

Definition at line 1361 of file rayopt.c.

{
    Vector norm[3];
    int    no_smooth = 0;

    COOPERATE /* support multitasking */

    if (one_texture)
       fprintf (f, "\t\t");
    else
       fprintf (f, "\tobject { ");

    if (smooth_angle > 0.0) {
       vert_normal (tri, norm);

       if (vect_equal (norm[0], norm[1]) && vect_equal (norm[1], norm[2]))
           no_smooth = 1;
    }

    if (smooth_angle > 0.0 && !no_smooth) {
       fprintf (f, "smooth_triangle { <");
       vect_print (f, vtable[tri->vert[0]], dec_point, ' ');
       fprintf (f, "> <");
       vect_print (f, norm[0], 3, ' ');
       fprintf (f, "> <");
       vect_print (f, vtable[tri->vert[1]], dec_point, ' ');
       fprintf (f, "> <");
       vect_print (f, norm[1], 3, ' ');
       fprintf (f, "> <");
       vect_print (f, vtable[tri->vert[2]], dec_point, ' ');
       fprintf (f, "> <");
       vect_print (f, norm[2], 3, ' ');
       fprintf (f, "> }");
    }
    else {
       fprintf (f, "triangle { <");
       vect_print (f, vtable[tri->vert[0]], dec_point, ' ');
       fprintf (f, "> <");
       vect_print (f, vtable[tri->vert[1]], dec_point, ' ');
       fprintf (f, "> <");
       vect_print (f, vtable[tri->vert[2]], dec_point, ' ');
       fprintf (f, "> }");
    }

    if (!one_texture) {
       fprintf (f, " ");
       write_pov10_texture (f, tri);
       fprintf (f, " }");
    }

    fprintf (f, "\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov20_bound ( FILE *  f,
GroupTree gnode 
)

Definition at line 1600 of file rayopt.c.

{
    if (gnode->obj_cnt > 1) {
       fprintf (f, "\tbounded_by { box { <");
       vect_print (f, gnode->vmin, dec_point + 1, ',');
       fprintf (f, ">, <");
       vect_print (f, gnode->vmax, dec_point + 1, ',');
       fprintf (f, "> } }\n");
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov20_header ( FILE *  f)

Definition at line 1526 of file rayopt.c.

{
    int i;

    if (psize >= MAX_TEX) {
       fprintf (f, "/* Too many textures, textures generated in-line */\n\n");
       fprintf (f, "#declare %s = texture {\n", object_name);
       fprintf (f, "    finish { Shiny }\n");
       fprintf (f, "    pigment { White }\n");
       fprintf (f, "}\n\n");
    }
    else {
       if (psize > 0)
           fprintf (f, "/* Texture declarations for object '%s' */\n", object_name);

       for (i = 0; i < psize; i++) {
           fprintf (f, "#declare %s_%u = texture {\n", object_name, i + 1);
           fprintf (f, "    finish { Shiny }\n");
           fprintf (f, "    pigment { color red %.3f green %.3f blue %.3f }\n",
                   ptable[i].red, ptable[i].green, ptable[i].blue);
           fprintf (f, "}\n\n");
       }
    }
}

Here is the caller graph for this function:

void write_pov20_texture ( FILE *  f,
Triangle tri 
)

Definition at line 1483 of file rayopt.c.

{
    if (tri->text_type == 1)
       fprintf (f, "texture { %s }", ttable[tri->text_index]);
    else if (psize < MAX_TEX)
       fprintf (f, "texture { %s_%u }",
               object_name, tri->text_index + 1);
    else
       fprintf (f, "texture { %s pigment { color red %.3f green %.3f blue %.3f } }",
               object_name, ptable[tri->text_index].red,
               ptable[tri->text_index].green, ptable[tri->text_index].blue);
}

Here is the caller graph for this function:

void write_pov20_transform ( FILE *  f,
Matrix  matrix 
)

Definition at line 1501 of file rayopt.c.

{
    Vector scale, shear, rotate, transl;

    /* Decode the matrix into separate operations */
    mat_decode (matrix, scale, shear, rotate, transl);

    fprintf (f, "\n\t/* Object transformation */\n");

    if (fabs(scale[X] - 1.0) > 0.001 || fabs(scale[Y] - 1.0) > 0.001 || fabs(scale[Z] - 1.0) > 0.001)
       fprintf (f, "\tscale <%.3f, %.3f, %.3f>\n", scale[X], scale[Y], scale[Z]);

    if (fabs(rotate[X]) > 0.01 || fabs(rotate[Y]) > 0.01 || fabs(rotate[Z]) > 0.01)
       fprintf (f, "\trotate <%.2f, %.2f, %.2f>\n", rotate[X], rotate[Y], rotate[Z]);

    if (fabs(transl[X]) > 0.0001 || fabs(transl[Y]) > 0.0001 || fabs(transl[Z]) > 0.0001)
       fprintf (f, "\ttranslate <%.4f, %.4f, %.4f>\n", transl[X], transl[Y], transl[Z]);

    /* Can't handle shear but warn if it's there */
    if (fabs(shear[X]) > 0.01 || fabs(shear[Y]) > 0.01 || fabs(shear[Z]) > 0.01)
       printf ("Warning: Significant shear in transformation (ignored)\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov20_tree ( FILE *  f,
GroupTree gnode,
int  level 
)

Definition at line 1429 of file rayopt.c.

{
    GroupTree *g;
    TriList2  *t;
    Triangle  *first_tri;
    int       one_texture;

    if (level == 1)
       fprintf (f, "\n/* Object '%s' */\n", object_name);

    if (gnode->obj_cnt > 1)
        fprintf (f, "union {\n");
    else
        fprintf (f, "object {\n");

    if (gnode->child != NULL) {
       for (g = gnode->child; g != NULL; g = g->next)
           write_pov20_tree (f, g, level+1);
    }
    else {
       first_tri = gnode->index[0]->next->tri;
       one_texture = 1;

       for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next) {
           if (t->tri->text_index != first_tri->text_index ||
              t->tri->text_type  != first_tri->text_type) {
                 one_texture = 0;
                 break;
           }
       }

       for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next) {
            fprintf (f, "\t");
           write_pov20_triangle (f, t->tri, one_texture);
        }

       if (one_texture) {
           fprintf (f, "\n\t");
           write_pov20_texture (f, first_tri);
       }
    }

    fprintf (f, "\n");

    if (bound_mode == 0)
       write_pov20_bound (f, gnode);

    if (level == 1 && use_transform)
       write_pov20_transform (f, trans_matrix);

    fprintf (f, "}\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_pov20_triangle ( FILE *  f,
Triangle tri,
int  one_texture 
)

Definition at line 1553 of file rayopt.c.

{
    Vector norm[3];
    int    no_smooth = 0;

    COOPERATE /* support multitasking */

    if (smooth_angle > 0.0) {
       vert_normal (tri, norm);

       if (vect_equal (norm[0], norm[1]) && vect_equal (norm[1], norm[2]))
           no_smooth = 1;
    }

    if (smooth_angle > 0.0 && !no_smooth) {
       fprintf (f, "smooth_triangle { <");
       vect_print (f, vtable[tri->vert[0]], dec_point, ',');
       fprintf (f, ">, <");
       vect_print (f, norm[0], 3, ',');
       fprintf (f, ">, <");
       vect_print (f, vtable[tri->vert[1]], dec_point, ',');
       fprintf (f, ">, <");
       vect_print (f, norm[1], 3, ',');
       fprintf (f, ">, <");
       vect_print (f, vtable[tri->vert[2]], dec_point, ',');
       fprintf (f, ">, <");
       vect_print (f, norm[2], 3, ',');
       fprintf (f, "> ");
    }
    else {
       fprintf (f, "triangle { <");
       vect_print (f, vtable[tri->vert[0]], dec_point, ',');
       fprintf (f, ">, <");
       vect_print (f, vtable[tri->vert[1]], dec_point, ',');
       fprintf (f, ">, <");
       vect_print (f, vtable[tri->vert[2]], dec_point, ',');
       fprintf (f, "> ");
    }

    if (!one_texture)
       write_pov20_texture (f, tri);

    fprintf (f, "}\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_vivid_header ( FILE *  f)

Definition at line 1691 of file rayopt.c.

{
    int i;

    if (psize > 0)
       fprintf (f, "/* Texture declarations for object '%s' */\n", object_name);

    for (i = 0; i < psize; i++) {
       fprintf (f, "#define %s_%u \\ \n", object_name, i + 1);
       fprintf (f, "    surface {           \\ \n");
       fprintf (f, "        diffuse %.3f %.3f %.3f \\ \n",
                  ptable[i].red, ptable[i].green, ptable[i].blue);
       fprintf (f, "        shine 70 white  \\ \n");
       fprintf (f, "    }\n\n");
    }
}

Here is the caller graph for this function:

void write_vivid_texture ( FILE *  f,
Triangle tri 
)

Definition at line 1680 of file rayopt.c.

{
    if (tri->text_type == 1)
       fprintf (f, "\n%s /* New texture */\n\n", ttable[tri->text_index]);
    else
       fprintf (f, "\n%s_%u /* New texture */\n\n",
               object_name, tri->text_index + 1);
}

Here is the caller graph for this function:

void write_vivid_transform ( FILE *  f,
Matrix  matrix 
)

Definition at line 1650 of file rayopt.c.

{
    Vector scale, shear, rotate, transl;

    /* Decode the matrix into separate operations */
    mat_decode (matrix, scale, shear, rotate, transl);

    fprintf (f, "\n/* Object transformation */\n");

    fprintf (f, "transform {\n");

    if (fabs(scale[X] - 1.0) > 0.001 || fabs(scale[Y] - 1.0) > 0.001 || fabs(scale[Z] - 1.0) > 0.001)
       fprintf (f, "\tscale %.3f %.3f %.3f\n", scale[X], scale[Y], scale[Z]);

    if (fabs(rotate[X]) > 0.01 || fabs(rotate[Y]) > 0.01 || fabs(rotate[Z]) > 0.01)
       fprintf (f, "\trotate %.2f %.2f %.2f\n", rotate[X], rotate[Y], rotate[Z]);

    if (fabs(transl[X]) > 0.0001 || fabs(transl[Y]) > 0.0001 || fabs(transl[Z]) > 0.0001)
       fprintf (f, "\ttranslate %.4f %.4f %.4f\n", transl[X], transl[Y], transl[Z]);
    else
       fprintf (f, "\ttranslate 0 0 0 // Null transformation\n");

    /* Can't handle shear but warn if it's there */
    if (fabs(shear[X]) > 0.01 || fabs(shear[Y]) > 0.01 || fabs(shear[Z]) > 0.01)
       printf ("Warning: Significant shear in transformation (ignored)\n");

    fprintf (f, "}\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_vivid_tree ( FILE *  f,
GroupTree gnode 
)

Definition at line 1613 of file rayopt.c.

{
    TriList2  *t;
    int       last_index, last_type;

    last_index = -1;
    last_type  = -1;

    fprintf (f, "\n/* Object '%s' */\n", object_name);

    if (use_transform)
       write_vivid_transform (f, trans_matrix);

    if (gnode->child != NULL)
       abortmsg ("Internal error", 1);

    for (t = gnode->index[0]->next; t != gnode->index[0]; t = t->next) {
       if (t->tri->text_index != last_index ||
           t->tri->text_type != last_type)
       {
           write_vivid_texture (f, t->tri);
           last_index = t->tri->text_index;
           last_type  = t->tri->text_type;
       }

       write_vivid_triangle (f, t->tri);
    }

    if (use_transform)
       fprintf (f, "transform_pop\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void write_vivid_triangle ( FILE *  f,
Triangle tri 
)

Definition at line 1710 of file rayopt.c.

{
    Vector norm[3];

    COOPERATE /* support multitasking */

    vert_normal (tri, norm);

    fprintf (f, "patch {\n");
    fprintf (f, "\tvertex ");
    vect_print (f, vtable[tri->vert[0]], dec_point, ' ');
    fprintf (f, " normal ");
    vect_print (f, norm[0], 3, ' ');
    fprintf (f, "\n");

    fprintf (f, "\tvertex ");
    vect_print (f, vtable[tri->vert[1]], dec_point, ' ');
    fprintf (f, " normal ");
    vect_print (f, norm[1], 3, ' ');
    fprintf (f, "\n");

    fprintf (f, "\tvertex ");
    vect_print (f, vtable[tri->vert[2]], dec_point, ' ');
    fprintf (f, " normal ");
    vect_print (f, norm[2], 3, ' ');
    fprintf (f, "\n");

    fprintf (f, "}\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

float bound_cost [static]

Definition at line 159 of file rayopt.c.

int bound_mode = 0 [static]

Definition at line 132 of file rayopt.c.

int dec_point = 4 [static]

Definition at line 135 of file rayopt.c.

float final_tpr [static]

Definition at line 158 of file rayopt.c.

Vector gmax = {-MAXFLOAT, -MAXFLOAT, -MAXFLOAT} [static]

Definition at line 120 of file rayopt.c.

Vector gmin = {+MAXFLOAT, +MAXFLOAT, +MAXFLOAT} [static]

Definition at line 119 of file rayopt.c.

GroupTree* groot [static]

Definition at line 128 of file rayopt.c.

char inc_file[64] = "rayopt.inc" [static]

Definition at line 139 of file rayopt.c.

int initialized = 0 [static]

Definition at line 130 of file rayopt.c.

unsigned last_bounds = 0 [static]

Definition at line 149 of file rayopt.c.

float last_index = 0.0 [static]

Definition at line 148 of file rayopt.c.

Palette last_pal [static]

Definition at line 151 of file rayopt.c.

char last_texture[64] = "" [static]

Definition at line 152 of file rayopt.c.

unsigned last_tri_cnt = 0 [static]

Definition at line 147 of file rayopt.c.

unsigned last_vert_cnt = 0 [static]

Definition at line 146 of file rayopt.c.

Vector last_vmax = {0.0, 0.0, 0.0} [static]

Definition at line 145 of file rayopt.c.

Vector last_vmin = {0.0, 0.0, 0.0} [static]

Definition at line 144 of file rayopt.c.

unsigned object_cnt = 0 [static]

Definition at line 142 of file rayopt.c.

char object_name[64] = "" [static]

Definition at line 155 of file rayopt.c.

float orig_tpr [static]

Definition at line 157 of file rayopt.c.

char out_file[64] = "rayopt.pov" [static]

Definition at line 138 of file rayopt.c.

int out_format = POV10 [static]

Definition at line 136 of file rayopt.c.

unsigned pmax [static]

Definition at line 108 of file rayopt.c.

unsigned psize [static]

Definition at line 109 of file rayopt.c.

Palette* ptable [static]

Definition at line 107 of file rayopt.c.

int quiet_mode = 0 [static]

Definition at line 131 of file rayopt.c.

const char RCSid[] = "$Id: rayopt.c,v 1.4 2007/09/05 01:36:37 greg Exp $" [static]

Definition at line 2 of file rayopt.c.

float smooth_angle = 0.0 [static]

Definition at line 133 of file rayopt.c.

unsigned texture_index [static]

Definition at line 153 of file rayopt.c.

char texture_type [static]

Definition at line 154 of file rayopt.c.

unsigned tmax [static]

Definition at line 112 of file rayopt.c.

unsigned tot_bounds = 0 [static]

Definition at line 141 of file rayopt.c.

Matrix trans_matrix [static]

Definition at line 122 of file rayopt.c.

TriList** tri_index [static]

Definition at line 126 of file rayopt.c.

unsigned tsize [static]

Definition at line 113 of file rayopt.c.

Texture* ttable [static]

Definition at line 111 of file rayopt.c.

int use_transform = 0 [static]

Definition at line 123 of file rayopt.c.

VertList** vert_hash [static]

Definition at line 125 of file rayopt.c.

unsigned vert_init = 0 [static]

Definition at line 134 of file rayopt.c.

unsigned vmax [static]

Definition at line 116 of file rayopt.c.

unsigned vsize [static]

Definition at line 117 of file rayopt.c.

Vector* vtable [static]

Definition at line 115 of file rayopt.c.