Good whatever time of day! I have some sprite:
A point has coordinates Actor.x; Actor.y.
AB length = 96
BC length = 86
AC length = 42
All calculations are approximate, I made it with help the ruler in Photoshop.
Sprite always towards mouse, angle (in radians) stores in Actor.direction variable. I draw sprite with scale 0.3.
All bullets toward mouse (that is Bullet.direction == Actor.direction). I need to create bullets in the B point. How I can calculate coordinates of the B point with any angle?
UPD
If I will create bullets in the coordinates:
x = Actor.x + 96 * math.cos(Actor.direction) * 0.3
y = Actor.y + 96 * math.sin(Actor.direction) * 0.3
I get it:
Excuse my bad English! It isn't my native language. Thank you in advance!
Let
cs = math.cos(Actor.direction)
sn = math.sin(Actor.direction)
point B will be shifted from A by
dx = - 42 * sn + 86 * cs
dy = 42 * cs + 86 * sn
Perhaps you will need to change signs before both 42s
(I did not account for scale)
Related
I am working on a drawing application. I summerize the main question to a tiny scenario:
User draws the line A1-B1 and also the point M1. Now user moves the line A1-B1 to a new position A2-B2 while the point M1 also should move with the line (like a rigid body). How can I calculate the new position of point M2?
I know it is possbile with complex calucations on lines or circles conjuction and finally detemrining if the new point is on the right or left of line (this question) etc. But as I want to recalculate live on any steps of dragging, I guess there should be a shortcut and light solution which all modeling softwares use. Is there really a shortcut formula rahter than the line or circle conjuctions?
To summerize the problem again I am looking for a light function with given A1,B1,A2,B2,M1 and looking for M2 position (two separate formula for x and y)
M2 = f(A1,B1,A2,B2,M1)
My guess: I think finding the center and the angle of rotation is one of the best options but I don't know again if there is a shotcut function to find them.
Edit: I prefer to implement it in an online website, so if there is a ready javascript library, it would be helpful, However I am now just looking for the mathematical logic.
Start with A1 and B1.
D = B1 - A1
C1 = D/|D|
Rotate C1 90 degrees counter-clockwise to get C'1:
C1 = (cx, cy)
C'1 = (-cy, cx)
Now take M1 - A1 and measure it against C1 and C'1:
j = (M1 - A) · C1
k = (M1 - A) · C'1
Now it's easy to prove:
M1 = A1 + j C1 + k C'1
So j and k tell you where M1 is, given A1 and B1.
When you get A2 and B2, use them to construct C2, rotate it to get C'2, and then you'll have:
M2 = A2 + j C2 + k C'2
I'm assuming points are objects which have x and y values. Like this:
A1 = {x: 100, y:100}
Here's a lightweight solution:
function reposition(A1,A2,B1,B2,M1)
{
//Getting the Angle Between Lines
var angle = Math.atan2(B2.y-B1.y, B2.x-B1.x)-Math.atan2(A2.y-A1.y, A2.x-A1.x);
//Rotating the point
var xdif = M1.x-A1.x; //point.x-origin.x
var ydif = M1.y-A1.y; //point.y-origin.y
//Returning M2
return {x:B1.x + Math.cos(angle) * xdif - Math.sin(angle) * ydif, y: B1.y + Math.sin(angle) * xdif + Math.cos(angle) * ydif}
}
I know to to do collision time with the ground.
Here's how I calculate that: gravityY = positive 9.81
float timeToGround = (velocity.y + Sqrt(velocity.y*velocity.y + 2f * gravityY * distanceToGround)) / gravityY;
How do I calculate the collision time to the roof/ceiling based on distance and initial velocity?
float timeToRoof = ?
I don't know where to look, thanks so much for your help
You need to solve quadratic equation for unknown time t
h = y0 + Vy * t - g*t^2 / 2
or
g*t^2/2 - Vy*t + (h-y0) = 0 // a,b,c coefficient grouped
for known height of starting point y0, roof height h, gravity g, y-component of initial velocity Vy
Hehe, thanks for your help.
Here's the answer:
float timeToRoof = (-velocity.y + Sqrt(velocity.y * velocity.y + 2f * gravity.y * distanceToRoof)) / gravity.y;
gravity.y = negative -9.81
velocity.y = current velocity
distanceToRoof = current distance to roof
I've created a mesh cone:
With points that are oriented as such:
p3
/
/
p1 ---- p2
I've calculate u = p2 - p1, v = p3 - p1
and then take the cross product u X v and normalize the vector before taking its perspective projection. But no matter which way I calculate u and v (e.g. u = p2 - p1, v = p3 - p2) my normals always face towards the inside of the cone.
I've looked at many other examples on here but none of them seems to work.
Any suggestions?
Edit - This is what I'm getting:
I've run the numbers through a vector calculator and all the calculations are correct.
One of the planes:
P1x: 0.866025
P1y: -0.500000
P1z: 9.000000
P2x: 0.939693
P2y: -0.342020
P2z: 9.000000
P3x: 0.000000
P3y: -0.000000
P3z: 10.000000
Vector U: 0.073667, 0.157980, 0.000000
Vector V: -0.866025, 0.500000, 1.000000
Normal: 0.157980, -0.073667, 0.173648
My code for calculating u, v, and n is:
//u = p2 - p1
vecU.m[1][1] = p2.m[1][1] - p1.m[1][1];
vecU.m[2][1] = p2.m[2][1] - p1.m[2][1];
vecU.m[3][1] = p1.m[3][1] - p1.m[3][1];
vecU.m[4][1] = 1;
printf("Vector U: %f, %f, %f\n", vecU.m[1][1], vecU.m[2][1], vecU.m[3][1]);
//v = p3 - p1
vecV.m[1][1] = p3.m[1][1] - p1.m[1][1];
vecV.m[2][1] = p3.m[2][1] - p1.m[2][1];
vecV.m[3][1] = p3.m[3][1] - p1.m[3][1];
vecV.m[4][1] = 1;
printf("Vector V: %f, %f, %f\n", vecV.m[1][1], vecV.m[2][1], vecV.m[3][1]);
//n = u X v
vecN.m[1][1] = (vecU.m[2][1] * vecV.m[3][1]) - (vecU.m[3][1] * vecV.m[2][1]);
vecN.m[2][1] = (vecU.m[3][1] * vecV.m[1][1]) - (vecU.m[1][1] * vecV.m[3][1]);
vecN.m[3][1] = (vecU.m[1][1] * vecV.m[2][1]) - (vecU.m[2][1] * vecV.m[1][1]);
vecN.m[4][1] = 1;
The easy answer ist switching u and v in the cross product, but I guess your question is rather something like "how do I determine if i just calculated the normal in the correct direction"? That should be determined by saving vertices counter-clockwise.
After seeing your edit:
I can't see an error in your calculations, but your drawing does not look like normals at all. It's not just about the sign of the normal, but you seem to just always point to the center of the ground surface of your cone.
I can't really say any more without seeing the actual code. Do all of your 'normals' in fact point to a single point?
I will try to be very descriptive with this. I'm editing a game right now and the scenario is a 3D area.
I have an initial angle, writen as a direction vector, and another vector which haves different coordinates. As we know, the angle between 2 vectors is given by the formula: Theta = ACos( DotProduct( vec1, vec2 ) / ( VectorLength( vec1 ) * VectorLength( vec2 ) ) )
So let's describe the scenario: I'm currently programming some kind of stationary weapon, a sentry gun, this thing moves slowly his "head", shooting bullets to enemies. That angle rotation thing is my problem.
Let's imagine this: I have my sentry gun on a empty 3D area, and a "enemy" spawns over there. I can currently get the direction vector of my sentry's view angle, and the direction vector between my sentry and the player. Let's guess, using the formula described, his separation angle is 45 degrees. My sentry gun thinks (calls a function) at every 0.1 seconds, and I want to move his head 5 degrees at every thinking function until it reach the the player (ie, both vectors are nearly equal), and that means it will reach the player (if player keeps on its position...) in 0.9 seconds (5 degrees from 45)
How I can move sentry's view angle slowly until it reach a target? In 2D is easily but know I'm fighting with a 3D scenario, and I'm currently lost with this.
Any help would be appreciated, and about coding, I will be grateful with a pseudocode. Thanks! (and sorry for my english)
What you need is called SLERP - spherical linear interpolation
Your starting direction vector is p0 there, goal direction is p1, Omega is your Theta, and t parameter varies in range 0..1 with needed step
Delphi example for 2D case (it is easy to control)
var
p0, p1: TPoint;
i, xx, yy: Integer;
omega, InvSinOmega, t, a0, a1: Double;
begin
P0 := Point(0, 200);
P1 := Point(200, 0);
omega := -Pi / 2;
InvSinOmega := 1.0 / Sin(omega);
Canvas.Brush.Color := clRed;
Canvas.Ellipse(120 + P0.X, 120 + P0.Y, 120 + P0.X + 7, 120 + P0.Y + 7);
Canvas.Ellipse(120 + P1.X, 120 + P1.Y, 120 + P1.X + 7, 120 + P1.Y + 7);
for i := 1 to 9 do begin
t := i / 10;
a0 := sin((1 - t) * omega) * InvSinOmega;
a1 := sin(t * omega) * InvSinOmega;
xx := Round(P0.X * a0 + P1.X * a1);
yy := Round(P0.Y * a0 + P1.Y * a1);
Canvas.Brush.Color := RGB(25 * i, 25 * i, 25 * i);
Canvas.Ellipse(120 + xx, 120 + yy, 120 + xx + 9, 120 + yy + 9);
end;
I am doing some multi-touch support that allow 2 fingers to rotate a photos. There are four points: 2 for previous fingers and 2 for current finger positions.
I calculated a new point by subtract the 2 previous fingers, and the second new point was calculate by subtracting the other 2 current finger.
Then, I calculate the angle like this:
radian1 = atan ( p1.y / p1.x );
radian2 = atan ( p2.y / p2.x );
I subtract radian2 and radian1 to get the final angle.
The problem is I can rotate the image beautifully but sometime if I rotate to certain position the photo got flipped e.g. a photo supposed in 270 but it flipped and appeared in 90 degree.
This is the javascript I have written according to the reply below:
var x1 = this.previousMousePoint.x * this.previousMousePoint2.x + this.previousMousePoint.y * this.previousMousePoint2.y;
var y1 = this.previousMousePoint.x * this.previousMousePoint2.y - this.previousMousePoint.y * this.previousMousePoint2.x;
var x2 = center.x * point.x + center.y * point.y;
var y2 = center.x * point.y - center.y * point.x;
var radian1 = Math.atan(y1 / x1);
var radian2 = Math.atan(y2 / x2);
this.anchor.matrix = this.anchor.matrix.rotate(radian2-radian1, pivot);
Is looking ok. but it's kind of slow when i try to rotate an image
The clean way to do this is use angle-subtraction formulas to get values proportional to the sine and cosine of the difference angle, and use atan() only once:
relevant formulas:
cos(a2 - a1) = cos(a1)*cos(a2) + sin(a1)*sin(a2)
sin(a2 - a1) = cos(a1)*sin(a2) - sin(a1)*cos(a2)
p1.x = cos(a1) * len(p1)
p1.y = sin(a1) * len(p1)
p2.x = cos(a2) * len(p2)
p2.y = sin(a2) * len(p2)
-> angle-subtraction: compute values proportional to sin and cos of (a2 - a1)
c12 = p1.x*p2.x + p1.y*p2.y [ = len(p1)*len(p2) * cos(a2 - a1) ]
s12 = p1.x*p2.y - p1.y*p2.x [ = len(p1)*len(p2) * sin(a2 - a1) ]
-> final result: find resulting difference angle a12 [ = a2 - a1 ]
a12 = atan(s12 / c12)
or (if you want a full 360-degree range):
a12 = atan2(s12, c12)
Also, if you want to rotate an image with the result, you may not need to convert (c12,s12) to an angle, anyway: ultimately, your image rotator will use a matrix with the sines and cosines of the resulting rotation angle. By normalizing (c12,s12), you will end up with (cos(a12), sin(a12)), which you may be able to use more directly.
Arc tan maps between 0 and pi. 270 corresponds to 3/2 * pi and will fold over to pi. May I suggest that you incrementally find the angle using the positions of the fingers instead of just starting and the ending positions.
Even if you decide not to actually rotate the figure (to reduce computation), you can still display a tilted line / box / number to indicate the tilt that the software has registered.