I would like to convert 2d Screen Coordinates to 3d World Coordinates.
I put together a hack but would like a solid solution. If possible please use your equation/algorithm on the example below (if there is already a link, could you use the link to show the solution to the problem below)
My Environment is Java/C++ for Android and iOS using OpenGL 2.0
Problem to Solve
Where screen
(0,0) is top left and bottom right is screenWidth and screenHeight.
screenWidth=667; screenHeight=375;
//Camera's position,where camera is looking at, and camera direction
CamPos (0.0f,0.0f,11.0f); CamLookAt (0.0f, 0.0f, 10.5f); CamDir(0.0f,1.0f,0.0f);
//The Frustum
left =1.3f; right=1.3f; bottom=1.0f; top=1.0f; near=3.0f; far=1000.0f;
Obj
//object's position in 3d space x,y,z and scaling
objPos(1.0f, -.5f, 5.0f); objScale(.1f,.1f,0.0f);
The problem is how to convert (600,200) screen coordinates (with scaling of (.1f,.1f.0.0f))to the object's (1.0f,-.5f,5.0f) world coordinates to check if they are colliding(I am doing simple box collision, just need the 2d screen coordinates converted to world). I will put the hack that I have below but I am sure there is a better answer. Thank you in advance for any help. Please use the numbers above to show how your algorithm works.
Hack
//this is 0,0 in screen coordinates//-Cam_Offset =hardcoded to camera's pos
float convertedZeroY= (((mCam->right)*(Cam_Offset))); //2
float convertedZeroX= -(((Cam_Offset)+convertedZeroY));
convertedZeroY=convertedZeroY/2;
convertedZeroX=convertedZeroX/2;
//this is the length from top to bottom in game coordinates
float normX=convertedZeroX*2;
float normY=convertedZeroY*2;
//this is the screen coordinates converted to 3d world coordinates
mInput->mUserInputConverted->mPos.x=(-(((mInput->x)/mCam->mScreenW)*normX)+convertedZeroX);
mInput->mUserInputConverted->mPos.y=(-(((mInput->y)/mCam->mScreenH)*(normY))+convertedZeroY);
Related
I'm trying to make a small circle move in another bigger circle as a ball moving in circle relative to Android phone tilting. I'm doing this in Godot but I think the principle is the same in all game engines probably. I make a scene in Godot and add two sprites as the two circles as the following picture. I get the accelerometer 3D vector, use x and y values and calculate the angle in x and y plate (relative to y axis i.e Vector2(0, 1) ) and rotate the mentioned scene to that degree using an animation, using this code
func _process(delta: float) -> void:
var vec3 = Input.get_accelerometer()
accelVec = Vector2(-stepify(vec3.x, 0.1), -stepify(vec3.y, 0.1))
var angle = accelVec.angle_to(Vector2(0, 1))
rotateTween.interpolate_property(self, "rotation", rotation, angle, 0.2,
Tween.TRANS_LINEAR)
rotateTween.start()
return
But the problem lies in here that when the x value of accelerometer 3D vector changes from a positive to negative value i.e when the ball is at top of the circle and is going to go to the other half of the circle, it actually moves from bottom of the circle to the desired point rather than from top of the circle.
I hope I explained the problem well, though I doubt it.
I added the Gif that shows actual test on an android phone here Testing in Android.
Any idea how to solve this problem?
Thanks in advance.
This is because Tween is interpolating linear values. It doesn't know it's working with angles, or that they should wrap around.
So when you're at -179 degrees and you tween to 179--a difference of 2 degrees--Tween just sees -179 -> 179 and goes through the whole circle.
You probably don't need a Tween here at all because _process() happens every frame.
I am using OpenGl to draw an image. Now when i try to move the image, it moves by too much. So if i say the following:
gl.glTranslatef(0, 1, -5.0f);
squirrel.draw(gl);
If i out one as a parameter, the image is now located half way of screen. How do i make it so i can say things like:
gl.glTranslatef(screen_width - image_width , 0);
Is there an alternative method for drawing images in OpenGl?
I previously used canvas to draw images, and i had no problem positioning images on the screen. However with openGl i'm experiencing issues.
All you need to remember is, the screen space in OpenGL ranges from -1,-1 (top left), and 1,1 (bottom right). So you need to provide normalized values to OpenGL. To move a point along x direction from one end of the screen (-1.0) to another (1.0), left to right, you will have to Translate by 2.0 by using glTranslatef(2.0, 0, 0). This point is on the border, so you will have to adjust depending on the actual size of your object and its location.
Assuming that i have an android phone with max x=400 and max y=300
I have a 5000 by 5000 px bitmap and i display a 400 by 300 part of it on screen. I scroll it around using touch events. I want to draw a smaller bitmap(30 by 30px) onto that larger bitmap at location (460,370). But i cant statically do it(as my game requires). I want to draw and undraw that smaller image according to the player's input or collision detections.
What i am confused about is that suppose currently (50,50) to (450,350) of the larger image is displayed on the screen and now ,due to a certain requirement of the game at this moment, i have to draw that 30by30 bitmap at (460,370) but this point is in two systems - 1)In the big bitmap's co-ordinate system it's 460,370 but when it will come inside the visible area of screen it will have values something between (0,0) and (400,300) depending upon its position on the screen as per the player's movements...
So how do i track that image- i mean using which co-ordinate system, and how do i go about doing all this?
I know I've put it here in a very confusing way but that's the best way i can put it and i'll be really glad, and grateful to you if somebody could help me on this.....
Terminology:
Let's call the coordinates on the big map world coordinates
Let's call the coordinates on the screen view coordinates. You are talking to the drawing system (canvas?) in view coordinates.
Your currently displayed region of the bigger map is 100% defined by an offset, let's call this (offsetX, offsetY). Formally, this offset maps your world coordinates onto your view coordinates.
If you have the small image displayed at position (x, y) in world coordinates, all you need to do is subtract your offset to get to view coordinates, i.e.
viewX = worldX - offsetX;
viewY = worldY - offsetY;
Right now, I am trying to create a simple app where a square follows where your finger touches as you move it along the screen. I would like to do this using opengl-es. I am fairly new to it and right now I am stuck on mapping the window coordinates reported by the touch event to the cartesian plane coordinate system that the opengl-es has. Right now, to get the x and y translation, I am using:
final int x = (e.getX()-(getWidth()/2))/(getWidth()/2) * SOME_SCALING_FACTOR;
final int y = ((getHeight()/2)-e.getY())/(getHeight()/2) * SOME_SCALING_FACTOR;
The logic behind this is that I think the cartesian plane is centered around the screen so I am trying to re-map my touch event coordinates in that way. However, my results are very inaccurate.
Is there another way I should be doing this?
I wouldn't use a SOME_SCALING_FACTOR there. It's better to configure OpenGL for it.
You may use code below to configure camera, then do your drawing.
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0, WINDOWx, 0, WINDOWy);
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();
The lower left point of screen will be origin, upper left is (0,WINDOWy) etc..
I've been playing with Android animation framework and I found the following 3D rotation sample code:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Transition3d.html
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.html
It does pretty much what I want but I want the ImageView to rotate while it's being translated from point A to point B and the it should rotate along it's own center(which is moving) instead of the center of the container of screen.
Does anyone know how to do that?
-Rachel
Well it's pretty close to what you posted. Essentially you're multiplying the rotational matrix by the translation matrix. That's essentially what happens under the covers. Android hides that detail from you with it's API:
Matrix matrix = transformation.getMatrix();
matrix.rotate( rotateX, rotateY );
matrix.postTranslate( transX, transY );
Rotate first then translate will rotate the image around it's own axis first before translating it.