Correct Implementation of Vector 3 in c++ - c++

I have just begun dabbling in c++. Is this the correct implementation of a vector 3? I don't want to leak any memory, or do anything that is just bad form in c++. Are my operator overload signatures correct?
class Vector
{
private:
double _x;
double _y;
double _z;
double LengthSquared();
friend std::ostream& operator<<(std::ostream& stream, const Vector& vector);
public:
Vector();
Vector(double x, double y, double z);
~Vector();
Vector(Vector& other);
double GetX() const;
double GetY() const;
double GetZ() const;
double Length();
Vector& Normalize();
double DotProduct(const Vector& vector) const;
Vector CrossProduct(const Vector& vector);
bool operator==(const Vector& vector) const;
bool operator!=(const Vector& other) const;
Vector& operator+=(const Vector& vector);
Vector operator+(const Vector& vector) const;
Vector& operator-=(const Vector& vector);
Vector operator-(const Vector& vector) const;
Vector& operator*=(double val);
double operator*(const Vector& vector) const;
Vector operator*(double val) const;
};
Vector::Vector() : _x(0.0), _y(0.0), _z(0.0)
{
}
Vector::Vector(double x, double y, double z) : _x(x), _y(y), _z(z)
{
}
Vector::~Vector()
{
}
Vector::Vector(Vector& other) : _x(other._x), _y(other._y), _z(other._z)
{
}
double Vector::GetX() const
{
return _x;
}
double Vector::GetY() const
{
return _y;
}
double Vector::GetZ() const
{
return _z;
}
double Vector::Length()
{
return sqrt(LengthSquared());
}
double Vector::LengthSquared()
{
return (_x * _x + _y * _y + _z * _z);
}
Vector& Vector::Normalize()
{
double length = Length();
if(length >0)
{
_x = _x / length;
_y = _y / length;
_z = _z / length;
}
else
{
_x = 0;
_y = 0;
_z = 0;
}
return *this;
}
double Vector::DotProduct(const Vector& vector) const
{
return _x * vector.GetX() + _y * vector.GetY() + _z * vector.GetZ();
}
Vector Vector::CrossProduct(const Vector& vector)
{
double nx = _y * vector.GetZ() - _z * vector.GetY();
double ny = _z * vector.GetX() - _x * vector.GetZ();
double nz = _x * vector.GetY() - _y * vector.GetX();
return Vector(nx, ny, nz);
}
bool Vector::operator==(const Vector& vector) const
{
if(this == &vector)
return true;
if((_x == vector.GetX()) && (_y == vector.GetY()) && (_z == vector.GetZ()))
return true;
return false;
}
bool Vector::operator!=(const Vector& vector) const
{
return !(*this == vector);
}
Vector& Vector::operator+=(const Vector& vector)
{
_x += vector.GetX();
_y += vector.GetY();
_z += vector.GetZ();
return *this;
}
Vector Vector::operator+(const Vector& vector) const
{
return Vector(_x, _y, _z) += vector;
}
Vector& Vector::operator-=(const Vector& vector)
{
_x -= vector.GetX();
_y -= vector.GetY();
_z -= vector.GetZ();
return *this;
}
Vector Vector::operator-(const Vector& vector) const
{
return Vector(_x, _y, _z) -= vector;
}
Vector& Vector::operator*=(double val)
{
_x *= val;
_y *= val;
_z *= val;
return *this;
}
double Vector::operator*(const Vector& vector) const
{
return this->DotProduct(vector);
}
Vector Vector::operator*(double val) const
{
return Vector(_x, _y, _z) *= val;
}
std::ostream& operator<<(std::ostream& stream, const Vector& vector)
{
return stream << "x: " << vector._x << ", y: " << vector._y << ", z: " << vector._z;
}

I would avoid the leading underscores on your attribute names. These particular names are legal but many led by _ are not.
Length and LengthSquared should be const.
The compiler generated copy constructor and destructor will do the right thing - no need to write them yourself and risk a copy-paste error.
Consider making DotProduct and CrossProduct non-member, non-friend "algorithm" functions. Also consider this for the non-mutating operators (which can then be written in the canonical form T operator+(T left, const T& right) { return left += right; }
Strongly consider not providing an operator* at all as it's not intuitive if it means scalar, dot, or cross product. Use named methods instead.

Related

Basic Shading in C++ to a BMP image. Facing ratio calculation

I am studying Shading and how light interacts with objects. I found a great website and wanted to implement knowledge from https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/shading-normals in my own way.
I wrote a code. It is supposed to calculate a facing ratio (cosine of the angle between a normal vector and a light Ray ) and generate a ".BMP" image with that. I took a surface as an object (well, on the image it will be a circle). The idea was to calculate the effect of this ratio on the color of the surface, i.e how light and object interact.
The code is as follows
template <typename T>
class Vec3
{
private:
T x, y, z;
public:
Vec3(): x{0},y{0},z{0} {}
Vec3(T xx): x{xx}, y{xx},z{xx} {}
Vec3(T xx, T yy, T zz): x{xx}, y{yy}, z{zz} {}
friend Vec3<T> operator+(const Vec3<T>& vec1, const Vec3<T>& vec2) { return Vec3<T>(vec1.x + vec2.x, vec1.y + vec2.y, vec1.z + vec2.z); }
friend Vec3<T> operator-(const Vec3<T>& vec1, const Vec3<T>& vec2) { return Vec3<T>(vec1.x - vec2.x, vec1.y - vec2.y, vec1.z - vec2.z); }
friend Vec3<T> operator*(const Vec3<T>& vec1, const Vec3<T>& vec2) { return Vec3<T>(vec1.x * vec2.x, vec1.y * vec2.y, vec1.z * vec2.z); }
friend Vec3<T> operator*(const Vec3<T>& vec1, const T& k) { return Vec3<T>(vec1.x * k, vec1.y * k, vec1.z * k); }
friend Vec3<T> operator/(const Vec3<T>& vec1, const T& k) { return Vec3<T>(vec1.x / k, vec1.y / k, vec1.z / k); }
Vec3<T> operator - () const { return Vec3<T>(-x, -y, -z); }
T dot (const Vec3<T>& v) const { return x * v.x + y * v.y + z * v.z; }
T lengthWithoutRoot() const { return x * x + y * y + z * z; }
T length() const { return sqrt(lengthWithoutRoot()); }
Vec3& normalize()
{
T nor2 = lengthWithoutRoot();
if (nor2 > 0) {
T divider = 1 / sqrt(nor2);
x *= divider, y *= divider, z *= divider;
}
return *this;
}
Vec3<T> reflection(const Vec3<T>& prim,const Vec3<T>& normal) // TO BE CHECKED
{
Vec3<T> reflection = prim - 2 * (prim.dot(normal)) * normal;
return reflection;
}
friend std::ostream& operator<<(std::ostream &out, const Vec3<T>& vec)
{
out << '(' << vec.x << ',' << vec.y << ',' << vec.z << ')';
return out;
}
const T& getX() { return x; }
const T& getY() { return y; }
const T& getZ() { return z; }
};
typedef Vec3<float> Vec3f;
class Sphere
{
private:
Vec3f center;
float radius;
public:
Sphere(const Vec3f& c, const float& r): center{c}, radius{r} {}
bool intersect(const Vec3f& primRay)
{
Vec3f vecRadius = center - primRay;
float distLength = vecRadius.length();
if (distLength > radius)
return false;
return true;
}
bool intersectSurface(const Vec3f& primRay)
{
Vec3f vecRadius = center - primRay;
float distLength = vecRadius.length();
if (distLength == radius)
return true;
return false;
}
float alphaPositive(const Vec3f& p, const Vec3f& source)
{
Vec3f primRay = (source-p).normalize();
Vec3f normal = (p-center).normalize();
float diff = primRay.dot(normal);
return std::max(diff,0.f) ;
}
};
int main()
{
Sphere sphere (Vec3f{ 250.0f, 250.0f, 0.0 }, 150.0f );
Vec3f source{ 100,200,0.0 };
Vec3f color{ 255,255,255 };
std::ofstream file;
file.open("DIF_SPHERE36.ppm");
file << "P6\n" << height << " " << width << "\n255\n";
for (float h = 0; h < 500; ++h)
{
for (float w = 0; w < 500; ++w)
{
Vec3f primRay = { h,w,0.0 };
if (sphere.intersect(primRay))
{
float facingRatio= sphere.alphaPositive(primRay, source);
color = Vec3f{255,0,0}*facingRatio;
file << unsigned char(color.getX()) << unsigned char(color.getY()) << unsigned char(color.getZ());
}
else
file << unsigned char(255) << unsigned char(255) << unsigned char(255);
}
}
file.close();
return 0;
}
However. I get smth strange, even when I try to change 'source' coordinates.
Facing ratio is calculated in alphaPositive function This is what a code must generate according to the idea
Thank you all for your comments.
I made following conclusions:
In function alphaPositive I had to use return std::max(diff,0.1f) instead of return std::max(diff,0.f).
Had to change positioning of the Object and Light by adding z-coordinates.
With that I managed to get a sphere with some effects.

How can I fix This error and what is the cause of it?

I get an error and when i click to see the error i takes me to a document called xutility.
This is the two errors:
Error C2064 term does not evaluate to a function taking 2 arguments.
Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\xutility 624
2.Error C2056 illegal expression Funtwo C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\xutility 624
Then when i looked at line 624 it shows me this
// FUNCTION TEMPLATE _Debug_lt_pred
template <class _Pr, class _Ty1, class _Ty2>
constexpr bool _Debug_lt_pred(_Pr&& _Pred, _Ty1&& _Left, _Ty2&& _Right) _NOEXCEPT_COND(
noexcept(_Pred(_Left, _Right))
&& noexcept(_Pred(_Right, _Left))) { // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
const auto _Result = static_cast<bool>(_Pred(_Left, _Right));
if (_Result) {
_STL_VERIFY(!_Pred(_Right, _Left), "invalid comparator");
}
return _Result;
}
My class:
class Vector3D : public Vector2
{
public:
Vector3D();
~Vector3D();
double GetMagnitude();
void Normalize();
void scale(Vector3D vector);
void scale(double vector3x, double vector3y, double vector3z);
Vector3D operator -();
Vector3D operator +(Vector3D other);
Vector3D operator -(Vector3D other);
Vector3D operator *(Vector3D other);
Vector3D operator /(Vector3D other);
bool operator < (Vector3D other);
bool operator > (Vector3D other);
bool operator <= (Vector3D other);
bool operator >= (Vector3D other);
bool operator == (Vector3D other);
bool operator != (Vector3D other);
void operator = (Vector3D other);
void operator += (Vector3D other);
void operator -= (Vector3D other);
void operator *= (Vector3D other);
void operator /= (Vector3D other);
friend ostream& operator <<(ostream& out, const Vector3D& v);
friend istream& operator >>(istream& in, Vector3D& v);
double m_z = 0;
};
< operator Implementation
bool Vector3D::operator<(Vector3D other)
{
if (GetMagnitude() < other.GetMagnitude())
return true;
return false;
}
For the Implementation of each member:
Vector3D::Vector3D()
{
}
Vector3D::~Vector3D()
{
}
double Vector3D::GetMagnitude()
{
return sqrt(pow(m_x, 2) + pow(m_y, 2) + pow(m_z, 2));
}
void Vector3D::Normalize()
{
double maxValue = std::max(m_x, m_y, m_z);
m_x = m_x / maxValue;
m_y = m_y / maxValue;
m_z = m_z / maxValue;
}
void Vector3D::scale(Vector3D vector)
{
m_x *= vector.m_x;
m_y *= vector.m_y;
m_z *= vector.m_z;
}
void Vector3D::scale(double vector3x, double vector3y, double vector3z)
{
m_x *= vector3x;
m_y *= vector3y;
m_z *= vector3z;
}
Vector3D Vector3D::operator-()
{
Vector3D v;
v.m_x = -m_x;
v.m_y = -m_y;
v.m_z = -m_z;
return v;
}
Vector3D Vector3D::operator+(Vector3D other)
{
Vector3D v;
v.m_x = m_x + other.m_x;
v.m_y = m_y + other.m_y;
v.m_z = m_z + other.m_z;
return v;
}
Vector3D Vector3D::operator-(Vector3D other)
{
Vector3D v;
v.m_x = m_x - other.m_x;
v.m_y = m_y - other.m_y;
v.m_z = m_z - other.m_z;
return v;
}
Vector3D Vector3D::operator*(Vector3D other)
{
Vector3D v;
v.m_x = m_x * other.m_x;
v.m_y = m_y * other.m_y;
v.m_z = m_z * other.m_z;
return v;
}
Vector3D Vector3D::operator/(Vector3D other)
{
Vector3D v;
v.m_x = m_x / other.m_x;
v.m_y = m_y / other.m_y;
v.m_z = m_z / other.m_z;
return v;
}
bool Vector3D::operator<(Vector3D other)
{
if (GetMagnitude() < other.GetMagnitude())
return true;
return false;
}
bool Vector3D::operator>(Vector3D other)
{
if (GetMagnitude() > other.GetMagnitude())
return true;
return false;
}
bool Vector3D::operator<=(Vector3D other)
{
if (GetMagnitude() <= other.GetMagnitude())
return true;
return false;
}
bool Vector3D::operator>=(Vector3D other)
{
if (GetMagnitude() >= other.GetMagnitude())
return true;
return false;
}
bool Vector3D::operator==(Vector3D other)
{
if (GetMagnitude() == other.GetMagnitude())
return true;
return false;
}
bool Vector3D::operator!=(Vector3D other)
{
if (GetMagnitude() != other.GetMagnitude())
return true;
return false;
}
void Vector3D::operator=(Vector3D other)
{
m_x = other.m_x;
m_y = other.m_y;
m_z = other.m_z;
}
void Vector3D::operator+=(Vector3D other)
{
m_x += other.m_x;
m_y += other.m_y;
m_z += other.m_z;
}
void Vector3D::operator-=(Vector3D other)
{
m_x -= other.m_x;
m_y -= other.m_y;
m_z -= other.m_z;
}
void Vector3D::operator*=(Vector3D other)
{
m_x *= other.m_x;
m_y *= other.m_y;
m_z *= other.m_z;
}
void Vector3D::operator/=(Vector3D other)
{
m_x /= other.m_x;
m_y /= other.m_y;
m_z /= other.m_z;
}
ostream& operator<<(ostream& out, const Vector3D& v)
{
out << v.m_x << ", " << v.m_y << ", " << v.m_z;
return out;
}
istream& operator>>(istream& in, Vector3D& v)
{
cout << "Vector 2 Input" << endl << "x:";
in >> v.m_x;
cout << "y : ";
in >> v.m_y;
cout << "z : ";
in >> v.m_z;
return in;
}
I am just inheriting two members from class vector 2. They are x and y. m_x and m_y.
You are attempting to alter the behaviour of the operators. Don't do that! Const correctness is not optional wrt operators. These are the operators you have declared incorrectly (and how they should have been declared).
Vector3D operator -() const;
Vector3D operator +(const Vector3D& other) const;
Vector3D operator -(const Vector3D& other) const;
Vector3D operator *(const Vector3D& other) const;
Vector3D operator /(const Vector3D& other) const;
bool operator < (const Vector3D& other) const;
bool operator > (const Vector3D& other) const;
bool operator <= (const Vector3D& other) const;
bool operator >= (const Vector3D& other) const;
bool operator == (const Vector3D& other) const;
bool operator != (const Vector3D& other) const;
// non-const methods, that return mutable reference to this.
Vector3D& operator = (const Vector3D& other);
Vector3D& operator += (const Vector3D& other);
Vector3D& operator -= (const Vector3D& other);
Vector3D& operator *= (const Vector3D& other);
Vector3D& operator /= (const Vector3D& other);
I'm assuming the error is because it is attempting to call operator < on a pair of vectors, however they are both const, and so no existing overload of operator < can work on the values (because they are both const).

C++ & Swap/Copy applied to a Point struct

I have written a Point struct I am using to model the n-body problem. I have found it difficult to fully understand and implement the copy & swap idiom and adapting it to my needs, which are mainly speed. Am I doing this correctly? Would it be different in C++17?
#pragma once
#include <algorithm>
struct Point
{
double x, y, z;
explicit Point(double X = 0, double Y = 0, double Z = 0) : x(X), y(Y), z(Z) {}
void swap(Point&, Point&);
inline bool operator==(Point b) const { return (x == b.x && y == b.y && z == b.z); }
inline bool operator!=(Point b) const { return (x != b.x || y != b.y || z != b.z); }
Point& operator=(Point&);
Point& operator+(Point&) const;
Point& operator-(Point&) const;
inline double operator*(Point& b) const { return b.x*x + b.y*y + b.z*z; } // Dot product
Point& operator%(Point&) const; // % = Cross product
inline Point& operator+=(Point& b) { return *this = *this + b; }
inline Point& operator-=(Point& b) { return *this = *this - b; }
inline Point& operator%=(Point& b) { return *this = *this % b; }
Point& operator*(double) const;
Point& operator/(double) const;
inline Point& operator*=(double k) { return *this = *this * k; }
inline Point& operator/=(double k) { return *this = *this / k; }
};
std::ostream &operator<<(std::ostream &os, const Point& a) {
os << "(" << a.x << ", " << a.y << ", " << a.z << ")";
return os;
}
void Point::swap(Point& a, Point& b) {
std::swap(a.x, b.x);
std::swap(a.y, b.y);
std::swap(a.z, b.z);
}
Point& Point::operator=(Point& b) {
swap(*this, b);
return *this;
}
Point& Point::operator+(Point& b) const {
Point *p = new Point(x + b.x, y + b.y, z + b.z);
return *p;
}
Point& Point::operator-(Point& b) const {
Point *p = new Point(x - b.x, y - b.y, z - b.z);
return *p;
}
Point& Point::operator%(Point& b) const {
Point *p = new Point(
y*b.z - z*b.y,
z*b.x - x*b.z,
x*b.y - y*b.x
);
return *p;
}
Point& Point::operator*(double k) const {
Point *p = new Point(k*x, k*y, k*z);
return *p;
}
Point& Point::operator/(double k) const {
Point *p = new Point(x/k, y/k, z/k);
return *p;
}
The copy/swap-ideom actually copies and swap()s the values. Your "adaptation" merely swap()s. A correct use of the copy/swap-ideom would look, e.g., like this:
Point& Point::operator= (Point other) { // note: by value, i.e., already copied
this->swap(other);
return *this;
}
(of course, this also assumes that your swap() function is a member taking just one additional argument: there is already an object to swap with).
If speed is your primary concern, the copy/swap-ideom is probably not particular suitable for the case of Point: the copy operation is essentially trivial. Swapping values is quite reasonable compared to relatively involved operations like copying an array old by a std::vector where the swap operation just amounts to a few pointer swaps in addition to copying probably multiple values and some allocation operations. That is, your Point assignment is probably best off to just assign all members:
Point& Point::operator= (Point const& other) { // note: no copy...
this->x = other.x;
this->y = other.y;
this->z = other.z;
return *this;
}
As was pointed out in comments, you should also not allocate new Point objects with new: C++ isn't Java or C#! You can just create an object on the stack it doesn't need to come from the heap, e.g.:
Point Point::operator+ (Point const& other) const {
return Point(this->x + other.x, this->y + other.y, this->z + other.z);
}

Overloading * operator gives no match error

Hi I am trying to create a ray tracer that renders a polygonized, triangle-based model.
I have a point 3D struct in point3d.h that holds x,y, and z coordinates.
#ifndef __POINT3D_H__
#define __POINT3D_H__
#include <iostream>
using namespace std;
struct Point3D
{
double x;
double y;
double z;
Point3D() : x(0.0), y(0.0), z(0.0) {}
Point3D(const double & nx, const double & ny, const double & nz) : x(nx), y(ny), z(nz) {}
Point3D operator+(const Point3D & rhs) const {
return Point3D(x + rhs.x, y + rhs.y, z + rhs.z); }
Point3D operator-(const Point3D & rhs) const {
return Point3D(x - rhs.x, y - rhs.y, z - rhs.z); }
Point3D operator*(double val) const {
return Point3D(x * val, y * val, z * val); }
Point3D operator/(double val) const {
return Point3D(x / val, y / val, z / val); }
Point3D operator+=(const Point3D & rhs) {
x += rhs.x; y += rhs.y; z += rhs.z; return *this; }
Point3D operator-=(const Point3D & rhs) {
x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; }
Point3D operator*=(double val) {
x *= val; y *= val; z *= val; return *this; }
Point3D operator/=(double val) {
x /= val; y /= val; z /= val; return *this; }
void print() {
cout << '(' << x << ',' << y << ',' << z << ')';
}
};
#endif
Here is where I try to use the * operator to multiple two Point3Ds together
Point3D phong(Point3D mColor, Point3D lColor, Point3D L, Point3D N, Point3D R, Point3D V)
{
Point3D k(1.0, 1.0, 1.0);
Point3D ambient = mColor * k.x;
Point3D diffuse_angle = ((N * L) / (length(N) * length(L)));
Point3D diffuse = lColor * k.y * diffuse_angle;
Point3D specular_angle = ((R * V) / (length(R) * length(V)));
double specular_x = pow(specular_angle.x, 100.0);
double specular_y = pow(specular_angle.y, 100.0);
double specular_z = pow(specular_angle.z, 100.0);
Point3D specular_power(specular_x, specular_y, specular_z);
Point3D specular = lColor * k.z * specular_power;
return ambient + (lColor * (diffuse + specular));
}
When I try to multiple two Point3D's together, I am getting a no match error.
Here is where the code fails. I feel like it is a simple mistake but I cannot figure it out. I am including the Point3d header file as follows: #include "point3d.h".
Point3D operator*(double val) const
You have just this version, Point3D * double and nothing else, but you are trying to use this operator for Point3D * Point3D. Point3D is not implicitly constructible from double, so this is why you have compilation error.
Point3D operator*(double val) const {
This is for multiplication Point3D * double. And by
N * L
you are trying to do Point3D * Point3D.
You can rectify this either by providing proper operator* for your class OR provide a conversion from double to your class through single argument constructor. Although I prefer former.
You should need a function like this
Point3D operator *(Point3D &temp) const {
}
Since you don't have function to multiply two 3d points you are getting errors.Try adding this function.
You need a function for the operation Point3D * Point3D, which can't be adapted for the call of Point3D::operator*(double val). Such as:
Point3D operator*(const Point3D & rhs) const {
return Point3D(x * rhs.x, y * rhs.y, z * rhs.z); }

Generating Catmull Rom spline and returning garbage

After creating my Catmull Rom Spline such as:
vector3 SplineVector = newSpline.createCatmulRomSpline(vectorOne, vectorTwo, vectorThree, vectorFour, i);
However, when I read out the result from
vector3 SplineVector
I get garbage values.
Here is a listing of my spline class, a segment of my vector3 class and in the implementation within the initialization.
initialization:
for(float i = 0.0f; i <= 1.0f; i += 0.1f)
{
vector3 SplineVector = newSpline.createCatmulRomSpline(vectorOne, vectorTwo, vectorThree, vectorFour, i);
cout << "\n\ncurve pos X: " << SplineVector.getx();
cout << "\ncurve pos Y: " << SplineVector.gety();
cout << "\ncurve pos Z: " << SplineVector.getz();
}
Vector3:
class vector3
{
public:
vector3::vector3():x(0),y(0),z(0)
{
}
vector3::~vector3()
{
}
vector3(float);
vector3(float inx,float iny,float inz): x(inx), y(iny), z(inz)
{
}
//Vector operators
_inline vector3 operator=(const vector3& invec){ // Assignment
return vector3(this->x=invec.x,this->y=invec.y,this->z=invec.z);
}
_inline vector3 operator+(const vector3& invec){//Addition
return vector3(this->x+invec.x,this->y+invec.y,this->z+invec.z);
}
_inline vector3 operator-(const vector3& invec){//Subtraction
return vector3(this->x-invec.x,this->y-invec.y,this->z-invec.z);
}
_inline vector3 operator*(const vector3& invec){//Multiplication
return vector3(this->x*invec.x,this->y*invec.y,this->z*invec.z);
}
_inline vector3 operator/(const vector3& invec){//Division
return vector3(this->x/invec.x,this->y/invec.y,this->z/invec.z);
}
//Scaler operators
_inline vector3& operator+=(const float& scaler){//Addition self-assignment
return vector3(this->x+=scaler,this->y+=scaler,this->z+=scaler);
}
_inline vector3& operator-=(const float& scaler){//Subtraction self-assignment
return vector3(this->x-=scaler,this->y-=scaler,this->z-=scaler);
}
_inline vector3& operator*=(const float& scaler){//Multiplication self-assignment
return vector3(this->x*=scaler,this->y*=scaler,this->z*=scaler);
}
_inline vector3& operator*(const float& scalar){
return vector3(this->x*scalar, this->y*scalar, this->z*scalar);
}
//Math methods
_inline vector3 operator^(vector3& invec){//Cross product
return vector3( (this->y*invec.z-this->z*invec.y),
(this->z*invec.x-this->x*invec.z),
(this->x*invec.y-this->y*invec.x));
}
_inline vector3 operator&(vector3& invec){//Dot product
return (this->x*invec.x)+(this->y*invec.y)+(this->z*invec.z);
}
_inline vector3 distance(vector3&);//Distance
_inline void normalize(){
float mag = sqrtf(this->x*this->x+this->y*this->y+this->z*this->z);
this->x/=mag;
this->y/=mag;
this->z/=mag;
}
float x;
float y;
float z;
float getx();
float gety();
float getz();
float getMagnitude();
private:
float mag;
};
Catmull Rom Spline Generation
_inline vector3 createCatmulRomSpline(vector3 P0, vector3 P1, vector3 P2, vector3 P3, float t)
{
float t2 = t*t;
float t3 = t2*t;
vector3 result = ((P1*2) + (P2 - P0) * t + (P0*2 - P1 * 5 + P2*4 - P3)*t2 + (P1*3 - P0- P2*3 + P3) * t3)*0.5f;
return result;
}
I have tried other peoples code and when it comes to outputting the data into the final vector, it outputs bogus values.
You had a number of things wrong with your operators, although most of them weren't used. I modified your class. I notice you have not shown your code for the getx() (etc) members. I implemented those inline, but perhaps they were responsible for the garbage? Here is the test program with my changes. It seems to work fine:
class vector3
{
public:
vector3::vector3()
:x(0), y(0), z(0)
{}
vector3::~vector3()
{}
vector3(float inx,float iny,float inz)
: x(inx), y(iny), z(inz)
{}
//Vector operators
_inline vector3& operator=(const vector3& invec) { // Assignment
x = invec.x;
y = invec.y;
z = invec.z;
return *this;
}
_inline vector3 operator+(const vector3& invec) const {//Addition
return vector3(x+invec.x,y+invec.y,z+invec.z);
}
_inline vector3 operator-(const vector3& invec) const {//Subtraction
return vector3(x-invec.x,y-invec.y,z-invec.z);
}
_inline vector3 operator*(const vector3& invec) const {//Multiplication
return vector3(x*invec.x,y*invec.y,z*invec.z);
}
_inline vector3 operator/(const vector3& invec) const {//Division
return vector3(x/invec.x,y/invec.y,z/invec.z);
}
//scalar operators
_inline vector3& operator+=(const float& scalar){//Addition self-assignment
x+=scalar,y+=scalar,z+=scalar;
return *this;
}
_inline vector3& operator-=(const float& scalar){//Subtraction self-assignment
x-=scalar,y-=scalar,z-=scalar;
return *this;
}
_inline vector3& operator*=(const float& scalar){//Multiplication self-assignment
x*=scalar,y*=scalar,z*=scalar;
return *this;
}
_inline vector3 operator*(const float& scalar) const {
return vector3(x*scalar, y*scalar, z*scalar);
}
//Math methods
_inline vector3 operator^(const vector3& invec) const {//Cross product
return vector3( (y*invec.z-z*invec.y),
(z*invec.x-x*invec.z),
(x*invec.y-y*invec.x));
}
_inline float operator&(const vector3& invec) const {//Dot product
return (x*invec.x)+(y*invec.y)+(z*invec.z);
}
_inline float distance(vector3&) const;//Distance
_inline void normalize(){
float mag = sqrtf(x*x+y*y+z*z);
x/=mag;
y/=mag;
z/=mag;
}
float x;
float y;
float z;
_inline float getx() const { return x; }
_inline float gety() const { return y; }
_inline float getz() const { return z; }
float getMagnitude() const;
};
_inline vector3 createCatmulRomSpline(vector3 P0, vector3 P1, vector3 P2, vector3 P3, float t)
{
float t2 = t*t;
float t3 = t2*t;
vector3 result = ((P1*2) + (P2 - P0) * t + (P0*2 - P1 * 5 + P2*4 - P3)*t2 + (P1*3 - P0- P2*3 + P3) * t3)*0.5f;
return result;
}
int main() {
vector3 vectorOne(0,0,0);
vector3 vectorTwo(5,10,1);
vector3 vectorThree(10,10,2);
vector3 vectorFour(15,0,3);
const int ndiv = 10;
for( int i = 0; i <= ndiv; i++ )
{
float t = (float)i / ndiv;
vector3 SplineVector = createCatmulRomSpline(vectorOne, vectorTwo, vectorThree, vectorFour, t);
cout << "curve pos X: " << SplineVector.getx() << "\n";
cout << "curve pos Y: " << SplineVector.gety() << "\n";
cout << "curve pos Z: " << SplineVector.getz() << "\n\n";
}
return 0;
}