Pointer Location Changing
Author |
Message |
apython1992
|
Posted: 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!
Description: |
|
Download |
Filename: |
raytracer.zip |
Filesize: |
308.43 KB |
Downloaded: |
194 Time(s) |
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
DemonWasp
|
Posted: 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
|
Posted: 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
|
Posted: 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
|
Posted: 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
|
Posted: 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.
|
|
|
|
|
|
|
|