libGDX: How to let the camera point to moving sprite? - scroll

I'm new to libGDX and android game dev. And I want to achieve this:
I have a Screen and within it, a ball sprite that is moving along the X axis. Now I want to center the viewport to the sprite when it moves. Just like in Angry birds, where the camera follows the bird flying across the sky.
How can I implement that within my game using OrthographicCamera?

This took me a while of Googling and testing, but I just found something and I think others may appreciate it.
To move the camera (and if you are using a spriteBatch), make sure to call setProjectionMatrix.
Ex:
camera.position.y += 5; // or whatever you want to change y by...
camera.position.x += 5;
camera.update();
spriteBatch.setProjectionMatrix(camera.combined);
Hope this helps someone!

In case you haven't figured this out yet, you need to convert the ball position to the camera position using
camera.unproject(ballPosition)
This converts the screen coordinates into world coordinates. Then call
camera.position(ballPosition)
to set the camera position to your ball's location in the world.

The
camera.translate(...);
function translates all of the involved attributes the camera by the given data. After the operation you need to call
camera.update();
to calculate the new matrices of the camera. This will push the camera to the direction you want.

Related

Convert screen space X,Y position into perspective projection with a specific z position

I'm using ThreeJS, but this is a general math question.
My end goal is to position an object in my scene using 2D screen space coordinates; however, I want a specific z position in the perspective projection.
As an example, I have a sphere that I want to place towards the bottom left of the screen while having the sphere be 5 units away from the camera. If the camera were to move, the sphere would maintain its perceived size and position.
I can't use an orthographic camera because the sphere needs to be able to move around in the perspective projection. At some point the sphere will be undocked from the screen and interact with the scene using physics.
I'm sure the solution is somewhere in the camera inverse matrix, however, that is beyond my abilities at the current moment.
Any help is greatly appreciated.
Thanks!
Your post includes too many questions, which is out of scope for StackOverflow. But I’ll try to answer just the main one:
Create a plane Mesh using PlaneGeometry.
Rotate it to face the camera, place it 5 units away from the camera.
Add it as a child with camera.add(plane); so whenever the camera moves, the plane moves with it.
Use a Raycaster’s .setfromCamera(cords, cam)
then
.intersectObject(plane)
method to convert x, y screen cords into an x, y, z world position where it
intersects the plane. You can read about it in the docs.
Once it’s working, make the plane invisible with visible = false
You can see the raycaster working in this official example: https://threejs.org/examples/#webgl_geometry_terrain_raycast

How do I place an element in front of the camera, facing it regardless of where it is?

I have this simple scene with a "tooltip" entity composed of some data, I'd like to know how to position it in front of the camera. The tooltip will have to face certain points a few meters away so the user can see it. It must obey camera direction (it can be gathered by calculating it from previousPoint to nextPoint where the camera will move), but only y axis (can't be tilted or anything like that).I tried digging through math but couldn't understand good enough to employ a solution for this little project; I appreciate all the help!
setTimeout(function(){
var camera = document.getElementById("cameraS");
var tt = document.getElementById("ttS");
var cameraPos = camera.getAttribute('position');
var ttPos = tt.getAttribute('position');
tt.setAttribute('position', cameraPos);
tt.setAttribute('rotation', {'y': -90});
}, 5000);
JSFiddle
EDIT
I made an image showing what I'm after: http://imgur.com/a/eDhqE
I have point A and point B; the camera will play an animation moving from previous point to the next, and upon reaching there the tooltip will be displayed a few meters away from the point (box) so we can see it. It must take camera orientation into consideration but it must be perpendicular to the ground (can't be tilted).
There is a command THREE.Object.lookAt(THREE.Vector3); that will rotate an object (assuming (0.0,1.0,0.0) is up) to face a vector. You can use this to have it face your camera.
If you only want Y rotation, you can copy the current rotation, then do look at, then copy the rotation.x and rotation.z from the previous frame rotation copy - so that way it'll only correct the y with .lookAt because you reset x and z.

Physijs jittering mesh and wrong rotation?

I am making a game in three.js and I have 2 questions. 1. I have a cube which gets pushed along but every few seconds it "Jitters" back a little. Why?. 2. When i click the left or right arrow key the cube meant to rotate on its Y-axis instead of rotating one way it sometimes rotates a little one way and then the other?.
So I realised that I was updating the camera in the Renderer update function not the physics update function so I moved it and now there is no jittering. Also for the rotation I changed .rotation.y -= 0.1; to .rotateOnAxis( new THREE.Vector3(0,1,0), -0.05); and now it works.

Three.js & OrbitControls.js - pan camera parallel to ground plane (like Google Earth)

I'm working on a simple Three.js demo that uses OrbitControls.js.
I'd like to change the behavior of panning in OrbitControls. Currently, when you pan the camera, it moves the camera in a plane that is perpendicular to the viewing direction. I'd like to change it so that the camera stays a constant distance from the ground plane and moves parallel to it. Google Earth uses a similar control setup.
Edit: I should have mentioned this detail in the first place, but I'd also like the point where you click and start dragging to remain directly under the cursor throughout the entire drag. There needs to be that solid connection between the mouse movement and what the user expects to happen on the screen. Otherwise, it feels as though I'm 'slipping' when I try to move around the scene.
Can someone give me a high-level explanation of how this might be done (with or without OrbitControls.js)?
EDIT: OrbitControls now supports panning parallel to the "ground plane", and it is the default.
To pan parallel to screen-space (the legacy behavior), set:
controls.screenSpacePanning = true;
Also available is MapControls, which has an API similar to that of Google Earth.
three.js r.94
Some time ago I was working on exactly this issue, i.e. adaptation of OrbitControls.js to map navigation.
Here's the code of MapControls.js.
Here's the demo of the controls.
I figured it out. Here's the overview:
Store the mousedown event somewhere.
When the mouse moves, get the new mousedown event.
For each of those points, find the points on the plane where those clicks are located (You'll need to put the points into camera space, transform them into world space, then fire a ray from the camera through each point to find their intersections with the plane. This page explains the ray-plane intersection test).
Subtract the world-space start intersection point from the world-space end intersection point to get the offset.
Subtract that offset from the camera's target point and you're done!
In the case of OrbitControl.js, the camera always looks at the target point, and its position is relative to that point. So when you change the target, the camera moves with it. Since the target always lies on the plane, the camera moves parallel to that plane (as long as you're panning).
You should set your camera 'up' to z axe:
camera.up.set(0,0,1)
And then, the main problem with OrbitControl is its panUp() function. It should be fixed.
My pull request : https://github.com/mrdoob/three.js/pull/12727
y axe is relative to camera axes and should be relative to a fixed plan in the world. To define the expected y axe, make a 90° rotation of camera x axe, based on world z axe.
v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
v.applyAxisAngle( new THREE.Vector3( 0, 0, 1 ), Math.PI / 2 );
v.multiplyScalar( distance );
panOffset.add( v )
Enjoy!

Getting coordinates of the mouse in relation to 3D space in THREE.js

I have struggled for the past 3 weeks trying to figure this out. If anyone could help me I would appreciate it so much.
I'm developing a game similar to Geometry Wars in where I have a triangle in the middle of the screen which you can move around.
The problem is I need the triangle to rotate and face toward the direction of the mouse curser. I don't need to worry about the z-axis per-say as I always have the camera in a fixed position (z=500) and I am treating the scene as a "2D scene" - all the action occurs on the z=0 plane.
Calculating the angle between the triangle and the mouse is elementary:
targetAngle = Math.atan2(mouseCoord.y-this.position.y, mouseCoord.x-this.position.x)
where this is the mesh.
The problem is that the mouseCoords are in standed Dom window format whilst the position of the triangle is in Three.js format.
Q) How would I convert the mouse coords to represent the coords on the z=0 plane where the triangle is?
I have tryed so many ways including ray intersection but nothing works ;(
Thank you all for your help and thank you so much for an amazing framework!!!!
I don't actually see the problem. use the THREE.vector3 with the z coord in 0. then use something like triangle.rotate(THREE.vector3(targetAngle,0,0) or something
I suspect your intersection isn't working because of a CSS offset by your canvas within the DOM.
If you need the triangle to look at something specific, you should simply be able to use the "lookAt" method of the triangle.
To have it look at the camera for example:
triangleMesh.lookAt(camera.position);

Resources