Per-pixel collision detection - why does XNA transform matrix return NaN when adding scaling?

Posted by JasperS on Game Development See other posts from Game Development or by JasperS
Published on 2013-07-01T12:04:39Z Indexed on 2013/07/01 16:31 UTC
Read the original article Hit count: 268

Filed under:

I looked at the TransformCollision sample on MSDN and added the Matrix.CreateTranslation part to a property in my collision detection code but I wanted to add scaling.

The code works fine when I leave scaling commented out but when I add it and then do a Matrix.Invert() on the created translation matrix the result is NaN ({NaN,NaN,NaN},{NaN,NaN,NaN},...)

Can anyone tell me why this is happening please?

Here's the code from the sample:

// Build the block's transform
            Matrix blockTransform =
                Matrix.CreateTranslation(new Vector3(-blockOrigin, 0.0f)) *
                // Matrix.CreateScale(block.Scale) *  would go here
                Matrix.CreateRotationZ(blocks[i].Rotation) *
                Matrix.CreateTranslation(new Vector3(blocks[i].Position, 0.0f));

public static bool IntersectPixels(
                        Matrix transformA, int widthA, int heightA, Color[] dataA,
                        Matrix transformB, int widthB, int heightB, Color[] dataB)
    {
        // Calculate a matrix which transforms from A's local space into
        // world space and then into B's local space
        Matrix transformAToB = transformA * Matrix.Invert(transformB);

        // When a point moves in A's local space, it moves in B's local space with a
        // fixed direction and distance proportional to the movement in A.
        // This algorithm steps through A one pixel at a time along A's X and Y axes
        // Calculate the analogous steps in B:
        Vector2 stepX = Vector2.TransformNormal(Vector2.UnitX, transformAToB);
        Vector2 stepY = Vector2.TransformNormal(Vector2.UnitY, transformAToB);

        // Calculate the top left corner of A in B's local space
        // This variable will be reused to keep track of the start of each row
        Vector2 yPosInB = Vector2.Transform(Vector2.Zero, transformAToB);

        // For each row of pixels in A
        for (int yA = 0; yA < heightA; yA++)
        {
            // Start at the beginning of the row
            Vector2 posInB = yPosInB;

            // For each pixel in this row
            for (int xA = 0; xA < widthA; xA++)
            {
                // Round to the nearest pixel
                int xB = (int)Math.Round(posInB.X);
                int yB = (int)Math.Round(posInB.Y);

                // If the pixel lies within the bounds of B
                if (0 <= xB && xB < widthB &&
                    0 <= yB && yB < heightB)
                {
                    // Get the colors of the overlapping pixels
                    Color colorA = dataA[xA + yA * widthA];
                    Color colorB = dataB[xB + yB * widthB];

                    // If both pixels are not completely transparent,
                    if (colorA.A != 0 && colorB.A != 0)
                    {
                        // then an intersection has been found
                        return true;
                    }
                }

                // Move to the next pixel in the row
                posInB += stepX;
            }

            // Move to the next row
            yPosInB += stepY;
        }

        // No intersection found
        return false;
    }

© Game Development or respective owner

Related posts about XNA