2
\$\begingroup\$

I am making a top-down 2D game and am currently working on implementing improved collision using SAT. I programmed a Shape class with a Vector2 center that is its position in world space. On top of this is a list of Vector2's that act as the vertices of the shape and are defined as offsets in local space. The Shape class also has a rotation variable that is used in the Update method with a transformation matrix to rotate it around the Z axis. Since the Shape is parented by a Collider which is then parented by an actor, I have programmed its rotation to lock in with the Collider's parent actor. The problem is when the actor is turning the Shape begins to behave very oddly and spin about the actor at varying speeds. Here is the code:

The Update method inside the Shape class:

    public void Update()
    {
        if (!Circle && Rotation != lastRotation)
        {
            lastRotation = Rotation;

            Matrix rotate = Matrix.CreateRotationZ(Rotation);

            for (int v = 0; v < Vertices.Count; v++)
            {
                Vertices[v] = Vector2.Transform(Vertices[v], rotate);
            }
        }
    }

The Update method inside the Collider class:

    public void Update()
    {
        if (BoundingShape != null)
        {
            BoundingShape.setCenter(position.X, position.Y);
            BoundingShape.Update();
        }
    }

Part of the Update method in the actor class involving the Collider (Test) and Shape:

        Test.Update();
        Test.setPos(position.X, position.Y);
        Test.BoundingShape.Rotation = Rotation;

I looked around quite a bit before asking so I apologize if something similar has already been answered. All help is greatly appreciated!

\$\endgroup\$
  • \$\begingroup\$ This might not be helpful, but are you aware of Gimbal Lock? If you're technically using 3 axis instead of 2 this might explain your strange behavior. If you're strictly 2D, this shouldn't happen. \$\endgroup\$ – user44880 Apr 22 '14 at 2:45
  • \$\begingroup\$ Yeah I looked into Gimbal Lock. Although rotation in 2D technically occurs around the Z axis my game is not 3D. I'm pretty sure this is different considering how fast the Shape will rotate sometimes. \$\endgroup\$ – Bagofsheep Apr 22 '14 at 2:51
1
\$\begingroup\$

In this line here:

Vertices[v] = Vector2.Transform(Vertices[v], rotate);

You are overwriting your shape's vertices with the transformed vertices. The transformation you are creating is an absolute rotation, but you are applying it like a relative rotation. If this were simple algebra, you could use a relative rotation instead:

Matrix rotate = Matrix.CreateRotationZ(Rotation - lastRotation); // DON'T DO THIS!!

The reason you don't do this is because floating-point error will accumulate in your vertices as you repeatedly transform them. Floating-point is an approximation, so tiny amounts of imprecision will add up to large errors over time.

Instead, you should start with a base set of vertices (like a template), and always apply the absolute rotation. Like so:

TransformedVertices[v] = Vector2.Transform(Vertices[v], rotate);

If you are applying a translation transformation (your setPos method?), you should do it in the same way. You should never modify the original vertices. Instead, store the position (as you are storing the rotation), and then apply both transformations at once to output a transformed set of vertices. You can combine transformation matrices by multiplying them together (note that the order is important).

This is the standard way of using transformations (particularly for rendering things). Your original set of vertices is said to exist in "model space", and the transformed set of vertices exist in "world space".

\$\endgroup\$
  • \$\begingroup\$ I understand now. I'll need to have a base list of vertices that is never modified, then have a copy list that is the result of transformations being applied to the base. The setPos method simply changes the x and y values of a position Vector2, it doesn't use any transformation matrices so no worries there. I read a lot about matrices so I know about combining matrices with multiplication but my actual programming experience with them is minimal. Thanks for the great reply! \$\endgroup\$ – Bagofsheep Apr 22 '14 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.