Libgdx: Rotate around z-axis (Matrix Transformation) - java

I basicly want to replicate the following code snippet (Y-Axis is up) to libgdx:
let archer = Vector3d(1.0,0.0,1.0)
let target = Vector3d(4.0,0.0,5.0)
let travel = target - archer
let transform = Matrix4d.CreateTranslation(-archer) *
Matrix4d.CreateRotationY(Math.Atan2(travel.Z,travel.X))
Vector3d.Transform(archer, transform) // transforms archer to (0,0,0)
Vector3d.Transform(target, transform) // transforms target to (5,0,0)
source:
https://gamedev.stackexchange.com/questions/33901/how-to-make-an-arrow-land-at-a-specific-position-in-3d-world-space
And here is my approach(Z-Axis is up):
archer = new Vector3(1,1,0);
target = new Vector3(4,5,0);
Vector3 travel = new Vector3(target).sub(new Vector3(archer));
float degree = (float) Math.toDegrees(Math.atan2(travel.y, travel.x));
Matrix4 transform = new Matrix4().setToTranslation(new Vector3(archer).mul(-1));
transform.mul(new Matrix4().rotate(0, 0, 1, degree));//in my case Z-Axis is up !
archer.mul(transform); //-1.2,0.39999998,0 should be: 0,0,0
target.mul(transform); //-2.6000001,5.2,0.0 should be: 5,0,0
I am getting wrong results and i can't find my mistake but i guess it has something to do with the rotate part in line 6

I suppose it should be
archer = new Vector3(1,0,1);
target = new Vector3(4,0,5);

Related

Is there a cleaner / simpler way to calculate the edge in a geometry that a line crosses?

In the code below it is fairly simple to check does the line cross into the geometry or not - it's also trivial to work out the coordinate that the line crosses into the geometry at. However (and I've tried quite a few different ways), it seems way more convoluted to work out which line segment it is on.
final GeometryFactory fact = new GeometryFactory();
// The thing we are testing.
final Geometry gTestPoly = fact.createPolygon(new Coordinate[] { new Coordinate(0, 0),
new Coordinate(0, 10), new Coordinate(10, 10),
new Coordinate(10, 0), new Coordinate(0, 0)}); // a square
// Preconditions
final Coordinate cOutsideThePoly = new Coordinate(-5, 5);
final Coordinate cInsideThePoly = new Coordinate(5, 5);
final Geometry gOutsideThePoly = fact.createPoint(cOutsideThePoly);
final Geometry gInsideThePoly = fact.createPoint(cInsideThePoly);
assertTrue(gTestPoly.contains(gInsideThePoly));
assertFalse(gTestPoly.contains(gOutsideThePoly));
final Geometry gIntersectingLine = fact.createLineString(new Coordinate[] {cOutsideThePoly, cInsideThePoly}); // a line that crosses into the square
final LineSegment lIntersectingLine = new LineSegment(cOutsideThePoly, cInsideThePoly);
// Easy - it crosses the boundary on just 1 edge.
assertTrue(gIntersectingLine.crosses(gTestPoly));
// But if I want to see which edge/line segment my intersecting line segment crosses at ?? [this feels quite clunky..]
final Geometry gLineVersionOfTestPoly = LinearComponentExtracter.getGeometry(gTestPoly, true);
final LinearIterator iSegments = new LinearIterator(gLineVersionOfTestPoly);
final LineSegment forTest = new LineSegment();
while (iSegments.hasNext()) {
final Coordinate from = iSegments.getSegmentStart();
final Coordinate to = iSegments.getSegmentEnd();
forTest.setCoordinates(from, to);
if (forTest.intersection(lIntersectingLine) != null) {
System.err.println("Matching " + forTest);
}
iSegments.next(); // move to next step.
}
I get what I expect for output -
Matching LINESTRING( 0.0 0.0, 0.0 10.0)
Yes understand could just grab all the coordinates (via getCoordinates()) and check line segments like that - again seems like I've missed the magic simple method..

Box rotation around multiple axises using Matrix4f

The question change a bit, I figured out how to rotate around a single axis
I want to rotate a box around the Y axis using an angle.
The box has a size, and a Vector3f to signal the rotation.
To rotate the box correctly what I do is rotate the origin position then rotate the origin position plus the size, and use those two references to render the box.
However this rotation does not work correctly and causes rendering artifacts.
This is my code to rotate the positions:
Matrix4f matrix = new Matrix4f();
// Rotate the origin position
Vector3f pos = new Vector3f(new Vector3f(blockX, blockY, blockZ));
matrix.m03 = pos.x;
matrix.m13 = pos.y;
matrix.m23 = pos.z;
Vector3f rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMin = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Rotate the position with the size
// Top left back is the position of the block
Vector3f sizeRot = new Vector3f(new Vector3f(blockX + size, blockY + size, blockZ + size));
matrix = new Matrix4f();
matrix.m03 = sizeRot.x;
matrix.m13 = sizeRot.y;
matrix.m23 = sizeRot.z;
rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMax = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Then here I use the locationMax and the locationMin to render the cube
What could be wrong with this code? Is the logic I am using to rotate the box correct? as in rotate the origin position then rotate the origin position plus the size..
EDIT: I released that rotating after translating is stupid so instead I just rotated the locationMax which is not translated (it is only the size) then I translated and I still get the same result (Graphical Artifacts).
New Code:
float rx = blockX, ry = blockY, rz = blockZ;
Matrix4f matrix = new Matrix4f();
Vector3f rot = new Vector3f(0, 1f, 0f);
matrix = new Matrix4f();
matrix.m03 = size;
matrix.m13 = size;
matrix.m23 = size;
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
matrix.translate(new Vector3f(rx, ry, rz), matrix);
float mx = matrix.m03;
float my = matrix.m13;
float mz = matrix.m23;
// Here is use rx, ry, rz and mx, my, mz to render the box
============ * I figured it out (See below)* =============
EDIT:
This is what I ended up doing:
// Origin point
Vector4f a = new Vector4f(blockX, blockY, blockZ, 1);
// Rotate a matrix 45 degrees
Matrix4f mat = new Matrix4f();
mat.rotate((float) Math.toRandians(45f), new Vector3f(
0, 1f, 0), mat);
/* Transform the matrix to each point */
Vector4f c = new Vector4f(size.x, 0, size.z, 1);
Matrix4f.transform(mat, c, c);
Vector4f.add(c, a, c);
Vector4f b = new Vector4f(size.x, 0, 0, 1);
Matrix4f.transform(mat, b, b);
Vector4f.add(b, a, b);
Vector4f d = new Vector4f(0, 0, size.z, 1);
Matrix4f.transform(mat, d, d);
Vector4f.add(d, a, d);
// Here is use a, b, c, and d to render the box.
The problem with this is that I want to rotate around all axises and not only around the Y axis. This makes the code very long and unreadable and There are a lot of bugs when I try to rotate around all axises.
Update Question:
How do I take the above code and make it so I can rotate around all 3 axises. I want to do this so I can have a billboard that will always face the camera.
This is how I calculate the angle between the camera and the object:
Vector3f angle = new Vector3f();
// Calculate the distance between camera and object
Vector3f.sub(game.getCamera().getLocation(),
new Vector3f(blockX, blockY, blockZ), angle);
// Calculate the angle around the Y axis.
float vectorAngle = (float) ((float) Math.atan2(angle.z, angle.x) * -1 + (Math.PI / 2.0f));
Billboards are a very common application of computer graphics (as I'm sure you've noticed, since you're asking the question!)
Ultimately I think you are over complicating the problem, based on:
as in rotate the origin position then rotate the origin position plus the size..
For computer graphics, the most common transformations are Scaling, Translating, and Rotating, and you do these in an order to achieve a desired effect (traditionally you scale, then rotate about the origin, then translate the vertex's position).
Additionally, you will have three main matrices to render a model in 3d: World Matrix, View Matrix, and Projection Matrix. I believe you are having misunderstandings of transforming from Model Space to World Space.
Graphics TRS and Matrix info. If you are having conceptual problems, or this answer is insufficient, I highly recommend looking at this link. I have yet to find a better resource explaining the fundamentals of computer graphics.
So right at the moment, you have your three angles (in degrees, in a Vector3) corresponding to the angle difference in the X,Y, and Z coordinate spaces from your billboard and your camera. With this information, we generate the View matrix by first gathering all of our matrix transformations in one place.
I'm going to assume that you already have your Translation and Scaling matrices, and that they both work. This means that we only need to generate our Rotation matrix, and then transform that matrix with the scaling matrix, and then transforming that matrix by our translation matrix.
X Rotation Matrix
Y Rotation Matrix
Z Rotation Matrix
(Images taken from CodingLabs link above)
So you will generate these three matrices, using the X,Y, and Z angles you calculated earlier, and then transform them to consolidate them into a single matrix, transform that matrix by the scaling matrix, and then transform that matrix by the translation matrix. Now you have your awesome matrix that, when you multiply a a vertex by it, will transform that vertex into the desired size, rotation, and position.
So you transform every single vertex point by this generated matrix.
And then after that, you should be done! Using these techniques will hopefully simplify your code greatly, and set you on the right path :)
So now how about some code?
//I do not guarantee that this code compiles! I did not write it in an IDE nor did I compile it
float angleToRotX = 180f;
float angleToRotY = 90f;
float angleToRotZ = 0f;
// example vertex
Vector4f vertex = new Vector4f(0, 1, 0, 1);
// Rotate vertex's X coordinates by the desired degrees
Matrix4f rotationXMatrix = new Matrix4f();
rotationXMatrix.rotX(angleToRotX);
Matrix4f rotationYMatrix = new Matrix4f();
rotationYMatrix.rotY(angleToRotY);
Matrix4f rotationZMatrix = new Matrix4f();
rotationZMatrix.rotZ(angleToRotZ);
//now let's translate it by 1.5, 1, 1.5 in the X,Y,Z directions
Matrix4f translationMatrix = new Matrix4f();
translationMatrix.setTranslate(new Vector3f(1.5, 1, 1.5));
/*
Now we have our three rotational matrices. So we multiply them (transform them) to get a single matrix to transform all of the points in this model to the desired world coordinates
*/
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.mul(rotationXMatrix);
rotationMatrix.mul(rotationYMatrix);
rotationMatrix.mul(rotationZMatrix);
Matrix4f worldMatrix = translationMatrix;
worldMatrix.mul(rotationMatrix);
//now worldMatrix, when applied to a vertex, will rotate it by X,Y,Z degrees about the origin of it's model space, and then translate it by the amount given in translationMatrix
worldMatrix.transform(vertex);
//now vertex should be (1.5, 0, 1.5, 1) with (x,y,z,1)
Now this code could really be simplified, and it is excessively verbose. Try it out! I don't have java downloaded on my machine, but I grabbed the methods from the java documentation Here
Here is an image of what is happening (again, taking from coding labs):
(Advanced Info: Quaternions. These are really cool way of orienting a model in 3d space, however I don't quite understand them to the degree I need to in order to explain it to someone else, and I also believe that your problem is more fundamental)
You could generate the matrix without much hassle. The OpenGL matrix looks like the following:
|lx,ux,vx,px| - lx,ly,lz = the left vector
|ly,uy,vy,py| - ux,uy,uz = the up vector
|lz,uz,vz,pz| - vx,vy,vz = the view vector
|0 ,0 ,0 ,1 | - px,py,pz = the translation
All you need to do, is set px,py,pz to the position of your box in the world,
your view vector to the normalized(camera position - box position), your up comes straight from your camera, and the left is calculated via normalized cross product. It's also good practice to reconstruct the up vector, after left one is derived (by another cross product). That's all there's to it.
My solution aims to save you some time coding, rather than explain everything in detail. Hope that is useful to someone.

How to Apply transformation to Polygon object in Java

i have made a transform and rendered a Polygon object with it(mesh is of type Polygon):
at.setToTranslation(gameObject.position.x, gameObject.position.y);
at.rotate(Math.toRadians(rotation));
at.scale(scale, scale);
g2d.setTransform(at);
g2d.fillPolygon(mesh);
now i want to return the exact mesh i rendered so that i can do collision checks on it. only problem is that if i return mesh it returns the un-transformed mesh. so i tried setting the transform to the Polygon object (mesh) like so:
mesh = (Polygon)at.createTransformedShape(mesh);
but unfortunately at.createTransformedShape() returns a Shape that can only be casted to Path2D.Double. so if anyone knows how to convert Path2D.Double to Polygon or knows another way to set the transformations to the mesh please please help.
If AffineTransform#createTransformedShape doesn't provide the desired result for Polygons (as it seems to be the case), you can split the Polygon into Points, transform each Point and combine into a new Polygon. Try:
//Polygon mesh
//AffineTransform at
int[] x = mesh.xpoints;
int[] y = mesh.ypoints;
int[] rx = new int[x.length];
int[] ry = new int[y.length];
for(int i=0; i<mesh.npoints; i++){
Point2d p = new Point2d.Double(x[i], y[i]);
at.transform(p,p);
rx[i]=p.x;
ry[i]=p.y;
}
mesh = new Polygon(rx, ry, mesh.npoints)

3D Picking OpenGL ES 2.0 after model matrix translation

Hey all I'm trying to implement 3D picking into my program, and it works perfectly if I don't move from the origin. It is perfectly accurate. But if I move the model matrix away from the origin (the viewmatrix eye is still at 0,0,0) the picking vectors are still drawn from the original location. It should still be drawing from the view matrix eye (0,0,0) but it isn't. Here's some of my code to see if you can find out why..
Vector3d near = unProject(x, y, 0, mMVPMatrix, this.width, this.height);
Vector3d far = unProject(x, y, 1, mMVPMatrix, this.width, this.height);
Vector3d pickingRay = far.subtract(near);
//pickingRay.z *= -1;
Vector3d normal = new Vector3d(0,0,1);
if (normal.dot(pickingRay) != 0 && pickingRay.z < 0)
{
float t = (-5f-normal.dot(mCamera.eye))/(normal.dot(pickingRay));
pickingRay = mCamera.eye.add(pickingRay.scale(t));
addObject(pickingRay.x, pickingRay.y, pickingRay.z+.5f, Shape.BOX);
//a line for the picking vector for debugging
PrimProperties a = new PrimProperties(); //new prim properties for size and center
Prim result = null;
result = new Line(a, mCamera.eye, far);//new line object for seeing look at vector
result.createVertices();
objects.add(result);
}
public static Vector3d unProject(
float winx, float winy, float winz,
float[] resultantMatrix,
float width, float height)
{
winy = height-winy;
float[] m = new float[16],
in = new float[4],
out = new float[4];
Matrix.invertM(m, 0, resultantMatrix, 0);
in[0] = (winx / width) * 2 - 1;
in[1] = (winy / height) * 2 - 1;
in[2] = 2 * winz - 1;
in[3] = 1;
Matrix.multiplyMV(out, 0, m, 0, in, 0);
if (out[3]==0)
return null;
out[3] = 1/out[3];
return new Vector3d(out[0] * out[3], out[1] * out[3], out[2] * out[3]);
}
Matrix.translateM(mModelMatrix, 0, this.diffX, this.diffY, 0); //i use this to move the model matrix based on pinch zooming stuff.
Any help would be greatly appreciated! Thanks.
I wonder which algorithm you have implemented. Is it a ray casting approach to the problem?
I didn't focus much on the code itself but this looks a way too simple implementation to be a fully operational ray casting solution.
In my humble experience, i would like to suggest you, depending on the complexity of your final project (which I don't know), to adopt a color picking solution.
This solution is usually the most flexible and the easiest to be implemented.
It consist in the rendering of the objects in your scene with unique flat colors (usually you disable lighting as well in your shaders) to a backbuffer...a texture, then you acquire the coordinates of the click (touch) and you read the color of the pixel in that specific coordinates.
Having the color of the pixel and the tables of the colors of the different objects you rendered, makes possible for you to understand what the user clicked from a logical perspective.
There are other approaches to the object picking problem, this is probably universally recognized as the fastest one.
Cheers
Maurizio

Strange error when creating physics body in Andengine

I`m trying to create a polygonal physics body by such code:
final float halfWidth = pAreaShape.getWidthScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
final float halfHeight = pAreaShape.getHeightScaled() * 0.5f / PIXEL_TO_METER_RATIO_DEFAULT;
final float centerX = 0;
final float left = -halfWidth;
final float right = halfWidth;
final float top = -halfHeight + 9f / PIXEL_TO_METER_RATIO_DEFAULT;
final float bottom = halfHeight;
final PolygonShape shape1 = new PolygonShape();
final Vector2[] vertices = {
new Vector2(centerX, bottom),
new Vector2(left+8f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-19f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(left+7f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-23f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(left+10f/PIXEL_TO_METER_RATIO_DEFAULT, top+14f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(left+13f/PIXEL_TO_METER_RATIO_DEFAULT, top+8f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-14f/PIXEL_TO_METER_RATIO_DEFAULT, top+8f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-11f/PIXEL_TO_METER_RATIO_DEFAULT, top+14f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-9f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-23f/PIXEL_TO_METER_RATIO_DEFAULT),
new Vector2(right-10f/PIXEL_TO_METER_RATIO_DEFAULT, bottom-19f/PIXEL_TO_METER_RATIO_DEFAULT)
};
Body body = PhysicsFactory.createPolygonBody(pPhysicsWorld, pAreaShape, vertices, pBodyType, pFixtureDef);
Variable vertices contains vertices of this shape.
And it doesn`t work — applications starts(shows black screen and applications title bar), than it quits without any errors(there is no crash dialog and no errors in LogCat).
BUT when i delete one of the elements of vertices array, it works fine.
What i`m doing wrong?
Box2D has a maximum of 8 vertices in a polygon, and will fail by assertion if you specify more. I'm not sure what version of Box2D ANDEngine uses, but try making a loop or edge shape

Categories