This question already has answers here:
Why can an aggreggate struct be brace-initialized, but not emplaced using the same list of arguments as in the brace initialization?
(2 answers)
Closed 1 year ago.
I have a fairly bog standard Vector4 struct (the math kind not the C++ kind) which is a POD and is templated:
template<typename T>
struct Vector4 {
T x, y, z, w;
Vector4 operator+(const Vector4& other) const { return Vector4{ x + other.x, y + other.y, z + other.z, w + other.w }; }
Vector4 operator-(const Vector4& other) const { return Vector4{ x - other.x, y - other.y, z - other.z, w - other.w }; }
Vector4 operator*(const Vector4& other) const { return Vector4{ x * other.x, y * other.y, z * other.z, w * other.w }; }
Vector4 operator/(const Vector4& other) const { return Vector4{ x / other.x, y / other.y, z / other.z, w / other.w }; }
Vector4 operator+(const T& a) const { return Vector4{ x + a, y + a, z + a, w + a }; }
Vector4 operator-(const T& a) const { return Vector4{ x - a, y - a, z - a, w - a }; }
Vector4 operator*(const T& a) const { return Vector4{ x * a, y * a, z * a, w * a }; }
Vector4 operator/(const T& a) const { return Vector4{ x / a, y / a, z / a, z / a }; }
Vector4& operator+=(const Vector4& other) { x += other.x; y += other.y; z += other.z; w += other.w; return *this; }
Vector4& operator-=(const Vector4& other) { x -= other.x; y -= other.y; z -= other.z; w -= other.w; return *this; }
Vector4& operator*=(const Vector4& other) { x *= other.x; y *= other.y; z *= other.z; w *= other.w; return *this; }
Vector4& operator/=(const Vector4& other) { x /= other.x; y /= other.y; z /= other.z; w /= other.w; return *this; }
Vector4& operator+=(const T& a) { x += a; y += a; z += a; w += a; return *this; }
Vector4& operator-=(const T& a) { x -= a; y -= a; z -= a; w -= a; return *this; }
Vector4& operator*=(const T& a) { x *= a; y *= a; z *= a; w *= a; return *this; }
Vector4& operator/=(const T& a) { x /= a; y /= a; z /= a; w /= a; return *this; }
T& operator[](size_t index) { return *(reinterpret_cast<T*>(this) + index); }
};
using Vector4f = Vector4<float>;
using Vector4i = Vector4<int>;
using Vector4i32 = Vector4<int32_t>;
using Vector4ui32 = Vector4<uint32_t>;
using Vector4i64 = Vector4<int64_t>;
using Vector4ui64 = Vector4<uint64_t>;
The problem I am having is that I cant make a std::vector of my Vector4 class. When I try the following:
std::vector<ogl::Vector4f> vec;
vec.emplace_back(1.0f, 2.0f, 3.0f, 4.0f);
I get this compile error
'Vector4::Vector4': no overloaded function takes 4 arguments
I have my own vector (C++ kind not math kind) class that I use and I tried using emplace_back with it but I got the same error. I also tried using and not using allocators (in my custom vector class) and have tried almost everything under the sun!
I can fix this issue by defining a constructor, but then it doesn't become a POD anymore. Normal construction using brace initialization works fine so I don't what's wrong.
If anyone can explain why this is happening/how to fix this (or if this is normal behaviour) it would be most appreciated.
emplace_back uses parentheses to initialize the value, which means a constructor is required to use it until C++20. C++20 introduced parenthesized initialization of aggregates, so you code becomes valid as is.
Until then you can just do
vec.push_back({1.0f, 2.0f, 3.0f, 4.0f});
Related
One time, my program runs and shows expected output, and sometime it don't (it compiles without any errors). Try-Catch doesen't seem to affect on this random output.
v3f is a simple class that holds 3 floats: x,y,z and some basic math operations on them (all of them work perfectly fine)
v3f calculate_normal(v3f a, v3f b, v3f c);
"calculate_normal" is just a simple multiplication and subtraction function that returns v3f, AND when it "decides" to work it gives expected output.
int main()
{
lv::v3f c(-0.5, -0.5, 0);
lv::v3f b(0, .5f, 0);
lv::v3f a(0.5, -0.5, 0);
/* if I add here
v3f d = a - b;
*/ it works !
lv::v3f normal;
std::cout << "1\n";
normal = lv::calculate_normal(a, b, c);
std::cout << "2\n";
std::cout << normal.x << " " << normal.y << " " << normal.z << std::endl;
std::cout << "3\n";
return 0;
}
I cout'ed 1, 2 and 3 to see when program breaks and it's sometimes outputting all:
output:
1
2
0 0 1
3
And sometimes it stops on "1" (before calculating normal)
output:
1
// - - - - - - - - - - - - - - "Vector3.h"
#ifndef _LV_VECTOR_3_H_
#define _LV_VECTOR_3_H_
namespace lv{
template <class T>
class Vector3
{
public:
T x, y, z;
Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z){}
float length()
{
return sqrt( pow(x, 2) + pow(y, 2) + pow(z, 2) );
}
Vector3<T> normal()
{
float l = length();
return Vector3<T>(x/l, y/l, z/l);
}
void normalize()
{
float l = length();
x /= l;
y /= l;
z /= l;
}
Vector3<T>& operator += (const Vector3<T>& o)
{
this->x += o.x;
this->y += o.y;
this->z += o.z;
return *this;
}
Vector3<T>& operator -= (const Vector3<T>& o)
{
this->x -= o.x;
this->y -= o.y;
this->z -= o.z;
return *this;
}
Vector3<T>& operator *= (const Vector3<T>& o)
{
this->x *= o.x;
this->y *= o.y;
this->z *= o.z;
return *this;
}
Vector3<T>& operator /= (const Vector3<T>& o)
{
this->x /= o.x;
this->y /= o.y;
this->z /= o.z;
return *this;
}
friend Vector3<T>& operator + (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x + p.x;
tmp->y = o.y + p.y;
tmp->z = o.z + p.z;
return *tmp;
}
friend Vector3<T>& operator - (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x - p.x;
tmp->y = o.y - p.y;
tmp->z = o.z - p.z;
return *tmp;
}
friend Vector3<T>& operator / (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x / p.x;
tmp->y = o.y / p.y;
tmp->y = o.z / p.z;
return *tmp;
}
friend Vector3<T>& operator * (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x * p.x;
tmp->y = o.y * p.y;
tmp->z = o.z * p.z;
return *tmp;
}
friend Vector3<T>& operator * (const Vector3<T>&o, float p)
{
Vector3<T>* tmp;
tmp->x = o.x * p;
tmp->y = o.y * p;
tmp->z = o.z * p;
return *tmp;
}
friend Vector3<T>& operator / (const Vector3<T>&o, float p)
{
Vector3<T>* tmp;
tmp->x = o.x / p;
tmp->y = o.y / p;
tmp->z = o.z / p;
return *tmp;
}
};
#define v3f Vector3<float>
#define v3i Vector3<int>
#define v3d Vector3<double>
#define v3ui Vector3<unsigned int>
}; // L V
#endif
// - - - - - - - - - - - - - - "Vector.h"
#ifndef _LV_VECTOR_H_
#define _LV_VECTOR_H_
#include "Vector2.h"
#include "Vector3.h"
#include "Vector4.h"
#endif
// - - - - - - - - - - - - - - "Utils.h"
#ifndef _LV_UTILS_H_
#define _LV_UTILS_H_
#include "Vector.h"
namespace lv {
v3f calculate_normal(v3f a, v3f b, v3f c)
{
std::cout << "a\n";
v3f u = b - a;
v3f v = c - a;
std::cout << "b\n";
v3f n;
n.x = u.y * v.z - u.z * v.y;
n.y = u.z * v.x - u.x * v.z;
n.z = u.x * v.y - u.y * v.x;
std::cout << "c\n";
return n;
}
}; // L V
#endif
// - - - - - - - - - - - - - - "main.cpp"
#include <iostream>
#include "Liviana/Math/Utils.h"
int main()
{
lv::v3f c(-0.5, -0.5, 0);
lv::v3f b(0, .5f, 0);
lv::v3f a(0.5, -0.5, 0);
lv::v3f normal;
std::cout << "1\n";
normal = lv::calculate_normal(a, b, c);
std::cout << "2\n";
std::cout << normal.x << " " << normal.y << " " << normal.z << std::endl;
std::cout << "3\n";
return 0;
}
Only the mutating operators should return references. The other operators should return values.
OK:
Vector3<T>& operator += (const Vector3<T>& o)
Not ok:
friend Vector3<T>& operator + (const Vector3<T>& o, const Vector3<T> p)
The above is not ok, because...what are you going to return a reference to? 1 + 2 is neither 1 nor 2. It's something else. You'll need storage for the result (a Vector3) and you'll need to return it by value.
friend Vector3<T> operator + (const Vector3<T>& o, const Vector3<T> p) {
Vector3<T> tmp;
tmp.x = o.x + p.x;
tmp.y = o.y + p.y;
tmp.z = o.z + p.z;
return tmp;
}
Note the & is gone from the return type.
You are dereferencing an uninitialized pointer in each of your arithmetic operators:
Vector3<T>& operator + (const Vector3<T>& o, const Vector3<T> p)
Vector3<T>* tmp; // Where does tmp point to?
tmp->x = o.x + p.x;
tmp->y = o.y + p.y;
tmp->z = o.z + p.z;
return *tmp;
}
Dereferencing a pointer that doesn't point to a valid object within its lifetime is Undefined Behaviour, and causes your program to be invalid and able to do literally anything.
You should instead avoid using pointers. Just use an ordinary local variable and return it by value:
Vector3<T> operator + (const Vector3<T>& o, const Vector3<T> p)
Vector3<T> tmp; // No more pointer
tmp.x = o.x + p.x;
tmp.y = o.y + p.y;
tmp.z = o.z + p.z;
return tmp;
}
I override the addition operation, so that I can add two vectors of my struct Vec3
// addition
Vec3 operator+(Vec3<T> &other) {
return Vec3(this->x + other.x, this->y + other.y, this->z + other.z);
}
// product with one scalar
Vec3 operator*(float scalar) {
return Vec3(this->x * scalar, this->y * scalar, this->z * scalar);
}
The Vec3 has just three attributes from type T.
When using it T is a float, and I execute this code:
vec temp = vecOne * skalarOne + vecTwo * scalarTwo;
I get this error:
Binary operator '+' can't be applied to the expressions of type
'pray::Vec3' and 'pray::Vec3'
I don't get this error if calculationg the multiplication first and save the result in a vector and then doing the vector addition.
Anyone any idea? Thanks!
You need to change the function signatures to
Vec3 operator+(const Vec3<T> &other) const
&c., otherwise an anonymous temporary cannot bind to it.
You should return a reference to the vec3 like this:
// addition
Vec3 operator+(const Vec3& other) {
return { x + other.x, y + other.y, z + other.z };
}
// product with one scalar
Vec3 operator*(float scalar) {
return { x * scalar, y * scalar, z * scalar };
}
Edit: Here is my complete runable solution, if the fix above wont work for you.
template <typename T>
class Vec3 {
public:
Vec3(T x, T y, T z) : x(x), y(y), z(z) {}
T x;
T y;
T z;
// addition
Vec3 operator+(const Vec3<T>& other) {
return { x + other.x, y + other.y, z + other.z };
}
// product with one scalar
Vec3 operator*(float scalar) {
return { x * scalar, y * scalar, z * scalar };
}
};
int main() {
Vec3<float> a(2, 2, 2);
Vec3<float> b(1, 2, 3);
float num = 3;
Vec3<float> c = a + b;
Vec3<float> d = a * num;
Vec3<float> e = a * num + b * num;
}
Let say that we have two rectangles, defined with their bottom-left and top-right corners. For example: rect1 (x1, y1)(x2, y2) and rect2 (x3, y3)(x4, y4).
I'm trying to find the coordinates(bottom-left and top-right) of the intersected rectangle.
Any ideas, algorithm, pseudo code, would be greatly appreciated.
p.s. I found similar questions but they check only if 2 rectangle intersect.
If the input rectangles are normalized, i.e. you already know that x1 < x2, y1 < y2 (and the same for the second rectangle), then all you need to do is calculate
int x5 = max(x1, x3);
int y5 = max(y1, y3);
int x6 = min(x2, x4);
int y6 = min(y2, y4);
and it will give you your intersection as rectangle (x5, y5)-(x6, y6). If the original rectangles do not intersect, the result will be a "degenerate" rectangle (with x5 >= x6 and/or y5 >= y6), which you can easily check for.
P.S. As usual, small details will depend on whether you have to consider touching rectangles as intersecting.
To look for an intersection, you will have to do some simple comparison of the points:
So as we can see from the image if x3, y3 is greater or equal to x1, y1 and less than or equal to x2, y2 then it is inside the first rectangle, similarly you will need to check if x4, y4 falls inside the range of x1,y1 to x2,y2 as well.
if both conditions prove to be true then you can be sure that the second rectangle is totally encompassed by the first.
You will need to check the other way around as well, if finding out which is inside which is important to you.
You also have to have the rectangles be axis aligned, otherwise this will not work reliably.
Let me know if you need more detail, although I think a quick Google search will uncover much more detail for you very easily, but let me know and I can make a rectangle collision tutorial if you like.
In More Detail:
To find out if the rectangles have any intersections you can check the coordinates of their defining points, for our purposes we shall use top left and bottom right corner coordinates.
We can utilise a class to make this easier for us, and to maximise on the usability of the code we can use a 2d Vector and a 2d Point:
2dVectorPoint.h
#include <cmath>
class Vector2D
{
public:
float x;
float y;
Vector2D() {}
Vector2D(float inX, float inY)
{
x = inX;
y = inY;
}
Vector2D& Set(float inX, float inY)
{
x = inX;
y = inY;
return (*this);
}
float& operator [](long k) { return ((&x)[k]); }
const float& operator [](long k) const { return ((&x)[k]); }
Vector2D& operator +=(const Vector2D& v)
{
x += v.x;
y += v.y;
return (*this);
}
Vector2D& operator -=(const Vector2D& v)
{
x -= v.x;
y -= v.y;
return (*this);
}
Vector2D& operator *=(float t)
{
x *= t;
y *= t;
return (*this);
}
Vector2D& operator /=(float t)
{
float f = 1.0F / t;
x *= f;
y *= f;
return (*this);
}
Vector2D& operator &=(const Vector2D& v)
{
x *= v.x;
y *= v.y;
return (*this);
}
Vector2D operator -(void) const { return (Vector2D(-x, -y)); }
Vector2D operator +(const Vector2D& v) const { return (Vector2D(x + v.x, y + v.y)); }
Vector2D operator -(const Vector2D& v) const { return (Vector2D(x - v.x, y - v.y)); }
Vector2D operator *(float t) const { return (Vector2D(x * t, y * t)); }
Vector2D operator /(float t) const { float f = 1.0F / t; return (Vector2D(x * , y * f)); }
float operator *(const Vector2D& v) const { return (x * v.x + y * v.y); }
Vector2D operator &(const Vector2D& v) const { return (Vector2D(x * v.x, y * v.y)); }
bool operator ==(const Vector2D& v) const { return ((x == v.x) && (y == v.y)); }
bool operator !=(const Vector2D& v) const { return ((x != v.x) || (y != v.y)); }
Vector2D& Normalize(void) { return (*this /= sqrtf(x * x + y * y)); }
Vector2D& Rotate(float angle);
};
class Point2D : public Vector2D
{
public:
Point2D() {}
Point2D(float r, float s) : Vector2D(r, s) {}
Point2D& operator =(const Vector2D& v)
{
x = v.x;
y = v.y;
return (*this);
}
Point2D& operator *=(float t)
{
x *= t;
y *= t;
return (*this);
}
Point2D& operator /=(float t)
{
float f = 1.0F / t;
x *= f;
y *= f;
return (*this);
}
Point2D operator -(void) const{ return (Point2D(-x, -y)); }
Point2D operator +(const Vector2D& v) const { return (Point2D(x + v.x, y + v.y)); }
Point2D operator -(const Vector2D& v) const { return (Point2D(x - v.x, y - v.y)); }
Vector2D operator -(const Point2D& p) const { return (Vector2D(x - p.x, y - p.y)); }
Point2D operator *(float t) const { return (Point2D(x * t, y * t)); }
Point2D operator /(float t) const
{
float f = 1.0F / t;
return (Point2D(x * f, y * f));
}
};
inline Vector2D operator *(float t, const Vector2D& v){ return (Vector2D(t * v.x, t * v.y));}
inline Point2D operator *(float t, const Point2D& p){ return (Point2D(t * p.x, t * p.y));}
inline float Dot(const Vector2D& v1, const Vector2D& v2){ return (v1 * v2);}
inline float Magnitude(const Vector2D& v){ return (sqrtf(v.x * v.x + v.y * v.y));}
inline float InverseMag(const Vector2D& v){ return (1.0F / sqrtf(v.x * v.x + v.y * v.y));}
inline float SquaredMag(const Vector2D& v){ return (v.x * v.x + v.y * v.y);}
struct Origin2D_
{
const Point2D& operator +(const Vector2D& v) { return (static_cast<const Point2D&>(v)); }
Point2D operator -(const Vector2D& v) { return (Point2D(-v.x, -v.y)); }
};
2dVectorPoint.cpp
#include "2dVectorPoint.h"
Origin2D_ Origin2D;
Vector2D& Vector2D::Rotate(float angle)
{
float s = sinf(angle);
float c = cosf(angle);
float nx = c * x - s * y;
float ny = s * x + c * y;
x = nx;
y = ny;
return (*this);
}
extern Origin2D_ Origin2D;
Code used is adapted from here to save my fingers.
Then we can utilise this to easily compare:
we can define rectangle 1 as having P1 and P2 as its bounds and rectangle 2 as having P3 and P4 as its bounds, giving us the following comparison:
if ( P2.y <= P3.y && P1.y >= P4.y && P2.x>= P3.x && P1.x <= P4.x )
{
return true;
}
This will return a true value for any instance of intersection or for rectangle 1 encompassing rectangle 2 totally.
To only check for intersections just remove the equality check (take all the = out of the above equation), and you will be checking only for intersections. If you have an intersection you could then use linear algebra to evaluate the exact coordinates.
Let's say that a box has a radius X and radius Y (I know it has not but this term is useful here).
You will have:
rect1_x_radius = (x2-x1)/2
rect1_y_radius = (y2-y1)/2
and
rect2_x_radius = (x4-x3)/2
rect2_y_radius = (y4-y3)/2
Now if rect middle points are further away than sum of their radiuses in appropriate direction - they do not collide.
Otherwise they do - this hint should suffice.
You should be now able to finish your assignment.
UPDATE:
OK - let's solve it for 1D - later you'll solve it for 2D. Look at this piece of ... art ;-)
You see 2 segments - now some calculations:
rA = (maxA-minA) / 2
rB = (maxB-minB) / 2
midA = minA + rA
midB = minB + rB
mid_dist = |midA - midB|
Now how to check if collision occurs? As I said if sum of 'radiuses' is less than segments' distance - there is no collision:
if ( mid_dist > fabs(rA+rB) )
{
// no intersection
}
else
{
// segments intersect
}
Now it is your work to calculate intersection / common part in 1D and 2D. It is up to you now (o ryou can read Andrey's answer).
Here is the same situation but in 2D - two 1D situations:
You can deal with the x and y direction separately.
Assume that x1 <= x3 (the first box is at least as far to the left as the second). Then, there is overlap if and only if x1 <= x3 <= x2.
Similarly, assume y1 <= y3 (the first box is at least as far to the bottom as the second). Then, there is overlap if and only if y1 <= y3 <= y2.
If there is overlap in both directions, there is a rectangle overlapping. You can find the coordinates by sorting the x and y coordinates and selecting the middle two.
In pseudocode:
if (((x1 <= x3 && x3 <= x2) || (x3 <= x1 && x1 <= x4)) // x-overlap
&&
((y1 <= y3 && y3 <= y2) || (y3 <= y1 && y1 <= y4)) // y-overlap
) {
int[] xs = {x1, x2, x3, x4};
int[] ys = {y1, y2, y3, y4};
sort(xs);
sort(ys);
// bottom-left: xs[1], ys[1]
// top-right: xs[2], ys[2]
}
Just in case a straightforward C# solution would suit anyone:
public struct Rectangle
{
public double Left { get; }
public double Top { get; }
public double Width { get; }
public double Height { get; }
public double Right => Left + Width;
public double Bottom => Top + Height;
public static Rectangle Empty { get; } = new Rectangle(0, 0, 0, 0);
public Rectangle(double left, double top, double width, double height)
{
Left = left;
Top = top;
Width = width;
Height = height;
}
public static bool RectanglesIntersect(Rectangle rectangle1, Rectangle rectangle2)
{
rectangle1 = rectangle1.Normalize();
rectangle2 = rectangle2.Normalize();
if (rectangle2.Left >= rectangle1.Right)
return false;
if (rectangle2.Right <= rectangle1.Left)
return false;
if (rectangle2.Top >= rectangle1.Bottom)
return false;
if (rectangle2.Bottom <= rectangle1.Top)
return false;
return true;
}
public static Rectangle GetIntersection(Rectangle rectangle1, Rectangle rectangle2)
{
rectangle1 = rectangle1.Normalize();
rectangle2 = rectangle2.Normalize();
if (rectangle1.IntersectsWith(rectangle2))
{
double left = Math.Max(rectangle1.Left, rectangle2.Left);
double width = Math.Min(rectangle1.Right, rectangle2.Right) - left;
double top = Math.Max(rectangle1.Top, rectangle2.Top);
double height = Math.Min(rectangle1.Bottom, rectangle2.Bottom) - top;
return new Rectangle(left, top, width, height);
}
return Empty;
}
public Rectangle GetIntersection(Rectangle rectangle)
{
return GetIntersection(this, rectangle);
}
public bool IntersectsWith(Rectangle rectangle)
{
return RectanglesIntersect(this, rectangle);
}
public Rectangle NormalizeWidth()
{
if (Width >= 0)
return this;
Rectangle result = new Rectangle(Left + Width, Top, -Width, Height);
return result;
}
public Rectangle NormalizeHeight()
{
if (Height >= 0)
return this;
Rectangle result = new Rectangle(Left, Top + Height, Width, -Height);
return result;
}
public Rectangle Normalize()
{
Rectangle result = NormalizeWidth().NormalizeHeight();
return result;
}
}
I've been trying to resolve a error for the last day or so and can't seem to work it through.
It's the kind of error that the fix is probably very easy :S
I tried to search for similar questions but the fixes don't apply.
main.c
int main(int argc, char *argv[]){
int width, height;
std::vector<Obj*> world;
world.push_back(new Sphere(Vec(0, 0, -22), 2, Vec(0.2, 0.2, 0.2), true));
(...)
return 0;
}
The error is found when I try to create a Sphere.
Relevant classes
Obj.h
class Obj
{
public:
Vec color;
bool culling;
virtual bool intersect(const Vec &ray_orig, Vec &ray_dir, float *t0 = NULL, float *t1 = NULL) = 0;
};
Sphere.h
class Sphere: public Obj
{
public:
Vec center;
float radius, radius2;
Sphere(Vec center, float radius, Vec color, bool culling);
bool intersect(const Vec &ray_orig, Vec &ray_dir, float *t0 = NULL, float *t1 = NULL);
};
Sphere.c
Sphere::Sphere(Vec center, float radius, Vec color, bool culling){
this->center = center;
this->radius = radius;
this->color = color;
this->culling = culling;
}
bool Sphere::intersect(const Vec &ray_orig, Vec &ray_dir, float *t0 = NULL, float *t1 = NULL) {...}
These second error appears when I do this->color = color;. Not sure if they are related.
Vec is a simple struct with 3 variables.
If you need more information I'll add as soon as possible.
Thank you in advance.
Jose
EDIT
Sorry for the delay.
intersect(...) is the only function in the obj class. Is there anyway to maintain the abstraction since there are several objects(sphere,box,...).
As requested here goes the definition of vec.h
vec.h
struct Vec {
float x, y, z;
Vec() {x = 0, y = 0, z = 0;}
Vec(float val) {x = val, y = val, z = val;}
Vec(float x_val,float y_val,float z_val) {x = x_val, y = y_val, z = z_val;}
Vec(const Vec& copy) : x(copy.x), y(copy.y), z(copy.z) { }
Vec operator+ (const Vec& p) const {
return Vec(x + p.x, y + p.y, z + p.z);
}
Vec operator- (const Vec& p) const {
return Vec(x - p.x, y - p.y, z - p.z);
}
Vec& operator += (const Vec& p) {
x += p.x; y += p.y; z += p.z;
return *this;
}
Vec& operator -= (const Vec& p) {
x -= p.x; y -= p.y; z -= p.z;
return *this;
}
Vec operator* (const float f) const {
return Vec(f * x, f * y, f * z);
}
Vec& operator*= (const float f) {
x *= f; y *= f; z *= f;
return *this;
}
Vec operator/ (const float f) const {
float inv = 1.f / f;
return Vec(inv * x, inv * y, inv * z);
}
Vec& operator/= (const float f) {
float inv = 1.f / f;
x *= inv; y *= inv; z *= inv;
return *this;
}
Vec& operator= (const Vec& p) {
x = p.x; y = p.y; z = p.z;
return *this;
}
bool operator== (const Vec& p) {
if(x == p.x && y == p.y && z == p.z)
return true;
return false;
}
float length_squared() const {
return x*x + y*y + z*z;
}
float length() const {
return sqrt(length_squared());
}
Vec norm() const {
float nor = x * x + y * y + z * z;
if (nor > 0) {
float invNor = 1 / sqrt(nor);
(float)x *= invNor, (float)y *= invNor, (float)z *= invNor;
}
return *this;
}
Vec cross(const Vec&b) {
return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);
}
float dot(const Vec& v) {
return x * v.x + y * v.y + z * v.z;
}
};
It seems the problem was indeed in the vec file.
Can't find a reasoning about the fix, but changing the Vec struct to a class fixed all the problems.
Thanks for the help.
I'm trying to make a Vec class to represent a set of 3 doubles, x, y, z, respectively. What I would like to do is make it so that I can multiply a scalar times the vector and have it multiply each component.
I have been able to get it to work when I mutliply a vector by a scalar, but not when I do the reverse. For example, the following works:
Vec a = Vec(1.0, 1.0, 1.0);
Vec b = a * 2.0;
But, whenever I try to multiply a scalar by a vector, it doesn't work. Ideally the command would look like this:
Vec a = Vec(1.0, 1.0, 1.0);
Vec b = 2.0 * a;
Here is the code I've done so far:
#include "Vec.h"
#include <limits>
#include <cmath>
#include "constants.h"
#include <iostream>
#include <string>
double Vec::angle( const Vec & vec) {
return acos((this->dot(vec))/(this->mag() * mag()));
}
double Vec::angle_d(const Vec & vec) {
return (angle(vec) * _PI / 180.0);
}
double Vec::angle_r(const Vec & vec) {
return this->angle(vec);
}
Vec Vec::cross( const Vec& vec) {
return Vec( (y * vec.z - z * vec.y),
(z * vec.x - x * vec.z),
(x * vec.y - y * vec.x));
}
double Vec::dot( const Vec & vec) {
return (x * vec.x + y * vec.y + z * vec.z);
}
double Vec::mag() {
return std::sqrt(x*x + y*y + z*z);
}
Vec Vec::operator=(const Vec& rhs) {
return Vec(rhs);
}
Vec Vec::operator*(const Vec& rhs) {
return Vec( x * rhs.x, y * rhs.y, z * rhs.z);
}
Vec Vec::operator*(const double rhs) {
return Vec(rhs * x, rhs * y, rhs * z);
}
Vec::Vec() :
x(std::numeric_limits<double>::signaling_NaN()),
y(std::numeric_limits<double>::signaling_NaN()),
z(std::numeric_limits<double>::signaling_NaN()) { }
Vec::Vec( double c) :
x(c), y(c), z(c) {}
Vec::Vec(const Vec & vec) :
x(vec.x), y(vec.y), z(vec.z) { }
Vec::Vec(double a, double b, double c)
: x(a), y(b), z(c) { }
You need a global operator that takes two arguments: a double and then a Vec, and it can be easily implemented by calling the operator you already have listed
inline Vec operator*(double s, const Vec& v) {
return v * s;
}
Try to create new global operator:
Vec operator*(int i, const Vec& rhs) {
return Vec(i * rhs.x, i * rhs.y, i * rhs.z);
}