Search code examples
c++mathgraphicscurves

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.


Solution

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