diff --git a/build/tizen/CMakeLists.txt b/build/tizen/CMakeLists.txt
index 1f119ad..168d55e 100644
--- a/build/tizen/CMakeLists.txt
+++ b/build/tizen/CMakeLists.txt
@@ -29,6 +29,7 @@ ENDIF()
SET(RESOURCE_DIR ${ROOT_SRC_DIR}/resources)
SET(LOCAL_IMAGES_DIR ${RESOURCE_DIR}/images)
+SET(LOCAL_GAME_DIR ${RESOURCE_DIR}/game)
SET(LOCAL_VIDEOS_DIR ${RESOURCE_DIR}/videos)
SET(LOCAL_MODELS_DIR ${RESOURCE_DIR}/models)
SET(LOCAL_SCRIPTS_DIR ${RESOURCE_DIR}/scripts)
@@ -37,6 +38,7 @@ IF(NOT DEFINED LOCAL_STYLE_DIR)
ENDIF()
SET(IMAGES_DIR ${APP_DATA_RES_DIR}/images/)
+SET(GAME_DIR ${APP_DATA_RES_DIR}/game/)
SET(VIDEOS_DIR ${APP_DATA_RES_DIR}/videos/)
SET(MODELS_DIR ${APP_DATA_RES_DIR}/models/)
SET(SCRIPTS_DIR ${APP_DATA_RES_DIR}/scripts/)
@@ -46,6 +48,7 @@ IF(NOT DEFINED LOCALE_DIR)
SET(LOCALE_DIR ${PREFIX}/share/locale)
ENDIF()
+SET(DEMO_GAME_DIR \\"${GAME_DIR}\\")
SET(DEMO_IMAGE_DIR \\"${IMAGES_DIR}\\")
SET(DEMO_VIDEO_DIR \\"${VIDEOS_DIR}\\")
SET(DEMO_MODEL_DIR \\"${MODELS_DIR}\\")
@@ -88,6 +91,11 @@ FOREACH(flag ${LOCAL_SCRIPTS_LIST})
INSTALL(FILES ${LOCAL_SCRIPTS_DIR}/${flag} DESTINATION ${SCRIPTS_DIR})
ENDFOREACH(flag)
+FILE(GLOB LOCAL_GAME_LIST RELATIVE "${LOCAL_GAME_DIR}" "${LOCAL_GAME_DIR}/*.*")
+FOREACH(flag ${LOCAL_GAME_LIST})
+ INSTALL(FILES ${LOCAL_GAME_DIR}/${flag} DESTINATION ${GAME_DIR})
+ENDFOREACH(flag)
+
#Create resources location file
CONFIGURE_FILE( resources-location.in ${DEMO_SHARED}/resources-location.cpp )
@@ -122,7 +130,7 @@ FOREACH(flag ${REQUIRED_PKGS_CFLAGS})
SET(REQUIRED_CFLAGS "${REQUIRED_CFLAGS} ${flag}")
ENDFOREACH(flag)
-SET(DALI_DEMO_CFLAGS "-DDEMO_IMAGE_DIR=${DEMO_IMAGE_DIR} -DDEMO_VIDEO_DIR=${DEMO_VIDEO_DIR} -DDEMO_MODEL_DIR=${DEMO_MODEL_DIR} -DDEMO_SCRIPT_DIR=${DEMO_SCRIPT_DIR} -DDEMO_STYLE_DIR=${DEMO_STYLE_DIR} -DDEMO_THEME_PATH=${DEMO_THEME_PATH} -DDEMO_EXAMPLE_BIN=${DEMO_EXAMPLE_BIN} -DDEMO_LOCALE_DIR=${DEMO_LOCALE_DIR} -fvisibility=hidden -DHIDE_DALI_INTERNALS -DDEMO_LANG=${DEMO_LANG}")
+SET(DALI_DEMO_CFLAGS "-DDEMO_GAME_DIR=${DEMO_GAME_DIR} -DDEMO_IMAGE_DIR=${DEMO_IMAGE_DIR} -DDEMO_VIDEO_DIR=${DEMO_VIDEO_DIR} -DDEMO_MODEL_DIR=${DEMO_MODEL_DIR} -DDEMO_SCRIPT_DIR=${DEMO_SCRIPT_DIR} -DDEMO_STYLE_DIR=${DEMO_STYLE_DIR} -DDEMO_THEME_PATH=${DEMO_THEME_PATH} -DDEMO_EXAMPLE_BIN=${DEMO_EXAMPLE_BIN} -DDEMO_LOCALE_DIR=${DEMO_LOCALE_DIR} -fvisibility=hidden -DHIDE_DALI_INTERNALS -DDEMO_LANG=${DEMO_LANG}")
###########################################################################
# Internationalization
diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml
index 14e92da..2a03e2a 100644
--- a/com.samsung.dali-demo.xml
+++ b/com.samsung.dali-demo.xml
@@ -172,4 +172,7 @@
+
+
+
diff --git a/demo/dali-demo.cpp b/demo/dali-demo.cpp
index 8c8142a..c879617 100644
--- a/demo/dali-demo.cpp
+++ b/demo/dali-demo.cpp
@@ -84,6 +84,7 @@ int DALI_EXPORT_API main(int argc, char **argv)
demo.AddExample(Example("sparkle.example", DALI_DEMO_STR_TITLE_SPARKLE));
demo.AddExample(Example("progress-bar.example", DALI_DEMO_STR_TITLE_PROGRESS_BAR));
demo.AddExample(Example("contact-cards.example", DALI_DEMO_STR_TITLE_CONTACT_CARDS));
+ demo.AddExample(Example("fpp-game.example", DALI_DEMO_STR_TITLE_FPP_GAME));
demo.SortAlphabetically( true );
diff --git a/examples/fpp-game/fpp-game-example.cpp b/examples/fpp-game/fpp-game-example.cpp
new file mode 100644
index 0000000..211028f
--- /dev/null
+++ b/examples/fpp-game/fpp-game-example.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "game-renderer.h"
+#include "game-model.h"
+#include "game-texture.h"
+#include "game-scene.h"
+
+#include "fpp-game-tutorial-controller.h"
+
+#include
+
+using namespace Dali;
+
+namespace
+{
+
+const char* SCENE_URL =
+{
+ DEMO_GAME_DIR "/scene.json"
+};
+
+}
+/* This example creates 3D environment with first person camera control
+ It contains following modules:
+
+ GameScene - responsible for loading and managing the scene data,
+ it wraps around stage. Owns list of entities. Scene can be deserialised
+ from json file ( see scene.json )
+ GameEntity - the renderable object that has also a transformation. It wraps DALi actors.
+
+ GameModel - loads models ( '.mod' file format ) and wraps DALi Geometry object. 'mod' format
+ is binary in order
+
+ GameTexture - manages textures. Loads them, creates samplers and wraps DALi TextureSet
+
+ GameRenderer - binds texture and model. It's created per entity. While renderer is always unique
+ for entity, the texture and model may be reused
+
+ GameCamera - Wraps the CameraActor. It provides not only that but also handles user input and
+ implements first-person-perspective camera behavior.
+ GameCamera uses Dali::Timer to provide per-frame ( or rather every 16ms ) update tick.
+
+
+ .-----------.
+ .---------------| GameScene |---------------.
+ | '-----------' |
+ | | |
+ v | v
+ .------------. .------------.|.------------. .------------.
+ | GameEntity | | GameEntity |v| ... | | GameEntity |
+ '------------' '------------' '------------' '------------'
+ |
+ v
+ .--------------.
+ | GameRenderer |
+ '--------------'
+ |
+ <------'-------->
+.--------------. .--------------.
+| GameTexture | | GameModel |
+'--------------' '--------------'
+ */
+class GameController : public ConnectionTracker
+{
+public:
+
+ GameController( Application& application )
+ : mApplication( application )
+ {
+ // Connect to the Application's Init signal
+ mApplication.InitSignal().Connect( this, &GameController::Create );
+ }
+
+ ~GameController()
+ {
+ }
+
+ // The Init signal is received once (only) during the Application lifetime
+ void Create( Application& application )
+ {
+ // Disable indicator
+ Dali::Window winHandle = application.GetWindow();
+ winHandle.ShowIndicator( Dali::Window::INVISIBLE );
+
+ // Get a handle to the stage
+ mStage = Stage::GetCurrent();
+
+ mStage.SetBackgroundColor( Color::BLACK );
+
+ // Use 3D layer
+ mStage.GetRootLayer().SetBehavior( Layer::LAYER_3D );
+
+ // Load game scene
+ mScene.Load( SCENE_URL );
+
+ // Display tutorial
+ mTutorialController.DisplayTutorial();
+
+ // Connect OnKeyEvent signal
+ mStage.KeyEventSignal().Connect( this, &GameController::OnKeyEvent );
+ }
+
+ // Handle a quit key event
+ void OnKeyEvent(const KeyEvent& event)
+ {
+ if(event.state == KeyEvent::Down)
+ {
+ if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
+ {
+ mApplication.Quit();
+ }
+ }
+ }
+
+private:
+
+ Application& mApplication;
+ GameScene mScene;
+ Stage mStage;
+ FppGameTutorialController mTutorialController;
+};
+
+void RunTest( Application& application )
+{
+ GameController test( application );
+
+ application.MainLoop();
+}
+
+// Entry point for Linux & Tizen applications
+//
+int DALI_EXPORT_API main( int argc, char **argv )
+{
+ Application application = Application::New( &argc, &argv );
+
+ RunTest( application );
+
+ return 0;
+}
diff --git a/examples/fpp-game/fpp-game-tutorial-controller.cpp b/examples/fpp-game/fpp-game-tutorial-controller.cpp
new file mode 100644
index 0000000..ec97bb8
--- /dev/null
+++ b/examples/fpp-game/fpp-game-tutorial-controller.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "fpp-game-tutorial-controller.h"
+
+#include
+#include
+#include
+#include
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+FppGameTutorialController::FppGameTutorialController()
+: mLeftTutorialComplete( false ),
+ mRightTutorialComplete( false )
+{
+
+}
+
+FppGameTutorialController::~FppGameTutorialController()
+{
+
+}
+
+void FppGameTutorialController::OnTouch( const TouchData& touchEvent )
+{
+ Vector2 size( mStage.GetSize() );
+
+ bool isLandscape( size.x > size.y );
+
+ if( !isLandscape )
+ {
+ std::swap( size.x, size.y );
+ }
+
+ Vector2 sizeHalf( size * 0.5f );
+
+ for( size_t i = 0; i < touchEvent.GetPointCount(); ++i )
+ {
+ Vector2 pos = touchEvent.GetScreenPosition( i );
+ if( !isLandscape )
+ {
+ std::swap( pos.x, pos.y );
+ }
+
+ // left label touched
+ if( touchEvent.GetState( i ) == PointState::STARTED )
+ {
+ if( pos.x < sizeHalf.x && !mLeftTutorialComplete )
+ {
+ mLeftTutorialComplete = true;
+ Animation animation = Animation::New( 1.0f );
+ animation.AnimateTo( Property( mLeftLabel, Actor::Property::COLOR_ALPHA ), 0.0f );
+
+ // connect complete signal
+ if( mRightTutorialComplete )
+ {
+ animation.FinishedSignal().Connect( this, &FppGameTutorialController::OnTutorialComplete );
+ }
+ animation.Play();
+ }
+ // right label touched
+ else if( !mRightTutorialComplete )
+ {
+ mRightTutorialComplete = true;
+ Animation animation = Animation::New( 1.0f );
+ animation.AnimateTo( Property( mRightLabel, Actor::Property::COLOR_ALPHA ), 0.0f );
+ // connect complete signal
+ if( mLeftTutorialComplete )
+ {
+ animation.FinishedSignal().Connect( this, &FppGameTutorialController::OnTutorialComplete );
+ }
+ animation.Play();
+ }
+ }
+ }
+}
+
+void FppGameTutorialController::DisplayTutorial()
+{
+ mStage = Stage::GetCurrent();
+
+ Vector2 stageSize( mStage.GetSize() );
+ bool isLandscape( stageSize.x > stageSize.y );
+ if( !isLandscape )
+ {
+ std::swap( stageSize.x, stageSize.y );
+ }
+
+ mUiRoot = Actor::New();
+ mStage.Add( mUiRoot );
+
+ // left tutorial text label
+ mLeftLabel = Toolkit::TextLabel::New("Touch here to walk");
+ mLeftLabel.SetParentOrigin( ParentOrigin::CENTER );
+ mLeftLabel.SetAnchorPoint( AnchorPoint::CENTER );
+ mLeftLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+ mLeftLabel.SetSize( Vector3( stageSize.x*0.5, stageSize.y, 1.0f ) );
+ mLeftLabel.SetProperty( Toolkit::Control::Property::BACKGROUND_COLOR, Vector4( 0.0, 0.0, 0.7, 0.2 ));
+ mLeftLabel.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); // White.
+ mLeftLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
+ mLeftLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
+
+ // right tutorial text label
+ mRightLabel = Toolkit::TextLabel::New("Touch here to look around");
+ mRightLabel.SetParentOrigin( ParentOrigin::CENTER );
+ mRightLabel.SetAnchorPoint( AnchorPoint::CENTER );
+ mRightLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+ mRightLabel.SetSize( Vector3( stageSize.x*0.5, stageSize.y, 1.0f ) );
+ mRightLabel.SetProperty( Toolkit::Control::Property::BACKGROUND_COLOR, Vector4( 0.5, 0.0, 0.0, 0.2 ));
+ mRightLabel.SetProperty( Toolkit::TextLabel::Property::TEXT_COLOR, Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); // White.
+ mRightLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
+ mRightLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
+
+ // create camera dedicated to be used with UI controls
+ CameraActor uiCamera = CameraActor::New();
+ mTutorialRenderTask = mStage.GetRenderTaskList().CreateTask();
+ mTutorialRenderTask.SetCameraActor( uiCamera );
+ mTutorialRenderTask.SetClearEnabled( false );
+ mTutorialRenderTask.SetSourceActor( mUiRoot );
+ mTutorialRenderTask.SetExclusive( true );
+
+ if( !isLandscape )
+ {
+ uiCamera.RotateBy( Degree(90.0f), Vector3( 0.0f, 0.0f, 1.0f ));
+ }
+
+ mLeftLabel.SetPosition( Vector3( -stageSize.x*0.25f, 0.0, 0.0 ) );
+ mRightLabel.SetPosition( Vector3( stageSize.x*0.25f, 0.0, 0.0 ) );
+
+ mUiRoot.Add( mLeftLabel );
+ mUiRoot.Add( mRightLabel );
+ mStage.Add( uiCamera );
+
+ Animation animation = Animation::New( 1.0f );
+ animation.AnimateTo( Property( mLeftLabel, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_OUT );
+ animation.AnimateTo( Property( mRightLabel, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_OUT );
+
+ animation.FinishedSignal().Connect( this, &FppGameTutorialController::OnTutorialAnimationFinished );
+
+ animation.Play();
+}
+
+void FppGameTutorialController::OnTutorialAnimationFinished( Animation& animation )
+{
+ // touch signal will wait for a single touch on each side of screen
+ mStage.TouchSignal().Connect( this, &FppGameTutorialController::OnTouch );
+}
+
+void FppGameTutorialController::OnTutorialComplete( Animation& animation )
+{
+ mStage.Remove( mUiRoot );
+ mUiRoot.Reset();
+ mStage.GetRenderTaskList().RemoveTask( mTutorialRenderTask );
+}
+
diff --git a/examples/fpp-game/fpp-game-tutorial-controller.h b/examples/fpp-game/fpp-game-tutorial-controller.h
new file mode 100644
index 0000000..897a922
--- /dev/null
+++ b/examples/fpp-game/fpp-game-tutorial-controller.h
@@ -0,0 +1,75 @@
+#ifndef FPPGAMETUTORIAL_H
+#define FPPGAMETUTORIAL_H
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+class FppGameTutorialController : public Dali::ConnectionTracker
+{
+public:
+
+ /**
+ * Creates new instance of FppGameTutorialController
+ */
+ FppGameTutorialController();
+
+ /**
+ * Destroys instance of FppGameTutorialController
+ */
+ ~FppGameTutorialController();
+
+ /**
+ * Displays UI with tutorial
+ */
+ void DisplayTutorial();
+
+ /**
+ * Handles tutorial touch input
+ * @param[in] touchEvent Incoming touch event in the UI space
+ */
+ void OnTouch( const Dali::TouchData& touchEvent );
+
+ /**
+ * Handles tutorial animation finished signal
+ * @param[in] animation Animation object
+ */
+ void OnTutorialAnimationFinished( Dali::Animation& animation );
+
+ /**
+ * Handles tutorial completion stage
+ * @param animation Animation object
+ */
+ void OnTutorialComplete( Dali::Animation& animation );
+
+private:
+
+ Dali::RenderTask mTutorialRenderTask; /// RenderTask associated with rendering tutorial
+ Dali::Actor mUiRoot; /// The parent actor for tutorial UI
+ Dali::Toolkit::TextLabel mLeftLabel; /// Text label displaying left message
+ Dali::Toolkit::TextLabel mRightLabel; /// Text label displaying right message
+ bool mLeftTutorialComplete; /// Flag indicating the walk (left) tutorial action has been performed
+ bool mRightTutorialComplete; /// Flag indicating the look (right) tutorial action has been performed
+ Dali::Stage mStage;
+};
+
+#endif // FPPGAMETUTORIAL_H
diff --git a/examples/fpp-game/game-camera.cpp b/examples/fpp-game/game-camera.cpp
new file mode 100644
index 0000000..7215c5a
--- /dev/null
+++ b/examples/fpp-game/game-camera.cpp
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "game-camera.h"
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace Dali;
+
+namespace
+{
+// Input sensitivity, the larger value, the more sensitive input
+// Default value has been chosen empirically
+const float CAMERA_SENSITIVITY ( 90.0f );
+
+// Vertical angle limit of the camera
+const float CAMERA_VERTICAL_LIMIT ( 80.0f );
+
+// Position where camera is instantiated by default
+const Vector3 CAMERA_DEFAULT_POSITION ( 1.0f, -1.5f, -3.0f );
+
+// Field-of-View in degrees
+const float CAMERA_DEFAULT_FOV ( 60.0f );
+
+// Near plane
+const float CAMERA_DEFAULT_NEAR ( 0.1f );
+
+// Far plane
+const float CAMERA_DEFAULT_FAR ( 100.0f );
+
+// Default forward vector
+const Vector3 CAMERA_FORWARD ( 0.0f, 0.0f, 1.0f );
+
+// Default up vector
+const Vector3 CAMERA_UP ( Vector3::YAXIS );
+}
+
+GameCamera::GameCamera()
+: mFovY( CAMERA_DEFAULT_FOV ),
+ mNear( CAMERA_DEFAULT_NEAR ),
+ mFar( CAMERA_DEFAULT_FAR ),
+ mWalkingTouchId( -1 ),
+ mLookingTouchId( -1 ),
+ mPortraitMode( false )
+{
+}
+
+GameCamera::~GameCamera()
+{
+ mTimer.Stop();
+ mCameraActor.Remove( mInterceptorActor );
+}
+
+void GameCamera::Initialise( float fovY, float near, float far )
+{
+ mFovY = fovY;
+ mNear = near;
+ mFar = far;
+
+ Vector2 stageSize = Stage::GetCurrent().GetSize();
+ mPortraitMode = stageSize.x < stageSize.y ? true : false;
+
+ // Initialise default camera
+ InitialiseDefaultCamera();
+
+ // Create input interceptor actor
+ CreateInterceptorActor();
+
+ // Start timer
+ mTimer = Timer::New( 16 );
+ mTimer.TickSignal().Connect( this, &GameCamera::OnTick );
+ mTimer.Start();
+}
+
+bool GameCamera::OnTick()
+{
+ Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+ // ---------------------------------------------------------------------
+ // update rotation
+ Vector2 tmp( mScreenLookDelta );
+ mScreenLookDelta = Vector2::ZERO;
+
+ if( mPortraitMode )
+ {
+ float yaw = ( (tmp.y / stageSize.y ) * CAMERA_SENSITIVITY );
+ float pitch = ( (tmp.x / stageSize.x ) * CAMERA_SENSITIVITY );
+ mCameraYawPitch.y -= yaw;
+ mCameraYawPitch.x -= pitch;
+ if( abs( mCameraYawPitch.y ) > CAMERA_VERTICAL_LIMIT )
+ {
+ mCameraYawPitch.y = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.y < 0) ? -1.0f : 1.0f );
+ }
+ }
+ else
+ {
+ float yaw = ( (tmp.y / stageSize.x ) * CAMERA_SENSITIVITY );
+ float pitch = ( (tmp.x / stageSize.y ) * CAMERA_SENSITIVITY );
+ mCameraYawPitch.x -= yaw;
+ mCameraYawPitch.y -= pitch;
+ if( abs( mCameraYawPitch.x ) > CAMERA_VERTICAL_LIMIT )
+ {
+ mCameraYawPitch.x = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.x < 0) ? -1.0f : 1.0f );
+ }
+ }
+
+ Quaternion rotation;
+ Quaternion rotX( Degree( mCameraYawPitch.x), Vector3( 1.0f, 0.0f, 0.0f ) );
+ Quaternion rotY( Degree( mCameraYawPitch.y), Vector3( 0.0f, 1.0f, 0.0f ) );
+ if (mPortraitMode )
+ {
+ Quaternion rotZ( Degree( mPortraitMode ? 90.0 : 0.0f), Vector3( 0.0f, 0.0f, 1.0f ) );
+ rotation = ( rotZ * rotX * rotY );
+ }
+ else
+ {
+ rotation = ( rotY * rotX );
+ }
+ mCameraActor.SetOrientation( rotation );
+
+ // ---------------------------------------------------------------------
+ // update position
+ Vector3 position( mCameraPosition );
+
+ // Rotate CAMERA_FORWARD vector
+ Vector3 forwardVector = rotation.Rotate( CAMERA_FORWARD );
+
+ // Cancel vertical movement
+ forwardVector.y = 0.0f;
+
+ // Normalize
+ forwardVector.Normalize();
+
+ // compute sideways vector
+ Vector3 sidewaysVector = forwardVector.Cross( CAMERA_UP );
+
+ sidewaysVector.Normalize();
+
+ const float forwardSpeed( mScreenWalkDelta.y / stageSize.y );
+ const float sidewaysSpeed( mScreenWalkDelta.x / stageSize.x );
+
+ // Adjust walking speed
+ if ( mPortraitMode )
+ {
+ position += forwardVector * (forwardSpeed * 0.5f);
+ }
+ else
+ {
+ position += forwardVector * (-forwardSpeed * 0.5f);
+ }
+
+ position += sidewaysVector * (sidewaysSpeed * 0.5f);
+
+ mCameraActor.SetPosition( position );
+
+ mCameraPosition = position;
+
+ return true;
+}
+
+void GameCamera::InitialiseDefaultCamera()
+{
+ Stage stage = Stage::GetCurrent();
+ mCameraActor = stage.GetRenderTaskList().GetTask(0).GetCameraActor();
+ mCameraActor.SetName( "GameCamera" );
+ mCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
+ mCameraActor.SetParentOrigin( ParentOrigin::CENTER );
+ mCameraActor.SetFieldOfView( Radian( Degree( mFovY ) ) );
+
+ // should be read from file
+ mCameraActor.SetNearClippingPlane( mNear );
+ mCameraActor.SetFarClippingPlane( mFar );
+ mCameraActor.SetPosition( CAMERA_DEFAULT_POSITION );
+
+ // Camera position is shadowed in order to avoid using GetCurrentPosition()
+ mCameraPosition = CAMERA_DEFAULT_POSITION;
+}
+
+void GameCamera::CreateInterceptorActor()
+{
+ Stage stage = Stage::GetCurrent();
+
+ mInterceptorActor = Actor::New();
+ mInterceptorActor.SetName( "GameInputInterceptor" );
+ mInterceptorActor.SetSize( Vector3( stage.GetSize().x, stage.GetSize().y, 1 ) );
+ mInterceptorActor.SetPosition( Vector3( 0.0, 0.0, 1.0 ) );
+ mInterceptorActor.SetAnchorPoint( AnchorPoint::CENTER );
+ mInterceptorActor.SetParentOrigin( ParentOrigin::CENTER );
+ mCameraActor.Add( mInterceptorActor );
+
+ // Connect TouchSignal to interceptor actor
+ mInterceptorActor.TouchSignal().Connect( this, &GameCamera::OnTouch );
+}
+
+bool GameCamera::OnTouch( Actor actor, const TouchData& touch )
+{
+ Stage stage = Stage::GetCurrent();
+
+ for( int i = 0; i < (int)touch.GetPointCount() && i < 3; ++i )
+ {
+ int id = touch.GetDeviceId( i );
+ Vector2 tmp( touch.GetScreenPosition( i ) );
+ Vector2 position;
+ float halfWindowSize;
+ if( mPortraitMode )
+ {
+ position.x = tmp.y;
+ position.y = tmp.x;
+ halfWindowSize = stage.GetSize().y / 2;
+ }
+ else
+ {
+ position.x = tmp.x;
+ position.y = tmp.y;
+ halfWindowSize = stage.GetSize().x / 2;
+ }
+
+ // touch started
+ if( touch.GetState( i ) == PointState::STARTED )
+ {
+ // start looking
+ if( position.x > halfWindowSize && mLookingTouchId < 0 )
+ {
+ mLookingTouchId = id;
+ mOldTouchLookPosition = position;
+ }
+ // start walking
+ else if( position.x < halfWindowSize && mWalkingTouchId < 0 )
+ {
+ mWalkingTouchId = id;
+ mOldTouchWalkPosition = position;
+ mScreenWalkDelta = Vector2::ZERO;
+ }
+ }
+ else if( touch.GetState( i ) == PointState::FINISHED ||
+ touch.GetState( i ) == PointState::LEAVE ||
+ touch.GetState( i ) == PointState::INTERRUPTED
+ )
+ {
+ // terminate look
+ if( mLookingTouchId == id )
+ {
+ mScreenLookDelta = Vector2::ZERO;
+ mOldTouchLookPosition = Vector2::ZERO;
+ mLookingTouchId = -1;
+ }
+ // terminate walking
+ else if( mWalkingTouchId == id )
+ {
+ mScreenWalkDelta = Vector2::ZERO;
+ mOldTouchWalkPosition = Vector2::ZERO;
+ mWalkingTouchId = -1;
+ }
+ }
+ else // on motion
+ {
+ // update looking
+ if( mLookingTouchId == id )
+ {
+ mScreenLookDelta.x += ( position.x - mOldTouchLookPosition.x );
+ mScreenLookDelta.y += ( position.y - mOldTouchLookPosition.y );
+ mOldTouchLookPosition = position;
+ }
+ // update walking
+ else if ( mWalkingTouchId == id )
+ {
+ mScreenWalkDelta.x += ( position.x - mOldTouchWalkPosition.x );
+ mScreenWalkDelta.y += ( position.y - mOldTouchWalkPosition.y );
+ mOldTouchWalkPosition = position;
+ }
+ }
+ }
+ return true;
+}
diff --git a/examples/fpp-game/game-camera.h b/examples/fpp-game/game-camera.h
new file mode 100644
index 0000000..f1d6306
--- /dev/null
+++ b/examples/fpp-game/game-camera.h
@@ -0,0 +1,122 @@
+#ifndef GAME_CAMERA_H
+#define GAME_CAMERA_H
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include
+#include
+#include
+
+/**
+ * @brief The GameCamera class
+ * First-person camera implementation with handling user input
+ *
+ * GameCamera uses the DALi camera for displaying 3D game view.
+ * Additionally it handles simple user input by attaching fullscreen
+ * sized 'interceptor' Actor to the front of the CameraActor ( to be always
+ * parallel to the view ). It is necessary, as with changing camera orientation
+ * the the stage cannot be used as a touch signal receiver ( it will simply
+ * go offscreen with camera rotation ).
+ *
+ * DALi camera uses left-handed coordinate system.
+ *
+ * The control scheme assumes that left half of the screen is responsible for
+ * movement, the right half of screen is a rotation.
+ */
+class GameCamera : public Dali::ConnectionTracker
+{
+public:
+
+ /**
+ * Creates an instance of GameCamera
+ */
+ GameCamera();
+
+ /**
+ * Destroys an instance of GameCamera
+ */
+ ~GameCamera();
+
+ /**
+ * Initialise with given fovY, near, far
+ * @param[in] fovY Field of view in degrees
+ * @param[in] near Near plane
+ * @param[in] far Far Plane
+ */
+ void Initialise( float fov, float near, float far );
+
+ /**
+ * Retrieves actor associated with camera object
+ * @return Returns camera actor
+ */
+ Dali::CameraActor GetCameraActor();
+
+private:
+
+ /**
+ * Sets up a perspective camera using Dali default camera
+ */
+ void InitialiseDefaultCamera();
+
+ /**
+ * Creates 'interceptor' actor. Interceptor actor is always parallel
+ * to the camera and positioned little bit in front of it in order to
+ * intercept user input.
+ */
+ void CreateInterceptorActor();
+
+ /**
+ * Handles onTouch signal on the 'interceptor' actor
+ * @param[in] actor Actor receiving signal
+ * @param[in] touch Touch data
+ */
+ bool OnTouch( Dali::Actor actor, const Dali::TouchData& touch );
+
+ /**
+ * Handles camera tick() update
+ * @return true if continue running timer, false otherwise
+ */
+ bool OnTick();
+
+private:
+
+ Dali::CameraActor mCameraActor; /// Camera actor
+ Dali::Actor mInterceptorActor; /// Actor intercepting user input
+
+ Dali::Timer mTimer; /// Per-frame timer
+
+ Dali::Vector2 mScreenLookDelta; /// Look delta vector in screen space
+ Dali::Vector2 mScreenWalkDelta; /// Walk delta vector in screen space
+ Dali::Vector2 mOldTouchLookPosition; /// Previous look vector in screen space
+ Dali::Vector2 mOldTouchWalkPosition; /// Previuus walk vector in screen space
+
+ Dali::Vector2 mCameraYawPitch; /// Camera yaw-pitch angles
+
+ float mFovY; /// Camera field-of-view
+ float mNear; /// Near plane
+ float mFar; /// Far plane
+
+ int mWalkingTouchId; /// Touch device id bound to the walking action
+ int mLookingTouchId; /// Touch device id bound to the looking action
+
+ Dali::Vector3 mCameraPosition; /// Current camera position ( shadowing the actor position )
+
+ bool mPortraitMode; /// flag if window is in portrait mode ( physically stage width < height )
+};
+
+#endif
diff --git a/examples/fpp-game/game-container.h b/examples/fpp-game/game-container.h
new file mode 100644
index 0000000..d7cc40b
--- /dev/null
+++ b/examples/fpp-game/game-container.h
@@ -0,0 +1,82 @@
+#ifndef GAME_CONTAINER_H
+#define GAME_CONTAINER_H
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include
+
+
+/**
+ * GameContainer is a vector which owns heap-allocated objects.
+ * Unlike vector this will call delete on the stored pointers during destruction.
+ * For example, you can define a vector of heap-allocated Node objects:
+ * @code
+ * typedef GameContainer< GameEntity* > EntityArray;
+ *
+ * EntityArray entites;
+ * entites.PushBack( new GameEntity() );
+ * // container is now responsible for calling delete on GameEntity
+ *
+ * @endcode
+ */
+template< class T > class GameContainer : public Dali::Vector< T >
+{
+public:
+
+ typedef typename Dali::Vector< T >::Iterator Iterator;
+ typedef typename Dali::Vector< T >::ConstIterator ConstIterator;
+
+ /**
+ * Create a owner container.
+ */
+ GameContainer()
+ {
+ }
+
+ /**
+ * Non-virtual destructor; GameCache is not suitable as base class.
+ */
+ ~GameContainer()
+ {
+ Clear();
+ Dali::VectorBase::Release();
+ }
+
+ /**
+ * Destroy all of the elements in the container.
+ */
+ void Clear()
+ {
+ ConstIterator end = Dali::Vector< T >::End();
+ for( Iterator iter = Dali::Vector< T >::Begin(); iter != end; ++iter )
+ {
+ delete (*iter);
+ }
+ Dali::Vector< T >::Clear();
+ }
+
+private:
+
+ // Undefined copy constructor.
+ GameContainer( const GameContainer& );
+
+ // Undefined assignment operator.
+ GameContainer& operator=( const GameContainer& );
+};
+
+#endif // GAMECACHE_H
diff --git a/examples/fpp-game/game-entity.cpp b/examples/fpp-game/game-entity.cpp
new file mode 100644
index 0000000..fed76a1
--- /dev/null
+++ b/examples/fpp-game/game-entity.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "game-entity.h"
+#include "game-renderer.h"
+
+GameEntity::GameEntity( const char* name )
+{
+ mActor = Dali::Actor::New();
+ mActor.SetName( name );
+}
+
+GameEntity::~GameEntity()
+{
+}
+
+void GameEntity::UpdateRenderer()
+{
+ if( mActor.GetRendererCount() )
+ {
+ Dali::Renderer currentRenderer = mActor.GetRendererAt( 0 );
+ if( currentRenderer == mGameRenderer.GetRenderer() )
+ {
+ return;
+ }
+ mActor.RemoveRenderer( currentRenderer );
+ }
+ if( mGameRenderer.GetRenderer() )
+ {
+ mActor.AddRenderer( mGameRenderer.GetRenderer() );
+ }
+}
+
+GameRenderer& GameEntity::GetGameRenderer()
+{
+ return mGameRenderer;
+}
+
+Dali::Actor& GameEntity::GetActor()
+{
+ return mActor;
+}
+
+void GameEntity::SetLocation( const Dali::Vector3& loc )
+{
+ mActor.SetPosition( loc );
+}
+
+void GameEntity::SetRotation( const Dali::Quaternion& rot )
+{
+ mActor.SetOrientation( rot );
+}
+
+void GameEntity::SetScale( const Dali::Vector3& scale )
+{
+ mActor.SetScale( scale );
+}
+
+void GameEntity::SetSize( const Dali::Vector3& size )
+{
+ mActor.SetSize( size );
+}
diff --git a/examples/fpp-game/game-entity.h b/examples/fpp-game/game-entity.h
new file mode 100644
index 0000000..3601bdf
--- /dev/null
+++ b/examples/fpp-game/game-entity.h
@@ -0,0 +1,92 @@
+#ifndef GAME_ENTITY_H
+#define GAME_ENTITY_H
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "game-renderer.h"
+
+#include
+
+/**
+ * @brief The GameEntity class
+ * GameEntity wraps the Dali::Actor class and binds the GameRenderer with
+ * loaded entity. Entities are owned by the GameScene and populated when
+ * scene is being deserialized.
+ */
+class GameEntity
+{
+public:
+
+ /**
+ * Creates an instance of GameEntity with given name
+ * @param[in] name Name of created entity
+ */
+ GameEntity( const char* name );
+
+ /**
+ * Destroys an instance of GameEntity
+ */
+ ~GameEntity();
+
+ /**
+ * Returns the GameRenderer object
+ */
+ GameRenderer& GetGameRenderer();
+
+ /**
+ * Returns associated DALi actor
+ * @return Returns actor associated with this GameEntity
+ */
+ Dali::Actor& GetActor();
+
+ /**
+ * Sets location of entity
+ * @param[in] location Local position of entity
+ */
+ void SetLocation( const Dali::Vector3& location );
+
+ /**
+ * Sets rotation of entity
+ * @param[in] rotation Local rotation of entity
+ */
+ void SetRotation( const Dali::Quaternion& rotation );
+
+ /**
+ * Sets scale of entity
+ * @param[in] scale Local scale of entity
+ */
+ void SetScale( const Dali::Vector3& scale );
+
+ /**
+ * Sets size of entity
+ * @param[in] size Bounding box of entity
+ */
+ void SetSize( const Dali::Vector3& size );
+
+ /**
+ * Updates Dali::Renderer in case if anything changed ( geometry, texture, etc. )
+ */
+ void UpdateRenderer();
+
+private:
+
+ Dali::Actor mActor;
+ GameRenderer mGameRenderer;
+};
+
+#endif
diff --git a/examples/fpp-game/game-model.cpp b/examples/fpp-game/game-model.cpp
new file mode 100644
index 0000000..3e6a585
--- /dev/null
+++ b/examples/fpp-game/game-model.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "game-model.h"
+#include "game-utils.h"
+
+using namespace GameUtils;
+
+namespace
+{
+// 'MODV' tag stored in the big-endian (network) order
+const uint32_t MODV_TAG( 0x4D4F4456 );
+}
+
+GameModel::GameModel( const char *filename )
+ : mUniqueId( false ),
+ mIsReady( false )
+{
+ ByteArray bytes;
+ if( !LoadFile( filename, bytes ) )
+ {
+ return;
+ }
+
+ mHeader = *(reinterpret_cast( bytes.data() ));
+
+ // expect big-endian
+ if( MODV_TAG != mHeader.tag )
+ {
+ // jump to little-endian variant
+ mHeader = *(reinterpret_cast( bytes.data() + bytes.size()/2 ));
+ }
+
+ mVertexBuffer = Dali::PropertyBuffer::New( Dali::Property::Map().
+ Add( "aPosition", Dali::Property::VECTOR3 ).
+ Add( "aNormal", Dali::Property::VECTOR3 ).
+ Add( "aTexCoord", Dali::Property::VECTOR2 )
+ );
+
+ mVertexBuffer.SetData( bytes.data() + mHeader.dataBeginOffset, mHeader.vertexBufferSize/mHeader.vertexStride );
+
+ mGeometry = Dali::Geometry::New();
+ mGeometry.AddVertexBuffer( mVertexBuffer );
+ mGeometry.SetType( Dali::Geometry::TRIANGLES );
+
+ mUniqueId = HashString( filename );
+
+ mIsReady = true;
+}
+
+GameModel::~GameModel()
+{
+}
+
+Dali::Geometry& GameModel::GetGeometry()
+{
+ return mGeometry;
+}
+
+bool GameModel::IsReady()
+{
+ return mIsReady;
+}
+
+uint32_t GameModel::GetUniqueId()
+{
+ return mUniqueId;
+}
diff --git a/examples/fpp-game/game-model.h b/examples/fpp-game/game-model.h
new file mode 100644
index 0000000..0c38e0a
--- /dev/null
+++ b/examples/fpp-game/game-model.h
@@ -0,0 +1,96 @@
+#ifndef GAME_MODEL_H
+#define GAME_MODEL_H
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include
+#include
+
+#include
+
+/**
+ * @brief The ModelHeader struct
+ * Model file header structure
+ */
+struct ModelHeader
+{
+ uint32_t tag; /// 'MODV' tag
+ uint32_t version; /// File version
+ uint32_t vertexBufferSize; /// total size of the vertex buffer to allocate
+ uint32_t attributeCount; /// number of stored attributes
+ uint32_t attributeFormat[16]; /// format encoded as ((type << 16)|(count)); 'type' represents primitive type, 'count' represents number of components ( 1-4 )
+ uint32_t attributeOffset[16]; /// attribute offsets
+ uint32_t attributeSize[16]; /// attribute size in bytes
+ uint32_t vertexStride; /// vertex stride
+ uint32_t reserved; /// reserved, may point at additional structure
+ uint32_t dataBeginOffset; /// start of actual vertex data
+};
+
+/**
+ * @brief The GameModel class
+ * GameModel represents model geometry. It loads model data from external model file ( .mod file ).
+ * Such data is ready to be used as GL buffer so it can be copied directly into the PropertyBuffer
+ * object.
+ *
+ * Model file is multi-architecture so can be loaded on little and big endian architectures
+ */
+class GameModel
+{
+public:
+
+ /**
+ * Creates an instance of GameModel and loads the '.mod' file
+ * @param[in] filename Name of file to load
+ */
+ GameModel( const char* filename );
+
+ /**
+ * Destroys an instance of GameModel
+ */
+ ~GameModel();
+
+ /**
+ * Returns DALi geometry object
+ * @return Returns DALi geometry object
+ */
+ Dali::Geometry& GetGeometry();
+
+ /**
+ * Checks status of model, returns false if failed to load
+ * @return true if model has been loaded, false otherwise
+ */
+ bool IsReady();
+
+ /**
+ * Returns unique Id of the texture
+ * @return Unique Id
+ */
+ uint32_t GetUniqueId();
+
+private:
+
+ Dali::Geometry mGeometry;
+ Dali::PropertyBuffer mVertexBuffer;
+
+ ModelHeader mHeader;
+
+ uint32_t mUniqueId;
+ bool mIsReady;
+};
+
+#endif
diff --git a/examples/fpp-game/game-renderer.cpp b/examples/fpp-game/game-renderer.cpp
new file mode 100644
index 0000000..b578539
--- /dev/null
+++ b/examples/fpp-game/game-renderer.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "game-model.h"
+#include "game-texture.h"
+#include "game-renderer.h"
+
+#include
+
+namespace
+{
+
+const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
+ attribute highp vec3 aPosition;\n
+ attribute highp vec3 aNormal;\n
+ attribute highp vec2 aTexCoord;\n
+ uniform highp mat4 uMvpMatrix;\n
+ varying highp vec2 vTexCoord;\n
+ void main()\n
+ {\n
+ gl_Position = uMvpMatrix * vec4(aPosition, 1.0 );\n
+ vTexCoord = aTexCoord;\n
+ vTexCoord.y = 1.0 - vTexCoord.y;\n
+ }\n
+)
+ ;
+const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+ uniform sampler2D sTexture;\n
+ varying highp vec2 vTexCoord;\n
+ void main()\n
+ {\n
+ gl_FragColor = texture2D( sTexture, vTexCoord ) * vec4(1.2, 1.2, 1.2, 1.0);\n
+ }\n
+);
+
+}
+
+GameRenderer::GameRenderer()
+ : mModel( NULL ),
+ mTexture( NULL )
+{
+}
+
+GameRenderer::~GameRenderer()
+{
+}
+
+void GameRenderer::SetModel( GameModel* model )
+{
+ mModel = model;
+ Setup();
+}
+
+void GameRenderer::SetMainTexture( GameTexture* texture )
+{
+ mTexture = texture;
+ Setup();
+}
+
+void GameRenderer::Setup()
+{
+ if( !mRenderer && mModel )
+ {
+ Dali::Shader shader = Dali::Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ mRenderer = Dali::Renderer::New( mModel->GetGeometry(), shader );
+ mRenderer.SetProperty( Dali::Renderer::Property::DEPTH_WRITE_MODE, Dali::DepthWriteMode::ON );
+ mRenderer.SetProperty( Dali::Renderer::Property::DEPTH_FUNCTION, Dali::DepthFunction::LESS_EQUAL );
+ mRenderer.SetProperty( Dali::Renderer::Property::DEPTH_TEST_MODE, Dali::DepthTestMode::ON );
+ }
+
+ Dali::TextureSet textureSet;
+ Dali::Geometry geometry;
+
+ if( mModel )
+ {
+ geometry = mModel->GetGeometry();
+ }
+
+ if( mTexture && mTexture->GetTextureSet() )
+ {
+ textureSet = mTexture->GetTextureSet();
+ }
+
+ if( textureSet && geometry )
+ {
+ mRenderer.SetGeometry( geometry );
+ mRenderer.SetTextures( textureSet );
+ }
+}
+
+Dali::Renderer& GameRenderer::GetRenderer()
+{
+ return mRenderer;
+}
+
+
+
diff --git a/examples/fpp-game/game-renderer.h b/examples/fpp-game/game-renderer.h
new file mode 100644
index 0000000..de1222b
--- /dev/null
+++ b/examples/fpp-game/game-renderer.h
@@ -0,0 +1,78 @@
+#ifndef GAME_RENDERER_H
+#define GAME_RENDERER_H
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include
+
+class GameModel;
+class GameTexture;
+
+/**
+ * @brief The GameRenderer class
+ * GameRenderer binds the main texture with model. Can be used by multiple entities. It wraps
+ * Dali::Renderer.
+ */
+class GameRenderer
+{
+public:
+
+ /**
+ * Creates an instance of the GameRenderer
+ */
+ GameRenderer();
+
+ /**
+ * Destroys an instance of the GameRenderer
+ */
+ ~GameRenderer();
+
+ /**
+ * Sets current model on the renderer
+ * Resets the Dali::Renderer or creates new one on first time setup
+ * @param[in] model Pointer to the GameModel object
+ */
+ void SetModel( GameModel* model );
+
+ /**
+ * Sets main texture on the renderer
+ * Resets the Dali::Renderer or creates new one on first time setup
+ * @param[in] texture Pointer to the GameTexture object
+ */
+ void SetMainTexture( GameTexture* texture );
+
+ /**
+ * Retrieves DALi renderer object
+ */
+ Dali::Renderer& GetRenderer();
+
+private:
+
+ /**
+ * Initialises rendering data
+ */
+ void Setup();
+
+private:
+
+ Dali::Renderer mRenderer;
+ GameModel* mModel;
+ GameTexture* mTexture;
+};
+
+#endif
diff --git a/examples/fpp-game/game-scene.cpp b/examples/fpp-game/game-scene.cpp
new file mode 100644
index 0000000..03b8e05
--- /dev/null
+++ b/examples/fpp-game/game-scene.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include
+#include
+
+#include "game-scene.h"
+#include "game-model.h"
+#include "game-texture.h"
+#include "game-entity.h"
+#include "game-renderer.h"
+#include "game-camera.h"
+
+#include "third-party/picojson.h"
+
+#include
+
+using namespace Dali;
+using namespace picojson;
+
+using std::vector;
+
+using namespace GameUtils;
+
+GameScene::GameScene()
+{
+}
+
+GameScene::~GameScene()
+{
+}
+
+bool GameScene::Load(const char *filename)
+{
+ ByteArray bytes;
+ if( !LoadFile( filename, bytes ) )
+ {
+ return false;
+ }
+
+ // add EOL
+ bytes.push_back( '\0');
+
+ picojson::value root;
+ picojson::parse( root, bytes.data() );
+
+ bool failed( false );
+
+ if( root.is