I had to generate an image that's a black circle, black being (0, 0 , 0) and white being (1, 1, 1), but I keep getting a completely black image. Here's all my code:
#include "cast.h"
#include "collisions.h"
#include <stdio.h>
#include "math.h"
int cast_ray(struct ray r, struct sphere spheres[], int num_spheres)
{
int isFound;
struct maybe_point mp;
isFound = 0;
for (int i = 0; i < num_spheres; i++)
{
mp = sphere_intersection_point(r, spheres[i]);
if (mp.isPoint == 1)
{
isFound = 1;
}
else
{
isFound = 0;
}
}
return isFound;
}
void print_pixel(double a, double b, double c)
{
int i, j, k;
i = a * 255;
j = b * 255;
k = c * 255;
printf("%d %d %d ", i, j, k);
}
void cast_all_rays(double min_x, double max_x, double min_y, double max_y,
int width, int height, struct point eye,
struct sphere spheres[], int num_spheres)
{
double width_interval, height_interval, y, x;
int intersect;
width_interval = (max_x - min_x)/width;
height_interval = (max_y - min_y)/height;
for (y = max_y; y > min_y; y = y - height_interval)
{
for (x = min_x; x < max_x; x = x + width_interval)
{
struct ray r;
r.p = eye;
r.dir.x = x;
r.dir.y = y;
r.dir.z = 0.0;
intersect = cast_ray(r, spheres, num_spheres);
if (intersect != 0)
{
print_pixel (0, 0, 0);
}
else
{
print_pixel (1, 1, 1);
}
}
I already had functions that I know are correct which find whether or not the ray intersects with a sphere. The function that I used to find intersection points was in the function cast_ray.
sphere_intersection_point(r, spheres[i]);
The print_pixel function translates the integer values by multiplying them with the max color value, which is 255.
And the cast_all_rays function casts rays into the whole scene from our eyes (going through all the x coordinates before changing the y). If the ray intersects with a sphere, the pixel is black, thus, forming a black circle in the end.
And here are the limits for the x, y, and radius (NOTE: I'M USING THE PPM FORMAT):
Eye at <0.0, 0.0, -14.0>.
A sphere at <1.0, 1.0, 0.0> with radius 2.0.
A sphere at <0.5, 1.5, -3.0> with radius 0.5.
min_x at -10, max_x at 10, min_y of -7.5, max_y at 7.5, width=1024, and height=768.
I need to generate an image of a black circle, but I keep getting an image that's completely black. I have a feeling that the problem lies inside the cast_all_rays function, but I just can't seem to find what it is. Help is appreciated! Thanks.
And just in case something went wrong with my testing, here's my test.c file for cast_all_rays:
#include "collisions.h"
#include "data.h"
#include "cast.h"
#include <stdio.h>
void cast_all_rays_tests(void)
{
printf("P3\n");
printf("%d %d\n", 1024, 768);
printf("255\n");
double min_x, max_x, min_y, max_y;
int width, height;
struct point eye;
struct sphere spheres[2];
eye.x = 0.0;
eye.y = 0.0;
eye.z = -14.0;
spheres[0].center.x = 1.0;
spheres[0].center.y = 1.0;
spheres[0].center.z = 0.0;
spheres[0].radius = 2.0;
spheres[1].center.x = 0.5;
spheres[1].center.y = 1.5;
spheres[1].center.z = -3.0;
spheres[1].radius = 0.5;
min_x = -10;
max_x = 10;
min_y = -7.5;
max_y = 7.5;
cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye, spheres, num_spheres);
}
int main()
{
cast_all_rays_tests();
return 0;
}
Not sure if this is the problem you're having, but you should only set isFound
if you intersect a sphere. Don't set it if you don't intersect. Otherwise your image will be governed by only the last sphere in the list.
if (mp.isPoint == 1)
{
isFound = 1;
}
//else
//{
// isFound = 0;
//}
Since your image is entirely black, it seems like your intersection code is bung or your field of view is too narrow. If you don't have any joy with the above change, maybe you should post details on your x- and y-limits, the eye position, and the position and radius of the sphere.
One more thing I noticed is r.dir.z = 0.0
. Do you subtract the eye position from this to get a direction, or is that your true ray direction? Surely you need to give a non-zero z-direction. Normally you set the x
and the y
based on your view plane and provide a constant z
such as 1
or -1
.
[edit]
To make it clearer from the comments below, I believe that you haven't correctly set up your ray direction. Instead you have simply set the direction to be the view-plane's pixel position, ignoring the eye position. The following would be more usual:
struct ray r;
r.p = eye;
r.dir.x = x - eye.x;
r.dir.y = y - eye.y;
r.dir.z = 0.0 - eye.z;