1
\$\begingroup\$

I have set myself onto the task of creating a class BaseObject, which represents a graphics object with an associated shape as the member variable shape, which is a pointer an object Polygon. I'll provide their declarations here, together with the relevant implementations of the functions I am certain is causing my problem. My problem? As simple as 2D matrix transformations are, they seem to distort my shapes in ways I do not like. I am using the SDL2 graphics library for this problem. Here is the declaration for the BaseObject class.

class BaseObject : public Entity
{
protected:
  Polygon shape; // Pointer to a shape
  static uint baseObjectCount; // Useless variable?
  Vector2 posVec; //Position vector
public:
// Positioning and geometry
  Vector2 positionRelativeTo(const BaseObject &other) const;
  double distanceTo(const BaseObject &other) const;

// Get, set, ready!!!!
  Vector2 getPos() const;
  void setPos(Vector2 newPosVector);
  void relPos(Vector2 relPosVector);

// Geometric transforms. Simple and temporary interface with the
// Polygon class.
  void rotate(double theta);
  void scale(double ratio);

// Return a pointer to the shape.
  Polygon* getShape();

// Rendering and game state interface
  virtual void setShape(Polygon &targetShape);
  virtual void render();
  virtual void update();

//Constructors and destructors
  BaseObject();
  BaseObject(Vector2 initPos);
  BaseObject(const BaseObject& other);
  ~BaseObject();
};

The declaration of the Polygon class.

class Polygon
{
protected:
    SDL_Renderer* renderer;
    Vector2 *vertices = NULL;
    Vector2 *posVec; //Relative position.
    uint numVertices;

public:
    void createCircle(double radius, uint numVertices);

    SDL_Point* makeSDL_PointArray();
    void setPosVec(Vector2 &argPosVec);
    void setRenderer(SDL_Renderer*);
    void setVertices(Vector2* vertices, uint numVertices);
    void translate(Vector2 translationVector);
    void rotate(double theta);
    void scale(double ratio);
    void draw();

    Polygon();
    Polygon(Vector2* vertices, uint numVertices);
    Polygon(const Polygon &other);
};

The Polygon class uses an array of Vector2 objects, which is my own implementation of 2D vectors. The classes in themselves work fine, so I won't create a wall of definitions of functions. Rather, I'd like to present you my code for the transformation.

void Vector2::transform(double a, double b, double c, double d)
{
    x = a*x + b*y;
    y = c*x + d*y;
}

The function alters the x and y coordinates of the Vector2 instance. Each Vector2 associated with the Polygon class is relative to the origin, and on paper this transformation works fine. The transform assumes the following structure of the transformation matrix, and each argument a, b, c and d corresponds to the values a, b, c and d in this matrix.

[ a, b ]   [ x ]
[      ] * [   ]
[ c, d ]   [ y ]

The function used to rotate a class Polygon is the following:

void Polygon::rotate(double theta)
{
    for (uint i = 0; i < numVertices; i++)
    {
        vertices[i].transform(cos(theta), sin(-theta), sin(theta), cos(theta));
    }
}

Here, the transform function of the Vector2 class is used as a base for implementing the rotation matrix. By looping through every vertex / Vector2 representing the polygon, this transformation should do the job of rotating the "polygon" around the origins. However, when using this function, the circle drawn gets distortes as if being skewed. I did think this might have to do with the Y-axis being inverted in computer graphics, but testing the transformation matrix on paper produces the desired result on vectors no matter the orientation of the y-axis. My assumption is that the distortion is caused by errors in the trigonometric function in the , but a double precision value should not make a 90 degree (2Pi/4 rad) rotation transform a circle into a squished ellipse. This leads me to again believe this is related to the inverted y-axis and errors in my linear algebra. Ideas? I do not think all of the code need sto be posted here, but I'd be willing to share more of it if my ideas are completely off the table.

Before the transformation.

After the transformation

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

The transform method of Vector class is wrong. If you want to perform a transformation of the vector that is equivalent to multiplying a vector by a transform matrix, you should modify your code as follows:

void Vector2::transform(double a, double b, double c, double d)
{
   double newX = a*x + b*y;
   y = c*x + d*y;
   x = newX;
}
\$\endgroup\$
1
  • \$\begingroup\$ I just slapped my hand across my forehead. Thanks! I really did not see that. \$\endgroup\$
    – Tom V M
    Commented Feb 26, 2015 at 23:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .