Lab 5: object_find_closest()

Objectives

To write and test the object_find_closest() function, where the idea is to:
  1. given the following input: object list, ray base and direction
  2. find the object that (a) intersects the ray and (b) is the closest object to the ray base along the ray (smallest t value)
  3. set the (pass-by-reference) distance value to the intersection point, set the hit and N vectors to the surface hit point and the normal at that hit point, and return the pointer to the closest object
The algorithm is as follows:
  1. iterate through the object list, inspecting in turn each object (via list_get_data(objs))
  2. if the distance to the object/ray intersection is less than 0, skip it (continue; side-effect is that we have computed the distance to the object/ray intersection)
  3. otherwise if the distance to the object/ray intersection is greater than 0.000001 and less than the current closest distance, set the currently found closest object and minimum distance to the current object and current distance to the ray/intersection point (also set the surface hit point and normal to the currently closest hit point and normal)
  4. at the end of the loop, if there is a closest hit object (it is not NULL set all the return values
  5. return the pointer to the closest hit object (even if NULL)
Note that the above algorithm is essentially no different from "find the smallest item on the list" problem.

In this lab the material and object lists are also placed within a model_t object which also contains the camera_t object.

Assignment

  1. Use the following prototype for the object_find_closest() function:
    
    object_t *object_find_closest(list_t*,vec_t,vec_t,double*,vec_t,vec_t);
    	
    and write the body of the function.
  2. You code should be such that the following main.c file works unaltered:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    #include <math.h>
    
    #include "vector.h"
    #include "matrix.h"
    #include "pixel.h"
    #include "list.h"
    #include "material.h"
    #include "object.h"
    #include "model.h"
    
    
    // prototypes
    int main(int argc, char *argv[]);
    
    int main(int argc, char *argv[])
    {
            model_t         *model;
            object_t        *obj;
            vec_t           pos = { 4.0,  3.0,  5.0};
            vec_t           dir = { 0.0,  0.0, -1.0};
            vec_t           hit, N;
            double          dis;
            FILE            *model_file=NULL, *hits_file=NULL;
    
      if(argc != 3) {
        fprintf(stderr,"Usage: %s  \n",argv[0]);
        exit(1);
      }
    
      // open model file
      if((model_file = fopen(argv[1],"r")) == NULL) {
         printf("Error opening input file: %s\n",argv[1]);
         return;
      }
    
      // create model
      model = model_init(model_file);
      
      // close file
      fclose(model_file);
    
      // verify that we have all materials
      material_list_print(model->mats,stdout);
                                  
      // verify that we have all objects 
      object_list_print(model->objs,stdout);
    
      // open hits file
      if((hits_file = fopen(argv[2],"r")) == NULL) {
         printf("Error opening input file: %s\n",argv[2]);
         return;
      }
    
      // read direction vectors from hits_file and perform hit comptuations
      while(fscanf(hits_file, "%lf %lf %lf",&dir[0],&dir[1],&dir[2]) == 3) {
        fprintf(stderr,"\n\n");
        vec_print(stderr,"Ray direction:", dir);
        vec_unit(dir,dir);
    
        dis = 0.0;
        obj = object_find_closest(model->objs,pos,dir,&dis,hit,N);
        if(dis > 0) {
          fprintf(stderr,"Hit: %-12s ",obj->name);
    
          fprintf(stderr,"Dist = %8.3lf ",dis);
          vec_print(stderr,"Loc = ",hit);
        } else
          fprintf(stderr,"Dist = %8.3lf \n",dis);
    
        fprintf(stderr, "\n\n");
        obj = object_find_closest(model->objs,pos,dir,&dis,hit,N);
        if(dis > 0) {
          fprintf(stderr,"Hit: %-12s ", obj->name);
    
          fprintf(stderr,"Dist = %8.3lf ",dis);
          vec_print(stderr,"Loc = ",hit);
        } else
          fprintf(stderr,"Dist = %8.3lf \n",dis);
      }
    
      // close hits file
      fclose(hits_file);
    
      return(0);
    }
    	
  3. Sample input file model.txt:
    material green
    {
       ambient 0 5 0
    }
    
    material yellow
    {
       ambient 6 5 0
    }
    
    material gray
    {
       ambient 4 4 4
    }
    
    plane leftwall
    {
       material green
       normal 3 0 1
       point  0 0 0
    }
    
    plane rightwall
    {
       material yellow
       normal -3 0 1
       point  8 0 0
    }
    
    plane floor
    {
       material gray
       normal 0 1 0
       point  0 0 0
    }
    	
  4. Sample input file hittest.txt:
    -0.5 -0.1 -1
     0.5 -0.1 -1
     0  -0.5 -1.0
     1   1   1
    	
  5. Sample output:
    loaded green 
    loaded yellow 
    loaded gray 
    loaded leftwall 
    loaded rightwall 
    loaded floor 
    material green
    {
       ambient 0 5 0
    }
    
    material yellow
    {
       ambient 6 5 0
    }
    
    material gray
    {
       ambient 4 4 4
    }
    
    plane leftwall
    {
       material green
       normal 3 0 1
       point  0 0 0
    }
    
    plane rightwall
    {
       material yellow
       normal -3 0 1
       point  8 0 0
    }
    
    plane floor
    {
       material gray
       normal 0 1 0
       point  0 0 0
    }
    
    
    
    Ray direction:  -0.500  -0.100  -1.000
    Hit: leftwall     Dist =    7.633 Loc =    0.600   2.320  -1.800
    
    
    Hit: leftwall     Dist =   15.266 Loc =    0.600   2.320  -1.800
    
    
    Ray direction:   0.500  -0.100  -1.000
    Hit: rightwall    Dist =    7.633 Loc =    7.400   2.320  -1.800
    
    
    Hit: rightwall    Dist =   15.266 Loc =    7.400   2.320  -1.800
    
    
    Ray direction:   0.000  -0.500  -1.000
    Hit: floor        Dist =    6.708 Loc =    4.000   0.000  -1.000
    
    
    Hit: floor        Dist =   13.416 Loc =    4.000   0.000  -1.000
    
    
    Ray direction:   1.000   1.000   1.000
    Dist =    0.000 
    
    
    Dist =    0.000 
    	
  6. Note that the program is now run with two arguments:
    ./main model.txt hittest.txt
    	

Turn in

Turn in all of your code, in one tar.gz archive of your lab05/ directory, including:
  1. A README file containing
    1. Course id--section no
    2. Name
    3. Lab description
    4. Brief solution description (e.g., program design, description of algorithm, etc., however appropriate).
    5. Lessons learned, identified interesting features of your program
    6. Any special usage instructions
  2. Makefile
  3. source code (.h headers and .c source)
  4. object code (do a make clean before tar)

How to hand in

See submit notes.