Rotate an Object in Its Direction of Motion

Rotate an object in its direction of motion

It's fairly straightforward to rotate a sprite in the direction of its motion. You can do this by converting the x and y components of the sprite's velocity into an angle with the atan2 function. You should rotate the sprite only when its speed is greater than some nominal value to prevent the sprite from resetting to zero degrees when the sprite's speed is (nearly) zero.

If we extend CGVector to compute speed and angle from the velocity's components by

extension CGVector {
func speed() -> CGFloat {
return sqrt(dx*dx+dy*dy)
}
func angle() -> CGFloat {
return atan2(dy, dx)
}
}

we can rotate a sprite to face in the direction of its motion with

override func didSimulatePhysics() {
if let body = sprite.physicsBody {
if (body.velocity.speed() > 0.01) {
sprite.zRotation = body.velocity.angle() - offset
}
}
}

where offset = CGFloat(M_PI_2) if your sprite faces up when zRotation is zero, and offset = 0 if your sprite faces to the right when zRotation is zero.

Calculating rotation along a path

First off how do you represent the road?

I recently done exactly this thing and I used Catmull-Rom splines for the road. To orient an object and make it follow the spline path you need to interpolate the current x,y,z position from a t that walks along the spline, then orient it along the Frenet Coordinates System or Frenet Frame for that particular position.

Basically for each point you need 3 vectors: the Tangent, the Normal, and the Binormal. The Tangent will be the actual direction you will like your object (car) to point at.

I choose Catmull-Rom because they are easy to deduct the tangents at any point - just make the (vector) difference between 2 other near points to the current one. (Say you are at t, pick t-epsilon and t+epsilon - with epsilon being a small enough constant).

For the other 2 vectors, you can use this iterative method - that is you start with a known set of vectors on one end, and you work a new set based on the previous one each updateframe() ).

Best way to translate mouse drag motion into 3d rotation of an object

Create an accumulator matrix and initialize it with the identity.

Each frame, apply that to your modelview/world matrix state before drawing the object.

Upon mouse motion, construct a rotation matrix about the X axis with some sensitivity_constant * delta_x. Construct another rotation matrix about the Y axis for the other component. Multiply one, then the other onto the accumulator.

The accumulator will change as you move the mouse. When drawing, it will orient the object as you expect.

Also, the person talking about quaternions is right; this will look good only for small incremental changes. If you drag it quickly on a diagonal, it won't rotate quite the way you expect.

Rotate UIImageView according to direction of travel

Your difficulty here probably has to do with the fact that iOS does not use cartesian coordiantes but the atan2 function does. Here is an example playground of how to calculate the angle and use the transform to align the imageview in the direction of travel. I'm using UIView transforms and animations here, but the same principles and coordinate system applies to CALayer's and CAAnimations:

import PlaygroundSupport
import UIKit

class V: UIViewController {
let imageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = UIImage(named: "arrow up.jpg")
view.addSubview(imageView)
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
imageView.sizeToFit()
imageView.center = view.center
let vector = CGVector(dx: 120, dy: 100)
let angle = atan2(vector.dy, vector.dx) - 1.5 * CGFloat.pi
print(angle/CGFloat.pi)
let rotationMatrix = CGAffineTransform(rotationAngle: angle)
self.imageView.transform = rotationMatrix
UIView.animate(withDuration: 5) {
self.imageView.center.x += vector.dx
self.imageView.center.y += vector.dy
}

}
}

PlaygroundPage.current.liveView = V()

Rotate object in the direction it's moving in Unity

Manually rotating while physics are active may give you some wacky results, but here goes

public class FaceVelocity : MonoBehaviour
{
private Rigidbody rigidBody;
void Awake()
{
rigidBody = getComponent<RigidBody2D>();
}
//Apply rotation in late update to make sure it's not undone by physics
void LateUpdate()
{
transform.right = rigidBody.velocity.normalized
}
}

If your objects rotates while in contact with something (aka where it's most likely to) it may disort physics. It may be better to to use a parent object for physics and a child object for visuals.

public class FaceVelocity : MonoBehaviour
{
private Rigidbody rigidBody;
void Awake()
{
rigidBody = transform.parent.getComponent<RigidBody2D>();
}
//Apply rotation in late update to make sure it's not undone
void LateUpdate()
{
transform.right = rigidBody.velocity.normalized
}
}

Although to me it sounds like you don't even need rigidbodies and particle physics would be enough. If you do not use rigidbodies, calculate velocity direction yourself:

public class FaceVelocity : MonoBehaviour
{
private Vector3 prevPos;
void Awake()
{
prevPos = transform.position;
}
//Apply rotation in late update to make sure it's not undone
void LateUpdate()
{
transform.right = (transform.position - prevpos).normalized
}
}


Related Topics



Leave a reply



Submit