Merge "Combine StencilMode and WriteToColorBuffer to RenderMode" into devel/master
[platform/core/uifw/dali-demo.git] / examples / mesh-visual / mesh-visual-example.cpp
1 #include <dali-toolkit/dali-toolkit.h>
2 #include <dali/public-api/object/property-map.h>
3
4 using namespace Dali;
5 using namespace Dali::Toolkit;
6
7 namespace
8 {
9   //Keeps information about each model for access.
10   struct Model
11   {
12     Control control; // Control housing the mesh visual of the model.
13     Vector2 rotation; // Keeps track of rotation about x and y axis for manual rotation.
14     Animation rotationAnimation; // Automatically rotates when left alone.
15   };
16
17   //Files for meshes
18   const char * const MODEL_FILE_TABLE[] =
19   {
20       DEMO_MODEL_DIR "Dino.obj",
21       DEMO_MODEL_DIR "ToyRobot-Metal.obj",
22       DEMO_MODEL_DIR "Toyrobot-Plastic.obj"
23   };
24
25   const char * const MATERIAL_FILE_TABLE[] =
26   {
27       DEMO_MODEL_DIR "Dino.mtl",
28       DEMO_MODEL_DIR "ToyRobot-Metal.mtl",
29       DEMO_MODEL_DIR "Toyrobot-Plastic.mtl"
30   };
31
32   const char * const TEXTURES_PATH( DEMO_IMAGE_DIR "" );
33
34   //Possible shading modes.
35   MeshVisual::ShadingMode::Value SHADING_MODE_TABLE[] =
36   {
37     MeshVisual::ShadingMode::TEXTURED_WITH_DETAILED_SPECULAR_LIGHTING,
38     MeshVisual::ShadingMode::TEXTURED_WITH_SPECULAR_LIGHTING,
39     MeshVisual::ShadingMode::TEXTURELESS_WITH_DIFFUSE_LIGHTING
40   };
41
42   //Button labels.
43   const char * const PAUSE =  "  ||  ";
44   const char * const PLAY =   "  >  ";
45   const char * const FIXED =  "FIXED";
46   const char * const MANUAL = "MANUAL";
47   const char * const FRONT =  "FRONT";
48   const char * const BACK =   "BACK";
49
50   //Image urls for the light.
51   const char * const LIGHT_URL_FRONT = DEMO_IMAGE_DIR "light-icon-front.png";
52   const char * const LIGHT_URL_BACK =  DEMO_IMAGE_DIR "light-icon-back.png";
53
54   const float X_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
55   const float Y_ROTATION_DISPLACEMENT_FACTOR = 60.0f;
56   const float MODEL_SCALE =                    0.75f;
57   const float LIGHT_SCALE =                    0.15f;
58   const float BUTTONS_OFFSET_BOTTOM =          0.08f;
59   const float BUTTONS_OFFSET_SIDE =            0.2f;
60   const int   NUM_MESHES =                     2;
61
62   //Used to identify actors.
63   const int MODEL_TAG = 0;
64   const int LIGHT_TAG = 1;
65   const int LAYER_TAG = 2;
66
67 } //End namespace
68
69 class MeshVisualController : public ConnectionTracker
70 {
71 public:
72
73   MeshVisualController( Application& application )
74   : mApplication( application ),   //Store handle to the application.
75     mModelIndex( 1 ),              //Start with metal robot.
76     mShadingModeIndex( 0 ),        //Start with texture and detailed specular lighting.
77     mTag( -1 ),                    //Non-valid default, which will get set to a correct value when used.
78     mSelectedModelIndex( -1 ),     //Non-valid default, which will get set to a correct value when used.
79     mPaused( false ),              //Animations play by default.
80     mLightFixed( true ),           //The light is fixed by default.
81     mLightFront( true )            //The light is in front by default.
82   {
83     // Connect to the Application's Init signal
84     mApplication.InitSignal().Connect( this, &MeshVisualController::Create );
85   }
86
87   ~MeshVisualController()
88   {
89   }
90
91   // The Init signal is received once (only) during the Application lifetime
92   void Create( Application& application )
93   {
94     // Get a handle to the stage
95     Stage stage = Stage::GetCurrent();
96     stage.SetBackgroundColor( Vector4( 0.0, 0.5, 1.0, 1.0 ) );
97
98     //Set up root layer to receive touch gestures.
99     Layer rootLayer = stage.GetRootLayer();
100     rootLayer.RegisterProperty( "Tag", LAYER_TAG ); //Used to differentiate between different kinds of actor.
101     rootLayer.TouchSignal().Connect( this, &MeshVisualController::OnTouch );
102
103     //Place models on the scene.
104     SetupModels( rootLayer );
105
106     //Place buttons on the scene.
107     SetupButtons( rootLayer );
108
109     //Add a light to the scene.
110     SetupLight( rootLayer );
111
112     //Allow for exiting of the application via key presses.
113     stage.KeyEventSignal().Connect( this, &MeshVisualController::OnKeyEvent );
114   }
115
116   //Loads and adds the models to the scene, inside containers for hit detection.
117   void SetupModels( Layer layer )
118   {
119     //Add containers to house each renderer-holding-actor.
120     for( int i = 0; i < NUM_MESHES; i++ )
121     {
122       mContainers[i] = Actor::New();
123       mContainers[i].SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
124       mContainers[i].RegisterProperty( "Tag", MODEL_TAG ); //Used to differentiate between different kinds of actor.
125       mContainers[i].RegisterProperty( "Model", Property::Value( i ) ); //Used to index into the model.
126       mContainers[i].TouchSignal().Connect( this, &MeshVisualController::OnTouch );
127       layer.Add( mContainers[i] );
128     }
129
130     //Position each container individually on screen
131
132     //Main, central model
133     mContainers[0].SetSizeModeFactor( Vector3( MODEL_SCALE, MODEL_SCALE, 0.0f ) );
134     mContainers[0].SetParentOrigin( ParentOrigin::CENTER );
135     mContainers[0].SetAnchorPoint( AnchorPoint::CENTER );
136
137     //Top left model
138     mContainers[1].SetSizeModeFactor( Vector3( MODEL_SCALE / 3.0f, MODEL_SCALE / 3.0f, 0.0f ) );
139     mContainers[1].SetParentOrigin( Vector3( 0.05, 0.03, 0.5 ) ); //Offset from top left
140     mContainers[1].SetAnchorPoint( AnchorPoint::TOP_LEFT );
141
142     //Set up models
143     for( int i = 0; i < NUM_MESHES; i++ )
144     {
145       //Create control to display model
146       Control control = Control::New();
147       control.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
148       control.SetParentOrigin( ParentOrigin::CENTER );
149       control.SetAnchorPoint( AnchorPoint::CENTER );
150       mContainers[i].Add( control );
151
152       //Make model spin to demonstrate 3D
153       Animation rotationAnimation = Animation::New( 15.0f );
154       float spin = i % 2 == 0 ? 1.0f : -1.0f; //Make actors spin in different directions to better show independence.
155       rotationAnimation.AnimateBy( Property( control, Actor::Property::ORIENTATION ),
156                                    Quaternion( Degree( 0.0f ), Degree( spin * 360.0f ), Degree( 0.0f ) ) );
157       rotationAnimation.SetLooping( true );
158       rotationAnimation.Play();
159
160       //Store model information in corresponding structs.
161       mModels[i].control = control;
162       mModels[i].rotation.x = 0.0f;
163       mModels[i].rotation.y = 0.0f;
164       mModels[i].rotationAnimation = rotationAnimation;
165     }
166
167     //Calling this sets the model in the controls.
168     ReloadModel();
169   }
170
171   //Place the various buttons on the bottom of the screen, with title labels where necessary.
172   void SetupButtons( Layer layer )
173   {
174     //Actor for positioning model and shading mode buttons.
175     Actor positionActorModel = Actor::New();
176     positionActorModel.SetParentOrigin( Vector3( BUTTONS_OFFSET_SIDE, 1.0 - BUTTONS_OFFSET_BOTTOM, 0.5 ) );
177     positionActorModel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
178     layer.Add( positionActorModel );
179
180     //Create button for model changing.
181     PushButton modelButton = Toolkit::PushButton::New();
182     modelButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
183     modelButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeModelClicked );
184     modelButton.SetParentOrigin( ParentOrigin::TOP_CENTER );
185     modelButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
186     modelButton.SetLabelText( "Model" );
187     positionActorModel.Add( modelButton );
188
189     //Create button for shading mode changing.
190     PushButton shadingModeButton = Toolkit::PushButton::New();
191     shadingModeButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
192     shadingModeButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeShadingModeClicked );
193     shadingModeButton.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
194     shadingModeButton.SetAnchorPoint( AnchorPoint::TOP_CENTER );
195     shadingModeButton.SetLabelText( "Shading Mode" );
196     positionActorModel.Add( shadingModeButton );
197
198     //Text label title for changing model or shading mode.
199     TextLabel changeTitleLabel = TextLabel::New( "Change" );
200     changeTitleLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
201     changeTitleLabel.SetProperty( TextLabel::Property::UNDERLINE, "{\"thickness\":\"2.0\"}" );
202     changeTitleLabel.SetParentOrigin( ParentOrigin::TOP_CENTER );
203     changeTitleLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
204     modelButton.Add( changeTitleLabel );
205
206     //Create button for pausing animations.
207     PushButton pauseButton = Toolkit::PushButton::New();
208     pauseButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
209     pauseButton.ClickedSignal().Connect( this, &MeshVisualController::OnPauseClicked );
210     pauseButton.SetParentOrigin( Vector3( 0.5, 1.0 - BUTTONS_OFFSET_BOTTOM, 0.5 ) );
211     pauseButton.SetAnchorPoint( AnchorPoint::CENTER );
212     pauseButton.SetLabelText( PAUSE );
213     layer.Add( pauseButton );
214
215     //Actor for positioning light position buttons.
216     Actor positionActorLight = Actor::New();
217     positionActorLight.SetParentOrigin( Vector3( 1.0 - BUTTONS_OFFSET_SIDE, 1.0 - BUTTONS_OFFSET_BOTTOM, 0.5 ) );
218     positionActorLight.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
219     layer.Add( positionActorLight );
220
221     //Create button for switching between manual and fixed light position.
222     PushButton lightModeButton = Toolkit::PushButton::New();
223     lightModeButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
224     lightModeButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeLightModeClicked );
225     lightModeButton.SetParentOrigin( ParentOrigin::TOP_CENTER );
226     lightModeButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
227     lightModeButton.SetLabelText( FIXED );
228     positionActorLight.Add( lightModeButton );
229
230     //Create button for switching between front and back light position.
231     PushButton lightSideButton = Toolkit::PushButton::New();
232     lightSideButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
233     lightSideButton.ClickedSignal().Connect( this, &MeshVisualController::OnChangeLightSideClicked );
234     lightSideButton.SetParentOrigin( ParentOrigin::BOTTOM_CENTER );
235     lightSideButton.SetAnchorPoint( AnchorPoint::TOP_CENTER );
236     lightSideButton.SetLabelText( FRONT );
237     positionActorLight.Add( lightSideButton );
238
239     //Text label title for light position mode.
240     TextLabel lightTitleLabel = TextLabel::New( "Light Position" );
241     lightTitleLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
242     lightTitleLabel.SetProperty( TextLabel::Property::UNDERLINE, "{\"thickness\":\"2.0\"}" );
243     lightTitleLabel.SetParentOrigin( ParentOrigin::TOP_CENTER );
244     lightTitleLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
245     lightModeButton.Add( lightTitleLabel );
246   }
247
248   //Add a point light source the the scene, on a layer above the first.
249   void SetupLight( Layer baseLayer )
250   {
251     //Create control to act as light source of scene.
252     mLightSource = Control::New();
253     mLightSource.RegisterProperty( "Tag", LIGHT_TAG );
254
255     //Set size of control based on screen dimensions.
256     Stage stage = Stage::GetCurrent();
257     if( stage.GetSize().width < stage.GetSize().height )
258     {
259       //Scale to width.
260       mLightSource.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH );
261       mLightSource.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
262       mLightSource.SetSizeModeFactor( Vector3( LIGHT_SCALE, 0.0f, 0.0f ) );
263     }
264     else
265     {
266       //Scale to height.
267       mLightSource.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::HEIGHT );
268       mLightSource.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
269       mLightSource.SetSizeModeFactor( Vector3( 0.0f, LIGHT_SCALE, 0.0f ) );
270     }
271
272     //Set position relative to top left, as the light source property is also relative to the top left.
273     mLightSource.SetParentOrigin( ParentOrigin::TOP_LEFT );
274     mLightSource.SetAnchorPoint( AnchorPoint::CENTER );
275     mLightSource.SetPosition( Stage::GetCurrent().GetSize().x * 0.85f, Stage::GetCurrent().GetSize().y * 0.125 );
276
277     //Supply an image to represent the light.
278     SetLightImage();
279
280     //Connect to touch signal for dragging.
281     mLightSource.TouchSignal().Connect( this, &MeshVisualController::OnTouch );
282
283     //Place the light source on a layer above the base, so that it is rendered above everything else.
284     Layer upperLayer = Layer::New();
285     upperLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
286     upperLayer.SetParentOrigin( ParentOrigin::CENTER );
287     upperLayer.SetAnchorPoint( AnchorPoint::CENTER );
288
289     baseLayer.Add( upperLayer );
290     upperLayer.Add( mLightSource );
291
292     //Decide which light to use to begin with.
293     SetLightMode();
294   }
295
296   //Sets the image to use for the light source depending on whether the light is in front or behind.
297   void SetLightImage()
298   {
299     std::string imageUrl;
300
301     if( mLightFront )
302     {
303       imageUrl = LIGHT_URL_FRONT;
304     }
305     else
306     {
307       imageUrl = LIGHT_URL_BACK;
308     }
309
310     Property::Map lightMap;
311     lightMap.Insert( Visual::Property::TYPE, Visual::IMAGE );
312     lightMap.Insert( ImageVisual::Property::URL, imageUrl );
313     mLightSource.SetProperty( Control::Property::BACKGROUND, Property::Value( lightMap ) );
314   }
315
316   //Updates the displayed models to account for parameter changes.
317   void ReloadModel()
318   {
319     //Create mesh property map
320     Property::Map map;
321     map.Insert( Visual::Property::TYPE,  Visual::MESH );
322     map.Insert( MeshVisual::Property::OBJECT_URL, MODEL_FILE_TABLE[mModelIndex] );
323     map.Insert( MeshVisual::Property::MATERIAL_URL, MATERIAL_FILE_TABLE[mModelIndex] );
324     map.Insert( MeshVisual::Property::TEXTURES_PATH, TEXTURES_PATH );
325     map.Insert( MeshVisual::Property::SHADING_MODE, SHADING_MODE_TABLE[mShadingModeIndex] );
326
327     //Set the two controls to use the mesh
328     for( int i = 0; i < NUM_MESHES; i++ )
329     {
330       mModels[i].control.SetProperty( Control::Property::BACKGROUND, Property::Value( map ) );
331     }
332   }
333
334   //Set the mode used to light the models.
335   void SetLightMode()
336   {
337     if( mLightFixed )
338     {
339       UseFixedLight();
340     }
341     else
342     {
343       UseManualLight();
344     }
345   }
346
347   //Make the models use a fixed, invisible light above the center of the stage.
348   void UseFixedLight()
349   {
350     //Hide draggable source
351     mLightSource.SetVisible( false );
352
353     //Use stage dimensions to place light at center, offset in z axis.
354     Stage stage = Stage::GetCurrent();
355     float width = stage.GetSize().width;
356     float height = stage.GetSize().height;
357     Vector3 lightPosition = Vector3( width / 2.0f, height / 2.0f,
358                                      ( mLightFront ? 1 : -1 ) * std::max( width, height ) * 5.0f );
359
360     //Set global light position
361     for( int i = 0; i < NUM_MESHES; ++i )
362     {
363       mModels[i].control.RegisterProperty( "lightPosition", lightPosition, Property::ANIMATABLE );
364     }
365   }
366
367   //Make the models use a light source that the user can drag around.
368   void UseManualLight()
369   {
370     //Show draggable source
371     mLightSource.SetVisible( true );
372
373     //Update to switch light position of models to that of the source.
374     UpdateLight();
375   }
376
377   //Updates the light position for each model to account for changes in the source on screen.
378   void UpdateLight()
379   {
380     //Set light position to the x and y of the light control, offset into/out of the screen.
381     Vector3 controlPosition = mLightSource.GetCurrentPosition();
382     Vector3 lightPosition = Vector3( controlPosition.x, controlPosition.y,
383                                      ( mLightFront ? 1 : -1 ) * Stage::GetCurrent().GetSize().x / 2.0f );
384
385     for( int i = 0; i < NUM_MESHES; ++i )
386     {
387       mModels[i].control.RegisterProperty( "lightPosition", lightPosition, Property::ANIMATABLE );
388     }
389   }
390
391   //If the light source is touched, move it by dragging it.
392   //If a model is touched, rotate it by panning around.
393   bool OnTouch( Actor actor, const TouchData& touch )
394   {
395     switch( touch.GetState( 0 ) )
396     {
397       case PointState::DOWN:
398       {
399         //Determine what was touched.
400         actor.GetProperty( actor.GetPropertyIndex( "Tag" ) ).Get( mTag );
401
402         if( mTag == MODEL_TAG )
403         {
404           //Find out which model has been selected
405           actor.GetProperty( actor.GetPropertyIndex( "Model" ) ).Get( mSelectedModelIndex );
406
407           //Pause current animation, as the touch gesture will be used to manually rotate the model
408           mModels[mSelectedModelIndex].rotationAnimation.Pause();
409
410           //Store start points.
411           mPanStart = touch.GetScreenPosition( 0 );
412           mRotationStart = mModels[mSelectedModelIndex].rotation;
413         }
414
415         break;
416       }
417       case PointState::MOTION:
418       {
419         //Switch on the kind of actor we're interacting with.
420         switch( mTag )
421         {
422           case MODEL_TAG: //Rotate model
423           {
424             //Calculate displacement and corresponding rotation.
425             Vector2 displacement = touch.GetScreenPosition( 0 ) - mPanStart;
426             mModels[mSelectedModelIndex].rotation = Vector2( mRotationStart.x - displacement.y / Y_ROTATION_DISPLACEMENT_FACTOR,   // Y displacement rotates around X axis
427                                                              mRotationStart.y + displacement.x / X_ROTATION_DISPLACEMENT_FACTOR ); // X displacement rotates around Y axis
428             Quaternion rotation = Quaternion( Radian( mModels[mSelectedModelIndex].rotation.x ), Vector3::XAXIS) *
429                                   Quaternion( Radian( mModels[mSelectedModelIndex].rotation.y ), Vector3::YAXIS);
430
431             //Apply rotation.
432             mModels[mSelectedModelIndex].control.SetOrientation( rotation );
433
434             break;
435           }
436           case LIGHT_TAG: //Drag light
437           {
438             //Set light source to new position and update the models accordingly.
439             mLightSource.SetPosition( Vector3( touch.GetScreenPosition( 0 ) ) );
440             UpdateLight();
441
442             break;
443           }
444         }
445
446         break;
447       }
448       case PointState::INTERRUPTED: //Same as finished.
449       case PointState::FINISHED:
450       {
451         if( mTag == MODEL_TAG )
452         {
453           //Return to automatic animation
454           if( !mPaused )
455           {
456             mModels[mSelectedModelIndex].rotationAnimation.Play();
457           }
458         }
459
460         break;
461       }
462       default:
463       {
464         //Other touch states do nothing.
465         break;
466       }
467     }
468
469     return true;
470   }
471
472   //Cycle through the list of models.
473   bool OnChangeModelClicked( Toolkit::Button button )
474   {
475     ++mModelIndex %= 3;
476
477     ReloadModel();
478
479     return true;
480   }
481
482   //Cycle through the list of shading modes.
483   bool OnChangeShadingModeClicked( Toolkit::Button button )
484   {
485     ++mShadingModeIndex %= 3;
486
487     ReloadModel();
488
489     return true;
490   }
491
492   //Pause all animations, and keep them paused even after user panning.
493   //This button is a toggle, so pressing again will start the animations again.
494   bool OnPauseClicked( Toolkit::Button button )
495   {
496     //Toggle pause state.
497     mPaused = !mPaused;
498
499     //If we wish to pause animations, do so and keep them paused.
500     if( mPaused )
501     {
502       for( int i = 0; i < NUM_MESHES ; ++i )
503       {
504         mModels[i].rotationAnimation.Pause();
505       }
506
507       button.SetLabelText( PLAY );
508     }
509     else //Unpause all animations again.
510     {
511       for( int i = 0; i < NUM_MESHES ; ++i )
512       {
513         mModels[i].rotationAnimation.Play();
514       }
515
516       button.SetLabelText( PAUSE );
517     }
518
519     return true;
520   }
521
522
523   //Switch between a fixed light source above/behind the screen, and a light source the user can drag around.
524   bool OnChangeLightModeClicked( Toolkit::Button button )
525   {
526     //Toggle state.
527     mLightFixed = !mLightFixed;
528
529     if( mLightFixed )
530     {
531       button.SetLabelText( FIXED );
532     }
533     else
534     {
535       button.SetLabelText( MANUAL );
536     }
537
538     SetLightMode();
539
540     return true;
541   }
542
543   //Switch between the light being in front of and behind the models.
544   bool OnChangeLightSideClicked( Toolkit::Button button )
545   {
546     //Toggle state.
547     mLightFront = !mLightFront;
548
549     if( mLightFront )
550     {
551       button.SetLabelText( FRONT );
552     }
553     else
554     {
555       button.SetLabelText( BACK );
556     }
557
558     //Change light image.
559     SetLightImage();
560
561     //Update light to account for the change.
562     SetLightMode();
563
564     return true;
565   }
566
567   //If escape or the back button is pressed, quit the application (and return to the launcher)
568   void OnKeyEvent( const KeyEvent& event )
569   {
570     if( event.state == KeyEvent::Down )
571     {
572       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
573       {
574         mApplication.Quit();
575       }
576     }
577   }
578
579 private:
580   Application&  mApplication;
581
582   //The models displayed on screen, including information about rotation.
583   Model mModels[NUM_MESHES];
584   Actor mContainers[NUM_MESHES];
585
586   //Acts as a global light source, which can be dragged around.
587   Control mLightSource;
588
589   //Used to detect panning to rotate the selected model.
590   Vector2 mPanStart;
591   Vector2 mRotationStart;
592
593   int mModelIndex; //Index of model to load.
594   int mShadingModeIndex; //Index of shading mode to use.
595   int mTag; //Identifies what kind of actor has been selected in OnTouch.
596   int mSelectedModelIndex; //Index of model selected on screen.
597   bool mPaused; //If true, all animations are paused and should stay so.
598   bool mLightFixed; //If false, the light is in manual.
599   bool mLightFront; //Bool for light being in front or behind the models.
600 };
601
602 // Entry point for Linux & Tizen applications
603 //
604 int main( int argc, char **argv )
605 {
606   Application application = Application::New( &argc, &argv );
607   MeshVisualController test( application );
608   application.MainLoop();
609   return 0;
610 }