I need to do some transform to elements in Unity for a project, with matrix values that I extract on a XML file :
<DOMBitmapInstance libraryItemName="Scene/Picture/CAM_U_cptgen_GEN_TOP_T1(4th_seat).png">
<matrix>
<Matrix a="0" b="1.66069030761719" c="-1.66069030761719" d="0" tx="178.5" ty="-673"/>
</matrix>
</DOMBitmapInstance>
My question is, how can I skew my image, because 'a' and 'd' are supposed to be for x and y scale, and 'b' and 'c' are for y and x skew.
I need to display images and to animate them in Unity, so this values can change.
For now on, I extract all values and already apply 'a' and 'd'.
Thanks in advance !
In a previous version of the project, I worked on the same project but generated, not the source file (plans have changed like they say) and It was generated in js, and I could easily extract Skew value because It was a rotation value like '90' degrees. But for the same project, now I have this numbers I don't really know how to apply them into a Unity Transform.
So, I found a solution, I'll post here if someone needs one day to do the same as me.
public void SetSkew(float b, float c)
{
float a = elementObject.transform.localScale.x;
elementObject.GetComponent<RectTransform>().localRotation = Quaternion.Euler(0, 0, Mathf.Atan2(c, a) * Mathf.Rad2Deg);
}
Related
I created a Unity3d project and I used some spotlights behind objects to get their shadows. I'm trying to get the real size (using my scale) of the shadow once reflected on the floor. Is there a way to do that?
I do believe your question would mostly belong to Mathematics Stack Exchange but here's an approach that I hope will lead you to the right direction.
The hypotheses I took here are:
you know your object height when scale = 1
your object isn't too large on its top (or you will have to include half its width to the maths)
your object pivot is placed at it's base (on a human : under its feet)
your object is placed on the floor (and therefore not in the air: otherwise it's a bit more complicated to calculate but the idea remains the same)
Here's a quick schema of the situation:
Now you can calculate your shadow's size using something like this:
Vector3 topPoint = YOUR_OBJECT.transform.position + YOUR_OBJECT.transform.lossyScale.y * YOUR_OBJECT_HEIGHT;
Vector3 lightFlatPoint = new Vector3(YOUR_LIGHT.transform.position.x, topPoint.y, YOUR_LIGHT.transform.position.z);
float lightDeltaY = YOUR_LIGHT.transform.position.y - topPoint.y;
float lightFlatToTopPointDistance = Vector3.Distance(lightFlatPoint, topPoint);
float shadowSize = ((YOUR_OBJECT.transform.lossyScale.y * YOUR_OBJECT_HEIGHT) / lightDeltaY) * lightFlatToTopPointDistance;
Hope this helps,
Sometimes when i move mouse (rotate camera around character), my character do rotation.
But i do not have any character rotation by mouse.
This is my rotation code, that depend only on keyboard input (I took this code from standard unity sample):
private void ConvertMoveInput()
{
Vector3 localMove = transform.InverseTransformDirection(_moveInput);
_turnAmount = Mathf.Atan2(localMove.x, localMove.z);
_forwardAmount = localMove.z;
}
I figure out that sometimes when i move mouse Mathf.Atan2 return the number PI, even if two arguments are still equals to zero. How does this happens?
My demo project here.
Remember, atan2(x, z) returns the angle between the z-axis and the vector (x, z):
But with atan2(0, 0), you're trying to find the angle between a point and either the z- or x-axis, which is meaningless:
Even though atan2(0, 0) is meaningless, most programming language math libraries have atan2(x, y) to return a value instead of an error code if x and y are valid numbers, and in the special case of atan2(0, 0), that return value is pi. The implementation of atan2() in the C++ standard library does this, and I think a lot of languages, including Unity's implementation of C#, followed suit.
This means that you need to check for the special case where x and z are both 0. Something like:
if ((localMove.x != 0) && (localMove.z != 0)) {
_turnAmount = Mathf.Atan2(localMove.x, localMove.z);
}
else {
_turnAmount = 0;
}
The tan function is periodic with a period of π. So calling tan on 0 and on π produces the same value (namely, zero).
That's one of the reasons you can't simply use atan to get back the original angle - you're losing a lot of the original information, and the angle you'll get will only ever be between -π/2 and +π/2.
Atan2 in Unity is designed to work around this - it takes the x and y coordinates, instead of their division (which is how you'd use atan). It can then figure out the correct quadrant for the angle - offset it appropriately. Just as importantly, it handles the case when the y coordinate is zero - which would normally result in a division-by-zero error. For example, [1; 0] might return 0°, [0; 1] 270° (note - I'm not sure about the exact numbers; it depends on where the "reference" is, and I haven't used this in Unity3D. The key point is the principle, not the exact values).
However, this can only work if at least one of the coordinates is not zero - the coordinate [0; 0] doesn't have any meaningful angle with respect to [0; 0]. All the angles are equally valid (or neither of them, depending on your viewpoint). Unity simply chooses π, out of all the possible options - for whatever reason. It really is as good a value as any other. The only real alternative would be to throw an exception and crash your game - which usually wouldn't be preferred to tiny glitches like this :)
I'm trying to create a .bvh file via kinect.
It means in need to get rotations of each bone of a skeleton. I need the rotations in Euler angles. I already tried many different approaches, but any of them gave me good result. Could anyone give me some advice what am I doing wrong?
Here is (I think) the main part of my code.
foreach (Skeleton skeleton in newSkeleton)
{
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
continue;
int j = 0;
foreach (BoneOrientation orientation in skeleton.BoneOrientations)
{
Matrix4 matrix = orientation.HierarchicalRotation.Matrix;
double y = Math.Asin(matrix.M13);
double x = Math.Atan2(-matrix.M23, matrix.M33);
double z = Math.Atan2(-matrix.M12, matrix.M11);
rotationMatrix[j, 0] = x * 180 / Math.PI;
rotationMatrix[j, 1] = y * 180 / Math.PI;
rotationMatrix[j, 2] = z * 180 / Math.PI;
j++;
}
}
My euler angles should be stored in the rotationMatrix array for further use (saving into bvh file). Here comes my problem... the rotations calculated this way doesn't make sense (I mean they have nothing to do with the position of me ahead of kinect) and they seems to be random.
Edit:
I would also need to explain some unclear topics about kinect. I tried to Google it, but didn't succeed.
Does kinect skeleton have something like zero pose? I mean any pose where all bone rotations are zero. (e.g. T-pose and so on)
What kind of standards does kinect use? I mean how does kinect store data into rotation matrices? I would like to know if the matrix is like
[X1, Y1, Z1,
X2, Y2, Z2,
X3, Y3, Z3]
or does it use some other order?
About the marices.. Is it possible to calculate Euler angles from the matrix given by kinect in standard way? I mean some of algorithms mentioned in this paper?
http://www.geometrictools.com/Documentation/EulerAngles.pdf
OK, after some more time spend researching, i think i might be able to answer some of mine questions. If is anyone interested...
i havent found any zero pose, but i created my own using some kind of calibration. I saved rotation matrices for my chosen zero pose (let's call these Mz), made these matrices trandposed (MzT) and I multiplied all the next matrices kinect gave me (let's call these Mr).
It means I calculated matrices for further use this way: M = MzT x Mr.
I used the conversion from link in 3. question for Rxyz order and all worked well, it means the rotation matrices given by kinect probably have the order given in the question. This should be answer to the third question as well.
I thought it would be simple as:
Vector3 point = Vector3.Transform(originalPoint, worldMatrix);
But apparently not... It make's the point's numbers shoot into the thousands.
Basically, what I'm trying to do is creating a collision system and every two points in this system is a line, so basically I want to collide lines. I want the lines to be able to scale, rotate, and translate based on a world matrix (so that the collision lines are in tune with the object's scale, rotation, and translation).
I've been trying for hours now and I can't seem to figure it out. I've tried multiplying by the View Matrix as well and while that is the closest to what I want, it seems to switching between two sets of numbers! It would be perfect if it stayed with the one set, I have no idea why it keeps changing...
Any help, please? :(
Edit: To add a little, I'm constantly updating the points in an Update call. But I don't know if that would change anything, either way the points = originalpoints first.
Steve H:
One line would have two points, so:
originalPoint[0] = new Vector3(-42.5f, 0f, 0f);
originalPoint[1] = new Vector3(42.5f, 0f, 0f);
point[0] = Vector3.Transform(originalPoint[0], worldMatrix);
point[1] = Vector3.Transform(originalPoint[1], worldMatrix);`
At first, point[0] & [1] equals the same as originalPoint[0] & [1]. But, the moment I move my player even just a few pixels...
point[0] = (-5782.5f, 0f, 0f)
point[1] = (-5697.5, 0f, 0f)
The player's position is -56.0f.
My worldMatrix goes as:
_world = Matrix.Identity // ISROT
* Matrix.CreateScale(_scale) // This object's scale
* Matrix.CreateFromQuaternion(_rotation) // It's rotation
* Matrix.CreateTranslation(_offset) // The offset from the centre
* Matrix.CreateFromQuaternion(_orbitRotation) // It's orbit around an object
* _orbitObjectWorld // The object to base this world from
* Matrix.CreateTranslation(_position); // This object's position
The objects display properly in graphics. They scale, rotate, translate completely fine. They follow the orbit's scale, rotation, and translation too but I haven't tested orbit much, yet.
I hope this is enough detail...
Edit: Upon further research, the original points are also being changed... :| I don't get why that's happening. They're the exact same as the new points...
I figured out my problem... -_-
So, after I create the line points, I do this at the end:
originalLines = collisionLines;
collisionLines & originalLines are both Vector3[] arrays.
I guess just by making one equal the other, it's like they're the exact same and changing one changes the other... that is something I did not know.
So I made this function:
void CreateOriginalPoints()
{
_originalPoints = new Vector3[_collisionPoints.Length];
for (int i = 0; i < _collisionPoints.Length; i++)
_originalPoints[i] = _collisionPoints[i];
}
And this solves the problem completely. It now makes complete sense to me why this problem was happening in the first place.
Thanks a lot Donnie & Steve H. I know you two didn't answer my question but it got me to poke around even deeper until I found the answer.
I'm a real noob who just started learning 3d programming and i have a really hard time learning about rotation in 3D space. My problem is that I can't seem to figure out how to rotate an object using it's local coordinates.
I have a basic class for 3d objects and, for starters, i want to implement functions that will rotate the object on a certain axis with x degrees. So far i have the following:
public void RollDeg(float angle)
{
this.rotation = Matrix4.Mult(rotation,
Matrix4.CreateRotationX(MyMath.Conversions.DegToRad(angle)));
}
public void PitchDeg(float angle)
{
this.rotation = Matrix4.Mult(rotation,
Matrix4.CreateRotationY(MyMath.Conversions.DegToRad(angle)));
}
public void YawDeg(float angle)
{
this.rotation = Matrix4.Mult(rotation,
Matrix4.CreateRotationZ(MyMath.Conversions.DegToRad(angle)));
}
'rotation' is a 4x4 matrix which starts as the identity matrix. Each time i want to roll/pitch/yaw the object, i call one of the functions above.
for drawing, i use another function that pushes a matrix onto the ModelView stack, multiplies it with the translation, rotation and scale matrices of the object (in this order) and begins drawing the vertices. ofcourse, finally i pop the matrix off the stack.
the problem is that the functions above rotate the object on the GLOBAL axis, not on the LOCAL ones, even if, from my understanding, every time you rotate an object, the local system changes it's axis and then, when a new rotation is applyied on top of the others, the local axis are used for the new one.
i read different tutorials about the math behind it and how to rotate objects, but i couldn't find one the could help me.
if anyone has the time, i would really appreciate if he could help me understand HOW to rotate around local axis and, maybe even more important, what i did wrong on my current implementation.
If you want to perform your transformations in this order : translation -> rotation -> scale (which makes perfectly sense, it's what's wanted usually), you have to multiply your matrices in the reverse order.
In a right-handed coordinate system (i.e. the one openGL uses), matrix multiplication must be performed from right to left. This is why :
ModelViewTransform = Transform * View * Model // <- you begin by the model, right ? so it's this way
Note that in directX they use a left-handed coordinate system. It has his shortcomings, but it's more intuitive.