I am trying to implement software renderer, which interpolation happens after vertex shading
The following is its declaration
template <class T>
class Interpolatable
{
// The function calculates an interpolated value
// along the fraction t between 0.0 and 1.0.
// When t = 1.0, endValue is returned.
virtual T interpolate(const T &endValue, float t)=0;
};
struct Vertex: public Interpolatable<?????????>
{
float x, y, z;
Vertex()=default;
Vertex(float, float, float);
virtual Vertex &interpolate(const Vertex &endValue, float t) const;
};
Is it possible to make Vertex's interpolate method return instance of Vertex?
The compiler keeps giving me errors
You can pass a class' name as a template argument safely, but any errors you're getting are due to a function signature mismatch.
struct Vertex: public Interpolatable<Vertex>
virtual T interpolate(const T &endValue, float t)=0;
virtual Vertex &interpolate(const Vertex &endValue, float t) const;
// ^reference ^declared const
It seems that your signatures should be:
virtual T interpolate(const T &endValue, float t) const =0;
virtual Vertex interpolate(const Vertex &endValue, float t) const;
It should work if you fix the three errors:
????????? should be Vertex
interpolate should return Vertex by value
interpolate should not be const (or should be const in the base class)
Related
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 8 months ago.
I have two classes that I want to define, Position and TangentVector, partially given as follows:
class Position
{
public:
Position(double x, double y, double z);
// getters
double x(){ return m_x };
double y(){ return m_x };
double z(){ return m_x };
void translate(const TangentVector& tangent_vector);
private:
double m_x;
double m_y;
double m_z;
}
class TangentVector
{
public:
Tangent(double x, double y, double z, Position position);
// getters
double x(){ return m_x };
double y(){ return m_x };
double z(){ return m_x };
private:
double m_x;
double m_y;
double m_z;
Position m_position;
}
The key thing to note with the classes is that TangentVector has a member of type Position (TangentVector depends on Position) while Position has a method that takes in an argument of type const TangentVector& (Position depends on TangentVector?).
For context's sake, Position is intended to represent a point on the unit sphere, and TangentVector describes a vector tangent to the sphere, with the origin of the vector specified by a Position. Since the definition of a VectorTangent requires a Position to be specified, it seems reasonable to say that VectorTangent depends on Position. However, now I want to define a function that takes a Position on the sphere, and "translates" it along the sphere by a direction and distance given by TangentVector. I would really like this translate method to live in the Position class, since it a function that modifies the state of Position. This would lend itself to the following usage, which I feel is fairly natural:
Position position{ 1.0, 0.0, 0.0 };
TangentVector tangent_vector{ 0.0, PI/2, 0.0, position };
position.translate(tangent_vector); // Now { 0.0, 1.0, 0.0 };
However, I fear that this results in some circular dependency. So...
Is this case an example of circular dependency? Is this case bad practice?
If so, how can this circular dependency be avoided? How can this code be modified such that it is in-line with good OOP practices?
(I considered making the Position m_position member a raw pointer instead. In this case, however, I intend m_position to be fully owned by TangentVector, rather than allow the possibility of it being altered external to the class. In the example usage code, I do not want the translate method to modify tangent_vector, which would happen if tangent_vector's constructor took in position as a pointer and stored it as a member.)
class Position takes only a reference to class TangentVector. Therefore you might pre-declare TangentVector as class TangentVector; before the declaration of class Position:
class TangentVector;
class Position
{
public:
Position(double x, double y, double z);
// getters
double x(){ return m_x };
double y(){ return m_x };
double z(){ return m_x };
void translate(const TangentVector& tangent_vector);
private:
double m_x;
double m_y;
double m_z;
};
Title may be a little bit confusing but basically I have a class 'Quaternion' which has 2 parameters, the first being another instance of a class Vector3 and the other being a float.
Vector3 takes 3 floats as parameters and assigns them to x, y, and z.
I want to set default parameters for the Quaternion class but I am unsure how to set default parameters with a class as a parameter.
Vector3
class Vector3 {
public:
float x, y, z;
Vector3(float uX, float uY, float uZ) {
this->x = uX;
this->y = uY;
this->z = uZ;
}
};
Quaternion
class Quaternion {
public:
Vector3 axis;
float scalar;
Quaternion(Vector3 uAxis, float uScalar = 0) {
axis = uAxis;
scalar = uScalar;
};
};
I would like to have the default parameter for uAxis to be a Vector3 with x, y, and z set to 1, 0, 0 respectively, but i am unsure how i can do this.
I think this is what you were looking for:
class Quaternion {
public:
Vector3 axis;
float scalar;
Quaternion(Vector3 uAxis = Vector3(1.0, 0.0, 0.0), float uScalar = 0) {
axis = uAxis;
scalar = uScalar;
};
};
It is possible to call a constructor of a class to set a default parameter. Here is the corresponding cpp reference default arguments.
This is what you want. Always use the initialisation list on the constructor unless you have to do something with the parameters docs. Also I am passing the uAxis as const reference which is always a good thing to do for ADT (Abstract Data Types) Unless you have special requirements.
class Quaternion
{
Vector3 axis;
float scalar;
public:
Quaternion(const Vector3 & uAxis = Vector3(1.0, 0.0, 0.0), float uScalar = 0) :
axis(uAxis),
scalar(uScalar)
{
}
};
Another option would be to use default member initialization for axis within Quaternion. That way, just creating a Quaternion q{} would set axis to whatever you want. [Demo]
class Quaternion {
public:
Vector3 axis{1.0, 0.0, 0.0};
float scalar{};
Quaternion() = default;
...
};
For the Quaternion(Vector3 uAxis, float uScalar) constructor, it would be preferable to use a member initializer list:
Quaternion(Vector3 uAxis, float uScalar) : axis{uAxis}, scalar{uScalar} {};
Also, you can remove Vector3's constructor, making Vector3 an aggregate:
struct Vector3 {
float x{};
float y{};
float z{};
};
Vector3 v{1.1, 2.2, 3.3};
so i am trying to build a game and i have the following code:
// Vector2 is just a struct that represents a vector is 2D space.
// predefining these structs
struct SILO;
struct ICBM;
struct MISSILE;
struct ICBM{
Vector2 launch;
Vector2 target;
Vector2 pos;
int Velocity;
ICBM(){
// Implementation not shown
}
void move(){
// implementation not shown
}
};
struct MISSILE{
Vector2 launch;
Vector2 target;
Vector2 pos;
int Velocity;
MISSILE(Vector2 t, SILO origin){
launch = (Vector2) {origin.Object.x, origin.Object.y};
target = t;
pos = launch;
Velocity = 10;
}
void move(){
// implementation not shown
}
};
struct SILO{
Rectangle Object; // Rectangle has attributes x and y
Vector2 pos;
};
I predefined all of the structs in the beginning so they can reference eachother. However, the constructor of the struct MISSILE will result in an error saying that SILO is an incomplete type.
I could change the constructor parameter into MISSILE(Vector2 t, SILO* origin). However, when i try to access the attributes, it will result in the same error.
Is there any way I can solve this problem WITHOUT changing the position of where SILO is defined?
You could use a SILO* in your MISSILE constructor, instead a copy of the whole object?!
MISSILE(Vector2 t, SILO* origin){
launch = (Vector2) {origin->Object.x, origin->Object.y};
Here is my code
struct Ray {
vec3 origin;
vec3 direction;
bool hit;
Sphere object;
float t;
};
struct Sphere {
vec3 origin;
float radius;
BasicMaterial material;
};
Now, when I create a Ray,my goal is that the object be NULL.
Ray r;
r. origin = origin;
r.direction = dir;
r.hit = false;
r.object = NULL;
r.t = FLT_MAX;
When I run it, I get
error C1503: undefined variable "NULL"
One way I could think of is make a dummy object and initialise with that every time. Is there any better way to do it?
Something like NULL doesn't exist in GLSL. See the most recent OpenGL Shading Language 4.60 Specification (HTML).
Sphere object is not an object reference. The type of object is the structure Sphere. When you assign a variable (s) of type Sphere to object
Sphere s;
Ray r;
r.object = s;
all the elements of s are copied to r.object. GLSL has no concept of objects, object references, inheritance or polymorphism.
Hence the element Sphere object in the structure Ray doesn't make sense. In GLSL you would need to write a function that calculates the intersection of a Ray and a Sphere:
struct Ray
{
vec3 origin;
vec3 direction;
};
struct Sphere
{
vec3 origin;
float radius;
BasicMaterial material;
};
bool IntersectRaySphere(in Ray r, in Sphere s, out float t)
{
// [...]
}
I have this class:
class Texture
{
public:
//I need this variable in this format
float diffuseColor[3];
}
But I'd like to make an easier interface than dealing with "diffuseColor[0]" and such, something like:
myTexture.color.r = 1.0f; //this is diffuseColor[0]
So I'm trying to get a class that works as a shell to the diffuseColor values, something like:
class Color
{
public:
float *r, *g, *b;
}
And in my Texture class:
class Texture
{
public:
Texture()
{
color.r = &diffuseColor[0];
color.g = &diffuseColor[1];
color.b = &diffuseColor[2];
}
Color color;
private:
float diffuseColor[3];
}
But the way it is now, I have to de-reference the color values if I want to use them:
(*myTexture.color.r) = 1.0f;
How can I achieve this without having to de-reference it everytime I want to use it?
You can use references which would be initialized in the member initializer list:
struct Color {
Color(float* colors): r(colors[0]), g(colors[1]), b(colors[2]) {}
float& r;
float& g;
float& b;
};
class Texture {
float diffuseColor[3];
public:
Color color;
Texture(): diffuseColor(), color(this->diffuseColor) {}
};
If you need to copy and/or assign Texture objects, you'll also need to implement a copy constructor and an assignment operator. Also note that this convenience has a relatively steep costs: both the pointers and the reference approach will increase the size of the Texture objects by 3 pointer. You might be better off to use accessors, instead, e.g.:
class Texture {
float diffuseColor[3];
public:
float& r() { return this->diffuseColor[0]; }
float& g() { return this->diffuseColor[1]; }
float& b() { return this->diffuseColor[2]; }
};
Maybe you can use the union language feature of C++:
union ColorUnion {
// first representation (Texture)
struct TextureColor {
float diffuseColor[3];
}
// second representation (RGB)
struct RGBColor {
float r;
float g;
float b;
}
};