Reputation: 599
I have these two structs defined:
#ifndef OBJECT_H_
#define OBJECT_H_
#include <stdio.h>
#include "vector.h"
struct object{
public:
int index; // identifies a object; must be greater than 0
float mat_ambient[3]; // material property used in Phong model
float mat_diffuse[3];
float mat_specular[3];
float mat_shineness;
float reflectance; // this number [0,1] determines how much
// reflected light contributes to the color
// of a pixel
virtual float intersect(Point, Vector, object*, Point*);
virtual Vector normal(Point, object*);
};
#endif /* OBJECT_H_ */
#ifndef SPHERE_H_
#define SPHERE_H_
#include "object.h"
struct sphere: public object {
public:
Point center;
float radius;
// intersect ray with sphere
float intersect(Point, Vector, object*, Point*);
// return the unit normal at a point on sphere
Vector normal(Point, object*);
};
#endif /* SPHERE_H_ */
However, when I try to compile, I get these two errors:
undefined reference to `vtable for object'
I know it's not my makefile, as it already added sphere.cpp and object.cpp Is there a function or a method missing from my structs that's causing this?
object.cpp
#include "object.h"
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include "sphere.h"
using namespace std;
/**********************************************************************
* This function intersects a ray with a given sphere 'sph'. You should
* use the parametric representation of a line and do the intersection.
* The function should return the parameter value for the intersection,
* which will be compared with others to determine which intersection
* is closest. The value -1.0 is returned if there is no intersection
*
* If there is an intersection, the point of intersection should be
* stored in the "hit" variable
**********************************************************************/
float sphere::intersect(Point A, Vector p, object *o, Point *hit) {
cout << "intersect" << endl;
sphere* s = (sphere*) o;
Point C = s->center;
Point B;
B.x = A.x + p.x;
B.y = A.y + p.y;
B.z = A.z + p.z;
float a = pow(B.x - A.x, 2) + pow(B.y - A.y, 2) + pow(B.z - A.z, 2);
float b = 2 * ((B.x - A.x) * (A.x - C.x) + (B.y - A.y) * (A.y - C.y) + (B.z - A.z) * (A.z - C.z));
float c = pow(A.x - C.x, 2) + pow(A.y - C.y, 2) + pow(A.z - C.z, 2) - pow(s->radius, 2);
float delta = pow(b, 2) - 4 * a * c;
if (delta < 0.0) {
//no intersection
return -1.0;
}
if (delta >= 0.0) {
//possibly more then one intersection, but at least one, return the smallest one
float d1 = (-b - sqrt(delta)) / (2 * a);
float d2 = (-b + sqrt(delta)) / (2 * a);
if (d1 < d2) {
hit->x = A.x + (p.x * d1);
hit->y = A.y + (p.y * d1);
hit->z = A.z + (p.z * d1);
return d1;
} else {
hit->x = A.x + (p.x * d2);
hit->y = A.y + (p.y * d2);
hit->z = A.z + (p.z * d2);
return d2;
}
}
return -1.0;
}
/******************************************
* computes a sphere normal - done for you
******************************************/
Vector sphere::normal(Point q, object *o) {
sphere *sph = (sphere *) o;
Vector rc;
rc = get_vec(sph->center, q);
normalize(&rc);
return rc;
}
Makefile
#! /usr/bin/make
SOURCE= scene.cpp image_util.cpp sphere.cpp vector.cpp trace.cpp raycast.cpp object.cpp include/InitShader.cpp
CC= g++
CFLAGS= -O3 -ggdb -O0 -Wall -pedantic -DGL_GLEXT_PROTOTYPES -std=c++11
EXECUTABLE= raycast
LDFLAGS = -lGL -lglut -lGLEW -lXext -lX11 -lm
INCLUDEFLAG= -I. -I$(INCLUDEDIR) -Iinclude/
LIBFLAG= -L$(LIBDIR)
OBJECT= $(SOURCE:.cpp=.o)
all: $(OBJECT) depend
$(CC) $(CFLAGS) $(INCLUDEFLAG) $(LIBFLAG) $(OBJECT) -o $(EXECUTABLE) $(LDFLAGS)
depend:
$(CC) -M $(SOURCE) > depend
$(OBJECT):
$(CC) $(CFLAGS) $(INCLUDEFLAG) -c -o $@ $(@:.o=.cpp)
clean_object:
rm -f $(OBJECT)
clean:
rm -f $(OBJECT) depend $(EXECUTABLE)
include depend
Upvotes: 3
Views: 1658
Reputation: 11
If there's no definition for object::intersect & object::normal, you should make them pure virtual functions as below:
#ifndef OBJECT_H_
#define OBJECT_H_
#include <stdio.h>
#include "vector.h"
struct object{
public:
int index; // identifies a object; must be greater than 0
float mat_ambient[3]; // material property used in Phong model
float mat_diffuse[3];
float mat_specular[3];
float mat_shineness;
float reflectance; // this number [0,1] determines how much reflected light contributes to the color of a pixel
virtual float intersect(Point, Vector, object*, Point*) = 0;
virtual Vector normal(Point, object*) = 0;
};
#endif /* OBJECT_H_ */
Try it and I think it would figure out your problem.
Upvotes: 1
Reputation: 10733
undefined reference to `vtable for object'
You are getting this error because you have not provided definition of virtual method in object. Basically vtable stores function pointers
i.e address of virtual function is required. So if you miss the definition of single virtual function, compiler won't be able to generate complete vtable for that class.
For your object class vtable
would be like something:-
&object::intersect
&object::normal
EDIT:-
That means corresponding to these:-
virtual float intersect(Point, Vector, object*, Point*);
virtual Vector normal(Point, object*);
You should have :-
float object::intersect(Point, Vector, object*, Point*)
{
}
Vector object::normal(Point, object*)
{
}
Upvotes: 5