welcome to linkAR technical documentation

next previous

Controlling the camera and target position

Introduction

The easiest way to control the camera in a target aiming and moving scenario is choosing the FPS option, managed through the following functions:

/** 1.- Set Initial camera target position in the scene*/
NSArray * camTargetPos = [NSArray arrayWithObjects:
                              FBOX(0.0f),
                              FBOX(50.0f),
                              FBOX(0.0f), nil];
 
    [glView setCameraTargetPos:camTargetPos];
 
/** 2.- Set Initial camera position in the scene*/
NSArray * camPos = [NSArray arrayWithObjects:
                              FBOX(100.0f),
                              FBOX(100.0f),
                              FBOX(100.0f), nil];
 
    [glView setCameraPosition:camPos];
 

The function parameter is an NSArray containing three NSNumber objects, with the values of X,Y and Z axis.
The following image will help you to understand the use:

As you can see, the first function sets the camera target. The camera will always point to those coordinates. The second function sets the camera position.

Spherical 3D polar coordinates

Here is introduced how to manage the camera position to place according to Spherical 3D polar coordinates. This coordinates make the movement in 3D spherical environments in a much simpler way (compared to cartesian coordinates).

The mathematic conversion from spherical to cartesian coordinates is ruled by the following functions:

x=r*sinθ*cosφ
y=r*cosθ
z=r*sinθ*sinφ

The Programmatic equivalence of that operations is the following:

+(NSArray*)getCameraPositionForScale:(double)scale angle1:(double)theta angle2:(double)phi{
    float result0=(float)(scale*sin(theta)*cos(phi));
    float result1=(float) (scale*cos(theta));
    float result2=(float)(scale*sin(theta)*sin(phi));
 
    return [NSArray arrayWithObjects:FBOX(result0),FBOX(result1),FBOX(result2), nil ];
}

*Note the second slot in the coordinate array controls the altitude (Z) to match the 3DRender engine axis

Implementation

In this example, the application will manage the camera position moving according to the spherical coordinates. However, as the camera function works with cartesian coordinates, we will need to apply the conversion from spherical to cartesian.

@interface ViewController (){
    //Camera Movements
    NSArray *camPos;
    double actualScale,angleMove1,angleMove2;
 
    ...
}

This variables will hold the position of the camera at any time. 7 Buttons will be added into the view to control the camera:



  1. Up and down buttons manage angleMove1;
  2. Left and right buttons manage angleMove2;
  3. Plus and minus buttons manage the scale;

Remember to link the controls from the Xib/Storyboard to the ViewController.

For each button a manage function will be added:

- (IBAction)moveUp_touch:(id)sender {
    // 1.-
    angleMove1=(float)( fmod(angleMove1,( 2*M_PI)));
    // 2.-
    if(angleMove1>=-M_PI/2&&angleMove1<=M_PI/2){
 
        float newAngle=(angleMove1+angleStep);
        if(newAngle>=-M_PI/2&&newAngle<=M_PI/2)
            angleMove1=newAngle;
 
    }else{
        float newAngle=(angleMove1-angleStep);
        if(newAngle<=-M_PI/2||newAngle>=M_PI/2)
            angleMove1=newAngle;
 
    }
 
    // 3.-
    camPos=[ViewController getCameraPositionForScale:actualScale angle1:angleMove1 angle2:angleMove2];
    [glView setCameraPosition:(camPos)];
}
 
 
- (IBAction)moveDown_touch:(id)sender {
    angleMove1=(float)( fmod(angleMove1,( 2*M_PI)));
    if(angleMove1>=-M_PI/2&&angleMove1<=M_PI/2){
 
        float newAngle=(angleMove1-angleStep);
        if(newAngle>=-M_PI/2&&newAngle<=M_PI/2)
            angleMove1=newAngle;
 
    }else{
        float newAngle=(angleMove1+angleStep);
        if(newAngle<=-M_PI/2||newAngle>=M_PI/2)
            angleMove1=newAngle;
 
    }
    camPos=[ViewController getCameraPositionForScale:actualScale angle1:angleMove1 angle2:angleMove2];
    [glView setCameraPosition:(camPos)];
}
  1. We ensure that the angles are in smallest range [0,2π], any angle out of that range is just a repeated one.
  2. For the Up and Down movement, it is needed to distinguish between the case in which the angle is in the first half or in the second half.
  3. After changing the coordinates, the camera position is recalculated.
- (IBAction)moveLeft_touch:(id)sender {
    angleMove2=(float) (angleMove2+angleStep);
    camPos=[ViewController getCameraPositionForScale:actualScale angle1:angleMove1 angle2:angleMove2];
    [glView setCameraPosition:(camPos)];
}
 
- (IBAction)moveRight_touch:(id)sender {
    angleMove2=(float) (angleMove2-angleStep);
    camPos=[ViewController getCameraPositionForScale:actualScale angle1:angleMove1 angle2:angleMove2];
    [glView setCameraPosition:(camPos)];
}
  • Left and right moves do not need to be filtered.
- (IBAction)zoomOut_touch:(id)sender {
    actualScale=actualScale*IncreasingScaleFactor;
    camPos=[ViewController getCameraPositionForScale:actualScale angle1:angleMove1 angle2:angleMove2];
    [glView setCameraPosition:(camPos)];
 
}
 
- (IBAction)zoomIn_touch:(id)sender {
    actualScale=actualScale*DecreasingScaleFactor;
    camPos=[ViewController getCameraPositionForScale:actualScale angle1:angleMove1 angle2:angleMove2];
    [glView setCameraPosition:(camPos)];
}
  • Modifying the coordinate radius will set the camera closer or further to the object. This will display the object greater or smaller, respectively.
- (IBAction)reset_touch:(id)sender {
    angleMove1=angleMove1InitialValue;
    angleMove2= angleMove2InitialValue;
    actualScale=actualScaleInitialValue;
    camPos=[ViewController getCameraPositionForScale:actualScale angle1:angleMove1 angle2:angleMove2];
 
    if(![glView setCameraPosition:camPos])
        NSLog(@"Error setting camera position");
 
 
    }
  • A reset will place the camera at the start position.

The start position is defined in constants, in this case the following values have been used:

#define actualScaleInitialValue 275.0
#define angleMove1InitialValue M_PI/2
#define angleMove2InitialValue M_PI/2
#define angleStep M_PI/10
#define DecreasingScaleFactor 0.8
#define IncreasingScaleFactor 1.2
 

next previous