Sign in to follow this  

Help With Vector Math

This topic is 4277 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm writing up a camera class today and I'm having troubles. The mouse handles perfectly fine, but motion is not so good looking. I believe it may have to do with my vector math functions. Is there anything wrong here? SimStructs.h
typedef struct SimVector
{
    float x, y, z;

    void operator= (SimVector v)
    {
        x = v.x;
        y = v.y;
        z = v.z;
    }

    void operator+= (SimVector v)
    {
        x += v.x;
        y += v.y;
        z += v.z;
    }

    void operator-= (SimVector v)
    {
        x -= v.x;
        y -= v.y;
        z -= v.z;
    }

    void operator*= (float a)
    {
        x *= a;
        y *= a;
        z *= a;
    }

    void operator/= (float a)
    {
        x /= a;
        y /= a;
        z /= a;
    }

    SimVector operator+ (SimVector v)
    {
        SimVector ret;
        ret.x = x + v.x;
        ret.y = y + v.y;
        ret.z = z + v.z;
        return ret;
    }

    SimVector operator- (SimVector v)
    {
        SimVector ret;
        ret.x = x - v.x;
        ret.y = y - v.y;
        ret.z = z - v.z;
        return ret;
    }

    SimVector operator* (float a)
    {
        SimVector ret;
        ret.x = x * a;
        ret.y = y * a;
        ret.z = z * a;
    }

    SimVector operator/ (float a)
    {
        SimVector ret;
        ret.x = x / a;
        ret.y = y / a;
        ret.z = z / a;
        return ret;
    }

    float operator[] (int a)
    {
        if(a == 0)
            return x;
        if(a == 1)
            return y;
        if(a == 2)
            return z;
    }
};

namespace SimStructs
{
    float GetMagnitude(SimVector v);
    void Normalize(SimVector &v);
    float DotProduct(SimVector v1, SimVector v2);
    SimVector CrossProduct(SimVector v1, SimVector v2);
}


SimStructs.cpp
float SimStructs::GetMagnitude(SimVector v)
{
    return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}

void SimStructs::Normalize(SimVector &v)
{
    float mag = 1.0f / SimStructs::GetMagnitude(v);

    v *= mag;
}

float SimStructs::DotProduct(SimVector v1, SimVector v2)
{
    return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
}

SimVector SimStructs::CrossProduct(SimVector v1, SimVector v2)
{
    SimVector ret;
    ret.x = (v1.y * v2.z - v1.z * v2.y);
    ret.y = (v1.z * v2.x - v1.x * v2.z);
    ret.z = (v1.x * v2.y - v1.y * v2.x);
    return ret;
}

Camera code:
void SimCamera::Move(float speed, float timestep)
{
    direction = target - position;
    SimStructs::Normalize(direction);

    position += (direction * speed * timestep);
    target += (direction * speed * timestep);
}

void SimCamera::Strafe(float speed, float timestep)
{
    direction = target - position;
    SimStructs::Normalize(direction);

    strafe = SimStructs::CrossProduct(direction, up);
    SimStructs::Normalize(strafe);

    position += (strafe * speed * timestep);
    target += (strafe * speed * timestep);
}

Usage:
    camera.MouseInput();

    if(globalInput.IsKeyDown(SDLK_w))
        camera.Move(1, frameInterval);
    if(globalInput.IsKeyDown(SDLK_s))
        camera.Move(-1, frameInterval);
    if(globalInput.IsKeyDown(SDLK_a))
        camera.Strafe(-1, frameInterval);
    if(globalInput.IsKeyDown(SDLK_d))
        camera.Strafe(1, frameInterval);

Share this post


Link to post
Share on other sites
Now that you've got your class working, it's time to clean it up and make it watertight. I'll take a Zahlman approach to this (that's right - it's official).

// "typedef" isn't required in C++. You can leave it out happily.
struct SimVector
{
float x, y, z;

// A constructor will make your life a trillion easier. That's
// right, a trillion. Note we initialise via the initialisation
// list.
SimVector(float x_, float y_, float z_) : x(x_), y(y_), z(z_)
{
}

// You don't need to write an assignment operator ( operator = ),
// because C++ will generate one for your automatically, with a
// member-wise copy. That's what you've got, so delete it and watch
// it still work.

// You should pass by reference rather by value. this means that
// instead of making a new SimVector, we get given a reference to
// the original one. It is declared "const" so we can't change it.
//
// You should return a (non-const) reference so people can do things
// like:
// SimVector v = SimVector(3, 4, 5);
// if ( (v += 4).x == 7 ) go_crazy();
//
SimVector& operator += (const SimVector& v)
{
x += v.x; y += v.y; z += v.z;
return *this;
}

// ...

// it's good practice to make your addition, subtraction, division and
// multiplication friend operators, because otherwise this:
// SimVector r = 3.6f * my_simvector;
// won't work, as you have only define an operator * that -takes- a float,
// not a float that takes a SimVector for multiplication.
inline friend SimVector operator + (const SimVector& lhs, const SimVector& rhs)
{
// thanks, constructor!
return SimVector(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
}

// finally, -I- prefer to have my major functions as friend functions. it gives
// them the same scope as your class, and makes for a logical place to put them.
inline friend float Magnitude(const SimVector& v)
{
return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
}


Hope that helps.

Share this post


Link to post
Share on other sites

This topic is 4277 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this