I'm writing a OpenGL application in which there is a rectangle placed on a 3D object. The 3D object can move around and rotate and the rectangle follows these movements.
What I would like to do is to point with the mouse towards the rectangle so that a dot would appear in that point on the rectangle, and I want the point to follow it as the 3D object that "holds" the rectangle moves around.
I know how to find the intersection on a plane, and I know how to find the world coordinates of the contact point. What I need is a way to convert the world coordinates to the 2D local coordinate system of the rectangle.
For example, suppose I have the plane positioned like this in the 3D world, with a given orientation (sorry, I can't really draw properly):
The black point in the center is the origin of the plane, while the blue point is the one I would like to find. The numbers near the points are their world coordinates; in this example the Z axis "comes out" of the screen.
I would like to map the coordinates of the blue point in the local coordinate system of the plane, like this:
I know that somehow this shouldn't be hard, but I can't find a way at all. Any hints would be appreciated!
You probably already use a transformation matrix to render the rectangle. If you have the 3D position of the point, just transform it with the inverse transformation matrix and you get a 3D position in the rectangle's space. If the local system is aligned with the rectangle, one of the coordinates should always be zero and you can drop it.
I found what I needed in this post here.
Basically the solution for me is to project the point onto the x and y axis of the local coordinate system of the rectangle.
In pseudo code it's like this:
// I compute the direction that go from the origin of the rectangle to its x axis, in world coordinates, and take the norm; same thing for the y axis
var xDir = Norm(mRectangle.LocalToWorld([1, 0, 0]) - mRectangle.LocalToWorld([0, 0, 0]));
var yDir = Norm(mRectangle.LocalToWorld([0, 1, 0]) - mRectangle.LocalToWorld([0, 0, 0]));
// I compute the dot product
mLocalPosition.x = Dot(xDir, (contactPoint - mRectangle.LocalToWorld([0, 0, 0])));
mLocalPosition.y = Dot(yDir, (contactPoint - mRectangle.LocalToWorld([0, 0, 0])));
// I can now set the position of the point converting the local coordinates found to world coordinates
mPoint.SetPosition(mRectangle.LocalToWorld([mLocalPosition.x, mLocalPosition.y, 0]));
Related
I am making a 3D game in which the player can rotate their view point via the mouse to look around the environment. I firstly just did x and y rotation via vertical and horizontal movement of the mouse and z via another control. But after playing the game I realised it did not rotate correctly. NOTE: I have a global variable matrix which represents the player's angle (3x1), at 0,0,0 it seems to work correctly as up or down is a direct x axis rotation and right or left is a direct y axis rotation, but if I move my camera diagonally for example then left doesn't directly correlate to a y axis rotation anymore.
Visually on a unit circle the players viewpoint wouldn't travel the full circumference anymore and would travel in a circle that is smaller that the circumference. This is the current code (x and yRateOfRot is the ratio of how far away from the centre the cursor is in each direction between -1 and 1):
private static void changeRotation(){
angle.set(Matrix.add(angle.matrix,new double[][]{
{ROTATION_SPEED * camera.xRateOfRot()},
{ROTATION_SPEED * camera.yRateOfRot()},
{ROTATION_SPEED * camera.zRateOfRot()}}));
}
I have looked at this source http://paulbourke.net/geometry/rotate/ and understand how to rotate via an arbitrary axis which I could do but I am not sure how to correlate this into getting a ratio to find out what the x,y and z change would be for looking in a specific direction i.e. at 0,0,0 the ratio of looking up would be x:1, y:0, z:0 but then at another angle the ratios would be different as looking up no longer means only an x rotation. Any information would be appreciated, thanks!
While working on Projectiles I thought that it would be a good idea to rotate the sprite as well, to make it look nicer.
I am currently using a 1-Dimensional Array, and the sprite's width and height can and will vary, so it makes it a bit more difficult for me to figure out on how to do this correctly.
I will be honest and straight out say it: I have absolutely no idea on how to do this. There have been a few searches that I have done to try to find some stuff, and there were some things out there, but the best I found was this:
DreamInCode ~ Rotating a 1-dimensional Array of Pixels
This method works fine, but only for square Sprites. I would also like to apply this for non-square (rectangular) Sprites. How could I set it up so that rectangular sprites can be rotated?
Currently, I'm attempting to make a laser, and it would look much better if it didn't only go along a vertical or horizontal axis.
You need to recalculate the coordinate points of your image (take a look here). You've to do a matrix product of every point of your sprite (x, y) for the rotation matrix, to get the new point in the space x' and y'.
You can assume that the bottom left (or the bottom up, depends on your system coordinate orientation) of your sprite is at (x,y) = (0,0)
And you should recalculate the color too (because if you have a pure red pixel surrounded by blue pixel at (x,y)=(10,5) when you rotate it can move for example to (x, y)=(8.33, 7.1) that it's not a real pixel position because pixel haven't float coordinate. So the pixel at real position (x, y)=(8, 7) will be not anymore pure red, but a red with a small percentage of blue)... but one thing for time.
It's easier than you think: you only have to copy the original rectangular sprites centered into bigger square ones with transparent background. .png files have that option and I think you may use them.
I have a little tech game I am messing around with and I can't figure out the formula to position 1 object given another objects origin.
So I have a Spaceship and a Cannon. I have the game setup to use units, so 1 unit = 16 pixels (pixel art).
Basically my cannon should be placed 0.5625 units on the X and 0 on the Y relative to the origin of the Spaceship, which is located at 0, 0 (bottom left corner).
The cannon should is independent on the angle of the spaceship, it can aim in different directions rather than being fixed to aim the way of the spaceship.
I have it constantly following the cursor, which works fine. Now when I rotate the Spaceship, obviously the origin of the Spaceship is changing in world coordinates, so my formula to place the cannon is all messed up, like so:
protected Vector2 weaponMount = new Vector2();
weaponMount.set(getBody().getPosition().x + 0.5625f, getBody()
.getPosition().y);
Obviously if I position the ship at a 90° angle, X is going to be different and the cannon would be waaaayyy off the ship. Here is a screenshot example of what I mean:
What would be the formula for this? I have tried using cos/sin but that does not work.
Any ideas?
weaponMount.set(0.5625f,0).setAngle(SpaceshipAngle).add(getBody().getPosition());
Where SpaceshipAngle is the angle of your Spaceship.
The origin of the spaceship is the point, arround which the spaceship will rotate and scale (the Texture of it). The position instead is always the lower left corner of the Texture and does not depend on the rotation.
Your problem is, that your offset does not depent on the rotation of your spaceship.
To take care about this rotation you should store a Vector2 offset, which describes your weapons offset (in your case it is a Vector2(0.5625f, 0)).
Next store a float angle describing your spaceships rotation.
Then you can rotate the offset by using: offset.setAngle(rotation).
The last thing is to set the weapons position. The code for this did not change so much:
weaponMount.set(getBody().getPosition().x + offset.x, getBody()
.getPosition().y + offset.y);
I'm creating a 3D renderer in Java, which currently can render the wireframe of a cube using Points and lines and rotate the cube, the question is, what should Z be? And what should be set to Z? I'm guessing that the size of the cube should be set to Z?
Thanks for your time! Any answers would be much appreciated.
Z usually means the out-of-plane direction if the current viewport lies in the x-y plane.
Your 3D world has its own coordinate system. You'll transform from 3D world coordinates to viewport coordinates when you render.
I think you might be missing some basic school math/geometry here. However, it's actually not that hard to understand.
Imagine a flat plane, e.g. a sheet of paper.
The first coordinate axis will go straight from left to right and we'll call it X. So X = 0 means your point is on the left border. X = 10 might mean your point is on the right border (really depends on how big you define a unit of 1; this could be in centimeters, inches, etc.). This is already enough to describe some point in one dimension (from left to right).
Now, we need a second axis. Let's call it Y. It's running from the top border (Y = 0) to the bottom (Y = 10). Now you're able to describe any point on the plane as you've got two positions. For example, (0, 0) would be the top left corner. (10, 10) would be the bottom right corner. (5, 0) would be the center point of the top border, etc.
What happens if we add yet another dimension? Call it Z. This will essentially be the height of your point above the sheet. For example, Z = 0 could mean your point is sitting on the sheet of painter, while Z = 10 means your point is sitting 10 cm above the paper. Now you use three coordinates to describe a point: (5, 5, 0) is the center of the paper. (5,5,5) is the center of the cube sitting on your paper filling it and being 10 cm high.
When programming in 3D, you can use the same terminology. The only real difference is, that you're using a so called projection/view matrix to determine how to display this 3d positions on screen. The easiest transform could be the following matrix:
1 0 0
0 1 0
Multiplying this with your 3d coordinates you'll get the following two terms:
2d-x = 3d-x
2d-y = 3d-y
This results in you viewing the cube (or whatever you're trying to display) from straight above essentially ignoring the Z axis again (you can't render something sticking out of your display, unless using some kind of 3d glasses or similar technology).
Overall, it's up to you how you use the coordinates and interpret them. Usually x and y refer to the plane (position on the ground or position inside a 2D world) while z might be the height or the depth (front or back). It really depends on the specific case. But in generic, it's really just another dimension like x and y.
3D means 3 "Dimensions". One dimension is "X", the other "Y", the third "Z". None have a sepcific direction, though it's convenient to conventionally assign a direction, for example "Forward", "Left", and "Up".
Something whose X, Y, and Z values are all equal to 0 resides at the origin, or center of the space. You can write this as (0,0,0) where the order of the parameters are (x,y,z).
A point or vertex at the location (1,0,0) is one unit in the X direction from the origin. So if you moved from (0,0,0) to (1,0,0), you would be moving purely in the X direction.
(0,1,0) is one unit in the Y direction away from the origin.
(0,0,1) is one unit in the Z direction away from the origin.
(1,1,0) is one unit in the X direction and one unit in the Y direction. So if X means "Forward", and Y means "Left", then (1,1,0) is forward-and-left of the origin.
So a basic cube can be defined by the following vertices:
(1,1,-1)
(1,-1,-1)
(-1,1,-1)
(-1,-1,-1)
(1,1,1)
(1,-1,1)
(-1,1,1)
(-1,-1,1)
Alright, so I got two angles. One is the joystick's angle, and the other is the camera to player angle. The camera's angle. Now I want it so when I press up on the joystick it moves the player away from the camera. How would I do this? And is there a easy way to do it in Java or Ardor3d?
edit: Here is the code of how I get my angles.
float camDegree = (float) Math.toDegrees(Math.atan2(
_canvas.getCanvasRenderer().getCamera().getLocation().getXf() - colladaNode.getTranslation().getXf(),
_canvas.getCanvasRenderer().getCamera().getLocation().getYf()) - colladaNode.getTranslation().getYf());
player.angle = (float) Math.toDegrees(Math.atan2(padX, padY));
Quaternion camQ = new Quaternion().fromAngleAxis(camDegree, Vector3.UNIT_Y);
I have to say that I don't really understand your question, but it seems to be about how to implement camera-relative control using a joystick.
The most important piece of advice I can give you is that it's better not to compute angles, but to work directly with vectors.
Suppose that the camera is looking in the direction v (in some types of game this vector will be pointing directly at the player, but not all types of game, and not always):
Typically you don't care about the vertical component of this vector, so remove it to get the horizontal component, which I'll call y for reasons that will become apparent later:
y = v − (v · up) up
where up is a unit vector pointing vertically upwards.
We can find the horizontal vector that's perpendicular to y using the cross product (and remembering the right hand rule):
x = v × up
Now you can see that y is a vector in the plane pointing forwards (away from the camera), and x a vector in the plane pointing right (sideway with respect to the camera). If you normalise these vectors:
x̂ = x / |x|
ŷ = y / |y|
then you can use x̂ and ŷ as the coordinate basis for camera-relative motion of the player. If your joystick readings are Jx and Jy, then move the player by
s (Jx x̂ + Jy ŷ)
where s is an appropriate scalar value proportional to the player's speed.
(Notice that no angles were computed at any point in this answer!)