Merge branch 'devel/master (1.2.30)' into tizen
[platform/core/uifw/dali-demo.git] / examples / rendering-cube / rendering-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 vec3 aColor;\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 vec4 vColor;\n
37 \n
38 void main()\n
39 {\n
40   mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
41   vertexPosition.xyz *= uSize;\n
42   vColor = vec4( aColor, 1.0 );\n
43   gl_Position = uMvpMatrix * vertexPosition;\n
44 }\n
45 );
46
47 /*
48  * Fragment shader
49  */
50 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
51 varying mediump vec4 vColor;\n
52 \n
53 void main()\n
54 {\n
55   gl_FragColor = vColor;\n
56 }\n
57 );
58
59 }
60
61 // This example shows how to create a cube with colors on each side
62 //
63 class DrawCubeController : public ConnectionTracker
64 {
65 public:
66
67   DrawCubeController( Application& application )
68   : mApplication( application )
69   {
70     // Connect to the Application's Init signal
71     mApplication.InitSignal().Connect( this, &DrawCubeController::Create );
72   }
73
74   ~DrawCubeController()
75   {
76     // Nothing to do here;
77   }
78
79   // The Init signal is received once (only) during the Application lifetime
80   void Create( Application& application )
81   {
82     // Get a handle to the stage
83     Stage stage = Stage::GetCurrent();
84     stage.SetBackgroundColor( Color::WHITE );
85
86     // Step 1. Create shader
87     CreateCubeShader();
88
89     // Step 2. Prepare geometry
90     CreateCubeGeometry();
91
92     // Step 3. Create a renderer
93     CreateRenderer();
94
95     // Step 4. Create an Actor
96     CreateActor();
97
98     // Step 5. Play animation to rotate the cube
99     PlayAnimation();
100
101     // Respond to a click anywhere on the stage
102     stage.GetRootLayer().TouchSignal().Connect( this, &DrawCubeController::OnTouch );
103   }
104
105   bool OnTouch( Actor actor, const TouchData& touch )
106   {
107     // quit the application
108     mApplication.Quit();
109     return true;
110   }
111
112   /**
113    * This function creates a cube geometry including texture coordinates.
114    * Also it demonstrates using the indexed draw feature by setting an index array.
115    */
116   void CreateCubeGeometry()
117   {
118     struct Vertex
119     {
120       Vector3 aPosition;
121       Vector3 aColor;
122     };
123
124     const Vector3 COLOR0( 1.0f, 1.0f, 0.0f );
125     const Vector3 COLOR1( 0.0f, 1.0f, 1.0f );
126     const Vector3 COLOR2( 1.0f, 0.0f, 1.0f );
127     const Vector3 COLOR3( 0.0f, 1.0f, 0.0f );
128     const Vector3 COLOR4( 0.0f, 0.0f, 1.0f );
129     const Vector3 COLOR5( 1.0f, 0.0f, 0.0f );
130
131     Vertex vertices[] = {
132       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR5 },
133       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR5 },
134       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR5 },
135       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR3 },
136       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR3 },
137       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR3 },
138       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR4 },
139       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR4 },
140       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR4 },
141       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR1 },
142       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR1 },
143       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR1 },
144       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR0 },
145       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR0 },
146       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR0 },
147       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR2 },
148       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR2 },
149       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR2 },
150       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR5 },
151       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR5 },
152       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR5 },
153       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR3 },
154       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR3 },
155       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR3 },
156       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR4 },
157       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR4 },
158       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR4 },
159       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR1 },
160       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR1 },
161       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR1 },
162       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR0 },
163       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR0 },
164       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR0 },
165       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR2 },
166       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR2 },
167       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR2 },
168     };
169
170     PropertyBuffer vertexBuffer = PropertyBuffer::New( Property::Map()
171                                                        .Add( "aPosition", Property::VECTOR3 )
172                                                        .Add( "aColor", Property::VECTOR3 ) );
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         );
195     mGeometry.SetType( Geometry::TRIANGLES );
196   }
197
198   /**
199    * Creates a shader using inlined variable VERTEX_SHADER and FRAGMENT_SHADER
200    *
201    * Shaders are very basic and all they do is transforming vertices and interpolating
202    * input per-vertex color.
203    */
204   void CreateCubeShader()
205   {
206     mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
207   }
208
209   /**
210    * Function creates renderer. It turns on depth test and depth write.
211    */
212   void CreateRenderer()
213   {
214     mRenderer = Renderer::New( mGeometry, mShader );
215
216     // Face culling is enabled to hide the backwards facing sides of the cube
217     // This is sufficient to render a single object; for more complex scenes depth-testing might be required
218     mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK );
219   }
220
221   /**
222    * Creates new actor and attaches renderer.
223    */
224   void CreateActor()
225   {
226     Stage stage = Stage::GetCurrent();
227
228     float quarterStageWidth = stage.GetSize().x * 0.25f;
229     mActor = Actor::New();
230     mActor.SetAnchorPoint( AnchorPoint::CENTER );
231     mActor.SetParentOrigin( ParentOrigin::CENTER );
232     mActor.SetPosition( Vector3( 0.0f, 0.0f, 0.0f ) );
233     mActor.SetSize( Vector3( quarterStageWidth, quarterStageWidth, quarterStageWidth ) );
234     mActor.AddRenderer( mRenderer );
235     stage.Add( mActor );
236   }
237
238   /**
239    * Plays animation
240    */
241   void PlayAnimation()
242   {
243     mAnimation = Animation::New( 5.0f );
244     mAnimation.SetLooping( true );
245     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::ZAXIS ) );
246     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::YAXIS ) );
247     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::XAXIS ) );
248     mAnimation.Play();
249   }
250
251 private:
252   Application&  mApplication;
253
254   Renderer mRenderer;
255   Shader mShader;
256   Geometry mGeometry;
257   Actor mActor;
258   Animation mAnimation;
259 };
260
261 void RunTest( Application& application )
262 {
263   DrawCubeController test( application );
264
265   application.MainLoop();
266 }
267
268 // Entry point for Linux & Tizen applications
269 //
270 int DALI_EXPORT_API main( int argc, char **argv )
271 {
272   Application application = Application::New( &argc, &argv );
273
274   RunTest( application );
275
276   return 0;
277 }