Sliding on a plane - math

I have a plane (Point, normal) and a circle(point, radius).
The circle moves around and hits the plane.
The position of the circle is reset to the touchPoint with the plane.
So far, so good.
But how can i modify the velocity of the circle, so it only moves
tangential to the plane?
So if it bumbs in the plane, the part of the velocity-vector which is
responsible for bumbing in the plane is consumed.
So, in the next step, it doesnt collide with the plane but can move on.
It "slides" on the plane.
Any ideas?

Since you give no code, I'll just state a few ideas without code.
The plane's definition of (Point, normal) is simpler if the normal vector is a unit vector (of length one). If it isn't, divide that vector by its length and it becomes a unit vector.
If the velocity of the circle is is given by a 3D Cartesian velocity vector, you can find the component of that velocity vector along the plane's unit normal vector by taking the dot product of those two vectors. The result is the directed size of the vector along the normal. You can then remove that component by multiplying the unit normal vector by that dot product, then subtracting that from the circle's velocity vector. The result of that subtraction is the circle's velocity along the plane. That apparently is what you wanted to find.
If you answer my questions in my comment under your question, I could show you some code in my current preferred language, Python 3.

Related

Calculate field of view of simple polygon from a point

Given a non-self-intersecting polygon as a list of points (p1...pn), and a point (A) outside that polygon:
I want to calculate the total angular field of view covered by the polygon from the point, as well as the direction from the point towards the middle of that field of view (as either a vector or angle from horizontal).
Visually, I want the angle Θ and direction of the green vector:
Diagram
I tried finding the minimum and maximum angles from horizontal to each of the polygon points, but I don't know how to tell which is the start of the range and which is the end. Assuming the smaller angle is the start gives incorrect results from the left of a simple box.
I'm guessing the solution will have something to do with whether the polygon points are in clockwise or counterclockwise order.
Whether the polygon goes clockwise or counterclockwise doesn't matter. What matters is that the extent of any edge, as seen from the point, must be less than π radians. That will tell us whether the edge -- as seen from the point -- goes counterclockwise from A to B, or from B to A.
For example, suppose the bearings (in radians) from the point to the vertices are {0, 2π/5, 4π/5, 6π/5, 8π/5}. If the edges are represented by the (unordered) pairs (A,C), (A,E), (B,D), (B,E), (C,D). Then the edges run:
0->4π/5
2π/5->6π/5
4π/5->6π/5
8π/5->0
8π/5->2π/5
So the range of the polygon is [8π/5, 6π/5].

Formula for calculating camera x,y,z position to force 3D point to appear at left side of the screen and rightmost position on the globe

I'd need a formula to calculate 3D position and direction or orientation of a camera in a following situation:
Camera starting position is looking directly into center of the Earth. Green line goes straight up to the sky
Position that camera needs to move to is looking like this
Starting position probably shouldn't matter, but the question is:
How to calculate camera position and direction given 3D coordinates of any point on the globe. In the camera final position, the distance from Earth is always fixed. From desired camera point of view, the chosen point should appear at the rightmost point of a globe.
I think what you want for camera position is a point on the intersection of a plane parallel to the tangent plane at the location, but somewhat further from the Center, and a sphere representing the fixed distance the camera should be from the center. The intersection will be a circle, so there are infinitely many camera positions that work.
Camera direction will be 1/2 determined by the location and 1/2 determined by how much earth you want in the picture.
Suppose (0,0,0) is the center of the earth, Re is the radius of the earth, and (a,b,c) is the location on the earth you want to look at. If it's in terms of latitude and longitude you should convert to Cartesian coordinates which is straightforward. Your camera should be on a plane perpendicular to the vector (a,b,c) and at a height kRe above the earth where k>1 is some number you can adjust. The equation for the plane is then ax+by+cz=d where d = kRe^2. Note that the plane passes through the point (ka,kb,kc) in space, which is what we wanted.
Since you want the camera to be at a certain height above the earth, say h*Re where 1 < k < h, you need to find points on ax+by+cz=d for which x^2+y^2+z^2 = h^2*Re^2. So we need the intersection of the plane and a sphere. It will be easier to manage if we have a coordinate system on the plane, which we get from an orthonormal system which includes (a,b,c). A good candidate for the second vector in the orthonormal system is the projection of the z-axis (polar axis, I assume). Projecting (0,0,1) onto (a,b,c),
proj_(a,b,c)(0,0,1) = (a,b,c).(0,0,1)/|(a,b,c)|^2 (a,b,c)
= c/Re^2 (a,b,c)
Then the "horizontal component" of (0,0,1) is
u = proj_Plane(0,0,1) = (0,0,1) - c/Re^2 (a,b,c)
= (-ac/Re^2,-bc/Re^2,1-c^2/Re^2)
You can normalize the vector to length 1 if you wish but there's no need. However, you do need to calculate and store the square of the length of the vector, namely
|u|^2 = ((ac)^2 + (bc)^2 + (Re^2-c^2))/Re^4
We could complicate this further by taking the cross product of (0,0,1) and the previous vector to get the third vector in the orthonormal system, then obtain a parametric equation for the intersection of the plane and sphere on which the camera lies, but if you just want the simplest answer we won't do that.
Now we need to solve for t such that
|(ka,kb,kc)+t(-ac/Re^2,-bc/Re^2,1-c^2/Re^2)|^2 = h^2 Re^2
|(ka,kb,kc)|^2 + 2t (a,b,c).u + t^2 |u|^2 = h^2 Re^2
Since (a,b,c) and u are perpendicular, the middle term drops out, and you have
t^2 = (h^2 Re^2 - k^2 Re^2)/|u|^2.
Substituting that value of t into
(ka,kb,kc)+t(-ac/Re^2,-bc/Re^2,1-c^2/Re^2)
gives the position of the camera in space.
As for direction, you'll have to experiment with that a bit. Some vector that looks like
(a,b,c) + s(-ac/Re^2,-bc/Re^2,1-c^2/Re^2)
should work. It's hard to say a priori because it depends on the camera magnification, width of the view screen, etc. I'm not sure offhand whether you'll need positive or negative values for s. You may also need to rotate the camera viewport, possibly by 90 degrees, I'm not sure.
If this doesn't work out, it's possible I made an error. Let me know how it works out and I'll check.

In a TBN Matrix are the normal, tangent, and bitangent vectors always perpendicular?

This is related to a problem described in another question (images there):
Opengl shader problems - weird light reflection artifacts
I have a .obj importer that creates a data structure and calculates the tangents and bitangents. Here is the data for the first triangle in my object:
My understanding of tangent space is that the normal points outward from the vertex, the tangent is perpendicular (orthogonal?) to the normal vector and points in the direction of positive S in the texture, and the bitangent is perpendicular to both. I'm not sure what you call it but I thought that these 3 vectors formed what would look like a rotated or transformed x,y,z axis. They wouldn't be 3 randomly oriented vectors, right?
Also my understanding: The normals in a normal map provide a new normal vector. But in tangent space texture maps there is no built in orientation between the rgb encoded normal and the per vertex normal. So you use a TBN matrix to bridge the gap and get them in the same space (or get the lighting in the right space).
But then I saw the object data... My structure has 270 vertices and all of them have a 0 for the Tangent Y. Is that correct for tangent data? Are these tangents in like a vertex normal space or something? Or do they just look completely wrong? Or am I confused about how this works and my data is right?
To get closer to solving my problem in the other question I need to make sure my data is right and my understanding on how tangent space lighting math works.
The tangent and bitangent vectors point in the direction of the S and T components of the texture coordinate (U and V for people not used to OpenGL terms). So the tangent vector points along S and the bitangent points along T.
So yes, these do not have to be orthogonal to either the normal or each other. They follow the direction of the texture mapping. Indeed, that's their purpose: to allow you to transform normals from model space into the texture's space. They define a mapping from model space into the space of the texture.
The tangent and bitangent will only be orthogonal to each other if the S and T components at that vertex are orthogonal. That is, if the texture mapping has no sheering. And while most texture mapping algorithms will try to minimize sheering, they can't eliminate it. So if you want an accurate matrix, you need a non-orthogonal tangent and bitangent.

Intersection between two Arcs? (arc = distance between pair of angles)

I'm trying to find a way to calculate the intersection between two arcs.
I need to use this to determine how much of an Arc is visually on the right half of a circle, and how much on the left.
I though about creating an arc of the right half, and intersect that with the actual arc.
But it takes me wayyy to much time to solve this, so I thought about asking here - someone must have done it before.
Edit:
I'm sorry the previous illustration was provided when my head was too heavy after crunching angles. I'll try to explain again:
In this link you can see that I cut the arc in the middle to two halves, the right part of the Arc contains 135 degrees, and the left part has 90.
This Arc starts at -180 and ends at 45. (or starts at 180 and ends at 405 if normalized).
I have managed to create this code in order to calculate the amount of arc degrees contained in the right part, and in the left part:
f1 = (angle2>270.0f?270.0f:angle2) - (angle1<90.0f?90.0f:angle1);
if (f1 < 0.0f) f1 = 0.0f;
f2 = (angle2>640.0f?640.0f:angle2) - (angle1<450.0f?450.0f:angle1);
if (f2 < 0.0f) f2 = 0.0f;
f3 = (angle2>90.0f?90.0f:angle2) - angle1;
if (f3<0.0f) f3=0.0f;
f4 = (angle2>450.0f?450.0f:angle2) - (angle1<270.0f?270.0f:angle1);
if (f4<0.0f) f4=0.0f;
It works great after normalizing the angles to be non-negative, but starting below 360 of course.
Then f1 + f2 gives me the sum of the left half, and f3 + f4 gives me the sum of the right half.
It also does not consider a case when the arc is defined as more than 360, which may be an "error" case.
BUT, this seems like more of a "workaround", and not a correct mathematical solution.
I'm looking for a more elegant solution, which should be based on "intersection" between two arc (because math has no "sides", its not visual";
Thanks!!
I think this works, but I haven't tested it thoroughly. You have 2 arcs and each arc has a start angle and a stop angle. I'll work this in degrees measured clockwise from north, as you have done, but it will be just as easy to work in radians measured anti-clockwise from east as the mathematicians do.
First 'normalise' your arcs, that is, reduce all the angles in them to lie in [0,360), so take out multiples of 360deg and make all the angles +ve. Make sure that the stop angle of each arc lies to clockwise of the start angle.
Next, choose the start angle of one of your arcs, it doesn't matter which. Sort all the angles you have (4 of them) into numerical order. If any of the angles are numerically smaller than the start angle you have chosen, add 360deg to them.
Re-sort the angles into increasing numerical order. Your chosen start angle will be the first element in the new list. From the start angle you already chose, what is the next angle in the list ?
1) If it is the stop angle of the same arc then either there is no overlap or this arc is entirely contained within the other arc. Make a note and find the next angle. If the next angle is the start angle of the other arc there is no overlap and you can stop; if it is the stop angle of the other arc then the overlap contains the whole of the first arc. Stop
2) If it is the start angle of the other arc, then the overlap begins at that angle. Make a note of this angle. The next angle your sweep encounters has to be a stop angle and the overlap ends there. Stop.
3) If it is the stop angle of the other arc then the overlap comprises the angle between the start angle of the first arc and this angle. Stop.
This isn't particularly elegant and relies on ifs rather more than I generally like but it should work and be relatively easy to translate into your favourite programming language.
And look, no trigonometry at all !
EDIT
Here's a more 'mathematical' approach since you seem to feel the need.
For an angle theta in (-pi,pi] the hyperbolic sine function (often called sinh) maps the angle to an interval on the real line in the interval (approximately) (-11.5,11.5]. Unlike arcsin and arccos the inverse of this function is also single-valued on the same interval. Follow these steps:
1) If an arc includes 0 break it into 2 arcs, (start,0) and (0,stop). You now have 2, 3 or 4 intervals on the real line.
2) Compute the intersection of those intervals and transform back from linear measurement into angular measurement. You now have the intersection of the two arcs.
This test can be resumed with a one-line test. Even if a good answer is already posted, let me present mine.
Let assume that the first arc is A:(a0,a1) and the second arc is B:(b0,b1). I assume that the angle values are unique, i.e. in the range [0°,360°[, [0,2*pi[ or ]-pi,pi] (the range itself is not important, we will see why). I will take the range ]-pi,pi] as the range of all angles.
To explain in details the approach, I first design a test for interval intersection in R. Thus, we have here a1>=a0 and b1>=b0. Following the same notations for real intervals, I compute the following quantity:
S = (b0-a1)*(b1-a0)
If S>0, the two segments are not overlapping, else their intersection is not empty. It is indeed easy to see why this formula works. If S>0, we have two cases:
b0>a1 implies that b1>a0, so there is no intersection: a0=<a1<b0=<b1.
b1<a0 implies that b0<b1, so there is no intersection: b0=<b1<a0=<a1.
So we have a single mathematical expression which performs well in R.
Now I expand it over the circular domain ]-pi,pi]. The hypotheses a0<a1 and b0<b1 are not true anymore: for example, an arc can go from pi/2 to -pi/2, it is the left hemicircle.
So I compute the following quantity:
S = (b0-a1)*(b1-a0)*H(a1-a0)*H(b1-b0)
where H is the step function defined by H(x)=-1 if x<0 else H(x)=1
Again, if S>0, there is no intersection between the arcs A and B. There are 16 cases to explore, and I will not do this here ... but it is easy to make them on a sheet :).
Remark: The value of S is not important, just the signs of the terms. The beauty of this formula is that it is independant from the range you have taken. Also, you can rewrite it as a logical test:
T := (b0>a1)^(b1>a0)^(a1>=a0)^(b1>=b0)
where ^ is logical XOR
EDIT
Alas, there is an obvious failure case in this formula ... So I correct it here. I realize that htere is a case where the intersection of the two arcs can be two arcs, for example when -pi<a0<b1<b0<a1<pi.
The solution to correct this is to introduce a second test: if the sum of the angles is above 2*pi, the arcs intersect for sure.
So the formula turns out to be:
T := (a1+b1-a0-b0+2*pi*((b1<b0)+(a1<a0))<2*pi) | ((b0>a1)^(b1>a0)^(a1>=a0)^(b1>=b0))
Ok, it is way less elegant than the previous one, but it is now correct.

Area of polygon - clockwise

From this threa Determine the centroid of multiple points I came to know that area of polygon can also be negative if we start in clockwise direction. Why it can be negative?
It is a product of the maths. You can use the sign if you wish to, or use an absolute value for the area.
You often get a similar effect with dot products and cross products. This can be effective, for example determining the orientation of a polygon in 3d (does the 'outside' side of the polygon face towards me or away from me?)
The sign tells you some useful information, that you can either use or discard. For example, what is the area below the curve sin(x) and above the x axis, for x over the interval [0,pi]. Yes, this is simply a definite integral. In MATLAB, I'd do it as:
>> quad(#sin,0,pi)
ans =
2
But suppose I computed that same definite integral, with limits of integration [pi,0]? Clearly, we would get -2.
>> quad(#sin,pi,0)
ans =
-2
And of course this makes sense. In either case, we can assure that we get the positive area by ignoring the sign. But the sign tells us something in that integral.
The sign computed for the area of a polygon is indeed useful in some problems. In the case of a triangle, a cross product will yield a vector that points in the direction orthogonal to the plane of the triangle containing the vectors. The magnitude of the vector will be twice the area of that triangle. Note that this vector can point in one of two directions orthogonal to a given plane, which one is indicated by the right hand rule. You can think of that sign as indicating which direction the vector pointed.

Resources