Commit f3ed04afa90327dc193250db21d5a698ec4cca14

Authored by Andrew Poor
1 parent fa6ffeff

Added support for setting light position in mesh renderer.

Change-Id: I1d0298c1e0cd30ac370bc27f45ffe0ade5d2d616
demo/dali-demo.cpp
@@ -42,7 +42,6 @@ int DALI_EXPORT_API main(int argc, char **argv) @@ -42,7 +42,6 @@ int DALI_EXPORT_API main(int argc, char **argv)
42 demo.AddExample(Example("dissolve-effect.example", DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION)); 42 demo.AddExample(Example("dissolve-effect.example", DALI_DEMO_STR_TITLE_DISSOLVE_TRANSITION));
43 demo.AddExample(Example("item-view.example", DALI_DEMO_STR_TITLE_ITEM_VIEW)); 43 demo.AddExample(Example("item-view.example", DALI_DEMO_STR_TITLE_ITEM_VIEW));
44 demo.AddExample(Example("magnifier.example", DALI_DEMO_STR_TITLE_MAGNIFIER)); 44 demo.AddExample(Example("magnifier.example", DALI_DEMO_STR_TITLE_MAGNIFIER));
45 - demo.AddExample(Example("model3d-view.example", DALI_DEMO_STR_TITLE_MODEL_3D_VIEWER));  
46 demo.AddExample(Example("motion-blur.example", DALI_DEMO_STR_TITLE_MOTION_BLUR)); 45 demo.AddExample(Example("motion-blur.example", DALI_DEMO_STR_TITLE_MOTION_BLUR));
47 demo.AddExample(Example("motion-stretch.example", DALI_DEMO_STR_TITLE_MOTION_STRETCH)); 46 demo.AddExample(Example("motion-stretch.example", DALI_DEMO_STR_TITLE_MOTION_STRETCH));
48 demo.AddExample(Example("page-turn-view.example", DALI_DEMO_STR_TITLE_PAGE_TURN_VIEW)); 47 demo.AddExample(Example("page-turn-view.example", DALI_DEMO_STR_TITLE_PAGE_TURN_VIEW));
examples/mesh-renderer/mesh-renderer-example.cpp
@@ -47,6 +47,11 @@ namespace @@ -47,6 +47,11 @@ namespace
47 const float MODEL_SCALE = 0.75f; 47 const float MODEL_SCALE = 0.75f;
48 const int NUM_MESHES = 3; 48 const int NUM_MESHES = 3;
49 49
  50 + //Used to identify actors.
  51 + const int MODEL_TAG = 0;
  52 + const int LIGHT_TAG = 1;
  53 + const int LAYER_TAG = 2;
  54 +
50 } //End namespace 55 } //End namespace
51 56
52 class MeshRendererController : public ConnectionTracker 57 class MeshRendererController : public ConnectionTracker
@@ -57,7 +62,9 @@ public: @@ -57,7 +62,9 @@ public:
57 : mApplication( application ), //Store handle to the application. 62 : mApplication( application ), //Store handle to the application.
58 mModelIndex( 1 ), //Start with metal robot. 63 mModelIndex( 1 ), //Start with metal robot.
59 mShaderIndex( 0 ), //Start with all textures. 64 mShaderIndex( 0 ), //Start with all textures.
60 - mSelectedModelIndex( 0 ) //Non-valid default, which will get set to a correct value when used. 65 + mTag( -1 ), //Non-valid default, which will get set to a correct value when used.
  66 + mSelectedModelIndex( -1 ), //Non-valid default, which will get set to a correct value when used.
  67 + mPaused( false ) //Animations play by default.
61 { 68 {
62 // Connect to the Application's Init signal 69 // Connect to the Application's Init signal
63 mApplication.InitSignal().Connect( this, &MeshRendererController::Create ); 70 mApplication.InitSignal().Connect( this, &MeshRendererController::Create );
@@ -90,25 +97,24 @@ public: @@ -90,25 +97,24 @@ public:
90 { 97 {
91 Stage stage = Stage::GetCurrent(); 98 Stage stage = Stage::GetCurrent();
92 99
93 - //Set up 3D layer to place objects on.  
94 - Layer layer = Layer::New();  
95 - layer.SetParentOrigin( ParentOrigin::CENTER );  
96 - layer.SetAnchorPoint( AnchorPoint::CENTER );  
97 - layer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );  
98 - layer.SetBehavior( Layer::LAYER_2D ); //We use a 2D layer as this is closer to UI work than full 3D scene creation.  
99 - layer.SetDepthTestDisabled( false ); //Enable depth testing, as otherwise the 2D layer would not do so.  
100 - stage.Add( layer );  
101 -  
102 - //Create gesture detector for panning of models.  
103 - mPanGestureDetector = PanGestureDetector::New();  
104 - mPanGestureDetector.DetectedSignal().Connect( this, &MeshRendererController::OnPan ); 100 + //Set up layer to place objects on.
  101 + Layer baseLayer = Layer::New();
  102 + baseLayer.SetParentOrigin( ParentOrigin::CENTER );
  103 + baseLayer.SetAnchorPoint( AnchorPoint::CENTER );
  104 + baseLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
  105 + baseLayer.SetBehavior( Layer::LAYER_2D ); //We use a 2D layer as this is closer to UI work than full 3D scene creation.
  106 + baseLayer.SetDepthTestDisabled( false ); //Enable depth testing, as otherwise the 2D layer would not do so.
  107 + baseLayer.RegisterProperty( "Tag", LAYER_TAG ); //Used to differentiate between different kinds of actor.
  108 + baseLayer.TouchedSignal().Connect( this, &MeshRendererController::OnTouch );
  109 + stage.Add( baseLayer );
105 110
106 //Add containers to house each renderer-holding-actor. 111 //Add containers to house each renderer-holding-actor.
107 for( int i = 0; i < NUM_MESHES; i++ ) 112 for( int i = 0; i < NUM_MESHES; i++ )
108 { 113 {
109 mContainers[i] = Actor::New(); 114 mContainers[i] = Actor::New();
110 mContainers[i].SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); 115 mContainers[i].SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
111 - mContainers[i].RegisterProperty( "Tag", Property::Value( i ) ); //Used to identify the actor and index into the model. 116 + mContainers[i].RegisterProperty( "Tag", MODEL_TAG ); //Used to differentiate between different kinds of actor.
  117 + mContainers[i].RegisterProperty( "Model", Property::Value( i ) ); //Used to index into the model.
112 118
113 //Position each container on screen 119 //Position each container on screen
114 if( i == 0 ) 120 if( i == 0 )
@@ -133,8 +139,8 @@ public: @@ -133,8 +139,8 @@ public:
133 mContainers[i].SetAnchorPoint( AnchorPoint::TOP_RIGHT ); 139 mContainers[i].SetAnchorPoint( AnchorPoint::TOP_RIGHT );
134 } 140 }
135 141
136 - mPanGestureDetector.Attach( mContainers[i] );  
137 - layer.Add( mContainers[i] ); 142 + mContainers[i].TouchedSignal().Connect( this, &MeshRendererController::OnTouch );
  143 + baseLayer.Add( mContainers[i] );
138 } 144 }
139 145
140 //Set up models 146 //Set up models
@@ -169,19 +175,65 @@ public: @@ -169,19 +175,65 @@ public:
169 Toolkit::PushButton modelButton = Toolkit::PushButton::New(); 175 Toolkit::PushButton modelButton = Toolkit::PushButton::New();
170 modelButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); 176 modelButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
171 modelButton.ClickedSignal().Connect( this, &MeshRendererController::OnChangeModelClicked ); 177 modelButton.ClickedSignal().Connect( this, &MeshRendererController::OnChangeModelClicked );
172 - modelButton.SetParentOrigin( Vector3( 0.1, 0.95, 0.5 ) ); //Offset from bottom left 178 + modelButton.SetParentOrigin( Vector3( 0.05, 0.95, 0.5 ) ); //Offset from bottom left
173 modelButton.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); 179 modelButton.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT );
174 modelButton.SetLabelText( "Change Model" ); 180 modelButton.SetLabelText( "Change Model" );
175 - layer.Add( modelButton ); 181 + baseLayer.Add( modelButton );
176 182
177 //Create button for shader changing 183 //Create button for shader changing
178 Toolkit::PushButton shaderButton = Toolkit::PushButton::New(); 184 Toolkit::PushButton shaderButton = Toolkit::PushButton::New();
179 shaderButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); 185 shaderButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
180 shaderButton.ClickedSignal().Connect( this, &MeshRendererController::OnChangeShaderClicked ); 186 shaderButton.ClickedSignal().Connect( this, &MeshRendererController::OnChangeShaderClicked );
181 - shaderButton.SetParentOrigin( Vector3( 0.9, 0.95, 0.5 ) ); //Offset from bottom right 187 + shaderButton.SetParentOrigin( Vector3( 0.95, 0.95, 0.5 ) ); //Offset from bottom right
182 shaderButton.SetAnchorPoint( AnchorPoint::BOTTOM_RIGHT ); 188 shaderButton.SetAnchorPoint( AnchorPoint::BOTTOM_RIGHT );
183 shaderButton.SetLabelText( "Change Shader" ); 189 shaderButton.SetLabelText( "Change Shader" );
184 - layer.Add( shaderButton ); 190 + baseLayer.Add( shaderButton );
  191 +
  192 + //Create button for pausing animations
  193 + Toolkit::PushButton pauseButton = Toolkit::PushButton::New();
  194 + pauseButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
  195 + pauseButton.ClickedSignal().Connect( this, &MeshRendererController::OnPauseClicked );
  196 + pauseButton.SetParentOrigin( Vector3( 0.5, 0.95, 0.5 ) ); //Offset from bottom center
  197 + pauseButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
  198 + pauseButton.SetLabelText( " || " );
  199 + baseLayer.Add( pauseButton );
  200 +
  201 + //Create control to act as light source of scene.
  202 + mLightSource = Control::New();
  203 + mLightSource.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::WIDTH );
  204 + mLightSource.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
  205 + mLightSource.RegisterProperty( "Tag", LIGHT_TAG );
  206 +
  207 + //Set position relative to top left, as the light source property is also relative to the top left.
  208 + mLightSource.SetParentOrigin( ParentOrigin::TOP_LEFT );
  209 + mLightSource.SetAnchorPoint( AnchorPoint::CENTER );
  210 + mLightSource.SetPosition( Stage::GetCurrent().GetSize().x * 0.5f, Stage::GetCurrent().GetSize().y * 0.1f );
  211 +
  212 + //Make white background.
  213 + Property::Map lightMap;
  214 + lightMap.Insert( "rendererType", "COLOR" );
  215 + lightMap.Insert( "mixColor", Color::WHITE );
  216 + mLightSource.SetProperty( Control::Property::BACKGROUND, Property::Value( lightMap ) );
  217 +
  218 + //Label to show what this actor is for the user.
  219 + TextLabel lightLabel = TextLabel::New( "Light" );
  220 + lightLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
  221 + lightLabel.SetParentOrigin( ParentOrigin::CENTER );
  222 + lightLabel.SetAnchorPoint( AnchorPoint::CENTER );
  223 + float padding = 5.0f;
  224 + lightLabel.SetPadding( Padding( padding, padding, padding, padding ) );
  225 + mLightSource.Add( lightLabel );
  226 +
  227 + //Connect to touch signal for dragging.
  228 + mLightSource.TouchedSignal().Connect( this, &MeshRendererController::OnTouch );
  229 +
  230 + //Place the light source on a layer above the base, so that it is rendered above everything else.
  231 + Layer upperLayer = Layer::New();
  232 + baseLayer.Add( upperLayer );
  233 + upperLayer.Add( mLightSource );
  234 +
  235 + //Calling this sets the light position of each model to that of the light source control.
  236 + UpdateLight();
185 } 237 }
186 238
187 //Updates the displayed models to account for parameter changes. 239 //Updates the displayed models to account for parameter changes.
@@ -194,6 +246,7 @@ public: @@ -194,6 +246,7 @@ public:
194 map.Insert( "materialUrl", MATERIAL_FILE[mModelIndex] ); 246 map.Insert( "materialUrl", MATERIAL_FILE[mModelIndex] );
195 map.Insert( "texturesPath", TEXTURES_PATH ); 247 map.Insert( "texturesPath", TEXTURES_PATH );
196 map.Insert( "shaderType", SHADER_TYPE[mShaderIndex] ); 248 map.Insert( "shaderType", SHADER_TYPE[mShaderIndex] );
  249 + map.Insert( "useSoftNormals", false );
197 250
198 //Set the two controls to use the mesh 251 //Set the two controls to use the mesh
199 for( int i = 0; i < NUM_MESHES; i++ ) 252 for( int i = 0; i < NUM_MESHES; i++ )
@@ -202,53 +255,101 @@ public: @@ -202,53 +255,101 @@ public:
202 } 255 }
203 } 256 }
204 257
205 - //Rotates the panned model based on the gesture.  
206 - void OnPan( Actor actor, const PanGesture& gesture ) 258 + //Updates the light position for each model to account for changes in the source on screen.
  259 + void UpdateLight()
207 { 260 {
208 - switch( gesture.state ) 261 + //Set light position to the x and y of the light control, offset out of the screen.
  262 + Vector3 controlPosition = mLightSource.GetCurrentPosition();
  263 + Vector3 lightPosition = Vector3( controlPosition.x, controlPosition.y, Stage::GetCurrent().GetSize().x * 2.0f );
  264 +
  265 + for( int i = 0; i < NUM_MESHES; ++i )
209 { 266 {
210 - case Gesture::Started:  
211 - {  
212 - //Find out which model has been selected  
213 - actor.GetProperty( actor.GetPropertyIndex( "Tag" ) ).Get( mSelectedModelIndex ); 267 + mModels[i].control.RegisterProperty( "lightPosition", lightPosition, Property::ANIMATABLE );
  268 + }
  269 + }
214 270
215 - //Pause current animation, as the gesture will be used to manually rotate the model  
216 - mModels[mSelectedModelIndex].rotationAnimation.Pause(); 271 + //If the light source is touched, move it by dragging it.
  272 + //If a model is touched, rotate it by panning around.
  273 + bool OnTouch( Actor actor, const TouchEvent& event )
  274 + {
  275 + //Get primary touch point.
  276 + const Dali::TouchPoint& point = event.GetPoint( 0 );
217 277
218 - break;  
219 - }  
220 - case Gesture::Continuing: 278 + switch( point.state )
  279 + {
  280 + case TouchPoint::Down:
221 { 281 {
222 - //Rotate based off the gesture.  
223 - mModels[mSelectedModelIndex].rotation.x -= gesture.displacement.y / X_ROTATION_DISPLACEMENT_FACTOR; // Y displacement rotates around X axis  
224 - mModels[mSelectedModelIndex].rotation.y += gesture.displacement.x / Y_ROTATION_DISPLACEMENT_FACTOR; // X displacement rotates around Y axis  
225 - Quaternion rotation = Quaternion( Radian( mModels[mSelectedModelIndex].rotation.x ), Vector3::XAXIS) *  
226 - Quaternion( Radian( mModels[mSelectedModelIndex].rotation.y ), Vector3::YAXIS); 282 + //Determine what was touched.
  283 + actor.GetProperty( actor.GetPropertyIndex( "Tag" ) ).Get( mTag );
  284 +
  285 + if( mTag == MODEL_TAG )
  286 + {
  287 + //Find out which model has been selected
  288 + actor.GetProperty( actor.GetPropertyIndex( "Model" ) ).Get( mSelectedModelIndex );
  289 +
  290 + //Pause current animation, as the touch gesture will be used to manually rotate the model
  291 + mModels[mSelectedModelIndex].rotationAnimation.Pause();
227 292
228 - mModels[mSelectedModelIndex].control.SetOrientation( rotation ); 293 + //Store start points.
  294 + mPanStart = point.screen;
  295 + mRotationStart = mModels[mSelectedModelIndex].rotation;
  296 + }
229 297
230 break; 298 break;
231 } 299 }
232 - case Gesture::Finished: 300 + case TouchPoint::Motion:
233 { 301 {
234 - //Return to automatic animation  
235 - mModels[mSelectedModelIndex].rotationAnimation.Play(); 302 + //Switch on the kind of actor we're interacting with.
  303 + switch( mTag )
  304 + {
  305 + case MODEL_TAG: //Rotate model
  306 + {
  307 + //Calculate displacement and corresponding rotation.
  308 + Vector2 displacement = point.screen - mPanStart;
  309 + mModels[mSelectedModelIndex].rotation = Vector2( mRotationStart.x - displacement.y / Y_ROTATION_DISPLACEMENT_FACTOR, // Y displacement rotates around X axis
  310 + mRotationStart.y + displacement.x / X_ROTATION_DISPLACEMENT_FACTOR ); // X displacement rotates around Y axis
  311 + Quaternion rotation = Quaternion( Radian( mModels[mSelectedModelIndex].rotation.x ), Vector3::XAXIS) *
  312 + Quaternion( Radian( mModels[mSelectedModelIndex].rotation.y ), Vector3::YAXIS);
  313 +
  314 + //Apply rotation.
  315 + mModels[mSelectedModelIndex].control.SetOrientation( rotation );
  316 +
  317 + break;
  318 + }
  319 + case LIGHT_TAG: //Drag light
  320 + {
  321 + //Set light source to new position and update the models accordingly.
  322 + mLightSource.SetPosition( Vector3( point.screen ) );
  323 + UpdateLight();
  324 +
  325 + break;
  326 + }
  327 + }
236 328
237 break; 329 break;
238 } 330 }
239 - case Gesture::Cancelled: 331 + case TouchPoint::Interrupted: //Same as finished.
  332 + case TouchPoint::Finished:
240 { 333 {
241 - //Return to automatic animation  
242 - mModels[mSelectedModelIndex].rotationAnimation.Play(); 334 + if( mTag == MODEL_TAG )
  335 + {
  336 + //Return to automatic animation
  337 + if( !mPaused )
  338 + {
  339 + mModels[mSelectedModelIndex].rotationAnimation.Play();
  340 + }
  341 + }
243 342
244 break; 343 break;
245 } 344 }
246 default: 345 default:
247 { 346 {
248 - //We can ignore other gestures and gesture states. 347 + //Other touch states do nothing.
249 break; 348 break;
250 } 349 }
251 } 350 }
  351 +
  352 + return true;
252 } 353 }
253 354
254 //Cycle through the list of models. 355 //Cycle through the list of models.
@@ -271,6 +372,36 @@ public: @@ -271,6 +372,36 @@ public:
271 return true; 372 return true;
272 } 373 }
273 374
  375 + //Pause all animations, and keep them paused even after user panning.
  376 + //This button is a toggle, so pressing again will start the animations again.
  377 + bool OnPauseClicked( Toolkit::Button button )
  378 + {
  379 + //Toggle pause state.
  380 + mPaused = !mPaused;
  381 +
  382 + //If we wish to pause animations, do so and keep them paused.
  383 + if( mPaused )
  384 + {
  385 + for( int i = 0; i < NUM_MESHES ; ++i )
  386 + {
  387 + mModels[i].rotationAnimation.Pause();
  388 + }
  389 +
  390 + button.SetLabelText( " > " );
  391 + }
  392 + else //Unpause all animations again.
  393 + {
  394 + for( int i = 0; i < NUM_MESHES ; ++i )
  395 + {
  396 + mModels[i].rotationAnimation.Play();
  397 + }
  398 +
  399 + button.SetLabelText( " || " );
  400 + }
  401 +
  402 + return true;
  403 + }
  404 +
274 //If escape or the back button is pressed, quit the application (and return to the launcher) 405 //If escape or the back button is pressed, quit the application (and return to the launcher)
275 void OnKeyEvent( const KeyEvent& event ) 406 void OnKeyEvent( const KeyEvent& event )
276 { 407 {
@@ -290,12 +421,18 @@ private: @@ -290,12 +421,18 @@ private:
290 Model mModels[NUM_MESHES]; 421 Model mModels[NUM_MESHES];
291 Actor mContainers[NUM_MESHES]; 422 Actor mContainers[NUM_MESHES];
292 423
  424 + //Acts as a global light source, which can be dragged around.
  425 + Control mLightSource;
  426 +
293 //Used to detect panning to rotate the selected model. 427 //Used to detect panning to rotate the selected model.
294 - PanGestureDetector mPanGestureDetector; 428 + Vector2 mPanStart;
  429 + Vector2 mRotationStart;
295 430
296 int mModelIndex; //Index of model to load. 431 int mModelIndex; //Index of model to load.
297 int mShaderIndex; //Index of shader type to use. 432 int mShaderIndex; //Index of shader type to use.
  433 + int mTag; //Identifies what kind of actor has been selected in OnTouch.
298 int mSelectedModelIndex; //Index of model selected on screen. 434 int mSelectedModelIndex; //Index of model selected on screen.
  435 + bool mPaused; //If true, all animations are paused and should stay so.
299 }; 436 };
300 437
301 void RunTest( Application& application ) 438 void RunTest( Application& application )