I have a 3D object in space. Here it is from a top-down perspective:
Y is towards us, so we can't see that axis. It's not tilting at all, so it's direction would be Vector2(0,0).
Now the object is tilting forward. It's tilting towards the positive X axis. The direction would now be Vector2(0,1)
Now it's tilting to the left, it's direction would be Vector(-1,0)
Now, finally, it's tilting forward and the left, it's direction would be around Vector(-0.7071, 0.7071)
I'm using Unity, so I have access to the object's Quaternion and Euler Angles as a Vector3. How would I calculate the object's tilt direction from the object's rotation?
As far as I understand your idea, you are looking for orthogonally casted parameters of normal vector (abstractly attached to the body). If it turns forward this vector after cast gets values (0,1) like you've said.
You can receive x and y components of that vector by decomposition - as a sum of two perpendicular vectors, each one represents one component (x,0) and (0,y).
Another way of achieving that result would be to have a point in 3D space P(0,0,1) which represents top of such vector. Now simply applying rotation matrix this point would be moved toward new position which is P(x,y,z) and here you can get x and y you are looking for.
I hope I didn't messed up something.
Related
I have a Unity AR project using Vuforia engine. What I am trying to achieve is to have the AR object always stand upright in the view whether the image target is horizontal on a table or or vertical on a wall.
Currently the object is sitting on the image target no matter which orientation
Hope that makes sense,
Thanks
I always use Vector3.ProjectOnPlane for this and then you can simply assign axis directions to Transform.up and Transform.right (below I explain why right and not maybe forward)
public void AlignObject(Transform obj, Transform imageTarget)
{
obj.position = imageTarget.position;
// Get your targets right vector in world space
var right = imageTarget.right;
// If not anyway the case ensure that your objects up vector equals the world up vector
obj.up = Vector3.up;
// Align your objects right vector with the image target's right vector
// projected down onto the global XZ plane => erasing its Y component
obj.right = Vector3.ProjectOnPlane(right, Vector3.up);
}
The assumption for this is: The target is usually never rotated in the Z axis. If you want it upright on a wall you would usually rotate it around its X axis.
Therefore we can assume the the image target will never be rotated more then 90° on the Z axis (in which case the mapped vector would flip about 180°) and thus if we map the right vector down onto the global XZ plane it always still points in the correct direction regardless of any rotations in Y and X axes.
If we would use the forward instead we take the risk that due to tracking inaccuracies the vertical targets forward vector actually points a tiny little bit towards us so when we map it down onto the XZ plane it points backwards not forwards and the object is flipped by 180°.
So using right works for a horizontal and a vertical target.
I'm not really like to post questions about problems without doing the research, but I'm close to give up, so I thought I give it a shot and ask you about my problem.
I want to create a custom collision detection in Unity ( So please don't advice "use rigidbody and\or colliders" because I don't want to use them by purpose).
The main idea: I want to detect Basic Sphere and Basic Box collision. I already find AABB vs Sphere theme with the following solution:
bool intersect(sphere, box) {
var x = Math.max(box.minX, Math.min(sphere.x, box.maxX));
var y = Math.max(box.minY, Math.min(sphere.y, box.maxY));
var z = Math.max(box.minZ, Math.min(sphere.z, box.maxZ));
var distance = Math.sqrt((x - sphere.x) * (x - sphere.x) +
(y - sphere.y) * (y - sphere.y) +
(z - sphere.z) * (z - sphere.z));
return distance < sphere.radius;
}
And this code does the job, the box bounding and the sphere center point with radius works fine, I can detect the Sphere collision on Box.
The problem is, I want to Rotating the Cube in Runtime, so that will screw up everything, the bounding will split away and the collision will gone (or collide on random places). I've read about some comments where they said, bounding not works with rotation, but I'm not sure what else can I use to solve this problem.
Can you help me with this topic please? I'll take every advice I can get (except Colliders & Rigidbodies of course).
Thank you very much.
You might try using the separating axis theorem. Essentially, for a polyhedron, you use the normal of each face to create an axis. Project the two shapes you are comparing onto each axis and look for an intersection. If there is no intersection along any of the axes, there is no intersection of shapes. For a sphere, you will just need to project onto the polyhedron's axes. There is a great 2D intro to this from metanet.
Edit: hey, check it out-- a Unity implementation.
A good method to find if an AABB (axis aligned bounding box) and sphere are intersecting is to find the closest point on the box to the sphere's center and determine if that point is within the sphere's radius. If so, then they are intersecting, if not then not.
I believe you can do the same thing with this more complicated scenario. You can represent a rotated AABB with a geometrical shape called a parallelepiped. You would then find the closest point on the parallelepiped to the center of the sphere and again check if that point exists within the sphere's radius. If so, then they intersect. If not, then not.
The difficult part is finding the closest point on the parallelepiped. You can represent a parallelepiped in code with 4 3d vectors: center, extentRight, extentUp, and extentForward. This is similar to how you can represent an AABB with a 3d vector for center along with 3 floats: extentRight, extentUp, and extentForward. The difference is that for the parallelepiped those 3 extents are not 1 dimensional scalars, but are full vectors.
When finding the closest point on an AABB surface to a given point, you are basically taking that given point and clamping it to the AABB's volume. You would, for example, call Math.Clamp(point.x, AABB.Min.x, AABB.Max.x) and so on for Y and Z.
The resulting X,Y,Z would be the closest point on the AABB surface to the given point.
To do this for a parallelepiped you need to solve the "linear combination" (math keyword) of extentRight(ER), extentUp(EU), and extentForward(EF) to get the given point. In other words, what scalars do you have to multiply ER, EU, and EF by to get to the given point? When you find those scalars you need to clamp them between 0 and 1 and then multiply them again by ER, EU, and EF respectively to get that closest point on the surface of the parallelepiped. Be sure to offset the given point by the Parallelepiped's min position so that the whole calculation is done in its local space.
I didn't want to spend any extra time learning how to solve for a linear combination (it seems it involves things like using an "augmented matrix" and "gaussian elimination") otherwise I'd include that here too. This should get you or anyone else reading this off to the right track hopefully.
Edit:
Actually I think its a lot simpler and you don't need a parallelepiped. If you have access to the rotation (Vector3 or Quaternion) that rotated the cube you could get the inverse of that and use that inverse rotation to orbit the sphere around the cube so that the new scenario is just the normal axis aligned cube and the orbited sphere. Then you can do a normal AABB - sphere collision detection.
I'm creating an asteroid mining game in Unity 3D, where "down" is the center of the planet you are on (So I am mostly using local rotations when dealing with vectors). I have a working physics-based character controller, but it has problems dealing with slopes. This is because when I add a force to the character, currently it pushes along the player's forward vector (see picture). What I want to do is calculate the vector that is parallel to this terrain surface, but in the direction that the player is facing (so that the player can move up the slope).
I originally thought that i could just find the vector perpendicular to the normal, but then how do I know which direction it will be in. Also complicating matters is the fact that the player could be oriented in any way in relation to the global x, y, and z.
Either way, I have the surface normals of the terrain, I have all of the player's directional vectors, but I just can't figure out how to put them all together. I can upload code or screenshots of the editor if necessary. Thanks.
The usual way is to factor out the component of the forward vector that is parallel to the surface normal:
fp = f - dot(f, n) * n
See vector rejection.
This formulation will also make fp shorter the steeper the slope is. If you don't want that, you can re-scale fp afterwards to have the same length as f.
What happens when I set the transform.up value in unity. Specifically could you explain this video in the link below
https://youtu.be/_XdqA3xbP2A
I know it changes what the object is looking at. But, does it look at a position, or how does it
work? What happens when I change the direct transform.up? I can’t seem to find a good explanation. Why does the vector in the video make a direction that is facing the mouse, why not use the mousePosition itself instead of subtracting?
Aside from that could you also explain what is going on in the video?
Thanks in advance!
Basically, when you move an object, you take its position and rotation as reference, so if you increment +1 on the Y position of an object and this object is rotated, you'll increment on that direction.
but with Vector3.up, you use the world space as reference, so
i want to give you a full answers here, but i would have to enter with some math, simplifying, the transform.up is the direction which the sprite is pointing, he gets the direction saying this:
"mousePosition.y" (GREEN) is the position Y of the mouse, and "mousePosition.x" (RED) is the X position of the mouse, with this two values, you have a coordinate, or a direction (Blue traced line), which unity transforms to quaternions and apply the value to your rotation (this in 2d). you want to use the Vector3 which uses a world space reference, because if you use a local reference, would happen something like this
and you would get the wrong direction.
Transform object automatically calculates a quaternion rotation using this up Vector like from default Vector3.up to new transform up vector.
Im doing collision detection in a game.
All the surfaces are orthagonal so I only need to determine which face of an obstacle my moving object has collided with.
I have the rectangle defining the intersection of the two objects and the vector representing the moving objects speed and direction of movement.
I reckon I need to translate the intersection rectangle along my moving objects vector until the intersection becomes a line, then I'll know which face was collided with 1st.
I have no idea how to do this mathematically of programatically however
Calculate the vector from (the corner of the obstacle internal to your object) to (the corner of your object internal to the obstacle). Whichever "side" of this vector your movement vector is on gives the "side" that touched first. If they have the same angle, the corner touched first.
E.g. here your movement vector is at about 260 degrees and then calculated vector is at about 240 degrees. Anticlockwise from calculated to movement is 20 degrees, clockwise is 340 degrees. Thus the anticlockwise side (bottom) collided first.
You need able to tell which two sides are in question, and which is "clockwise" and "anticlockwise" - I hope this is trivial.
You can compare the aspect ratio of the velocity vector to the aspect ratio of the intersection rectangle.
For this particular example, if the velocity vector is steeper than the intersection rectangle (i.e. defines a taller and skinnier rectangle), then the collision was on the bottom face.
If the velocity vector is shallower, then the collision was on the left face of the moving rectangle.
If the velocity vector is the same aspect ratio as the intersection rectangle (i.e. the velocity lays on the diagonal of the intersection rectangle), then they collided on the corners.
Actually I may have figured it out...
Find the point on the intersection rectangle that isnt on the objects
rectangle
draw a line from there in the vectors direction
whatever side it intersects with is the side that collided 1st