The C++ Augmented Reality Toolkit

7. Using ARLib

The ARLib toolkit was written for both Windows and Linux. It consists of a single static library that is linked into the final Augmented Reality application.

7.1 Installation

Before applications can be developed using ARLib, the library needs to be built.

Linux

ARLib has the following external dependencies and they must be installed prior to building the library:

Once these dependencies have been installed, the ARLib static library can be built by typing “Make”. This process creates a file called “libAR.so” in the “lib” folder. The file should be moved either to another location, where it can be located by the linker, or alternatively, the LD_LIBRARY_PATH can be updated to include the lib folder path.

Windows

The Windows version of ARLib has the following dependencies:

A Visual Studio .NET C++ solution file exists within the “vcc” folder. This should be loaded into Visual Studio and built using the “Build” option. The file “AR.lib” will be created in the “lib” folder.

7.2 The “Hello World” ARLib Application

To demonstrate the ease of use of ARLib, a basic application is described below. The basic application uses no custom functionality, but has instead all the features of all AR applications developed using ARLib. Note that the source files for this application can be found in the “examples\BasicApp” folder.

The first requirement of the application is to include the relevant header files:


#include <arlib.h>

#include <arapplication.h>

#include <arappbase.h>

These are the main header files. As more functionality of ARLib is used, then additional files will need to be included.

ARLib uses namespaces to group functional areas. The top level namespace is ARLib and within this namespace, there are the functional namespaces.


using namespace ARLib::Application;

The final piece of code required is the main function.


int main(int argc, char *argv[])

{

	ARApplication<ARAppBase> app(&argc, argv);

	app.Run();



	return 1;

}

The first line of code constructs an ARApplication variable called “app”. The ARApplication is a template class and therefore requires a template argument. The argument in this case is the ARAppBase class name. This class provides all the base functionality for ARLib applications, including display and user interface operations. This functionality can be changed by specifying a custom class name as the template argument for ARApplication. However, the custom class must be derived from ARAppBase.

The next line of code calls the Run method of the ARApplication. This method puts the application into Augmented Reality mode and will display the specified images or video with computer graphics overlaid.

Once the above code has been written, it can be built, but before it can be executed, there are some additional requirements.

All ARLib applications are configured through external configuration files, so some additional files will need to be created for the basic application. Fortunately, template versions of these files with default settings are supplied with the ARLib application. The folder “config” should be copied to the location of the final application executable. For details on how to modify the configuration files, see Appendix D.

7.3 Running an ARLib Application

Running the executable without any command-line arguments will attempt to connect to a video source if one is available. In Linux this can be a webcam and in Windows this can either be a webcam or an IEEE1394/firewire device. If no video source is available, a pre-recorded sequence of .tif files can be viewed. To specify a sequence, the following command-line argument should be used:

AppName -sequence <filename>

The filename parameter should be the first image to be used in a numbered sequence of files ie. footage.0001.tif.

As well as displaying sequences of files, a single image can also be viewed:

AppName - image <filename>

For a complete list of available command-line arguments, see Appendix B.

Once the application is running, there are numerous keys that can be used to control the functionality, see Appendix C for a complete list. Some of the more useful keys are:

Tab Toggles between the display of messages and debug information.
F Toggles between full screen and windowed mode.
+/- Zoom in and out.
Space Pauses the sequence.

7.4 Adjusting for Varying Lighting Conditions

Although the routines used in ARLib attempt to minimise the amount of adjustments required, in varying lighting conditions, they will generally need to be tweaked to get the best results when detecting markers. The main adjustments that will need to be made are in the segmentation process, when the colour image is converted to black and white. The Otsu thresholding technique described in Chapter 3 automatically calculates the relevant values, but does not cater for the fact that the scene may either be brightly lit or is in low light. Therefore, the Otsu values need to be offset to cater for the current lighting.

The following steps describe the process for adjusting the Otsu thresholding value:

1. Press the ‘A’ key to display the alpha channel of the image. This makes the adjustment easier to see.

2. Press the ‘U’ key to enter update mode. This will display each option that can be updated at the top of the screen. Use the left and right arrow keys to navigate backwards and forwards through the available options.

3. Navigate to the option called “Otsu Threshold Offset” and use the up and down arrow keys to adjust the value until the markers are more pronounced. The ideal setting is to have more white than black, whilst ensuring that the definition of the markers is as clear as possible.

4. Once the Otsu value has been adjusted press the escape key to exit update mode.

5. To switch back into colour mode, press ‘C’.

7.5 A Custom ARLib Application

The basic functionality of ARLib supports the augmentation of static images or models. To add animated effects, a custom implementation needs to be made. To demonstrate how to implement custom code, the “Clock” example (found in “examples\Clock” folder) is described below.

The “Clock” example comprises of three source files, one header file and two implementation files.

clock.h

The clock header file details the custom functionality that will be provided by the Clock class. The first requirement is to include the ARLib headers that will be used:


#include <arappbase.h>

#include <arboundingbox.h>

#include <arstring.h>

The next step is to define the class:


class Clock : public ARLib::Application::ARAppBase

All custom implementations must be derived from the ARAppBase class.

The final stage of the class definition is to list the methods that are to be overridden from the ARAppBase class:


public:

	virtual void	OnGetApplicationTitle( ARLib::Utility::ARString &title );

	virtual void	OnGetDetailHelp( ARLib::Utility::ARString &help );

	virtual void	OnInit( int *argc, char *argv[] );

	virtual void	OnInitDisplayAR();

	virtual void	OnDisplayAR( ARLib::Detection::ARBoundingBox *marker );

The details behind these methods will be described in the next section.

clock.cpp

First define the header files and namespaces that are to be used:


#include <clock.h>

#include <armodels.h>

#include <time.h>

#include <sys/timeb.h>



// specify the ARLib namespaces that are to be used

using namespace ARLib::Application;

using namespace ARLib::Graphics;

using namespace ARLib::Utility;

Next define the constant variables that are to be used by the custom implementation:


// define OpenGL colour parameters

const GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };

const GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };

const GLfloat lightPos[]     = { 10.0f, 10.0f, -10.0f, 1.0f };



// Constants for loaded obj files

#define OBJ_MINUTE_HAND	101

#define OBJ_HOUR_HAND	102

#define OBJ_SECOND_HAND	103

Now the custom implementation code is created:


void Clock::OnGetApplicationTitle( ARString &title )

{

	// Set the title for the AR Application

	title = "Augmented Ticking Clock";

}

This OnGetApplicationTitle method tells ARLib the name of the application. The title is used in the application’s main window title bar.


void Clock::OnGetDetailHelp( ARString &help )

{

	// Set the detail help for the application

	help = "An augmented reality application that displays a ticking clock.";

}

The OnGetDetailHelp method defines additional help text that will be displayed when the application is executed with the help switch ( -? or -help),


void Clock::OnInit( int *argc, char *argv[] )

{

	// Call base implementation

	ARAppBase::OnInit( argc, argv );



	// Load custom models that will be used

	ARModels::Add( "models/bighand.obj" , OBJ_MINUTE_HAND );

	ARModels::Add( "models/smallhand.obj" , OBJ_HOUR_HAND );

	ARModels::Add( "models/secondhand.obj" , OBJ_SECOND_HAND );

}

The OnInit method is where all custom initialisation is performed. The first command in the OnInit should be to call the ARAppBase::OnInt method to allow default initialisation to be done. In this example, three additional models are to be loaded.


void Clock::OnInitDisplayAR()

{

	// Call base implementation

	ARAppBase::OnInitDisplayAR();



	// Setup OpenGL lights

	glLightfv( GL_LIGHT0, GL_AMBIENT, ambientLight );

	glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuseLight );

	glLightfv( GL_LIGHT0, GL_POSITION, lightPos );



	glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );



	glEnable( GL_LIGHTING );

	glEnable( GL_LIGHT0 );

	glEnable( GL_COLOR_MATERIAL );

}

The OnInitDisplayAR is called prior to displaying all the augmented graphics. Again as with the OnInit method, the ARAppBase implementation is called first, followed by the custom code. In this example, the OpenGL lighting is being setup for the scene.


void Clock::OnDisplayAR( ARLib::Detection::ARBoundingBox *marker )

{

	ARAppBase::OnDisplayAR( marker );



	// get the time

	time_t theTime;

	time( &theTime );



	// break up the time useful elements e.g. hours, minutes and seconds

	tm *fullTime = localtime( &theTime );

	

	// Draw the Second hand

	glPushMatrix();

	glRotatef(-(6 * fullTime->tm_sec),0,1,0);

	ARModels::glDrawList( OBJ_SECOND_HAND );

	glPopMatrix();



	// Draw the Hour hand

	glPushMatrix();

	glRotatef(-((30*fullTime->tm_hour)+((fullTime->tm_min/60.0)*5)*6),0,1,0);

	ARModels::glDrawList( OBJ_HOUR_HAND );

	glPopMatrix();



	// Draw the Minute hand

	glPushMatrix();

	glRotatef(-(6*fullTime->tm_min),0,1,0);

	ARModels::glDrawList( OBJ_MINUTE_HAND );

	glPopMatrix();



}

The final custom method is OnDisplayAR. This method is called for each marker that is detected and requires augmented graphics to be displayed. Here, the ARAppBase code is executed, although this is optional. In the case of the Clock, a static clock model is associated with the markers, therefore the default implementation can handle the drawing of the static models. The rest of the code deals with drawing the clock’s hour, minute and second hands.

main.cpp

The final source file in the clock application is the main function. The code in this file is the same as for the basic application except the ARApplication template argument is the Clock class:


#include <arlib.h>

#include <arapplication.h>

#include <clock.h>



using namespace ARLib::Application;



int main(int argc, char *argv[])

{

	ARApplication<Clock> app(&argc, argv);

	app.Run();



	return 1;

}

<< 6. Camera Orientation 8. Conclusion >>