Me again, trying to translate some C# code to Java with LibGDX. There is a method in C#'s Matrix class called CreateRotationZ(float radians) which rotates the matrix around “its z axis”.
What do this mean?
You have three axes: X, Y, and Z. A transformation matrix represents some manipulation of those. A rotation “around” an axis essentially rotates the other two axes, while the one you’re rotating around stays still. As an example, let’s say Z points upwards, and you have a Tower object. If you rotate it around the Z axis, you’d see it spin as people would conventionally visualize it.
Thanks. Thats a good explanation. But I cant figure out how to achive that function in one of the following classes: Affine2 or Matrix4
Matrix4.rotate(x, y, z, degrees) (or any of the equivalents) should work fine. Simply set X = 0, Y = 0, Z = 1, and that’ll rotate you around the Z axis.
Thanks
Just as an additional option:
If you want to translate math code from XNA to Java, you might also want to use JOML instead of libGDX.
JOML is being used by some other JGO’ers now and it provides certain methods that outperform libGDX.
Since I also had XNA in mind when designing JOML (migration guide is soon to come) it actually also supports creating a dedicated “rotate about Z” matrix via Matrix4f.rotationZ(radians) - see its JavaDocs.
Also note that JOML provides everything there is in XNA, such as building a reflection matrix or a matrix for projective shadows.
KaiHH: I am sure your library is awesome. Personally dont to want to use an extra lib for one single method. I will try with LibGDX’s Matrix4 a little bit more. Maybe you can help me?
Trying to convert this code:
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));
/// <summary>
/// Determines if there is overlap of the non-transparent pixels between two
/// sprites.
/// </summary>
/// <param name="transformA">World transform of the first sprite.</param>
/// <param name="widthA">Width of the first sprite's texture.</param>
/// <param name="heightA">Height of the first sprite's texture.</param>
/// <param name="dataA">Pixel color data of the first sprite.</param>
/// <param name="transformB">World transform of the second sprite.</param>
/// <param name="widthB">Width of the second sprite's texture.</param>
/// <param name="heightB">Height of the second sprite's texture.</param>
/// <param name="dataB">Pixel color data of the second sprite.</param>
/// <returns>True if non-transparent pixels overlap; false otherwise</returns>
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;
}
Here is my code:
public static boolean pixelPerfectRotation(Matrix4 m1, Image2D img1, Matrix4 m2, Image2D img2){
Matrix4 AtoB = m1.mul(m2.inv());
Vector3 trans = AtoB.getTranslation(new Vector3());
Matrix4 AtoBnorm = new Matrix4(AtoB).translate(-trans.x, -trans.y, 0);
Vector3 stepX = Vector3.X.cpy().mul(AtoBnorm);
Vector3 stepY = Vector3.Y.cpy().mul(AtoBnorm);
Vector3 yPosInB = Vector3.Zero.cpy().mul(AtoB);
int widthA = img1.getWidth();
int widthB = img2.getWidth();
int heightA = img1.getHeight();
int heightB = img2.getHeight();
for (int yA = 0; yA < heightA; yA++){
Vector3 posInB = yPosInB.cpy();
for (int xA = 0; xA < widthA; xA++){
int xB = Math.round(posInB.x);
int yB = Math.round(posInB.y);
if (0 <= xB && xB < widthB && 0 <= yB && yB < heightB){
int alpha1 = img1.getPixel(xA, yA) & 0x000000FF;
int alpha2 = img2.getPixel(xB, yB) & 0x000000FF;
if (alpha1 != 0 && alpha2 != 0)
return true;
}
posInB.x += stepX.x;
posInB.y += stepX.y;
}
yPosInB.x += stepY.x;
yPosInB.y += stepY.y;
}
return false;
}
public static Matrix4 createMatrix(Entity entity){
Matrix4 m = new Matrix4();
m.setToTranslation(-(entity.width() / 2), -(entity.height() / 2), 0);
m.rotate(0, 0, 1, -entity.getRotation());
m.translate(entity.x(), entity.y(), 0);
return m;
}