How to get the real position were a point is drawn after translate and rotate in P5JS - rotation

I read a lot, and tried many things, but can't get this done, and it seems simple
I have the following p5js code
function setup() {
let canvas = createCanvas(400, 400);
noLoop();
}
function draw() {
background(220);
push();
translate(50,100);
point(25,25);
// MISSING CODE to get 75,125
pop();
}
And I'm trying to figure out if there is a way to get the actual coordinates were the point is drawn,
I read about getTransform, the matrix, and a lot of stuff, but seems impossible to get it done. Also I need to use rotation in the transform, so that makes it even harder
Thanks!

Use variables, so you can keep track of how much you translated and the location of your point, so you can them add them to obtain the desired result.
let trans_x = 50
let trans_y = 100
let point_x = 25
let point_y = 25
translate(trans_x, trans_y);
point(point_x, point_y);
result_x = trans_x + point_x // 50+25=75
result_y = trans_y + point_y // 100+25=125
You could use Vectors so you don't have to define 2 variables, but you get the idea.
Usually you would call WorldPosition to the absolute position of the object and RelativePosition to the position the object relative to the CameraPosition
The translation would be called CameraPosition and to make your code more efficient you should only draw objects that their RelativePosition falls inside the drawable area.

Related

Oriented projectiles keep facing camera

I'm trying to render a 2d image that represent a projectile in a 3d world and i have difficulty to make the projectile face the camera without changing its direction. Im using JOML math library.
my working code to orient the projectile in his direction
public Quaternionf findRotation(Vector3f objectRay, Vector3f targetRay) {
Vector3f oppositeVector = new Vector3f(-objectRay.x, -objectRay.y, -objectRay.z);
// cas vecteur opposé
if(oppositeVector.x == targetRay.x && oppositeVector.y == targetRay.y && oppositeVector.z == targetRay.z) {
AxisAngle4f axis = new AxisAngle4f((float) Math.toRadians(180), 0, 0, 1);
Quaternionf result = new Quaternionf(axis);
return result;
}
objectRay = objectRay.normalize();
targetRay = targetRay.normalize();
double angleDif = Math.acos(new Vector3f(targetRay).dot(objectRay));
if (angleDif!=0) {
Vector3f orthoRay = new Vector3f(objectRay).cross(targetRay);
orthoRay = orthoRay.normalize();
AxisAngle4f deltaQ = new AxisAngle4f((float) angleDif, orthoRay.x, orthoRay.y, orthoRay.z);
Quaternionf result = new Quaternionf(deltaQ);
return result.normalize();
}
return new Quaternionf();
}
Now i want to add a vector3f cameraPosition parameter to rotate the projectile only on its x axis to face the camera but i dont know how to do it.
For example with this code the projectile correctly rotate around his x axis but not face the camera so i want to know how to find the correct angle.
this.lasers[i].getModel().rotate((float) Math.toRadians(5), 1, 0, 0);
I tried this to rotate around axis X with transforming vector before compute angle.
this.lasers[i] = new VisualEffect(this.position, new Vector3f(1,1,1), color, new Vector2f(0,0.33f));
this.lasers[i].setModel(new Matrix4f().scale(this.lasers[i].getScale()));
this.lasers[i].getModel().rotate(rotation);
this.lasers[i].getModel().translateLocal(this.lasers[i].getPosition());
Vector3f vec = new Vector3f(cameraPosition).sub(this.position);
Vector4f vecSpaceModel = this.lasers[i].getModel().transform(new Vector4f(vec, 1.0f));
Vector4f normalSpaceModel = this.lasers[i].getModel().transform(new Vector4f(normal, 1.0f));
float angleX = new Vector2f(vecSpaceModel.y, vecSpaceModel.z).angle(new Vector2f(normalSpaceModel.y, normalSpaceModel.z));
this.lasers[i].getModel().rotate(angleX, 1, 0, 0);
Since you are using JOML, you can massively simplify your whole setup.
Let's assume that:
projectilePosition is the position of the projectile,
targetPosition is the position the projectile is flying at/towards, and
cameraPosition is the position of the "camera" (which we ultimately want the projectile to face)
We will also assume that the local coordinate system of the projectile is such that its +X axis points along the projectile's path (like how you depicted it) and the +Z axis points away from the projectile towards the viewer when the viewer is "facing" the projectile. So, the projectile itself is defined as a quad on the XY plane within its own local coordinate system.
What we must do now is create a basis transformation that will effectively transform the projectile such that its X axis points towards the "target" and its Z axis points "as best as we can" towards the camera.
This is very reminiscent of what we know as the "lookAt" transformation in OpenGL. And in fact, we are just going to use that. However, since the common "lookAt" is the inverse of what we wanted to do, we will also just invert it.
So, all in all, your complete model matrix/transformation for a single projectile will look like this (in JOML):
Vector3f projectilePosition = ...;
Vector3f cameraPosition = ...;
Vector3f targetPosition = ...;
Vector3f projectileToCamera = new Vector3f(cameraPosition).sub(projectilePosition);
modelMatrix
.setLookAt(projectilePosition, targetPosition, projectileToCamera)
.invert()
.rotateXYZ((float) Math.toRadians(-90), 0, (float) Math.toRadians(90));
In case you do not want to use lookAt and invert, you can also do:
Vector3f projectileToTarget = new Vector3f(targetPosition).sub(projectilePosition);
modelMatrix
.translation(projectilePosition)
.rotateTowards(projectileToTarget, projectileToCamera)
.rotateXYZ((float) Math.toRadians(-90), 0, (float) Math.toRadians(-90));
yielding the same result as the above code.
Note that nowhere do we actually need angles or trigonometric functions. This is very common when you already have all positions/directions given as vectors, you can simply use linear algebra without converting from/to angles.
The last part with the rotateXYZ(90°, 0°, 90°) is to express that we do not want the -Z axis of the projectile to point towards the target (which is what lookAt will do by default), but we want the X axis to point to the target.
Yet another way is to realize that what we do here is also known as a "cylindrical" or "axial" billboard, and can also be expressed like so:
Vector3f projectileToTarget = new Vector3f(targetPosition).sub(quadPosition).normalize();
modelMatrix
.billboardCylindrical(projectilePosition, cameraPosition, projectileToTarget)
.rotateZ((float) Math.toRadians(90));
(Note that in this case projectileToTarget needs to be unit!)
A test with a simple scene containing 24 projectiles all targeting "the center" with the camera hovering over them will look like this:
The corresponding simple LWJGL 3 / JOML demo generating this image.

In A-Frame/THREE.js, is there a method like the Camera.ScreenToWorldPoint() from Unity?

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

Processing Bullets interaction

Hi How do I make bullets to collide with the objects in Processing ?
Bullets are fired and being translated and rotated
but whenever i try to use function dist() it always gives me 0 as the position of the vector
How do i get the correct vector position if i want the bullet to collide with objects using distance and make the the other object disappear ?
Here's the code
void move(){
passed = passed + time;
if (passed > bulletLife) {
alive = false;
}
forward.x = sin(theta);
forward.y = -cos(theta);
float speed = 15.0f;
velocity = PVector.mult(forward, speed);
side.add(forward);
void display(){
pushMatrix();
translate(side.x, side.y);
rotate(theta);
stroke(255);
ellipse(side.x, side.y, 30, 30);
popMatrix();
Thanks
You're getting 0 from dist() because translate() moves the coordinate system! I think, more than your question, you need to reconsider your code overall. You translate to side.x, side.y (which will then be 0,0 until you call popMatrix()) but then you draw the ellipse at side.x, side.y which is offset from its actual position.
In other words: if the position is 100,200, you're actually drawing the object at 200,400!
If you skip the translate() part, you can use this to draw your object:
void display() {
stroke(255);
ellipse(side.x, side.y, 30,30);
}
And this to check collision:
if (dist(side.x, side.y, bullet.x, bullet.y) == 0) {
collision = true;
}
else {
collision = false;
}
You can also see my collision-detection functions for Processing, which have lots of examples that might help.

howto generate a smooth movement in xna for wp7?

i want to create a game and addes a image to my game, now i want it to move down smoothly. i have a code like this:
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
pos.Y = pos.Y + 1;
base.Update(gameTime);
}
the movement works but it dont looks smooth, it looks like it jiggle. pos is a vector2 for the position in the image.
how to make it more smooth?
If you want movement to be smooth without adding a physics library you just have to factor in gameTime to your position update.
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
pos.Y = pos.Y * 100 * (float)gameTime.ElapsedGameTime.TotalSeconds;
base.Update(gameTime);
}
I don't have access to XNA + visual studio right now, but the changes I made should give you an idea of what to try out. Keep in mind the Update call happens multiple times a second so the elapsed time will be a small number so then you have to multiply it by a larger "movement" value in this case I put 100. Tweak 100 until you see the movement speed you desire.
Beanish is right, you should multiply by GameTime if you want smoothness. Physics is an overkill if you only want your animation to look smooth.
The best way I've found to do animation is by using position interpolation, for this to work you have to know the initial (you already know this) and final position of the image.
If you want to move from A to B in, say, 2 seconds, you can use the following code.
Vector2 a = new Vector2(0, 0);
Vector2 b = new Vector2(0, 100);
float elapsedTime = 0;
float duration = 2.0;
public override void Update(GameTime gameTime)
{
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
elapsedTime += dt;
if (elapsedTime > 1)
elapsedTime = 1;
float param = elapsedTime / duration;
pos = Vector2.Lerp(a, b, param);
}
The best thing about using this approach is that you can now use "easing" to make you animation look really really nice.
To do this just add a Power operation to the interpolator parameter:
pos = Vector2.Lerp(a, b, (float)Math.Pow(param /2.0, 0.5));
This will make you image slow down as it arrives to B. You can play with the exponent value (0.5) to get different results, try 2.0 for example.
Another important thing is that your image will always stop at B. If you use the Euler integration approach (your approach, adding a velocity each frame) you might have some trouble making the image stop at the right position (aka B) and it gets even worse when using 2 or 3 dimesions.
To know more about easing, check Robert Penner's Easing Equations.
First I can tell you what the problem isn't. You don't need a physics engine to have smooth movement. And changing the Update to include the ElapsedGameTime will not make a lick of difference for the smoothness (assuming you haven't changed the default of IsFixedTimestep to false). When there is a fixed timestep, ElapsedGameTime will always have the same value, it will not vary.
I don't how much you are doing in your code, but if it's too much, XNA will start skipping the Draw portion of your code, and this can definitely cause jerkiness. One way to check: in your Update method, test the value of IsRunningSlowly. Whenever it is true, XNA will skip some Draw calls.
If you are not doing anything complicated, then the culprit may be the refresh rate of your monitor. If it is set to anything other than 60Hz, you will have jerkiness. You could fix this by changing your monitor's refresh rate. Alternatively you can change the value of TargetElapsedTime to match your monitor's rate.
You should consider adding to your game a library for handling physics, as for example FarseerPhysics. By calculating the position in a per time base with physics rules applied your movements will be smooth and natural.

3D Rotation Matrix deforms over time in Processing/Java

Im working on a project where i want to generate a 3D mesh to represent a certain amount of data.
To create this mesh i want to use transformation Matrixes, so i created a class based upon the mathematical algorithms found on a couple of websites.
Everything seems to work, scale/translation but as soon as im rotating a mesh on its x-axis its starts to deform after 2 to 3 complete rotations. It feels like my scale values are increasing which transforms my mesh. I'm struggling with this problem for a couple of days but i can't figure out what's going wrong.
To make things more clear you can download my complete setup here.
I defined the coordinates of a box and put them through the transformation matrix before writing them to the screen
This is the formula for rotating my object
void appendRotation(float inXAngle, float inYAngle, float inZAngle, PVector inPivot ) {
boolean setPivot = false;
if (inPivot.x != 0 || inPivot.y != 0 || inPivot.z != 0) {
setPivot = true;
}
// If a setPivot = true, translate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,inPivot.z); }
}
// Create a rotationmatrix
Matrix3D rotationMatrix = new Matrix3D();
// xsin en xcos
float xSinCal = sin(radians(inXAngle));
float xCosCal = cos(radians(inXAngle));
// ysin en ycos
float ySinCal = sin(radians(inYAngle));
float yCosCal = cos(radians(inYAngle));
// zsin en zcos
float zSinCal = sin(radians(inZAngle));
float zCosCal = cos(radians(inZAngle));
// Rotate around x
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[1][1] = xCosCal;
rotationMatrix.matrix[1][2] = xSinCal;
rotationMatrix.matrix[2][1] = -xSinCal;
rotationMatrix.matrix[2][2] = xCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around y
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = yCosCal;
rotationMatrix.matrix[0][2] = -ySinCal;
rotationMatrix.matrix[2][0] = ySinCal;
rotationMatrix.matrix[2][2] = yCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around z
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = zCosCal;
rotationMatrix.matrix[0][1] = zSinCal;
rotationMatrix.matrix[1][0] = -zSinCal;
rotationMatrix.matrix[1][1] = zCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Untranslate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(-inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,-inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,-inPivot.z); }
}
}
Does anyone have a clue?
You never want to cumulatively transform matrices. This will introduce error into your matrices and cause problems such as scaling or skewing the orthographic components.
The correct method would be to keep track of the cumulative pitch, yaw, roll angles. Then reconstruct the transformation matrix from those angles every update.
If there is any chance: avoid multiplying rotation matrices. Keep track of the cumulative rotation and compute a new rotation matrix at each step.
If it is impossible to avoid multiplying the rotation matrices then renormalize them (starts on page 16). It works for me just fine for more than 10 thousand multiplications.
However, I suspect that it will not help you, numerical errors usually requires more than 2 steps to manifest themselves. It seems to me the reason for your problem is somewhere else.
Yaw, pitch and roll are not good for arbitrary rotations. Euler angles suffer from singularities and instability. Look at 38:25 (presentation of David Sachs)
http://www.youtube.com/watch?v=C7JQ7Rpwn2k
Good luck!
As #don mentions, try to avoid cumulative transformations, as you can run into all sort of problems. Rotating by one axis at a time might lead you to Gimbal Lock issues. Try to do all rotations in one go.
Also, bare in mind that Processing comes with it's own Matrix3D class called PMatrix3D which has a rotate() method which takes an angle(in radians) and x,y,z values for the rotation axis.
Here is an example function that would rotate a bunch of PVectors:
PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){
int vl = verts.length;
PVector[] clone = new PVector[vl];
for(int i = 0; i<vl;i++) clone[i] = verts[i].get();
//rotate using a matrix
PMatrix3D rMat = new PMatrix3D();
rMat.rotate(angle,axis.x,axis.y,axis.z);
PVector[] dst = new PVector[vl];
for(int i = 0; i<vl;i++) {
dst[i] = new PVector();
rMat.mult(clone[i],dst[i]);
}
return dst;
}
and here is an example using it.
HTH
A shot in the dark: I don't know the rules or the name of the programming language you are using, but this procedure looks suspicious:
void setIdentity() {
this.matrix = identityMatrix;
}
Are you sure your are taking a copy of identityMatrix? If it is just a reference you are copying, then identityMatrix will be modified by later operations, and soon nothing makes sense.
Though the matrix renormalization suggested probably works fine in practice, it is a bit ad-hoc from a mathematical point of view. A better way of doing it is to represent the cumulative rotations using quaternions, which are only converted to a rotation matrix upon application. The quaternions will also drift slowly from orthogonality (though slower), but the important thing is that they have a well-defined renormalization.
Good starting information for implementing this can be:
http://www.cprogramming.com/tutorial/3d/quaternions.html
http://www.scheib.net/school/library/quaternions.pdf
A useful academic reference can be:
K. Shoemake, “Animating rotation with quaternion curves,” ACM
SIGGRAPH Comput. Graph., vol. 19, no. 3, pp. 245–254, 1985. DOI:10.1145/325165.325242

Resources