Archived

This topic is now archived and is closed to further replies.

My vector class isn't working! Stack overflow!

This topic is 5009 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

Ok, here is how thinks are right now... I'm writing this game, a cover on Pong, SuperPong, and it MUST be ready on wednesday, and my program is almost ready. But one thing remains: the collision detection! I'm using a plane class and a vector class from the book "OpenGL Game Developing". And it should work, because it works in a hockey demo demonstrated in the same book. So, the problem is this: One of my balls(no not those balls) in SuperPong is not bouncing correct. I have set one of my gamefield walls at x=50(it's a vertical one). And the ball doesn't even bounce back there, it just continues in the same direction. The mystic part is that it eventually bounces back, but the plane seems to be at x=80 or something. And then on the way back from the mystic wall the program crashes when the ball reaches origo. The debugger says it's a Stack Overflow error, and complains about the vector class. I know it is a hard issue, but please guys I need your help with this one! Really! Here is the vector class:
#ifndef __VECTOR_H
#define __VECTOR_H

#include <math.h>

/*
     VECTOR.H

     scalar_t
     CVector class

     OpenGL Game Programming
     by Kevin Hawkins and Dave Astle

     Some operators of the CVector class based on
     operators of the CVector class by Bas Kuenen.
     Copyright (c) 2000 Bas Kuenen. All Rights Reserved.
     homepage: baskuenen.cfxweb.net
*/

typedef float scalar_t;

class CVector
{
public:
     scalar_t x;
     scalar_t y;
     scalar_t z;    // x,y,z coordinates


public:
     CVector(scalar_t a = 0, scalar_t b = 0, scalar_t c = 0) : x(a), y(b), z(c) {}
     CVector(const CVector &vec) : x(vec.x), y(vec.y), z(vec.z) {}

     // vector assignment

     const CVector &operator=(const CVector &vec)
     {
          x = vec.x;
          y = vec.y;
          z = vec.z;

          return *this;
     }

     // vecector equality

     const bool operator==(const CVector &vec) const
     {
          return ((x == vec.x) && (y == vec.y) && (z == vec.z));
     }

     // vecector inequality

     const bool operator!=(const CVector &vec) const
     {
          return !(*this == vec);
     }

     // vector add

     const CVector operator+(const CVector &vec) const
     {
          return CVector(x + vec.x, y + vec.y, z + vec.z);
     }

     // vector add (opposite of negation)

     const CVector operator+() const
     {    
          return CVector(*this);
     }

     // vector increment

     const CVector& operator+=(const CVector& vec)
     {    x += vec.x;
          y += vec.y;
          z += vec.z;
          return *this;
     }

     // vector subtraction

     const CVector operator-(const CVector& vec) const
     {    
          return CVector(x - vec.x, y - vec.y, z - vec.z);
     }
     
     // vector negation

     const CVector operator-() const
     {    
          return CVector(-x, -y, -z);
     }

     // vector decrement

     const CVector &operator-=(const CVector& vec)
     {
          x -= vec.x;
          y -= vec.y;
          z -= vec.z;

          return *this;
     }

     // scalar self-multiply

     const CVector &operator*=(const scalar_t &s)
     {
          x *= s;
          y *= s;
          z *= s;
          
          return *this;
     }

     // scalar self-divecide

     const CVector &operator/=(const scalar_t &s)
     {
          const float recip = 1/s; // for speed, one divecision


          x *= recip;
          y *= recip;
          z *= recip;

          return *this;
     }

     // post multiply by scalar

     const CVector operator*(const scalar_t &s) const
     {
          return CVector(x*s, y*s, z*s);
     }

     // pre multiply by scalar

     friend inline const CVector operator*(const scalar_t &s, const CVector &vec)
     {
          return vec*s;
     }

/*   friend inline const CVector operator*(const CVector &vec, const scalar_t &s)
     {
          return CVector(vec.x*s, vec.y*s, vec.z*s);
     }

*/   // divecide by scalar

     const CVector operator/(scalar_t s) const
     {
          s = 1/s;

          return CVector(s*x, s*y, s*z);
     }

     // cross product

     const CVector CrossProduct(const CVector &vec) const
     {
          return CVector(y*vec.z - z*vec.y, z*vec.x - x*vec.z, x*vec.y - y*vec.x);
     }

     // cross product

     const CVector operator^(const CVector &vec) const
     {
          return CVector(y*vec.z - z*vec.y, z*vec.x - x*vec.z, x*vec.y - y*vec.x);
     }

     // dot product

     const scalar_t DotProduct(const CVector &vec) const
     {
          return x*vec.x + y*vec.x + z*vec.z;
     }

     // dot product

     const scalar_t operator%(const CVector &vec) const
     {
          return x*vec.x + y*vec.x + z*vec.z;
     }


     // length of vector

     const scalar_t Length() const
     {
          return (scalar_t)sqrt((double)(x*x + y*y + z*z));
     }

     // return the unit vector

     const CVector UnitVector() const
     {
          return (*this) / Length();
     }

     // normalize this vector

     void Normalize()
     {
          (*this) /= Length();
     }

     const double operator!() const
     {
         return sqrtf((x*x) + (y*y)+ (z*z));
     }

     // return vector with specified length

     const CVector operator | (const double length) const
     {
          return (*this) * (length / !(*this));
     }

     // set length of vector equal to length

     const CVector& operator |= (const float length)
     {
          return *this = *this | length;
     }

     // return angle between two vectors

     const float inline Angle(const CVector& normal) const
     {
          return acosf(*this % normal);
     }

     // reflect this vector off surface with normal vector

     const CVector inline Reflection(const CVector& normal) const
     {    
          const CVector vec(*this | 1);     // normalize this vector

          return (vec - normal * 2.0 * (vec % normal)) * !*this;
     }

};

#endif
And here is the collision code...
void CMainBall::Move(float deltaTime, CField *field)
{
	if (deltaTime <= 0) return;

     double fastestTime = deltaTime;
     CPlane *planeCollision = NULL;
     for (int idx = 0; idx < 4; idx++)
     {
		  CPlane *plane = &field->fieldWalls[idx];
          double collisionTime;
          double aa, b, c;

          // dot product

          aa = plane->N % (a * 0.5);
          b = plane->N % v;
          c = plane->N % pos + plane->D - Radius;

          if (aa == 0)         // first degree

          {
               if (b != 0 && c != 0)    // must have velocity

               {
                    collisionTime = -c/b;
                    if (collisionTime >= 0 && collisionTime < fastestTime)
                    {
                         fastestTime = collisionTime;
                         planeCollision = plane;
                    }
               }
          }
          else
          {    //   Second degree equation

               double D = b*b - 4*aa*c;       //   Calc determinant

               if (D >= 0)
               {    
                    //   Calc solution (cannot be negative, so the negative solution is dropped)

                    collisionTime = (- b - sqrt(D)) / (2*aa);
                    if (collisionTime >= 0 && collisionTime < fastestTime)
                    {
                         fastestTime = collisionTime;
                         planeCollision = plane;  
                    }
               }
          }
     }

     // apply friction (coefficient = 0.2)

     if (v.Length() > 0.0)
          a = -v * 0.2;

     //   Move to collision point & set velocity there

     pos += v * fastestTime + a * (fastestTime*fastestTime*0.5);
     v += a * fastestTime;

     // only allow velocity to max out at 800

     if (v.Length() > 800.0)
          v |= 800.0;       // set velocity equal to 800

          
     if (planeCollision)
     {    //   Bounce - invert height direction

          v = v.Reflection(planeCollision->N);
     }

     //   Recursive call

     Move(deltaTime - fastestTime, field);

}
[edited by - AfroMogli on March 27, 2004 4:35:10 AM]

Share this post


Link to post
Share on other sites
Have you tried increasing the stack size? I know in VC++ you can use the /STACK option to set the stack size to a larger value.

----------------------------------------
"Before criticizing someone, walk a mile in their shoes.
Then, when you do criticize them, you will be a mile away and have their shoes." -- Deep Thoughts
"If you have any trouble sounding condescending, find a Unix user to show you how it''s done." - Scott Adams
FaceHat Software -- Wear the hat.

Share this post


Link to post
Share on other sites
Your Move() function is a recursive function with no terminating condition. You''re just calling the function infinitely. This is a bad thing.

Share this post


Link to post
Share on other sites
One thing I did notice is that your equality operation won''t work. You''re using == on floats. Test the difference against eplison instead.

You have to remember that you''re unique, just like everybody else.

Share this post


Link to post
Share on other sites
Ok, I fixed the Stack Overflow-error by removing the the iterating part.
Now I have another BIG problem. The ball, when it has bounced of a wall(this is happening with all walls) it "gets stuck" when it reaches the opppsoite axis.
Ok, I know sounds crazy but it''s in that way. Here is a step by step explanation of the problem:

1. The ball:s velocity is set to (10, 0, 0).
2. The ball is heading in the positive X direction as it should do.
3. It reaches the vertical wall which is at x=50.
4. It bounces of the wall, and is now heading in the negative X direction.
5. When it reaches the border between the positive x-axis and the negative x-axis it just stops!

My guess is that it is something wrong at the Move(). But I cannot fix the problem because of my limited collision and physics knowledge.

So PLEASE help me guys!

Share this post


Link to post
Share on other sites
Pseudo code:

...
ball.pos=(0,0)
ball.vel=(2,4)
ball.radius=3

while !exit
t=time()
dt=time()-t

ball.pos.x+=dt*ball.vel.x
ball.pos.y+=dt*ball.vel.y

resolveCollision()

endwhile
...

func resolveCollision()

r=ball.radius
//right
dx=50-r-ball.pos.x
if dx<0 //out of field
ball.pos.x+=2*dx
ball.vel.x=-ball.vel.x
endif
//left
dx=-50+r-ball.pos.x
if dx>0 //out of field
ball.pos.x+=2*dx
ball.vel.x=-ball.vel.x
endif
//top
dy=50-r-ball.pos.y
if dy<0 //out of field
ball.pos.y+=2*dy
ball.vel.y=-ball.vel.y
endif
//bottom
dy=-50+r-ball.pos.y
if dy>0 //out of field
ball.pos.y+=2*dy
ball.vel.y=-ball.vel.y
endif

endfunc



I think this works well, did not try it. If the ball has not got very very much velocity and dt is small enough, it should work well.

Share this post


Link to post
Share on other sites