So I want to compute the volume of spheres (unit balls), cuboids (cubes) that are transformed using arbitrary transformation matrices.
e.g.: I got my Sphere with a radius of 1 in the center of my 3D-Space. Then i got a Transformation to apply to that Sphere. What would the volume (resp. radius) be after that? How can i extract that information from the Transformation Matrix? I know that translation and rotation matrices wont affect that, but scaling matrices will.
Thanks in Advance!
The transformation's determinant specifies how the volume of any object changes. If the determinant is 1, the volume is preserved. If it is negative, there is a mirroring included which results in a reversed face order.
Only use the linear part of the matrix to calculate the determinant (disregarding translations and perspective transformations).
Another measure that you might be interested in are the matrice's eigen values and eigen vectors (or singular values). They specify the orientation of the ellipsoid that a matrix transforms a unit sphere into.
If the transformation is a rigid motion, then the mass is unaffected by the transform. If the transform is the composition of a rigid motion and a uniform scaling, then the volume is multiplied by the cube of the scale factor.
That is, if S is a homogeneous scaling transform in the form:
[ s 0 0 0 ]
[ 0 s 0 0 ]
S = [ 0 0 s 0 ]
[ 0 0 0 1 ]
and R is a rigid homogeneous transform, then the mass m of a body transformed by S.R or R.S is m*s^3.
Other than these two special cases (rigid motion and uniform scaled motion), and ignoring trivial cases such as the case where the transform maps all points to a plane, there is no simple formula for the transformed volumes.
OpenGL transform matrix is stored like this:
double m[16]; // it is 4x4 matrix stored as 1 dimensional array for speed
m[0]=xx; m[4]=yx; m[ 8]=zx; m[12]=x0;
m[1]=xy; m[5]=yy; m[ 9]=zy; m[13]=y0;
m[2]=xz; m[6]=yz; m[10]=zz; m[14]=z0;
m[3]= 0; m[7]= 0; m[11]= 0; m[15]= 1;
where:
X(xx,xy,xz) is unit vector of X axis in GCS (global coordinate system)
Y(yx,yy,yz) is unit vector of Y axis in GCS
Z(zx,zy,zz) is unit vector of Z axis in GCS
P(x0,y0,z0) is origin of represented coordinate system in GCS
when orthogonal transforms are applied (rotation,translation,scale...)
then shape is 'preserved'
cube became cuboid and sphere became ellipsoid
then the size of axises vector is the scale in that axis
so if Volume of object before transformation is V0
then Volume after transform is:
V1=V0*|X|*|Y|*|Z|
when non orthogonal transforms are applied (skew,projections,...)
skew is one of the non-orthogonal but linear transforms
Volume can be computed as for orthogonal transforms
but the shape will be broken.
because non orthogonal transforms change
not only size but the shape itself !!!
non-linear transforms like projections always broke the Volume nonlinearly
in this case you have to compute the Volume the hard way
transform object surface and compute the Volume via integration ...
How to determine orthogonality of transform?
easy transforms are orthogonal if X,Y,Z vectors are perpendicular
to each other then transform is linear so:
XY = X x Y; XY /= |XY|; Z0=Z/|Z|;
XZ = X x Z; XZ /= |XZ|; Y0=Y/|Y|;
YZ = Y x Z; YZ /= |YZ|; X0=X/|X|;
if ((XY!=Z0)&&(XY!=-Z0)) non linear;
if ((XZ!=Y0)&&(XZ!=-Y0)) non linear;
if ((YZ!=X0)&&(YZ!=-X0)) non linear;
do not forget to do the comparisons with some accuracy
to avoid FP problems
How to detect non linearity of transform?
create a set of points evenly placed inside some cube (same distance between them)
transform them
now if the point distances are not the same along new axises
but change with distance from origin then transform is non-linear
Related
I'm trying to apply friction to a 3D collision. The information I have is:
The velocity of the collision
The surface normal of the collider
An arbitrary friction coefficient (0 - 1 inclusive)
What I would like to do is multiply the portion of the velocity that is parallel to the plane by the friction coefficient, while leaving the portion parallel to the normal intact.
How can I go about performing this operation?
I was thinking perhaps this will involve the use of the dot-product, but then I started reading about matrices, then vector projection, and now I'm pretty lost.
I was able to solve the problem by doing the following:
Get a tangent vector for the normal
Use the normal and the tangent vector to get a rotation matrix for the surface
Use the inverse of the rotation matrix to transform the velocity vector
Scale the x and z components of the transformed vector by the friction coefficient
Use the rotation matrix to transform the velocity back again
I doubt this is the most efficient way of doing it, but it seems to have worked.
If you can do vector addition, scalar multiplication (i.e. multiplying a vector by a number) and the dot product, then this is all you need:
Vin = (V•Vnormal)Vnormal
Vpar = V - Vin
Vpar = kVpar (where k is the coefficient, and "=" means assignment)
Vin = -Vin
V = Vin + Vpar
The problem I need to solve is to rotate a 4-simplex given in 4D on the hyperplane with normal vector (1, 1, 1, 1) so that I can draw it in 3D. For instance I need to know the rotation for the regular one having vertices e_i (that is the coordinate vectors), and all its sub-simplices after division.
In order to understand the problem, let's go one dimension back. If you have a 3-simplex in 3D on the hyperplane with normal vector (1, 1, 1) like here (http://upload.wikimedia.org/wikipedia/commons/thumb/3/38/2D-simplex.svg/150px-2D-simplex.svg.png), one can follow the idea of Nosredna to the question
Rotate normal vector onto axis plane
It works fine in 3D, but in 4D there is no cross products, so I cannot extend this answer to my question. On the other hand using rotation matrices I managed to rotate the simplex around the x axes by -45 degree, then rotating around the y axes by around 35 degree (atan(sqrt(2)/2) using the coordinate rotation matrices (http:// upload.wikimedia.org/math/2/8/5/2851c9dc2031127e6dacfb84b96446d8.png).
I also tried to calculate a rotation matrix from axes rotations like in http://ken-soft.com/2009/01/08/graph4d-rotation4d-project-to-2d/ but I could not find out what should be the angles to use. So I used R=rotXU*rotYU*rotZU with the angles pi/4, -atan(sqrt(2)/2, and -pi/6, which looked good, but somehow the result wasn't ok.
Sorry, I could not put the images directly as I'm a newbie...
Thank you for any answer!
There are no rotation axes in 4D, for the same reason there is no cross product: the group of 4D rotations is 6-dimentional, and the space you are rotating is 4-dimentional. Imagine, for example, a simultaneous rotation in XY plane and ZT plane: it has no non-zero stationary vectors, and therefore no axes.
The most appropriate thing to do is to work with the usual transormation matrix, which is applicable in any dimention N:
[ a11 ... a1N d1 ]
...
[ aN1 ... aNN dN ]
[ 0 ... 0 1 ]
Here d1 ... dN represent translations, and the NxN submatrix aIJ represent rotations, dilations, projections, and mirroring. To limit to rotations only make this matrix orthogonal: its product with its own transpose should be the unit matrix. This is a common practice for N=2 and N=3, you just do the same for N=4.
To find the appropriate rotation matrix in your case write down add the requirement that the entire 4th row of an orthogonal 4x4 matrix is zero, and that would give you a bunch of solutions, each being an acceptable answer to your question.
I'm trying to derive the matrix of a rigid transform to map between two coordinate spaces. I have the origin and the axis directions of the target coordinate space in terms of the known coordinate space; does anyone know how I can solve for the 4x4 rigid transformation matrix given these?
So, in other words, I have two coordinate spaces, A and B, and I know
Point3D originOfBInA;
Vector3D xAxisOfBInA; // Unit vector
Vector3D yAxisOfBInA; // Unit vector
Vector3D yAxisOfBInA; // Unit vector
And I'm trying to find the 4x4 matrix
Matrix4x4 AtoB;
First construct the 4x4 matrix for the change of basis (call it M) by using your unit vectors (Ax, Ay, Az) and the origin (T) as column vectors:
M =
[Ax Ay Az T] <-- 3x4
[0 0 0 1]
To transform the coordinates of a point p (specified with respect to frame A) to q (with respect to frame B), just multiply by the inverse of M:
q = M-1p
As far as I know, Direct3D works with an LH coordinate system right?
So how would I get position and x/y/z axis (local orientation axis) out of a LH 4x4 (world) matrix?
Thanks.
In case you don't know: LH stands for left-handed
If the 4x4 matrix is what I think it is (a homogeneous rigid body transformation matrix, same as an element of SE(3)) then it should be fairly easy to get what you want. Any rigid body transformation can be represented by a 4x4 matrix of the form
g_ab = [ R, p;
0, 1]
in block matrix notation. The ab subscript denotes that the transformation will take the coordinates of a point represented in frame b and will tell you what the coordinates are as represented in frame a. R here is a 3x3 rotation matrix and p is a vector that, when the rotation matrix is unity (no rotation) tells you the coordinates of the origin of b in frame a. Usually, however, a rotation is present, so you have to do as below.
The position of the coordinate system described by the matrix will be given by applying the transformation to the point (0,0,0). This will well you what world coordinates the point is located at. The trick is that, when dealing with SE(3), you have to add a 1 at the end of points and a 0 at the end of vectors, which makes them vectors of length 4 instead of length 3, and hence operable on by the matrix! So, to transform point (0,0,0) in your local coordinate frame to the world frame, you'd right multiply your matrix (let's call it g_SA) by the vector (0,0,0,1). To get the world coordinates of a vector (x,y,z) you multiply the matrix by (x,y,z,0). You can think of that as being because vectors are differences of points, so the 1 in the last element goes the away. So, for example, to find the representation of your local x-axis in the world coordinates, you multiply g_SA*(1,0,0,0). To find the y-axis you do g_SA*(0,1,0,0), and so on.
The best place I've seen this discussed (and where I learned it from) is A Mathematical Introduction to Robotic Manipulation by Murray, Li and Sastry and the chapter you are interested in is 2.3.1.
I'm experimenting with using axis-angle vectors for rotations in my hobby game engine. This is a 3-component vector along the axis of rotation with a length of the rotation in radians. I like them because:
Unlike quats or rotation matrices, I can actually see the numbers and visualize the rotation in my mind
They're a little less memory than quaternions or matrices.
I can represent values outside the range of -Pi to Pi (This is important if I store an angular velocity)
However, I have a tight loop that updates the rotation of all of my objects (tens of thousands) based on their angular velocity. Currently, the only way I know to combine two rotation axis vectors is to convert them to quaternions, multiply them, and then convert the result back to an axis/angle. Through profiling, I've identified this as a bottleneck. Does anyone know a more straightforward approach?
You representation is equivalent to quaternion rotation, provided your rotation vectors are unit length. If you don't want to use some canned quaternion data structure you should simply ensure your rotation vectors are of unit length, and then work out the equivalent quaternion multiplications / reciprocal computation to determine the aggregate rotation. You might be able to reduce the number of multiplications or additions.
If your angle is the only thing that is changing (i.e. the axis of rotation is constant), then you can simply use a linear scaling of the angle, and, if you'd like, mod it to be in the range [0, 2π). So, if you have a rotation rate of α raidans per second, starting from an initial angle of θ0 at time t0, then the final rotation angle at time t is given by:
θ(t) = θ0+α(t-t0) mod 2π
You then just apply that rotation to your collection of vectors.
If none of this improves your performance, you should consider using a canned quaternion library as such things are already optimized for the kinds of application you're disucssing.
You can keep them as angle axis values.
Build a cross-product (anti-symmetric) matrix using the angle axis values (x,y,z) and weight the elements of this matrix by multiplying them by the angle value. Now sum up all of these cross-product matrices (one for each angle axis value) and find the final rotation matrix by using the matrix exponential.
If matrix A represents this cross-product matrix (built from Angle Axis value) then,
exp(A) is equivalent to the rotation matrix R (i.e., equivalent to your quaternion in matrix form).
Therefore,
exp (A1 + A2) = R1 * R2
probably a more expensive calucation in the end...
You should use unit quaternions rather than scaled vectors to represent your rotations. It can be shown (not by me) that any representation of rotations using three parameters will run into problems (i.e. is singular) at some point. In your case it occurs where your vector has a length of 0 (i.e. the identity) and at lengths of 2pi, 4pi, etc. In these cases the representation becomes singular. Unit quaternions and rotation matrices do not have this problem.
From your description, it sounds like you are updating your rotation state as a result of numerical integration. In this case you can update your rotation state by converting your rotational rate (\omega) to a quaternion rate (q_dot). If we represent your quaternion as q = [q0 q1 q2 q3] where q0 is the scalar part then:
q_dot = E*\omega
where
[ -q1 -q2 -q3 ]
E = [ q0 -q3 q2 ]
[ q3 q0 -q1 ]
[ -q2 q1 q0 ]
Then your update becomes
q(k+1) = q(k) + q_dot*dt
for simple integration. You could choose a different integrator if you choose.
Old question, but another example of stack overflow answering questions the OP wasn't asking. OP already listed out his reasoning for not using quaternions to represent velocity. I was in the same boat.
That said, the way you combine two angular velocities, with each represented by a vector, which represents the axis of rotation with its magnitude representing the amount of rotation.
Just add them together. Component-by-component. Hope that helps some other soul out there.