> 1) In normalize, are we to assume that the origin is (0,0,1)? You don't need an origin for normalize -- you will pass it a vector to normalize. That direction vector, however, should be relative to the origin of the ray. By the way, the origin of object space is (0, 0, 0). > 2) In intersect_sphere, is our return value t? Also, what is the > intersection point used for? It's possible to return t, but I'd return a simple TRUE/FALSE and return t through a variable parameter. The intersection point will be used for lighting calculations and for reflection. > 3) In main, 3dx 3dy are the direction of the ray? The x and y coordinates in the nested loop are given in image space (pixel locations within the image). You need the corresponding x and y locations in object space (where the objects reside) to determine the direction coordinates of the initial ray (z is always 1.0 in this case) -- these values are 3dx and 3dy. -------------------------------------------------------------------------- > I am having trouble with the diffuse > lighting block in my lighting function. The problem is that you're not using the correct vectors to compute diffuse. You need the normal (which is computed as the intersection point minus the object center) normalized, and the vector from the intersection point to the center of the light (normalized). You have the vector from the origin to the center of the light. You also need to spend some time looking at and learning about C. You're trying to write Java code with C, which doesn't work well at times. Try looking at the many code examples in the textbook to get some ideas. As your code is currently written, you'll lose points on the assignment. -------------------------------------------------------------------------- > is length=sqrt(x*x+y*y) or do I also need z*z? You also need z, so it's sqrt (x*x + y*y + z*z) > I know I need a variable t > that keeps track of the closest object to the ray. So should I pass a > temporary t to the intersect function in case the t returned is not the > closest object? Yes. > The other thing I'm confused with is what I need to pass > for the function to work. I need the OBJ_T, do I pass the whole array or > can I pass a pointer just to the object in question? You only need to pass the object that you're testing for intersection. > And I need a RAY_T, > which contains a POINT_T origin (which is what, (0,0,0)?) and a direction > (which is the normalized vector, right?). For the rays we're dealing with at this point, yes, the origin of the ray would be (0, 0, 0). And dir is a normalized vector. > I saw today in class that you > had an intersect point and a direction t, what's the difference? t is a length represented by a single double. The intersection point is an (x, y, z) point in space. So, t is the length along the vector from the origin to the intersection point. -------------------------------------------------------------------------- > If ray origin is always (0,0,0), do we need to have a separate variable > > POINT_T ro = {0, 0, 0} > > or shall we just use zeroes? In later versions of the ray tracer, ray origins will be points other than the origin, so you need a separate field to keep track of the origin. -------------------------------------------------------------------------- > I assume you were in a hurry when you wrote the outline for the program. In > the do_lighting function normal and ray are POINT_T, but I think they must > be RAY_T, as we decided today. Is it right? Actually, the lighting routine only needs the normal direction and ray (or view) direction. The origin represented by the intersection point (ipoint) can be used for both. In my code, I only pass the vector information since that's all that do_lighting needs. You may, however, pass normal and ray as RAY_T if you like. -------------------------------------------------------------------------- > I'm having difficulties with my intersect_sphere function in ray.c. The > function is always returning true, so my entire image comes out as the > color of the sphere. I was wondering if you could take a look at my > function and see if you could find the error that I have been unable to > (I submitted my program with the handin command). I really appreciate the > help. You had some difficult problems to track down, but here they are -- - in rt.h, you have this line typedef POINT_T[3]; Since there is no type associated with the above, it defaults to int. You should have typedef double POINT_T [3]; - in main, you need to compute threeDx and threeDy correctly; you have threeDx= -0.5 + (i/500); threeDy= 0.5 - (j/500); which will always result in -0.5 and 0.5 due to integer division. You should have threeDx= -0.5 + (i/500.0); threeDy= 0.5 - (j/500.0); to force the floating point conversion. - in trace, you need to initialize dist (or closest t) to something large so that smaller t's will be recognized when you compare them dist = 1000; - in intersect_sphere, you forgot to subtract the square of the radius in computing C. -------------------------------------------------------------------------- > Hey, I have a few questions about the outlines that you posted. First > off, in the parameter list for the intersect functions you have a RAY_T > pointer, int intersect_sphere (OBJ_T sphere, RAY_T ray, POINT_T ipoint, > RAY_T *normal, double *dist), my question is would the origin be the > intersection point and what would be the direction(I'm guessing that > it's the normalized intersection point)? First, you should *never* normalize a point, only a direction. We've declared them both to be of POINT_T for simplicity, but make sure you keep them straight when coding. For the normal pointer listed above, the origin will be set to the intersection point and the direction is computed using the difference between the intersection point and the center of the sphere, as we discussed in class. Note that if there is no intersection point, we need not set the fields of normal since the function will return FALSE and thus, we will not try to access these fields when we return to main. > Also, would you tell me the coordinates of the light you used in the > progression notes? I'm having trouble telling whether or not my diffuse > lighting is correct, or if I'm close but not quite there. Set the center of the light at (5.0, 10.0, -2.0). -------------------------------------------------------------------------- > I have calculated some points with a calculator that should create > intersections(example: x: 0, y:0, z:1 after normalizing) and there are no > intersections in my program. if you could find out what was wrong I would > greatly appreciate it. Here's a list of some of the problems I found with your program: - In intersect_sphere, your parentheses are wrong in computing b. Overall, you have too many parens in your code -- that's why this problem took a while to track down. The code originally multiplied 2 only by the first component: b = ( 2 * (ray.direction[X] * (ray.origin[X] - sphere.center[X])) + (ray.direction[Y] * (ray.origin[Y] - sphere.center[Y])) + (ray.direction[Z] * (ray.origin[Z] - sphere.center[Z]))); when it should be b = ( 2 * ((ray.direction[X] * (ray.origin[X] - sphere.center[X])) + (ray.direction[Y] * (ray.origin[Y] - sphere.center[Y])) + (ray.direction[Z] * (ray.origin[Z] - sphere.center[Z])))); Note that you don't need an extra set of parens around the entire equation. Plus, you can leave out some parens due to operator precedence. Compare the above to b = 2 * (ray.direction[X] * (ray.origin[X] - sphere.center[X]) + ray.direction[Y] * (ray.origin[Y] - sphere.center[Y]) + ray.direction[Z] * (ray.origin[Z] - sphere.center[Z])); - In intersect_sphere, you have some problems in returning t. First, if you want to set t, you should write *t = t1; not t = &t1; The latter will not work, since you are setting the local var t to an address that won't (and shouldn't) be passed back to main. The other problem is in the comparisons. You have if(t1 < t2) if(t1 >= 0) { t = &t1; return 1; } else { if(t2 >= 0) { t = &t2; return 1; } } The first else will match the inner if, but that's not what you want. Also, what if t1 = -0.5 and t2 = 0.5? Now, t1 < t2, but your code doesn't allow for t2 to be assigned to t (you'd need another else inside the first nested if). - In main, you declare new variables after you call define_objects(objs). All declarations should precede any function call. - In your main loop, you have for(y = 0; y <= H; y++) but y should always be strictly less than H. Same for x and W. -------------------------------------------------------------------------- > In the intersect_plane function the intersection point should be this > i[X] = (ray.org[X]+ray.dir[X])*t1; > i[Y] = (ray.org[Y]+ray.dir[Y])*t1; > i[Z] = (ray.org[Z]+ray.dir[Z])*t1; > that is the intersection is equal to the ray origin plus the ray > direction times t, correct? No -- the parentheses are in the wrong place above. Instead, the equations should be i [X] = ray.org [X] + (ray.dir [X] * t1); etc. (actually, the parens above are not needed). > And for the normal, the origin should be 0,0,0 and the direction should > the center of the plane? No -- as we computed for the sphere, the origin of the normal should be the intersection point. The normal direction will be (0, 1, 0) everywhere on the plane. -------------------------------------------------------------------------- > At the end of the lighting routine, do you add the sum of the effects, as > contained in the local variable, COLOR, to the original object color before > doing the cap? To get the final color, sum the effects (ambient, diffuse, and specular). The color of the object is taken into consideration during those calculations. The sum, however, may exceed 1.0, at which point you must cap it to 1.0. -------------------------------------------------------------------------- > In our do_lighting function, how to do we compute the N vector for the > specular lighting? You need to compute the N (or normal) vector in the intersect_sphere or intersect_plane function, since the normal is determined differently for different objects. (The method for computing the normal in each case was given in class.) You can then pass it to do_lighting at a later point in the program. -------------------------------------------------------------------------- > The following statements won't compile -- why? > excerpt from intersect_sphere: > > /* set normal origin to intersection point */ > *normal.or[X] = ipoint[X]; > *normal.or[Y] = ipoint[Y]; > *normal.or[Z] = ipoint[Z]; > > /* set normal direction */ > *normal.dir[X] = ipoint[X] - sphere.center[X]; > *normal.dir[Y] = ipoint[Y] - sphere.center[Y]; > *normal.dir[Z] = ipoint[Z] - sphere.center[Z]; > > command prompt: > > flare1[83] cc -lm ray.c > "ray.c", line 124: left operand of "." must be struct/union object > "ray.c", line 124: cannot dereference non-pointer type > "ray.c", line 125: left operand of "." must be struct/union object > "ray.c", line 125: cannot dereference non-pointer type > "ray.c", line 126: left operand of "." must be struct/union object > "ray.c", line 126: cannot dereference non-pointer type > "ray.c", line 128: left operand of "." must be struct/union object > "ray.c", line 128: cannot dereference non-pointer type > "ray.c", line 129: left operand of "." must be struct/union object > "ray.c", line 129: cannot dereference non-pointer type > "ray.c", line 130: left operand of "." must be struct/union object > "ray.c", line 130: cannot dereference non-pointer type > cc: acomp failed for ray.c Since the '.' operator has precedence over the '*' (dereference) operator, the compiler is interpreting your statement as *(normal.or[X]) = ipoint[X]; which is not what you want. Instead, you should write (*normal).or[X] = ipoint[X]; Of course, this is much more easily written as normal -> or[X] = ipoint[X]; -------------------------------------------------------------------------- > How do I calculate the color for the diffuse lighting? I know I have to > find the vector that is the difference between the center of the light > source and the intersection point, and that I have to normalize that vector, > but then what? Where does the color for the ray come from? I know I have > to find a dot product, but I am not sure which one. To calculate diffuse lighting, you need to compute the dot product of the light vector (as you mention above) and the surface normal vector associated with the ray/object intersection point for this ray. Then, multiply that value by the color of the object asssociated with the intersection point. -------------------------------------------------------------------------- > ... So I was wondering, if the > plane is defined as A=0.0, B=-1.0, C=0.0, and D=0.9, how do you get a > normal of (0,1,0)? As far as I can tell, my Normalize routine gives (0, > -1.0, 0). Simply define the plane with A = 0.0, B = 1.0, and C = 0.0. The D term determines the length from the origin, so the -0.9 is included there. A, B, and C represent the plane's normal, but since a plane has two sides, it has two normals, so you can set it to either. -------------------------------------------------------------------------- > ... my checkerboard half works...the plane is below the > spheres in the scene, but only have two blocks, a black one and a white > one. I was wondering if you could point me in the right direction. I > don't know what I'm doing wrong since I copied the checkerboard formula > straight from my notes. The problem is that you're assigning the checkerboard color to *color (which is what you're adding the ambient, diffuse, and specular components to). Instead, you should set a temporary variable to hold whatever the color value the get_color function pointer returns. -------------------------------------------------------------------------- > my program keeps ending up with a segmentation fault that i can't locate The problem is in the way your variables are declared. In your main routine, you have the following declarations: double *dist, *col; RAY_T *normal; These represent pointers only -- no space has been allocated to hold the data associated with these pointers. Thus, when you execute statements like *col = 0.3; *dist = 1000.0; later in the program, you're trying to store data in locations that are invalid. That's why you get the segmentation fault. Instead, you should declare the variables (not as pointers), then if you ever need to pass a pointer to the variable, use the referencing operation (e.g., &col). -------------------------------------------------------------------------- > i cant figure out what is wrong with my do lighting routine. Your problem in do_lighting is the one we discussed in class yesterday. *col should start out as 0.0, then should be increased by ambient, diffuse, and specular light. You should never set *col to objs[obj_num].color directly. -------------------------------------------------------------------------- > My checkerboard has a checker in the middle that's twice as wide as > the others. How can I fix it? The problem comes up when x goes from negative to positive. Change the checkerboard computation from if (((int) x + (int) y + (int) z) & 1) to if ((int) floor (x) + (int) floor (y) + (int) floor (z)) & 1) --------------------------------------------------------------------------