Unity translate point relative to another point - c#

I have two points--let's say, A(x1,y1,z1) and B(x2,y2,z2). What I do need is to move both of those points into direction of the Vector AB while pressing the Horizontal axis. How can I achieve that using the Translate method? Like I need to write something like this:
A.translate(pointingVector, Space.World)
The point B moves automatically fitting the transform of the point A, so no need to move it as moving the A point would also move the AB vector without changing its length and direction.

If I understand what you're saying correctly, then this is simply a matter of moving the 2 points along the Vector that they create. So first you need to create the directional Vector:
// Gets a vector that points from the first point's position to the second's.
var (or Vector3) direction = p1.position - p2.position;
Then just increase the 2 points' position by that vector whenever you press the horizontal axis:
p1.position += direction * Time.deltaTime

Related

Force an AR object to always stand upright in Unity / Vuforia

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.

Sphere vs Rotation Box Custom Collision Problem (C#, Unity)

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.

Drag 3D object on specific axis using the mouse cursor

I am trying to build a simple game, where the user can place some elements and move them around.
What I want is to give the user an option to move the objects on specific axis according to his/her decision.
Pretty much like the movement gizmo in unity.
I know how I can drag an object in the world with the mouse but how can I move on specific axis (e.g. Z axis).
I tried to read the "Mouse X" value, but it only work on a specific viewing angle, if I look at the object from different angle the object won't move correctly.
What I did is this:
private void OnMouseDrag()
{
transform.Translate(moveAxis * Input.GetAxis("Mouse X");
}
where moveAxis is a Vector3 that represents the axis, and the script is attached to the arrow gizmo.
Here's one approach:
Convert the moveAxis direction from local space to screen space. Make sure you have a cached Camera field/variable, because calling Camera.main and/or GetComponent<Camera> is a slow operation:
// Get world direction from moveAxis
Vector3 worldDirection = transform.TransformDirection(moveAxis);
Vector2 screenDirection = camera.WorldToScreenPoint(worldDirection + transform.position)
- camera.WorldToScreenPoint(transform.position);
// optionally, normalize the vector in screen space.
// screenDirection.Normalize();
You can normalize the screen direction if you don't want the angle of the axis on the screen to matter to how fast dragging occurs. You probably don't want to normalize it but give it a try if you want a different feel.
Then, calculate the dot product between the axis direction & the movement of the mouse to calculate a magnitude:
Vector2 mouseMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
float translateMagnitude = Vector2.Dot(mouseMovement, screenDirection);
mouseMovement.x must be negative for left and positive is right and mouseMovement.y must be negative for down and positive for up. If either axis is inverted, multiply that axis's value by -1f.
This way, translateMagnitude will be positive if the mouse is moved in the direction of the axis in screen space, and negative if it is moved against it.
Then, multiply the magnitude by some configurable sensitivity factor and multiply that by the axis vector for the Translate call:
public float translateSensitivity;
...
transform.Translate(moveAxis * translateSensitivity * translateMagnitude);

How to rotate parent to move child in Unity3D?

I have a relatively complicated math problem I need to solve for a game I'm working on in Unity. I've tried a couple things but nothing has worked.
Basically, I need to apply an offset rotation (Quaternion) to a parent, where the result of this rotation is to move its child in a given direction.
To explain it better, the problem would be simple if it could be guaranteed that the parent's forward vector was pointed at the child. Then I would simply create a ghost position by adding the desired direction to the child, and then use a LookAt rotation to rotate the parent to look at that ghost position. (The child doesn't need to be put in a specific position, it just needs to move generally in that direction)
What makes this complicated is that A. the parent could be at any rotation, and B. the child could be at any position relative the parent.
For context, I'm working on a procedural animation system and I'd like to have the bones bend in the direction of the Agent's velocity. With the IK'd bones this is easy, just move the IK. But for the actual bones, I need a way to move a bone in a direction by rotating its parent's bone.
Thanks for any help!
First, we need to have the child's current position and the target position in the coordinate system of the parent. It sounds as if the child's position already is expressed in this coordinate system. Then, if the target position is in world coordinates, you simply do this with the inverse parent world transform:
pTargetLocal = parent.worldMatrix^-1 * pTarget
Once we have this, we want to find a rotation R, such that pCurrentLocal is rotated towards pTargetLocal. Assuming unit vectors (as rotations preserve lengths), this equals:
parent.worldMatrix * pTargetLocal = parent.worldMatrix * R * pCurrentLocal
pTargetLocal = R * pCurrentLocal
Once we have R, we just need to update parent.worldMatrix = parent.worldMatrix * R.
This can be solved by representing R in axis-angle format. The axis would be axis = Vector3.Cross(pCurrentLocal, pTargetLocal) and the angle is angle = Vector3.Angle(pCurrentLocal, pTargetLocal). You can either calculate a quaternion or a matrix from these parameters and multiply it with the current parent transform.
I assumed that the rotation center is the origin of the parent's local coordinate system. You could also rotate about another center to incorporate a translation component.

Get 2D direction that represents tilt direction of 3D object

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.

Categories