3d rotation about arbitrary axis from 3D math primer for graphics - math

The steps are for rotating the vetor v around the vector n by an angle theta so that v lands at v', can someone please elaborate how he got the perpendicular component for v', thank you

If we were doing a rotation in 2d you have a rotation matrix
R = ( cos theta -sin theta )
( sin theta cos theta )
And the rotation of a vector v is R v. Using i, j for our two basis vectors the result of rotating x i + y j is
(x cos theta - y sin theta) i + (x sin theta + y sin theta) j
in particular the rotation of a vector along the i axis x i is
(x cos theta) i + (x sin theta) j
Now in the 3D case you can consider this as basically a rotation in the plane spanned by v_perp and w. Let i be a unit length vector in the v_perp direction and j be a unit length vector in the w direction. Let x be the length of v_perp, so v_perp = x i. The rotation of this is
(x cos theta) i + (x sin theta) j
= cos theta v_perp + sin theta w
As w has been set to be a vector of length x. This is the formula given.

Related

Upwards tangent vector of triangle in 3D space

I have a triangle in 3D cartesian space, it forms a surface. I have a normal vector of that surface. What I want to find out, is a vector tangent to that surface, which points the most "upwards". (The orange one on image, forgive my paint skills)
Let one triangle edge vector is A. Get perpendicular vector in the plane
P = N x A
and normalize P and A
p = P / len(P)
a = A / len(A)
Any unit vector in the plane is combination of these base vectors
v = p * cos(t) + a * sin(t) (1)
We want that Z-component of v to be maximal (as far as I understand most "upwards")
vz = pz * cos(t) + az * sin(t) (2)
has extremum when it's derivative by t is zero
0 = (pz * cos(t) + az * sin(t))' = -pz * sin(t) + az * cos(t)
tan(t) = az / pz
t = atan2(az , pz)
put t values into (1) and get needed vector v

Eric Lengyel, Mathematics, Plucker Coordinates Exercise

At the chapter 3 of "Eric Lengyel, Foundations Of Game Engine Development, Volume 1: Mathematics" i can not understand, how to solve exercise 10 ( on the "3.5 Plucker Coordinates" theme).
"Let {v|m1} and {v|m2} be parallel lines having the same direction but different moments. Find a formula for the distance d between theese two lines by considering the triangle formed by the origin and the closest point to the origin on each line"
It seemed simple to me at first, but after many attempts I can't figure out where to start. I've tried different ways, but couldn't get the right answer:
d = (| (v x (m2 - m1) |) / (sqr(v))
maybe someone know, what's the problem.
Thanks!
Table in that chapter (line G) shows "homogeneous point closest to the origin" as
p = (v x m) / v^2
Difference between such points for two lines with m1 and m2 moments is vector
diff = p1-p2 = (v x m1) / v^2 - (v x m2) / v^2 = (v x (m1-m2)) / v^2
Length of this vector is needed distance, because Op1 and Op2 vectors are perpendicular to direction v, points O, p1 and p2 belongs to a plane, perpendicular to lines, and diff=p1-p2 belonging that plane is perpendicular to the lines too, hence it's length is the distance between lines.
P.S. Op1p2 is triangle mentioned in the problem statement
P.P.S
Point p lies on Pluecker line if
p x v = m
multiply both parts by v
v x (p x v) = v x m
transform the left part by Lagrange identity
p * (v.dot.v) - v * (p.dot.v) = p * v^2
(because (p.dot.v)== 0 for perpendicular to the line)
p * v^2 = v x m
p = (v x m) / v^2

Cone from direction vector

I have a normalized direction vector (from a 3d position to a light position) and I would like this vector to be rotated by some angle so I can create a "cone".
Id like to simulate cone tracing by using the direction vector as the center of the cone and create an X number of samples to create more rays to sample from.
What I would like to know is basically the math behind:
https://docs.unrealengine.com/latest/INT/BlueprintAPI/Math/Random/RandomUnitVectorinCone/index.html
Which seems to do exactly what Im looking for.
1) Make arbitrary vector P, perpendicular to your direction vector D.
You can choose component with max magnitude, exchange it with middle-magnitude component, negate it, and make min magnitude component zero.
For example, if z- component is maximal and y-component is minimal, you may make such P:
D = (dx, dy, dz)
p = (-dz, 0, dx)
P = Normalize(p) //unit vector
2) Make vector Q perpendicular both D and P through vector product:
Q = D x P //unit vector
3) Generate random point in the PQ plane disk
RMax = Tan(Phi) //where Phi is cone angle
Theta = Random(0..2*Pi)
r = RMax * Sqrt(Random(0..1))
V = r * (P * Cos(Theta) + Q * Sin(Theta))
4) Normalize vector V
Note that distribution of vectors is slightly non-uniform on the sphere segment.(it is uniform on the plane disk). There are methods to generate uniform distribution on the sphere but some work needed to apply them to segment (my first attempt before edit was wrong).
Edit: Modification to make sphere-uniform distribution (not checked thoroughly)
RMax = Tan(Phi) //where Phi is cone angle
Theta = Random(0..2*Pi)
u = Random(Cos(Phi)..1)
r = RMax * Sqrt(1 - u^2)
V = r * (P * Cos(Theta) + Q * Sin(Theta))

Converting 2D projection rotation angles to 3D object

I am projecting a 3D matrix of density values into 3 2D planes (ZX,ZY,XY). I then rotate each projection by 3 different angles: Pzx, Pzy, Pxy using the rotation matrix below:
How do I convert these 3 separate angles so that I can apply them to a 3D transformation matrix which will rotate the 3D object about X,Y,Z (or Z,Y,X) such as the rotation matrix below:
To be clear, I do not wish to apply angles Pzx, Pzy, Pxy to the 3D object, but instead calculate what those individual rotations in 2D would translate to in 3D.
This problem yields a system of equations. Let R_3d be the rotation in 3d space, R_xy the rotation in the xy plane, and [*]_xy be the projection of * onto the xy plane. Then for any point v:
I: [R_3d v]_zx = R_zx [v]_zx
II: [R_3d v]_zy = R_zy [v]_zy
III: [R_3d v]_xy = R_xy [v]_xy
We see that every coordinate is present in two equations. Let's check the relevant equations for the x-coordinate:
a := alpha, b := beta, c := gamma
I: cos b cos c x - cos b sin c y + sin b z = sin Pzx z + cos Pzx x
III: cos b cos c x - cos b sin c y + sin b z = cos Pxy x - sin Pxy y
We see that the following relation mus hold for any v (right hand side of both equations):
sin Pzx z + cos Pzx x = cos Pxy x - sin Pxy y
Similar equations exist for the other two coordinates. Only if these conditions are met, an exact 3d rotation can exist. If I'm not mistaken, that's only the case if Pzx=Pzy=Pxy=0. In general, an approximate solution can be calculated. I would suggest a least-squares solution based on the following energy:
E(a, b, c) = Sum { for all v in data set } ( || [R_3d v]_zx - R_zx [v]_zx ||^2
+ || [R_3d v]_zy - R_zy [v]_zy ||^2
+ || [R_3d v]_xy - R_xy [v]_xy ||^2 )
And the optimal rotation parameters are:
{a, b, c}* = arg min {a, b, c} E(a,b,c)
This solution will minimize the distance of the two projections of corresponding points.
Unfortunately, the problem is not a linear least-squares problem which would be easy to solve. Instead, iterative methods can solve this problem (e.g. Levenberg–Marquardt). Look for an implementation of that algorithm in your programming language, plug in the energy and solve for the optimal rotation parameters.

Finding a line making an angle θ with a known line

I have a line from (a, b) to (x, y), and I would like to draw a line starting at (x, y), with length ℓ, that makes an angle of θ with the original line.
How do I compute the coordinates of the endpoint of this new line? See the diagram:
It's nearly always simpler to use vector algebra for this kind of thing, rather than Cartesian coordinates. Let's start by labelling the points:
Let R(θ) be the matrix that rotates by θ radians counter-clockwise:
Then compute:
v = B − A (the vector from A to B)
v̂ = v / |v| (the unit vector in the direction of v)
ŵ = R(−θ) v̂ (the unit vector in the direction of BC; your rotation is clockwise, so we need R(−θ) here, not R(θ))
w = ℓ ŵ (the vector of length ℓ in the direction of BC)
C = B + w
This approach avoids the need to compute an arctangent, which would need some care (if done naïvely, it runs into trouble when B is vertically above or below A; but most languages have a function like atan2 for handling this case).
In any sensible programming language with a vector library you should be able to write this as a one-liner, perhaps like this:
C = B + (B - A).unit().rotate(-theta) * l
OK, so after a lot of scribbling, I came up with this:
The dashed lines represent lines parallel to the x- and y-axes.
m = x − a
n = y − b
α = tan−1 (n / m)
β = α − θ
p = ℓ cos β
q = ℓ sin β
c = x + p
d = y + q

Resources