Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Pointer Location Changing
Index -> Programming, C++ -> C++ Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
apython1992




PostPosted: Tue Jun 28, 2011 12:40 pm   Post subject: Pointer Location Changing

Hey guys. So a while back I started writing a raytracer in Python, which was a lot of fun, but after wiping out my hard drive and forgetting to back it up, I lost it for good, and so here I am starting it again, this time in C++. My knowledge in C++ is extremely limited, and I'm mainly doing this to pick up some knowledge on pointers and all that jazz. Anyway, I've started laying out the groundwork for the raytracer, and I'm doing some primitive testing right now to see if my primary rays intersect a plane I set into the scene. I've been treating almost everything with pointers, because it involves passing a lot of objects around. I have a class for primitive objects, like planes, spheres, and rays, and I figured it would be easiest to represent a plane by its normal vector with an origin. So, to get a "back wall" plane for example, i would create a plane with a normal vector of [0, 0, -1], with a point of say, (0, 0, 100). However, when testing for the intersection, the value of the normal's direction vector changes (it actually for some reason occupies a different location in memory, which I'm really stumped on because I've been passing pointers around). I've attached my source code so you can see the class definitions and try running it, but to narrow the scope down a bit the differences I see occur within main.cpp (see my comments on the direction in init_scene() and raytrace()).

c++:


#include <iostream>
#include <vector>
#include "plane.h"
#include "sphere.h"
#include "ray.h"

/*
Dimensions are:
x - increasing from left to right
y - increasing from down to up
z - increasing going into the screen
*/


#define SCREEN_X    1280
#define SCREEN_Y    800
#define DEPTH       16

const int SCENE_POS[3] = {-640, 400, 500};

using namespace std;

typedef vector<Sphere *> svec;
typedef vector<Plane *> pvec;

// globals
svec spheres;
pvec planes;
int grid[SCREEN_Y][SCREEN_X] = {{0}};

// function prototypes
void init_scene();
void set_values(int *arr, int a, int b, int c);
void set_values(double *arr, double a, double b, double c);
double *raytrace(Ray *ray);

int main()
{
    int origin[3] = {0, 0, 0};
    double direction[3];

    init_scene();

    // Iterate through screen plane and fire rays through pixels to see
    // what they hit
    for (int j = 0; j < SCREEN_Y; j++)
    {
        //cout << j / 8.0 << endl;
        for (int i = 0; i < SCREEN_X; i++)
        {
            // Calculate direction from origin based on current pixel
            direction[0] = SCENE_POS[0] + i;
            direction[1] = SCENE_POS[1] - j;
            direction[2] = SCENE_POS[2];

            // Create a ray with these values
            Ray ray(origin, direction);

            // RAYTRACE
            double *intersect = raytrace(&ray);
            delete [] intersect;
            return 0;
        }
    }
    return 0;
}

void init_scene()
{
    // Create planes
    int p_origin[3], p_color[3];
    double p_direction[3];

    // Back wall
    set_values(p_origin, 0, 0, 300);
    set_values(p_direction, 0, 0, -1);    // This is what the direction should always be
    set_values(p_color, 255, 0, 0);
    Ray p_normal(p_origin, p_direction);
    Plane plane(&p_normal, p_color);
    planes.push_back(&plane);

    // Create Spheres
    int s_origin[3], s_color[3], s_radius;

    //center sphere
    s_radius = 15;
    set_values(s_origin, 100, 100, 100);
    set_values(s_color, 0, 0, 255);
    Sphere sphere(&s_radius, s_origin, s_color, false);
    spheres.push_back(&sphere);
}

void set_values(int *arr, int a, int b, int c)
{
    arr[0] = a;
    arr[1] = b;
    arr[2] = c;
}

void set_values(double *arr, double a, double b, double c)
{
    arr[0] = a;
    arr[1] = b;
    arr[2] = c;
}

double *raytrace(Ray *ray)
{
    double *intersect;

    // See if ray hits any planes
    for (unsigned int i = 0; i < planes.size(); i++)
    {
        cout << planes[i]->m_normal->get_direction()[0]<< " " << planes[i]->m_normal->get_direction()[1] << " " << planes[i]->m_normal->get_direction()[2] << endl; // This prints out very different values
        intersect = planes[i]->get_intersect(ray);
    }

    if (intersect != 0)
    {
        cout << intersect[0] << endl << intersect[1] << endl << intersect[2] << endl;
    }
    else cout << "No intersect." << endl;
    return intersect;
}


Without me seeing much of any kind of C++ code, I have no idea what kinds of coding practices are good/not so good, so I'd appreciate some feedback there as well. Thanks!



raytracer.zip
 Description:

Download
 Filename:  raytracer.zip
 Filesize:  308.43 KB
 Downloaded:  194 Time(s)

Sponsor
Sponsor
Sponsor
sponsor
DemonWasp




PostPosted: Tue Jun 28, 2011 9:02 pm   Post subject: RE:Pointer Location Changing

I'm using g++ 4.4.5.

I compiled with "-Wall -Wextra -Werror -pedantic", with varying optimization levels. Using different levels of optimization often points out subtle bugs, because optimization really makes use of the fact that C++ is a ridiculously underdefined language, so anything you're doing that's even slightly undefined comes to focus very quickly.

I didn't get any warnings until I turned on optimization (-02), which I find to be curious. The one warning I did get was that in raytrace(Ray*), you potentially use intersect before it's initialized (if there are no planes)...not your problem, but good to fix.

Output with varying levels of optimization:

-O0, or no optimization:
code:

0 0 -1
No intersect.


-O1:
code:

0 0 -1
Segmentation fault.


-O2:
code:

0 0 -1
No intersect.


-O3:
code:

0 0 -1
No intersect.


This shows us that the code is (probably) using undefined behaviour. The output of your code will change from one machine to the next, from one compiler to the next, and so forth. Helpfully, g++ has avoided telling us anything of value.


I think I've spotted the problem, though: in init_scene(), you create several objects on the stack (Ray, Plane, Sphere), take their addresses, and store them as pointers. This is a big no-no, as they will then out-live the stack frame they were allocated in, and subsequent stack activity will stomp all over them and their precious data. If your objects are going to outlive the method, then they should be allocated on the heap, with new (or malloc, etc).

I'm pretty sure this is your problem (though, I would have expected g++ to warn me about that...). This neatly explains why our results vary, and why my results vary depending on optimization level: the stack frame is of a different size, which means that later stack activity overwrites it in different ways (or, doesn't actually overwrite it, whichever).
apython1992




PostPosted: Tue Jun 28, 2011 10:15 pm   Post subject: RE:Pointer Location Changing

My gosh, you're totally right. I'm well aware that declaring pointers on the stack is a big no-no because they will just get popped off anyway, but for some reason here I was just treating them as temporary pointers for permanent objects to contain...I forgot to note that the internal pointers would of course need to hang around afterwards. Doh! Thanks for the help Demonwasp, I realize this one was a bit more of a pain what with the several source files and all. I can't fix it right now to guarantee that this will solve the problem, but I'll let you know how this goes once I can change it tomorrow. Thank you!
apython1992




PostPosted: Fri Jul 01, 2011 9:45 pm   Post subject: RE:Pointer Location Changing

I got around to addressing the problem. I allocated the pointers from the heap instead, and as expected it works like a charm. Thanks, DemonWasp!
DemonWasp




PostPosted: Sat Jul 02, 2011 1:20 am   Post subject: RE:Pointer Location Changing

No problem. I find it weird that g++ refused to warn about this -- it knows the objects are being allocated on the stack, and it knows that you're sending their addresses out of the frame, so...where's the warning? I'm pretty sure I've seen compilers warn about this before...
apython1992




PostPosted: Sat Jul 02, 2011 10:37 am   Post subject: RE:Pointer Location Changing

I find that really bizarre too, I'm sure I've been warned of this at other places in the project. Anyway, at least it's fixed now.
Display posts from previous:   
   Index -> Programming, C++ -> C++ Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 6 Posts ]
Jump to:   


Style:  
Search: