I'm trying to create some bounding boxes around some objects that I have.
I create them like this:
struct boundingBox{
float top;
float bottom;
float left;
float right;
};
I'm having issues setting their values. I have this function which I was hoping would set their values:
void makeBoundingBox(boundingBox bound, float t, float b, float l, float r){
bound.top =t;
bound.bottom =b;
bound.left=l;
bound.right=r;
}
and I am trying to set them like this:
makeBoundingBox(car,b_Size,b_Size,b_Size,b_Size); //where car is a boundingBox object and b_Size is a calculated box size
When I'm using the above line, the values aren't set; I know this because I print to the console to check the values and they always come back 0. However, if within the same function I use makeBoundingBox, I set car.top = 500 manually instead, and print, the car.top is set successfully to 500 and works...
Does the makeBoundingBox method not work correctly by passing a struct object how I am expecting it too?
You're passing the box by value. For the routine to change the actual argument, pass it by reference. I.e.
void makeBoundingBox(boundingBox& bound, float t, float b, float l, float r){
bound.top =t;
bound.bottom =b;
bound.left=l;
bound.right=r;
}
However, instead of that, in C++11 just write
boundingBox{ 1, 1, 10, 10 }
when you need a boundingBox with those values.
In C++03 you can instead define a constructor for the boundingBox class.
Read up on that in your favorite C++ text book.
Here is an example class definition:
struct boundingBox{
float top;
float bottom;
float left;
float right;
boundingBox( float a_top, float a_bottom, float a_left, float a_right )
: top( a_top ), bottom( a_bottom )
, left( a_left ), right( a_right )
{}
};
and you can then create an instance like
boundingBox( 1, 1, 10, 10 )
As a general observation, using float instead of double can create some problems (especially with C++11 curly braces initialization), it has less precision than double, and it has no special advantages except where you need zillions of values, like a few billion.
So, use double.
That's the default floating point type in C++, e.g. it's the type of 3.14.
You're passing the boundingBox by value, not by reference. This means the makeBoundingBox function is operating on a local copy and changes do not propagate back to the original object.
Change your function definition as follows:
void makeBoundingBox(boundingBox& bound, float t, float b, float l, float r)
You're passing the struct to the function by VALUE, you need to pass by REFERENCE so:
void makeBoundingBox(boundingBox &bound, float t, float b, float l, float r){
bound.top =t;
bound.bottom =b;
bound.left=l;
bound.right=r;
}
Notice the & to pass by reference.
In your function call, do the same & in front of the variable name.
Related
I'm only beginning in C++ and I'm struggling to understand some code from a custom vector class in an article I'm working through. The author writes it as:
class vec3
{
public:
vec3() {}
vec3(float e0, float e1, float e2)
{
e[0] = e0;
e[1] = e1;
e[2] = e2;
}
(...)
But so far I've only seen class definitions where the types of data it holds are defined, such as:
class vec3
{
public:
float m_x;
float m_y;
float m_z;
vec3(float x, float y, float z) : m_x(x), m_y(y), m_z(z)
{}
My guess was that the code in the article is creating an empty vector which it then populates with floats or there was something assumed in the definition. Is this just a syntax difference or is there something more fundamental that I'm missing? Apologies for what seems like a basic question but I couldn't find any similar questions. . . it might be too basic for that! But I just wanted to understand it before I moved on.
Thanks,
Paddy
In the code you've posted, you are correct that there is no declaration for the variable e anywhere. I'm not sure if this is because you didn't post that part of the code from the book, or if the book omitted that for brevity.
Without knowing what the book author was meaning by e, I don't want to suggest a completion of the code. There are several things that e could be declared as that would be compatible with the code you've posted.
It defines e as just a float array [e[3]].
With this information added, then there is no relevant difference between three separate members and an array. In the end, both variants will require the same amount of memory, and in most cases, the (optimised!) code generated by the compiler will be exactly the same:
float getY()
{
return m_y;
// will result in address of object + offset to m_y
}
float getY()
{
return e[1];
// will result in address of object + offset to e + offset to second element
// as both offsets are constant, they will be joined to one single summand
// and we are back at first variant...
}
One of the few things you can do with arrays but not with separate members is having a loop, such as the following:
float magnitude()
{
float sum = 0.0F;
for(auto f : e)
sum += f*f;
return sqrtf(sum);
}
However, for such short loops, loop unrolling is pretty likely, and the code generated again is with high probability equivalent to the separate member variant:
float magnitude()
{
return sqrtf(m_x * m_x + m_y * m_y + m_z * m_z);
}
With an array, you could pass all three members in one single parameter to other functions (as pointer to first element), with separate members, you'd have to pass all of them separately (well, there are ways around, but they either require extra effort or are "dirty"...).
I recently started using C++ and I just created a class that allows the integration of a user-defined system of ode's. It uses two different integrators in order to compare its performance. Here is the general layout of the code:
class integrators {
private:
double ti; // initial time
double *xi; // initial solution
double tf; // end time
double dt; // time step
int n; // number of ode's
public:
// Function prototypes
double f(double, double *, double *); // function to integrate
double rk4(int, double, double, double, double *, double *);
double dp8(int, double, double, double, double *, double *);
};
// 4th Order Runge-Kutta function
double integrators::rk4(int n, double ti, double tf, double dt, double *xi, double *xf) {
// Function statements
}
// 8th Order Dormand-Prince function
double integrators::dp8(int n, double ti, double tf, double dt, double *xi, double *xf) {
// Function statements
}
// System of first order differential equations
double integrators::f(double t, double *x, double *dx) {
// Function statements
}
int main() {
// Initial conditions and time related parameters
const int n = 4;
double t0, tmax, dt;
double x0[n], xf[n];
x0[0] = 0.0;
x0[1] = 0.0;
x0[2] = 1.0;
x0[3] = 2.0;
// Calling class integrators
integrators example01;
integrators example02;
// First integrator
example02.dp8(n, t0, tmax, dt, x0, xf);
// Second integrator
example01.rk4(n, t0, tmax, dt, x0, xf);
}
The problem is that the array containing the initial conditions x0 in main, changes after executing the first integrator and I cannot use the same initial conditions for the second integrator, unless I define another array with the same initial conditions (x0_rk4 and x0_dp8). Is there a more professional way to keep this array constant in order to use it in both integrators?
The easiest way is to make a local copy of array inside integrating functions.
Change the way you are passing 'n' to function to 'const int n', so you can make something like double currentSolution[n]; inside and copy elements from initial array to new one. This approach will save your initial array intact, unless you will "accidently" modify it somewhere.
To prevent this probability of accident modification we need to go deeper and use one of stl containers. I think you will be fine with std::valarray<T>.
Change the way you are passing it to const std::valarray<double>& and again make non-const local copy.
No, not really. But there exist a more elegant solution:
std::array<double, n> x0_rk4 = { 0.0, 0.0, 1.0, 2.0 };
auto x0_dp8 = x0_rk4; // copy!
You will have to use x0_rk4.data() to access the underlying array. Note that it would be better if you used std::array and other modern C++ features instead of raw pointers and the like.
I am trying to understand a framework I have been provided with and slowly debugging it. In my case I have an array of vec3, memorized with a pointer
vec3 *cx =....;
First of all, every time I try to check the content of a glm::vec3 through debugging I see many values: x, r, s, y, g, t, z, b, p. I don't know why I have all these members, and according to the documentation I see that glm::vec3 is a struct with inside:
if(GLM_COMPONENT == GLM_COMPONENT_ONLY_XYZW)
value_type x, y, z;
elif(GLM_COMPONENT == GLM_COMPONENT_MS_EXT)
union
{
struct{value_type x, y, z;};
struct{value_type r, g, b;};
struct{value_type s, t, p;};
};
else//(GLM_COMPONENT == GLM_COMPONENT_GLSL_NAMES)
union {value_type x, r, s;};
union {value_type y, g, t;};
union {value_type z, b, p;};
endif//GLM_COMPONENT
I don't know where in the huge framework I am studying which one of the options above is actually chosen. And I don't know the meaning of all those members.
I only know that through debugging I see all those values but, as any other vec3, I use the x,y,z values for my calculations.
After this, I would like to know what actually happens if I cast an array of vec3 to an array of doubles. In practice:
double * cast = (double*)cx;
What does it give me back?
In order to understand, I tried to do this:
vec3 boh(1.0);
vec3 boh2(2.0);
vec3 * try = new vec3[2];
try[0] = boh;
try[1] = boh2;
double* try2 = (double*)try;
I realize that try points to the first vec3, which is boh1, so if I go debugging, I see all the x, r, s, y, g, t, z, b, p set to 1.0. Likewise try2 should be pointing to "something" related to boh1, but the debug shows me that try2 has the value 0.0078125018480932340. So, what is actually happening?
Officially, that is undefined behavior. It all depends what the glm::vec3 structure contains.
I would refer to the glm reference pages. They clearly explains what glm::vec3 is and how to use it.
I am writing a small program for learning C++ and 3D.
I have already written a vertex class with usefull methods. (like Dot,Cross, etc...)
class cVector {
...
float x, y, z;
...
float dot(cVector& v);
cVector cross(cVector& v);
...
}
Now I realize OpenGL expects buffers where elements are more like a struct (VBO).
struct sVector {
float x, y, z;
}
So my vertex class is no longer useless, because if i want to manipulate data in the buffer :
1 - I need to extract data of elements in the buffer.
2 - Create a temporary instance of vertex class with the data.
3 - Use vertex class method. (Dot, cross, etc...)
4 - Put the data back to the buffer.
It's not very efficient :(.
I wonder if I should not use a struct to organize my vectors and create global functions that take a pointer to a struct as an argument.
I could handle data buffers more efficiently (just moving pointer) but I feel i would lose the "convenient power" of C++.
In every 3D C++ source code i ever see, all use class for vertex but i dont understand how they can manipulate large amount of vertex in a "struct like" buffer.
Can you help me to understand ? What is the best approach ?
The most common approach in a language like C++ is actually neither of these things.
You are more likely to encounter the following:
struct Vector3 {
union {
struct {
float x,y,z;
};
float v [3];
};
...
Vector3 (float x_, float y_, float z_) : x (x_), y (y_), z (z_) { };
float Norm (void) { return sqrt ((x * x) + (y * y) + (z * z)); }
void Normalize (void) {
float norm = Norm ();
v [0] /= norm;
v [1] /= norm;
v [2] /= norm;
}
};
The reason for this is because using anonymous unions and structs, you can treat the data as either an array of floats (v [...]) or reference the individual components by their name (x, y, z) without a lot of muss or fuss. You get the best of both worlds by using the language more intelligently.
As for the difference between a struct and a class in this particular case, there is none from the perspective of memory representation. The only real difference between a class and a struct in C++ is the default access; struct has public access by default.
When GL needs to access the object's internal memory, you would accomplish this by passing it the pointer: Vector3::v or the individual components, depending on the particular function.
For instance:
Vector3 vec (1.0f, 2.0f, 3.0f);
---------------------------------
glVertex3fv (vec.v);
and
glVertex3f (vec.x, vec.y, vec.z);
are equivalent
On a side-note, anonymous structures are a non-standard extension to C++ but supported virtually everywhere. In the case that you have a compiler that does not support them, you may have to qualify access to x, y, and z by giving the struct a name.
struct Vector3 {
union {
struct {
float x,y,z;
} s;
float v [3];
};
};
If you write your struct this way, then:
Vector3 vec;
assert (vec.v [0] == vec.s.x);
It is messier to have to qualify x that way (using an anonymous struct you can use vec.x).
There is exactly one difference between struct and class: For class the default scope is private, while for struct it is public.
So
class cVector {
...
float x, y, z; // data
...
float dot(cVector& v); // just a function
cVector cross(cVector& v); // just a function
...
}
and
struct sVector {
float x, y, z; // data
}
have exactly the same memory layout (given that x,y,z are the only members variables of cVector).
You can use &v.x to get a pointer to (x,y,z) for OpenGL, e.g. glVertex3f(&v.x);.
You can even do the following to get a pointer to a continuous sequence of vertices for usage with OpenGL:
std::vector<cVector> vertices(100);
const float* data = &(vertices[0].x);
Suppose we want two constructors for a class representing complex numbers:
Complex (double re, double img) // construct from cartesian coordinates
Complex (double A, double w) // construct from polar coordinates
but the parameters (number and type) are the same: what is the more elegant way
to identify what is intended? Adding a third parameter to one of the constructors?
It is better to add static methods with appropriate names and let them to create the objects.
static Complex createFromCartesian(double re, double img);
static Complex createFromPolar(double A, double w);
You can't have two constructors (or any functions) with the same signatures. The best solution is probably to create classes for your coordinate types and overload on those. For example:
struct CartCoord {
CartCoord( double re, double img ) : mRe(re), mImg(img) {}
double mRe, mImg;
};
struct PolarCoord {
PolarCoord( double a, double v ) : mA(a), mV(v) {}
double mA, mV;
};
Then your constructors become:
Complex( const CartCoord & c );
Complex( const PolarCoord & c);
In use:
Complex c( CartCoord( 1, 2 ) );
You can also use them with overloaded operators of the Complex class. For example, assuming you have a binary + operator for the class define as:
Complex operator+( const Complex &, const Complex & );
then:
Complex a( CartCoord( 0, 0 ) );
Complex b = a + PolarCoord( 1, 1 );
As we have a conversion constructor from PolarCoord to Complex, this will be used in the + expression. This is more natural (IMHO) than calling static functions to create the temporary..
This is an example of Koenig's dictum (or at least a version of it) - whenever faced with a difficult problem, introduce a new level of classes to solve it.
Use the named constructor idiom described here at the Parashift C++ FAQ.
You can't - if the method signatures are the same, you're stuffed.
Of course, you could always create a subclass for each type of coordinate system, but that's far from ideal - especially if you later find a good reason to want to subclass Complex for other reasons...
Instead of having two constructors, you need to have only one, but add a third parameter, for example:
Complex (double re, double img, enum type) {
if(type == polar) {
..treat as polar coordinates..
} else {
..treat as cartesian coordinates..
}
}
'enum type' can have a default type as well so you don't have to supply what type of coordinates you intend to use every time, the default should off course be what's most used.
Complex (double re, double img, enum type = polar);
Since no one mentioned it, you can use tags:
class Complex{
struct CartCoord{};
struct PolarCoord{};
Complex( CartCoord, double re, double img);
Complex( PolarCoord, double a, double v);
};
int main(){
auto c1 = Complex(Complex::CartCoord{}, 5, 6);
auto c2 = Complex(Complex::PolarCoord{}, 5, 6);
}
I don't know if it is good practice in C++ but I would name these two methods differently, at least for a maintainability point of view.
I would probably create more classes, but then I am an adept of Boost Strong Typedef library.
For me it does not make sense to use double to represent both coordinates, module and angles.
So I would have:
class CoordinateX {};
class CoordinateY {};
class Modulus {};
class Angle {};
class Complex
{
public:
Complex(CoordinateX, CoordinateY);
Complex(Modulus, Angle);
};
And there it's perfectly clear, and there is no ambiguity. Also you add some compile-time check of "units" in a loose sense. It rarely makes sense (if ever) to add an X-coordinate and an Y-coordinate, or worse a distance and an angle.
For me the more elegant way would be to create a class representing cartesian coordinates and another representing polar coordinates, then give object of the relevant class to the constructors.
That way you would have two constructor using different parameters.
I use this simple alternative way while practicing C++, I don't know if it is what you want.
class Vector{
public:
float x, y;
Vector();
Vector(float , float, bool);
float get_distance(Vector v); // find distance from another vector
float get_magnitude(); // find distance from origin point
Vector add(Vector v);
Vector subtract(Vector v);
Vector multiply(Vector v); // multiply by vector
Vector multiply(float scalar); // multiply by scalar
float get_angle();
};
Vector::Vector(float a, float b, bool is_cartesian = true){
if(is_cartesian){
x = a;
y = b;
}
else{
x = a * cos( b );
y = a * sin( b );
}
}