Ball collision time with ceiling - math

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

Related

Point positioning inside rectangle with only two known vertexes

I'm working on a js widget, and I've come across a positioning problem, which I can't seem to solve with my limited geometry knowledge or by help of Wikipedia/google.
I have a quadrilateral rectangle, which is positioned at an angle. I know its two opposite vertexes and width/height ratio. And there's a point on it, which coordinates I also know.
I need to find how far (in %s of width/height) is that point from rectangle's sides. Is it possible to do so?
Having two corners P1 = (x1,y1) and P2 = (x2,y2) and point Q, you can find diagonal length
dx = (x2 - x1)
dy = (y2 - y1)
dlen = sqrt(dx^2 + dy^2)
and unit direction vector
dx = dx / dlen
dy = dy / dlen
and center of rectangle
cx = x1 + dx/2
cy = y1 + dy/2
Width and height (with known r = w/h ratio)
w = dlen / sqrt(1 + r^2)
h = w / r
Now we need direction of side of length w. Note that given information does not allow to choose exact rectangle orientation from two possible cases.
Angle between diagonal and side
sina = r / sqrt(1 + r^2)
cosa = 1 / sqrt(1 + r^2)
Side direction vector
wx = dx * cosa - dy * sina
wy = dx * sina + dy * cosa
and for the second orientation
wx' = dx * cosa + dy * sina
wy' = -dx * sina + dy * cosa
The second side vector
hx = -wy
hy = wx
Now we can find length of projection of point p onto sides W and H using dot product
qx = q.x - x1
qy = q.y - y1
qw = qx * wx + qy * wy
qh = qx * hx + qy * hy
The last values are coordinates in W-H basis, so value qw varies from 0 for points at the "left" to w for points at the "right" side. You can divide these values by w and h to get percent values.
Note again - there are two possible rectangles and correspondingly two positions of point Q

Moving slowly an initial angle until it reach a final angle

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;

How to find the angle between 2 pairs of points?

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.

Computing the 3D coordinates on a unit sphere from a 2D point

I have a square bitmap of a circle and I want to compute the normals of all the pixels in that circle as if it were a sphere of radius 1:
The sphere/circle is centered in the bitmap.
What is the equation for this?
Don't know much about how people program 3D stuff, so I'll just give the pure math and hope it's useful.
Sphere of radius 1, centered on origin, is the set of points satisfying:
x2 + y2 + z2 = 1
We want the 3D coordinates of a point on the sphere where x and y are known. So, just solve for z:
z = ±sqrt(1 - x2 - y2).
Now, let us consider a unit vector pointing outward from the sphere. It's a unit sphere, so we can just use the vector from the origin to (x, y, z), which is, of course, <x, y, z>.
Now we want the equation of a plane tangent to the sphere at (x, y, z), but this will be using its own x, y, and z variables, so instead I'll make it tangent to the sphere at (x0, y0, z0). This is simply:
x0x + y0y + z0z = 1
Hope this helps.
(OP):
you mean something like:
const int R = 31, SZ = power_of_two(R*2);
std::vector<vec4_t> p;
for(int y=0; y<SZ; y++) {
for(int x=0; x<SZ; x++) {
const float rx = (float)(x-R)/R, ry = (float)(y-R)/R;
if(rx*rx+ry*ry > 1) { // outside sphere
p.push_back(vec4_t(0,0,0,0));
} else {
vec3_t normal(rx,sqrt(1.-rx*rx-ry*ry),ry);
p.push_back(vec4_t(normal,1));
}
}
}
It does make a nice spherical shading-like shading if I treat the normals as colours and blit it; is it right?
(TZ)
Sorry, I'm not familiar with those aspects of C++. Haven't used the language very much, nor recently.
This formula is often used for "fake-envmapping" effect.
double x = 2.0 * pixel_x / bitmap_size - 1.0;
double y = 2.0 * pixel_y / bitmap_size - 1.0;
double r2 = x*x + y*y;
if (r2 < 1)
{
// Inside the circle
double z = sqrt(1 - r2);
.. here the normal is (x, y, z) ...
}
Obviously you're limited to assuming all the points are on one half of the sphere or similar, because of the missing dimension. Past that, it's pretty simple.
The middle of the circle has a normal facing precisely in or out, perpendicular to the plane the circle is drawn on.
Each point on the edge of the circle is facing away from the middle, and thus you can calculate the normal for that.
For any point between the middle and the edge, you use the distance from the middle, and some simple trig (which eludes me at the moment). A lerp is roughly accurate at some points, but not quite what you need, since it's a curve. Simple curve though, and you know the beginning and end values, so figuring them out should only take a simple equation.
I think I get what you're trying to do: generate a grid of depth data for an image. Sort of like ray-tracing a sphere.
In that case, you want a Ray-Sphere Intersection test:
http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter1.htm
Your rays will be simple perpendicular rays, based off your U/V coordinates (times two, since your sphere has a diameter of 2). This will give you the front-facing points on the sphere.
From there, calculate normals as below (point - origin, the radius is already 1 unit).
Ripped off from the link above:
You have to combine two equations:
Ray: R(t) = R0 + t * Rd , t > 0 with R0 = [X0, Y0, Z0] and Rd = [Xd, Yd, Zd]
Sphere: S = the set of points[xs, ys, zs], where (xs - xc)2 + (ys - yc)2 + (zs - zc)2 = Sr2
To do this, calculate your ray (x * pixel / width, y * pixel / width, z: 1), then:
A = Xd^2 + Yd^2 + Zd^2
B = 2 * (Xd * (X0 - Xc) + Yd * (Y0 - Yc) + Zd * (Z0 - Zc))
C = (X0 - Xc)^2 + (Y0 - Yc)^2 + (Z0 - Zc)^2 - Sr^2
Plug into quadratic equation:
t0, t1 = (- B + (B^2 - 4*C)^1/2) / 2
Check discriminant (B^2 - 4*C), and if real root, the intersection is:
Ri = [xi, yi, zi] = [x0 + xd * ti , y0 + yd * ti, z0 + zd * ti]
And the surface normal is:
SN = [(xi - xc)/Sr, (yi - yc)/Sr, (zi - zc)/Sr]
Boiling it all down:
So, since we're talking unit values, and rays that point straight at Z (no x or y component), we can boil down these equations greatly:
Ray:
X0 = 2 * pixelX / width
Y0 = 2 * pixelY / height
Z0 = 0
Xd = 0
Yd = 0
Zd = 1
Sphere:
Xc = 1
Yc = 1
Zc = 1
Factors:
A = 1 (unit ray)
B
= 2 * (0 + 0 + (0 - 1))
= -2 (no x/y component)
C
= (X0 - 1) ^ 2 + (Y0 - 1) ^ 2 + (0 - 1) ^ 2 - 1
= (X0 - 1) ^ 2 + (Y0 - 1) ^ 2
Discriminant
= (-2) ^ 2 - 4 * 1 * C
= 4 - 4 * C
From here:
If discriminant < 0:
Z = ?, Normal = ?
Else:
t = (2 + (discriminant) ^ 1 / 2) / 2
If t < 0 (hopefully never or always the case)
t = -t
Then:
Z: t
Nx: Xi - 1
Ny: Yi - 1
Nz: t - 1
Boiled farther still:
Intuitively it looks like C (X^2 + Y^2) and the square-root are the most prominent figures here. If I had a better recollection of my math (in particular, transformations on exponents of sums), then I'd bet I could derive this down to what Tom Zych gave you. Since I can't, I'll just leave it as above.

Intersection on circle of vector originating inside circle

I have a circle. Inside the circle is a point. I have a vector originating at this point. I'd like to know what point on the circle this vector intersects. Here is a drawing:
http://n4te.com/temp/circle.png http://n4te.com/temp/circle.png
The red dot is the point I am trying to determine.
I know these things: the center of the circle, the origin of the vector, and the direction of the vector.
I know this is basic stuff, but I'm still having trouble. Most of the Googlings bring me to line-circle collision, which is related but not quite the same. Thanks for any help you can provide!
Elementary vector algebra.
O — center of circle (vector)
r — its radius (scalar)
A — origin of ray (vector)
k — direction of ray (vector)
Solve (A + kt - O)² = r² for scalar t, choose positive root, and A + kt is your point.
Further explanation:
. is dot product, ² for a vector is dot product of the vector with itself. Expand LHS
(A + kt - O)² = (A - O)² + 2(k.(A - O))t + k²t².
The quadratic is k²t² + 2(k.(A - O))t + (A - O)² - r² = 0. In terms of your variables, this becomes (rayVX² + rayVY²)t² + 2(rayVX(rayX - circleX) + rayVY(rayY - circleY))t + (rayX - circleX)² + (rayY - circleY)² - r² = 0.
Much thanks to Anton Tykhyy for his detailed answer. This was the resulting Java code:
float xDiff = rayX - circleX;
float yDiff = rayY - circleY;
float a = rayVX * rayVX + rayVY * rayVY;
float b = 2 * (rayVX * (rayX - circleX) + rayVY * (rayY - circleY));
float c = xDiff * xDiff + yDiff * yDiff - r * r;
float disc = b * b - 4 * a * c;
if (disc >= 0) {
float t = (-b + (float)Math.sqrt(disc)) / (2 * a);
float x = rayX + rayVX * t;
float y = rayY + rayVY * t;
// Do something with point.
}

Resources