Jeff Stevens
Jeff Stevens

Reputation: 137

Implementing basic Raytracer in C

So I am currently working on a tutorial to implement a very basic raytracer (currently just drawing solid spheres). Said tutorial is located here: http://thingsiamdoing.com/intro-to-ray-tracing/

The tutorial is completely language agnostic and deals only in pseudocode. I attempted to convert this pseudocode into C but have encountered difficulty. My program compiles fine, yet the outputted .ppm image file experiences an early EOF error. The lack of information about the problem has left me stuck.

Here is my C code, which is meant to be a direct translation of the pseudocode:

#include <stdio.h>
#include <math.h>

#define WIDTH 512
#define HEIGHT 512

typedef struct {
    float x, y, z;
} vector;

float vectorDot(vector *v1, vector *v2) {
    return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
}

void writeppm(char *filename, unsigned char *img, int width, int height){
    FILE *f;
    f = fopen(filename, "w");
    fprintf(f, "P6 %d %d %d\n", width, height, 255);
    fwrite(img, 3, width*height, f);
    fclose(f);
}

float check_ray(px, py, pz, dx, dy, dz, r) {
    vector v1 = {px, py, pz};
    vector v2 = {dx, dy, dz};
    float det, b;
    b = -vectorDot(&v1, &v2);
    det = b*b - vectorDot(&v1, &v1) + r*r;

    if (det<0)
        return -1;

    det = sqrtf(det);
    float t1 = b - det;
    float t2 = b + det;

    return t1;
}

int main(void) {
    int img[WIDTH*HEIGHT*3], distToPlane;
    float cameraY, cameraZ, cameraX, pixelWorldX, pixelWorldY, pixelWorldZ, amp, rayX, rayY, rayZ;
    for (int px = 0; px<WIDTH; px++) {
        for (int py = 0; py<HEIGHT; py++) {
            distToPlane = 100;
            pixelWorldX = distToPlane;
            pixelWorldY = (px - WIDTH / 2) / WIDTH;
            pixelWorldZ = (py - HEIGHT / 2) / WIDTH;

            rayX = pixelWorldX - cameraX;
            rayY = pixelWorldY - cameraY;
            rayZ = pixelWorldZ - cameraZ;

            amp = 1/sqrtf(rayX*rayX + rayY*rayY + rayZ*rayZ);
            rayX *= amp;
            rayY *= amp;
            rayZ *= amp;

            if (check_ray(50, 50, 50, rayX, rayY, rayZ, 50)) {
                img[(py + px*WIDTH)*3 + 0] = 0;
                img[(py + px*WIDTH)*3 + 1] = 0;
                img[(py + px*WIDTH)*3 + 2] = 128;
            }
            else {
                img[(py + px*WIDTH)*3 + 0] = 255;
                img[(py + px*WIDTH)*3 + 1] = 255;                                 
                img[(py + px*WIDTH)*3 + 2] = 255;
            }
        }
    }
    writeppm("image.ppm", "img", WIDTH, HEIGHT);
}

I am fairly confident the error does not lie with my function to write the .ppm file as I have used this for other work and it has been fine.

Upvotes: 3

Views: 1333

Answers (2)

Weather Vane
Weather Vane

Reputation: 34583

I see two errors in main

int img[WIDTH*HEIGHT*3];
...
writeppm("image.ppm", "img", WIDTH, HEIGHT);

should be

unsigned char img[WIDTH*HEIGHT*3];
...
writeppm("image.ppm", img, WIDTH, HEIGHT);

Upvotes: 2

thurizas
thurizas

Reputation: 2528

You may want to remove the quotes from around "img" in the following line of code:

writeppm("image.ppm", "img", WIDTH, HEIGHT);

seeing as how its prototype is void writeppm(char *, unsigned char *, int, int), although I am surprised that your compiler didn't at least give you a warning about a type mismatch.

Also, for the record, I would suggest putting some error checking code (like checking the return value of fwrite, or checking the return value of fopen)--- but that's just me.

Also, if you are not, please compile with all the warning enabled (eg with gcc use -ansi -Wall -pedantic), this will help you catch type mismatches and other little gotcha-ya's

Upvotes: 3

Related Questions