I have screen co-ordinates as x=216,y=726,w=504,h=284 and we need to convert these to normalized device co-ordinates [-1,1] before drawing using glDraw in openglES.
Please any help would be really appreciated. I am relatively new to openglES.
Thanks in advance.
Generally, when mapping coordinates from one coordinate system to another, here's the procedure:
targetPosition.x = targetLeftMost + (sourcePosition.x / sourceWidth) * targetWidth
targetPosition.y = targetTopMost + (sourcePosition.y / sourceHeight) * targetHeight
So for you, it should be:
targetPosition.x = -1 + (sourcePosition.x / 504) * targetWidth //(targetWidth = 2?)
This should get you started.
Related
I know a method from Unity whichs is very useful to convert a screen position to a world position : https://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html
I've been looking for something similar in A-Frame/THREE.js, but I didn't find anything.
Is there an easy way to convert a screen position to a world position in a plane which is positioned a given distance from the camera ?
This is typically done using Raycaster. An equivalent function using three.js would be written like this:
function screenToWorldPoint(screenSpaceCoord, target = new THREE.Vector3()) {
// convert the screen-space coordinates to normalized device coordinates
// (x and y ranging from -1 to 1):
const ndc = new THREE.Vector2()
ndc.x = 2 * screenSpaceCoord.x / screenWidth - 1;
ndc.y = 2 * screenSpaceCoord.y / screenHeight - 1;
// `Raycaster` can be used to convert this into a ray:
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(ndc, camera);
// finally, apply the distance:
return raycaster.ray.at(screenSpaceCoord.z, target);
}
Note that coordinates in browsers are usually measured from the top/left corner with y pointing downwards. In that case, the NDC calculation should be:
ndc.y = 1 - 2 * screenSpaceCoord.y / screenHeight;
Another note: instead of using a set distance in screenSpaceCoord.z you could also let three.js compute an intersection with any Object in your scene. For that you can use raycaster.intersectObject() and get a precise depth for the point of intersection with that object. See the documentation and various examples linked here: https://threejs.org/docs/#api/core/Raycaster
video game link
I'm trying to make a game (see link above) , and I need to have the stick rotate around himself to maintain the orientation face to center of the circle.
this is how I declare the Sprite, and how I move it around the circle:
declaration:
line = new Sprite(new Texture(Gdx.files.internal("drawable/blockLine.png")));
line.setSize(140, 20);
lineX = Gdx.graphics.getWidth()/2 - line.getWidth()/2;
lineY = (Gdx.graphics.getHeight()/2 - line.getHeight()/2) + circle.getHeight()/2;
movement:
Point point = rotatePoint(new Point(lineX, lineY), new Point(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2), angle+= Gdx.graphics.getDeltaTime() * lineSpeed);
line.setPosition(point.x, point.y);
rotatePoint function:
Point rotatePoint(Point point, Point center, double angle){
angle = (angle ) * (Math.PI/180); // Convert to radians
float rotatedX = (int) (Math.cos(angle) * (point.x - center.x) - Math.sin(angle) * (point.y-center.y) + center.x);
float rotatedY = (int) (Math.sin(angle) * (point.x - center.x) + Math.cos(angle) * (point.y - center.y) + center.y);
return new Point(rotatedX,rotatedY);
}
Any sugestions ?
I can't test right now but I think the rotation of the line should simply be:
Math.atan2(rotatedPoint.getOriginX() - middlePoint.getOriginX(), rotatedPoint.getOriginY() - middlePoint.getOriginY()));
Then you'll have to adjust rad to degrees or whatever you'll use. Tell me if it doesn't work!
I would take a different approach, I just created a method that places n Buttons around a click on the screen. I am using something that looks like this:
float rotation; // in degree's
float distance; //Distance from origin (radius of circle).
vector2 originOfRotation; //Center of circle
vector2 originOfSprite; //Origin of rotation sprite we are calculating
Vector2 direction = new vector2(0, 1); //pointing up
//rotate the direction
direction.rotate(rotation);
// add distance based of the direction. Warning: originOfRotation will change because of chaining method.
// use originOfRotation.cpy() if you do not want to init each frame
originOfSprite = originOfRotation.add(direction.scl(distance));
Now you have the position of your sprite. You need to increment rotation by x each frame to have it rotate. If you want the orientation of the sprite to change you can use the direction vector, probably rotated by 180 again. Efficiency wise I'm not sure what the difference would be.
I have a problem about getting the mouse coordinates, it behaves irrelevant after zooming.
I have a JS fiddle link of my code, it will show what the problem I face, is it bug in three.js or the way I approach to draw a line is wrong, please give your feedback.
http://jsfiddle.net/ebeit303/ceej4jxq/1/
var elem = self.renderer.domElement,
boundingRect = elem.getBoundingClientRect(),
x = (e.clientX - boundingRect.left) * (elem.width / boundingRect.width),
y = (e.clientY - boundingRect.top) * (elem.height / boundingRect.height);
var vector = new THREE.Vector3((x / $("container").width()) * 2 - 1, -(y / $("container").height()) * 2 + 1, 0.5);
var pos = projector.unprojectVector(vector, camera);
var dir = pos.clone().sub(camera.position).normalize().multiplyScalar(-1);
var distance = camera.position.z / dir.z;
var pos1 = camera.position.clone().sub(dir.multiplyScalar(distance));
Thanks in advance..
Your camera near plane in your fiddle is 0.0001, and your camera far plane is 10,000,000,000.
Consequently, you are having numerical problems in your code when you call unprojectVector().
The issue is closely related to the depth buffer precision problems described here: http://www.opengl.org/wiki/Depth_Buffer_Precision.
Set your near plane to 1, or greater, and your far plane to the smallest value you can get away with, say 10000.
three.js r.68
I have an app that finds QR finder marks from the AVCaptureDevice sample buffer delegate. Now I am trying to put boxes on the screen to cover the QR marks. However, I am having trouble converting between 1280x720 pixel resolution and the cameraView size.
I'm trying to write a method that converts a CGRect based on these parameters (and the fact that the view coordinate system is upside-down), but it won't work. It might have something to do with the orientation of the camera device as well. Here is my code for the converting method:
-(CGRect) convertRect:(CGRect) oldRect From90DegreeRotatedCameraSize1280x720ToUIViewSize:(CGSize) viewSize
{
//remember that we are using a gravity of resize aspect fill
double xScale = viewSize.width / 720;
double yScale = viewSize.height / 1280;
if (xScale < yScale)
return CGRectMake(oldRect.origin.x * xScale, viewSize.height - oldRect.origin.y * xScale, oldRect.size.height * xScale, oldRect.size.width * xScale);
else
return CGRectMake(oldRect.origin.x * yScale, viewSize.height - oldRect.origin.y * yScale, oldRect.size.height * yScale, oldRect.size.width * yScale);
}
Anyone got an elegant to solution to this relatively simple spacial coordinate problem?
EDIT -
I did a NSLog of the connection video orientation and it turns out that it never changes from 1 (which I think is enum'ed to portrait orientation.) From this, it should be easier to find a solution because the coordinates do not change in different orientations.
Any ideas, coder community?
Figured it out:
When iOS fills a view, it centers it so that the both sides are cut off. In order to transition between view coordinates, you need to scale and THEN translate in the direction that was cut off:
return CGRectMake(oldRect.origin.x * xScale, oldRect.origin.y * xScale - (1280 * xScale - viewSize.height) / 2, oldRect.size.height * xScale, oldRect.size.width * yScale);
Is it possible to rotate an image around a specific point, rather than the center? I see options for RVG's, but not for Magick::Image's :/
http://www.simplesystems.org/RMagick/doc/rvgxform.html#rotate <- RVG pivot point
angle -= angleSpeed * delta;
image.x = target.x + sin(angle) * distanceFromTarget;
image.y = target.y + cos(angle) * distanceFromTarget;
you could try changing the anchor point of the image to where you want it to rotate around, instead of the center