creating a vector of abstract objects

Hello, I am writing a ray tracer and thought the best way to handle the scene's "objects" would be to have an abstract superclass (called Object) with just pure virtual methods (maybe just a colour field) and all other objects derived from this class (so far just Sphere and Plane) who each define their own versions of each method.

I then want to do this:
1
2
vector<Object*> objs;
objs.push_back(&s1);


where s1 is a Sphere object

I have Stroustrup's text and have read the appropriate sections thoroughly and thought this would be okay, but the compiler won't let me.

Here is the Sphere class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifndef SPHERE_HH

#define SPHERE_HH



#include "vector.h"

#include "object.h"



/**

 * Defines a simple Sphere located at 'center' 

 * with the specified radius

 */

class Sphere : public Object {

	

public:



	Vector center;

	double radius;

	

    /**

     * A simple constructor for the Sphere

     */

    Sphere(Vector c, double r, COLOR col) : Object(col) {

		 this->center = c;

		 this->radius = r;

	 }



    /**

     * Sphere's intersection method.

     */

    virtual Vector intersect(Vector pos, Vector dir)

	{

		Vector vdif = pos-center;

		double a = dir.dot(vdif);

		double len = vdif.length();

		double b = len*len-radius*radius;

		double delta = a*a-b;



		Vector vout(0,0,0,-1);   //-1 indicates no intersection    

		if(delta<0.0) return vout;



		double k1 = -a+sqrt(delta);

		double k2 = -a-sqrt(delta);



		Vector p1 = pos + (dir*k1);

		Vector p2 = pos + (dir*k2);



		if(k1<0)				//Return the pt closest to 'pos'

			return (k2>0)? p2: vout;

		else if (k2<0)

			return p1;

		else

		  return (k1<k2)? p1: p2;



	}



   /**

     * Returns the unit normal vector at a given point.

	 * Assumption: The point p lies on the sphere.

     */

	virtual Vector normal(Vector p)

	{

		Vector n = p - center;

		n.normalise();

		return n;

	}

};



#endif //!SPHERE_HH 



And the object class:


1
2
3
4
5
6
7
8
9
10
11
12
13
      class Object {
	
	public: 
		COLOR C;
		int ID;
	
	    //Object() : C(cols[0]) {}
		Object(COLOR c) : C(c) {}
		
		virtual Vector intersect(Vector pos, Vector dir) = 0;
		
		virtual Vector normal(Vector p) = 0;
}


I have tried the Object class with/without default/any constructor, can't work out what I am doing wrong.

Any suggestions would be greatly appreciated
Thankyou,
Anna.
It's #include <vector>

Next time post the error as well. Just saying "there's an error" isn't very descriptive.

EDIT: Oh, yeah. std::vector is all lowercase. Don't forget the namespace and don't forget to include the header in all files that need it.
Last edited on
Yes I have appropriate #includes, namespace etc., just left out stuff to save space, and I have a Vector class (as in mathematical vector - I assumed that would be pretty standard for graphics).

The error is: "expected declarator, constructor or type declaration before '.' token " (as in the objs.push_back(...))

Thanks.
I will need to see the code around that.
Yes, please post more code.

Also, irrelevant to your compile error, you should define a virtual destructor in Object.
Here is my main tracer program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*========================================================================
 * A simple ray tracer
 *========================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <vector>
#include "vector.h"
#include "sphere.h"
#include "plane.h"
#include "object.h"

using namespace std;

#define WIDTH  401    //Image size (preferably, be an odd number)
#define HEIGHT 401
#define EDIST 1000   //Distance of the image plane from eye position
#define EPSILON 1e-3

Sphere s1(Vector(0., 0., -1500.), 100, cols[1]);   // red sphere
Sphere s2(Vector(100, 0., -2000), 300, cols[2]);   // blue sphere

vector<Object*> objs;

objs.push_back(&s1);
objs.push_back(&s2);

Vector L(-100, 400, -1000);      // light

/*
 * This function compares the given ray with all objects in the scene
 * and computes the closest point  of intersection.
 *
 * [For each object, use the 'intersect' method of the object's class to
 *  find the intersection point. Then compare all such intersection points to
 *  get the point closest to the eye]
 *
 * The index of the closest object is returned as an integer value of the 'k' field
 * of the intersection point.
 */

Vector closestPt(Vector p, Vector dir) {
	
	Vector p1 = objs[0]->intersect(p, dir);
	Vector p2 = objs[1]->intersect(p, dir);
	
	double dist1;
	double dist2; 
	
	if (p1.k == -1 && p2.k == -1)
		return p1;   // no intersection
	
	if (p1.k != -1 && p2.k != -1)   {   // intersects both
		dist1 = p.dist(p1);
		dist2 = p.dist(p2);

		if (dist1 < dist2) {  // p1 closest
			p1.k = 1;
			return p1;   
		}
		else {                // p2 closest
			p2.k = 2;
			return p2;  
		}
	}
	
	else if (p1.k == -1) {    // only p2 exists
		p2.k = 2;
		return p2; 
	}
	else {                    // only p1 exists
		p1.k = 1;
		return p1;
	}
}

/*
 * Return the color value on the object that gives the closest intersection point.
 *
 * If reflections and refractions are to be included, then secondary rays will 
 * have to be traced from the point, by converting this method to a recursive
 * procedure
 */

COLOR trace(Vector p, Vector dir) {

	Vector Q = closestPt(p, dir);   
	COLOR C;                        // return value
	
	if (Q.k == -1) {
		C = cols[0];   // no intersection - set background color
		return C;
	}
		
	Vector shadow_ray = L - Q;   // shadow ray originates at Q, direction L - Q
	shadow_ray.normalise();
	
	Vector sq = closestPt(Q, shadow_ray);  // intersection pt of shadow ray
	
	if ((sq.k != -1) && (Q.dist(sq) > EPSILON)) { // shadow ray intersected by another object
		C = cols[0]; 
		return C;          // shadow color
	}
	
	else {               // no intersection 
		C = cols[Q.k];    
		Vector n;
		
		if (Q.k == 1)   // the red sphere - get suface normal at pt sq
			n = objs[0]->normal(Q);
			 
		if (Q.k == 2) // the blue sphere - get surface normal at pt sq
			n = objs[1]->normal(Q);	
			
		double scale_factor = n.dot(shadow_ray);
		
		C.r = C.r * scale_factor;
		C.g = C.g * scale_factor;
		C.b = C.b * scale_factor;
	}
		
		return C;
}

void display() {
	
  glClear(GL_COLOR_BUFFER_BIT);
  int i, j;      //pixel coordinates
  int iwid = WIDTH/2;   //Half of width (truncated)
  int jhgt = HEIGHT/2;  //Half of height (truncated)
  
  Vector eye(0, 0, 0);    //Eye is always at the origin
	
  COLOR c;

  glBegin(GL_QUADS);

  for(i=0; i<WIDTH; i++)						//Scan every "pixel"
  {
	  for(j=0; j<HEIGHT; j++)
	  {
	  	Vector primary_ray(i - iwid, j - jhgt, -EDIST);
	  	primary_ray.normalise();
	  	c = trace(eye, primary_ray);
	  	
		  glColor3f(c.r, c.g, c.b);
		  glVertex2d(i-0.5, j-0.5);				//Draw each pixel with its color value
		  glVertex2d(i+0.5, j-0.5);
		  glVertex2d(i+0.5, j+0.5);
		  glVertex2d(i-0.5, j+0.5);
	  }
  }

  glEnd();
  glFlush();
}
/*
 *  Initialisation of graphics parameters
 */
void init()
{
  glMatrixMode(GL_PROJECTION);
  gluOrtho2D(0,WIDTH,0,HEIGHT);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glClearColor(0,0,0,1);
}


/**
 * Standard main function.
 */
int main(int argc, char *argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(20, 20);
    glutCreateWindow("Raytracing");

    glutDisplayFunc(display);
    init();

    glutMainLoop();
}


So far it's just two spheres - it works without the Object class - but I want to add more objects of different types - ie floor plane/cube. The compiler stops at line 27 with the error:

tracer.cpp:28: error: expected constructor, destructor, or type conversion before ‘.’ token
tracer.cpp:29: error: expected constructor, destructor, or type conversion before ‘.’ token


I have added a virtual destructor

Thanks
Ah. Now that's more like it.
You can't call functions from global scope. Only functions may call functions.
Ah! Thankyou so much :)
Topic archived. No new replies allowed.