Hashmat Khalil
Hashmat Khalil

Reputation: 1816

scenekit node rotation and movement in 3D Space

Let's say we have a SCNNode and we want to rotate, change flight direction and move in space with no gravity. The node currently is just a camera. actually it should react to gyroscope accelerometer data. i think scene update can be done in - (void)renderer:(id <SCNSceneRenderer>)aRenderer didSimulatePhysicsAtTime:(NSTimeInterval)time.

The problem I'm facing is how to utilise the gyroscope & accelerometer data for calculating flight direction, and how to calculate the rotation direction & movement. I refreshed my memory about 3D rotation matrix for each axis(x,y,z) but still missing above mentioned part to solve this problem. May be thinking very complicated and the solution is very easy.

- (void)viewDidLoad
{

SCNView *scnView = (SCNView *) self.view;
SCNScene *scene = [SCNScene scene];
scnView.scene = scene;

_cameraNode = [[SCNNode alloc] init];
_cameraNode.camera = [SCNCamera camera];
_cameraNode.camera.zFar = 500;
_cameraNode.position = SCNVector3Make(0, 60, 50);
_cameraNode.rotation  = SCNVector4Make(1, 0, 0, -M_PI_4*0.75);
[scene.rootNode addChildNode:_cameraNode];

scnView.pointOfView = _cameraNode;
[self setupAccelerometer];
}

- (void)setupAccelerometer
{
_motionManager = [[CMMotionManager alloc] init];
GameViewController * __weak weakSelf = self;

if ([[GCController controllers] count] == 0 && [_motionManager isAccelerometerAvailable] == YES) {
    [_motionManager setAccelerometerUpdateInterval:1/60.0];
    [_motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
        [weakSelf accelerometerDidChange:accelerometerData.acceleration];
    }];
}
}

- (void)accelerometerDidChange:(CMAcceleration)acceleration
{
 //acceleration.x
 //acceleration.y
 //acceleration.z
 // now we have the data and saved somewhere

}

Upvotes: 3

Views: 3087

Answers (1)

rickster
rickster

Reputation: 126107

If you want to combine gyroscope and accelerometer data to get an orientation, you'd probably be better off letting CoreMotion do that for you. The methods listed under Managing Device Motion Updates in the docs get you CMDeviceMotion objects; from one of those you can get a CMAttitude that represents an orientation, and from that you can get a rotation matrix or quaternion that you can apply to a node in your scene. (Possibly after further transforming it so that a neutral orientation fits into your scene the way you want.)

After you've oriented the node the way you want, getting a flight direction from that should be pretty simple:

  1. Choose a flight direction in terms of the local coordinate space of the node and make a vector that points in that direction; e.g. a camera looks in the -z direction of its node, so if you want the camera node to look along its flight path you'll use a vector like {0, 0, -1}.

  2. Convert that vector to scene space with convertPosition:toNode: and the scene's rootNode. This gets you the flight direction in terms of the scene, taking the node's orientation into account.

  3. Use the converted vector to move the node, either by assigning it as the velocity for the node's physics body or by using it to come up with a new position and moving the node there with an action or animation.

Upvotes: 5

Related Questions