Multiply vec3 with mat4 using glm - c++

At the moment, I convert the vec3 to vec4, multiply it with the matrix, and then cast it back to vec3
Code:
glm::vec3 transformed = glm::vec3(matrix * glm::vec4(point, 0.0))
It works, but I think it is not the good way to calculate it. Is it possible to apply a mat4 on a vec3, without casting it to vec4 and back?

When working with OpenGL it is very wise to stick with homogeneous coordinates. For 3D space these are 4D vectors where normally the fourth element equals 1. When you do this all your calculations are in 4 dimensional space, so no conversions needed anywhere.
Also note that in your example, you will actually lose any translation that may have been recorded in the transformation matrix. If you want to keep this you'll need to use 1 for the 4th element, not 0.
Appendix F of the Red Book describes how and why homogeneous coordinates are used within OpenGL.

mat4 is a 4 by 4 matrix, so you need a 4 dimension vector to multiply it.
That 4th dimension is really useful for 3D math, to distinguish between 3D space points (1) and 3D vectors (0)
Here I missing lots of operator, but I hope that you get the idea.
class point3
{
public:
vec4 p;
public:
point3();
point3(const point3& rhs);
point3(const point3& rhs);
point3(float x, float y, float z);
point3& operator=(const point3&rhs);
vector3 operator-(const point3&rhs);
point3 operator+(const vector3&rhs);
point3& operator+=(const vector3&rhs);
};
point3::point3():p.x(0), p.y(0), p.z(0), p.w(1)
{
}
point3::point3(const point3& rhs):p(rhs.p)
{
}
point3::point3(const point3& rhs):p(rhs.p)
{
}
point3::point3(float x, float y, float z):p.x(x), p.y(y), p.z(z), p.w(1)
{
}
point3& point3::operator=(const point3&rhs)
{
return (p=rhs.p);
}
vector3 point3::operator-(const point3&rhs)
{
vector3 result;
result.p=(p-rhs.p);
return result;
}
point3 point3::operator+(const vector3&rhs)
{
point3 result;
result.p=(p+rhs.p);
return result;
}
point3& point3::operator+=(const vector3&rhs)
{
p=(p+rhs.p);
return p;
}
class vector3
{
public:
vec4 p;
public:
vector3();
vector3(const vector3& rhs);
vector3(const vector3& rhs);
vector3(float x, float y, float z);
vector3& operator=(const vector3&rhs);
vector3 operator-(const vector3&rhs);
point3 operator-(const point3&rhs);
point3 operator+(const point3&rhs);
vector3 operator+(const vector3&rhs);
vector3& operator+=(const vector3&rhs);
};
vector3::vector3():p.x(0), p.y(0), p.z(0), p.w(0)
{
}
vector3::vector3(const vector3& rhs):p(rhs.p)
{
}
vector3::vector3(const vector3& rhs):p(rhs.p)
{
}
vector3::vector3(float x, float y, float z):p.x(x), p.y(y), p.z(z), p.w(0)
{
}
vector3& vector3::operator=(const vector3&rhs)
{
p=rhs.p;
return p;
}
vector3 vector3::operator-(const vector3&rhs)
{
vector3 result;
result.p=(p-rhs.p);
return result;
}
point3 vector3::operator-(const point3&rhs)
{
point3 result;
result.p=(p-rhs.p);
return result;
}
point3 vector3::operator+(const point3&rhs)
{
point3 result;
result.p=(p+rhs.p);
return result;
}
vector3 vector3::operator+(const vector3&rhs)
{
vector3 result;
result.p=(p+rhs.p);
return result;
}
vector3& vector3::operator+=(const vector3&rhs)
{
p=(p+rhs.p);
return p;
}

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.

Conversion from class to identical class with different template types

I have the simple class "vec2". I would like this class to be able to store doubles and double references in the class template, or even int and int references. Here is the desired behavior-
vec2<double> base(5, 5); //normal vec2
vec2<double&> reference(base.x, base.y); //vec2 reference to vec2 "base"
vec2<double> third;
base.x++; //base.x equals 6, this also changes reference.x to 6;
third = reference; //conversion between vec2<double> and vec2<double&>
I would also like modifying a reference instance of vec2 to be impossible, except by changing the variables it is referencing- so the following code would give a compiler error
vec2<double&> reference(base.x, base.y); //vec2 reference to vec2 "base"
reference.x = 5; //undesired behaviour
Is there a way to make the members x and y public when dealing with non-reference class types, but private when the class type is a reference? This would require methods specific to when it is a reference that will return the values of x and y. In the reference version it would also need to not have the overloaded operator methods that can affect the references. I slightly understand template specialization, but not enough to actually implement it.
Anyways, the main point of this is to find out how to take a class of type vec2<double>, and convert it to a class of type vec2<double&>.
Or, conversely, take a class of type vec2<double&>, and convert it to a class of type vec2<double>.
Here is my simple vec2 class-
template <class T> class vec2{
public:
vec2(){
x = 0;
y = 0;
}
vec2(T X, T Y){
x = X;
y = Y;
}
void normalize(){ //this function should inaccesable to any "reference version" of vec2
*this /= magnitude();
}
void rotate(double radians, vec2 center){ //this should also be inaccesable to reference versions
vec2 ogPts = *this -= center;
x = ogPts.x*cos(radians) - ogPts.y*sin(radians);
y = ogPts.y*cos(radians) + ogPts.x*sin(radians);
*this += center;
}
double magnitude() const{
return sqrt(x * x + y * y); //this should be available to both
}
T x;
T y;
vec2 operator+(const vec2 &v) const{ //available to both
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{ //available to both
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{ //available to both
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T v) const{ //available to both, but should work even if v is not a reference variable and T is a reference
return vec2(x*v, y*v);
}
vec2 operator/(T v) const{ //available to both, but should work even if v is not a reference variable and T is a reference
return vec2(x/v, y/v);
}
vec2 operator+=(const vec2 &v){ //inaccesable to reference versions of the class
x += v.x;
y += v.y;
return *this;
}
vec2 operator-=(const vec2 &v){ //inaccesable to reference versions
x -= v.x;
y -= v.y;
return *this;
}
vec2 operator*=(const vec2 &v){ //inaccesable to reference versions
x *= v.x;
y *= v.y;
return *this;
}
vec2 operator*=(T v){ //inaccesable to reference versions
x *= v;
y *= v;
return *this;
}
vec2 operator/=(T v){ //inaccesable to reference versions
x /= v;
y /= v;
return *this;
}
bool operator==(const vec2 &v) const{ //this should be available to both
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{ //this should be available to both
return (v.x != x || v.y != y);
}
};
Any help is much appreciated! I haven't worked with templates much, in fact, I just started yesterday! Thanks in advance for your time!
I did a bit more research, and managed to learn a lot on template specialization. Here is the functioning vec2 class which implements everything I wanted, plus a "perpindiculate" function and a "swap" function-
template <class T> class vec2{
public:
vec2(){
x = 0;
y = 0;
}
vec2(T X, T Y){
x = X;
y = Y;
}
operator vec2<T&>(){
return vec2<T&>(x, y);
}
void swap(){
std::swap(x, y);
}
void perpindiculate(){
std::swap(x, y);
y = -y;
}
void normalize(){
*this /= magnitude();
}
void rotate(double radians, vec2 center){
vec2 ogPts = *this -= center;
x = ogPts.x*cos(radians) - ogPts.y*sin(radians);
y = ogPts.y*cos(radians) + ogPts.x*sin(radians);
*this += center;
}
double magnitude() const{
return sqrt(x * x + y * y);
}
vec2 operator+(const vec2 &v) const{
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T v) const{
return vec2(x*v, y*v);
}
vec2 operator/(T v) const{
return vec2(x/v, y/v);
}
vec2 operator+=(const vec2 &v){
x += v.x;
y += v.y;
return *this;
}
vec2 operator-=(const vec2 &v){
x -= v.x;
y -= v.y;
return *this;
}
vec2 operator*=(const vec2 &v){
x *= v.x;
y *= v.y;
return *this;
}
vec2 operator*=(T v){
x *= v;
y *= v;
return *this;
}
vec2 operator/=(T v){
x /= v;
y /= v;
return *this;
}
bool operator==(const vec2 &v) const{
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{
return (v.x != x || v.y != y);
}
T x;
T y;
};
template<class T>
class vec2<T&>{
public:
vec2(T& X, T& Y) : x{X}, y{Y} {}
operator vec2<T>(){
return vec2<T>(x, y);
}
vec2<T> swap() const{
return vec2<T>(y, x);
}
vec2<T> perpindiculate() const{
return vec2<T>(-y, x);
}
vec2<T> normalize() const{
return *this / magnitude();
}
vec2<T> rotate(double radians, vec2 center) const{
return vec2<T>(x*cos(radians) - y*sin(radians), y*cos(radians) + x*sin(radians));
}
double magnitude() const{
return sqrt(x * x + y * y);
}
vec2 operator+(const vec2 &v) const{
return vec2(x+v.x, y+v.y);
}
vec2 operator-(const vec2 &v) const{
return vec2(x-v.x, y-v.y);
}
vec2 operator*(const vec2 &v) const{
return vec2(x*v.x, y*v.y);
}
vec2 operator*(T& v) const{
return vec2(x*v, y*v);
}
vec2 operator/(T& v) const{
return vec2(x/v, y/v);
}
bool operator==(const vec2 &v) const{
return (v.x == x && v.y == y);
}
bool operator!=(const vec2 &v) const{
return (v.x != x || v.y != y);
}
T getx(){
return x;
}
T gety(){
return y;
}
private:
T& x;
T& y;
};
Here is an example of it working-
double x = 5; //create future reference variables
double y = 3;
vec2<double&> vecref(x, y); //create vec2 referring to x and y
x = 7; //change x and y values, also changing vecref's values as well
y = 8;
vec2<double> vecOffRef = vecref; //conversion from a reference vec to a normal one
vec2<double&> vecOffRefref = vecOffRef; //conversion from a normal vec to a reference one
vecOffRef.normalize(); //normalize vec, also normalizing vecOffRefref
/* x equals 7, y = 8
vecRef equals (7, 8)
vecOffRef equals (0.6585, .7525)
vecOffRefRef equals (0.6585, .7525) */
A simplified version. By making the fields private, they can't be modified. I didn't try implementing all the operator= methods, but your code should work.
I'm not quite sure where your confusion is. A scan didn't see any problems, except I'd make the fields private so no one can touch them, and add accessor methods instead.
#include <iostream>
using namespace std;
template <class T>
class MyClass {
private:
T x;
T y;
public:
MyClass(T _x, T _y) : x(_x), y(_y) {}
T getX() const { return x; }
T getY() const { return y; }
};
int main(int, char **) {
double x {1.0};
double y {2.5};
MyClass<double> withDouble(x, y);
MyClass<double &> withRef{x, y};
cout << "withDouble: " << withDouble.getX() << ", " << withDouble.getY() << endl;
cout << "withRef: " << withRef.getX() << ", " << withRef.getY() << endl;
x = 3.9;
y = 5.4;
cout << "withRef: " << withRef.getX() << ", " << withRef.getY() << endl;
}

No operator "*" matches these operands... operand types are: const Vec2 * float

I get error "Error (active) E0349 no operator "*" matches these operands... operand types are: const Vec2 * float" in the function Project. I have defined operator * and it seems like the parameters match... I don't see where I did wrong..
class Vec2
{
public:
float x;
float y;
Vec2 operator*(const float &right) {
Vec2 result;
result.x = x * right;
result.y = y * right;
return result;
}
float MagnitudeSq() const
{
return sqrt(x * x + y * y);
}
float DistanceSq(const Vec2& v2)
{
return pow((v2.x - x), 2) + pow((v2.y - y), 2);
}
float Dot(const Vec2& v2)
{
return x*v2.x + y*v2.y;
}
Vec2 Project(const Vec2& v2)
{
*this = v2 * std::fmax(0, std::fmin(1, (*this).Dot(v2) / this->MagnitudeSq()));
}
};
You should declare the operator * of vec2 as acting on a const object.
Vec2 operator*(const float &right) const {
// ^^^^^^
This is because in the method Vec2 Project(const Vec2& v2) you are using the operator* on v2 which you have declared const in the prototype.
change the Line
Vec2 operator*(const float &right) {
to
Vec2 operator*(const float &right) const {
and it should work.
You are trying to perform a non const member function on a const object right now.

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;
}