Merge "A simple control using visuals" into devel/master
[platform/core/uifw/dali-demo.git] / examples / rendering-textured-cube / rendering-textured-cube.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <dali/dali.h>
19 #include <dali-toolkit/dali-toolkit.h>
20
21 using namespace Dali;
22 using namespace Toolkit;
23
24 namespace
25 {
26
27 /*
28  * Vertex shader
29  */
30 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
31 attribute mediump vec3 aPosition;\n // DALi shader builtin
32 attribute mediump vec2 aTexCoord;\n // DALi shader builtin
33 uniform   mediump mat4 uMvpMatrix;\n // DALi shader builtin
34 uniform   mediump vec3 uSize;\n // DALi shader builtin
35 \n
36 varying mediump vec2 vTexCoord;\n
37 void main()\n
38 {\n
39   mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
40   vertexPosition.xyz *= uSize;\n
41   vTexCoord = aTexCoord;\n
42   gl_Position = uMvpMatrix * vertexPosition;\n
43 }\n
44 );
45
46 /*
47  * Fragment shader
48  */
49 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
50 uniform sampler2D uTexture;\n
51 \n
52 varying mediump vec2 vTexCoord;\n
53 void main()\n
54 {\n
55   mediump vec4 texColor = texture2D( uTexture, vTexCoord );\n
56   gl_FragColor = texColor;\n
57 }\n
58 );
59
60 const char* TEXTURE_URL = DEMO_IMAGE_DIR "wood.png";
61
62 }
63
64 // This example shows how to create textured cube
65 //
66 class TexturedCubeController : public ConnectionTracker
67 {
68 public:
69
70   TexturedCubeController( Application& application )
71   : mApplication( application )
72   {
73     // Connect to the Application's Init signal
74     mApplication.InitSignal().Connect( this, &TexturedCubeController::Create );
75   }
76
77   ~TexturedCubeController()
78   {
79     // Nothing to do here;
80   }
81
82   // The Init signal is received once (only) during the Application lifetime
83   void Create( Application& application )
84   {
85     // Get a handle to the stage
86     Stage stage = Stage::GetCurrent();
87     stage.SetBackgroundColor( Color::WHITE );
88
89     // Step 1. Create shader
90     CreateCubeShader();
91
92     // Step 2. Load a texture
93     CreateTexture();
94
95     // Step 3. Prepare geometry
96     CreateCubeGeometry();
97
98     // Step 4. Create a renderer
99     CreateRenderer();
100
101     // Step 5. Create an Actor
102     CreateActor();
103
104     // Step 6. Play animation to rotate the cube
105     PlayAnimation();
106
107     // Respond to a click anywhere on the stage
108     stage.GetRootLayer().TouchSignal().Connect( this, &TexturedCubeController::OnTouch );
109   }
110
111   bool OnTouch( Actor actor, const TouchData& touch )
112   {
113     // quit the application
114     mApplication.Quit();
115     return true;
116   }
117
118   /**
119    * @brief CreateCubeGeometry
120    * This function creates a cube geometry including texture coordinates.
121    * Also it demonstrates using the indexed draw feature by setting an index array.
122    */
123   void CreateCubeGeometry()
124   {
125     struct Vertex
126     {
127       Vector3 aPosition;
128       Vector2 aTexCoord;
129     };
130
131     Vertex vertices[] = {
132       { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
133       { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
134       { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
135       { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
136       { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
137       { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 0.0, 1.0 ) },
138       { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
139       { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
140       { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
141       { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
142       { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
143       { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
144       { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
145       { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
146       { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
147       { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
148       { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
149       { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 0.0, 1.0 ) },
150       { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
151       { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 1.0, 0.0 ) },
152       { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
153       { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
154       { Vector3( -1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
155       { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
156       { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
157       { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
158       { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
159       { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
160       { Vector3( -1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
161       { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
162       { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
163       { Vector3( -1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
164       { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
165       { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
166       { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 1.0, 0.0 ) },
167       { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
168     };
169
170     PropertyBuffer vertexBuffer = PropertyBuffer::New( Property::Map()
171                                                        .Add( "aPosition", Property::VECTOR3 )
172                                                        .Add( "aTexCoord", Property::VECTOR2 ) );
173     vertexBuffer.SetData( vertices, sizeof(vertices) / sizeof(Vertex) );
174
175     // create indices
176     const unsigned short INDEX_CUBE[] = {
177       2, 1, 0,
178       5, 4, 3,
179       8, 7, 6,
180       11, 10, 9,
181       14, 13, 12,
182       17, 16, 15,
183       20, 19, 18,
184       23, 22, 21,
185       26, 25, 24,
186       29, 28, 27,
187       32, 31, 30,
188       35, 34, 33
189     };
190     mGeometry = Geometry::New();
191     mGeometry.AddVertexBuffer( vertexBuffer );
192     mGeometry.SetIndexBuffer( INDEX_CUBE,
193                               sizeof(INDEX_CUBE)/sizeof(INDEX_CUBE[0]) );
194     mGeometry.SetType( Geometry::TRIANGLES );
195   }
196
197   /**
198    * Creates a shader using inlined variable VERTEX_SHADER and FRAGMENT_SHADER
199    *
200    * Shaders are very basic and all they do is transforming vertices and sampling
201    * a texture.
202    */
203   void CreateCubeShader()
204   {
205     mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
206   }
207
208   /**
209    * This function loads a pixel data from a file. In order to load it we use SyncImageLoader utility.
210    * If loading succeeds returned PixelData object can be used to create a texture.
211    * Texture must be uploaded. In the end the texture must be set on the TextureSet object.
212    */
213   void CreateTexture()
214   {
215     // Load image from file
216     PixelData pixels = SyncImageLoader::Load( TEXTURE_URL );
217
218     Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
219     texture.Upload( pixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight() );
220
221     // create TextureSet
222     mTextureSet = TextureSet::New();
223     mTextureSet.SetTexture( 0, texture );
224   }
225
226   /**
227    * Function creates renderer. It turns on depth test and depth write.
228    */
229   void CreateRenderer()
230   {
231     mRenderer = Renderer::New( mGeometry, mShader );
232     mRenderer.SetTextures( mTextureSet );
233
234     // Face culling is enabled to hide the backwards facing sides of the cube
235     // This is sufficient to render a single object; for more complex scenes depth-testing might be required
236     mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK );
237   }
238
239   /**
240    * Creates new actor and attaches renderer.
241    */
242   void CreateActor()
243   {
244     Stage stage = Stage::GetCurrent();
245
246     float quarterStageWidth = stage.GetSize().x * 0.25f;
247     mActor = Actor::New();
248     mActor.SetAnchorPoint( AnchorPoint::CENTER );
249     mActor.SetParentOrigin( ParentOrigin::CENTER );
250     mActor.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) );
251     mActor.SetSize( Vector3( quarterStageWidth, quarterStageWidth, quarterStageWidth ) );
252     mActor.AddRenderer( mRenderer );
253     stage.Add( mActor );
254   }
255
256   /**
257    * Plays animation
258    */
259   void PlayAnimation()
260   {
261     mAnimation = Animation::New( 5.0f );
262     mAnimation.SetLooping( true );
263     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::ZAXIS ) );
264     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::YAXIS ) );
265     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::XAXIS ) );
266     mAnimation.Play();
267   }
268
269 private:
270   Application&  mApplication;
271
272   Renderer mRenderer;
273   Shader mShader;
274   Geometry mGeometry;
275   TextureSet mTextureSet;
276   Actor mActor;
277   Animation mAnimation;
278 };
279
280 void RunTest( Application& application )
281 {
282   TexturedCubeController test( application );
283
284   application.MainLoop();
285 }
286
287 // Entry point for Linux & Tizen applications
288 //
289 int DALI_EXPORT_API main( int argc, char **argv )
290 {
291   Application application = Application::New( &argc, &argv );
292
293   RunTest( application );
294
295   return 0;
296 }