53e4d1a8ea540111a30e376e1d331c2fb358071d
[platform/core/uifw/dali-demo.git] / examples / rendering-cube / rendering-cube.cpp
1 /*
2  * Copyright (c) 2020 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 window
83     Window window = application.GetWindow();
84     window.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 window
102     window.GetRootLayer().TouchSignal().Connect( this, &DrawCubeController::OnTouch );
103
104     // Respond to key events
105     window.KeyEventSignal().Connect( this, &DrawCubeController::OnKeyEvent );
106   }
107
108   bool OnTouch( Actor actor, const TouchEvent& touch )
109   {
110     // quit the application
111     mApplication.Quit();
112     return true;
113   }
114
115   /**
116    * @brief Called when any key event is received
117    *
118    * Will use this to quit the application if Back or the Escape key is received
119    * @param[in] event The key event information
120    */
121   void OnKeyEvent( const KeyEvent& event )
122   {
123     if( event.GetState() == KeyEvent::DOWN )
124     {
125       if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
126       {
127         mApplication.Quit();
128       }
129     }
130   }
131
132   /**
133    * This function creates a cube geometry including texture coordinates.
134    * Also it demonstrates using the indexed draw feature by setting an index array.
135    */
136   void CreateCubeGeometry()
137   {
138     struct Vertex
139     {
140       Vector3 aPosition;
141       Vector3 aColor;
142     };
143
144     const Vector3 COLOR0( 1.0f, 1.0f, 0.0f );
145     const Vector3 COLOR1( 0.0f, 1.0f, 1.0f );
146     const Vector3 COLOR2( 1.0f, 0.0f, 1.0f );
147     const Vector3 COLOR3( 0.0f, 1.0f, 0.0f );
148     const Vector3 COLOR4( 0.0f, 0.0f, 1.0f );
149     const Vector3 COLOR5( 1.0f, 0.0f, 0.0f );
150
151     Vertex vertices[] = {
152       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR5 },
153       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR5 },
154       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR5 },
155       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR3 },
156       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR3 },
157       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR3 },
158       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR4 },
159       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR4 },
160       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR4 },
161       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR1 },
162       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR1 },
163       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR1 },
164       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR0 },
165       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR0 },
166       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR0 },
167       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR2 },
168       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR2 },
169       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR2 },
170       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR5 },
171       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR5 },
172       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR5 },
173       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR3 },
174       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR3 },
175       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR3 },
176       { Vector3(  1.0f, 1.0f, 1.0f ), COLOR4 },
177       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR4 },
178       { Vector3(  1.0f,-1.0f,-1.0f ), COLOR4 },
179       { Vector3(  1.0f,-1.0f, 1.0f ), COLOR1 },
180       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR1 },
181       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR1 },
182       { Vector3( -1.0f,-1.0f,-1.0f ), COLOR0 },
183       { Vector3( -1.0f,-1.0f, 1.0f ), COLOR0 },
184       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR0 },
185       { Vector3(  1.0f, 1.0f,-1.0f ), COLOR2 },
186       { Vector3( -1.0f, 1.0f,-1.0f ), COLOR2 },
187       { Vector3( -1.0f, 1.0f, 1.0f ), COLOR2 },
188     };
189
190     VertexBuffer vertexBuffer = VertexBuffer::New( Property::Map()
191                                                        .Add( "aPosition", Property::VECTOR3 )
192                                                        .Add( "aColor", Property::VECTOR3 ) );
193     vertexBuffer.SetData( vertices, sizeof(vertices) / sizeof(Vertex) );
194
195     // create indices
196     const unsigned short INDEX_CUBE[] = {
197       2, 1, 0,
198       5, 4, 3,
199       8, 7, 6,
200       11, 10, 9,
201       14, 13, 12,
202       17, 16, 15,
203       20, 19, 18,
204       23, 22, 21,
205       26, 25, 24,
206       29, 28, 27,
207       32, 31, 30,
208       35, 34, 33
209     };
210     mGeometry = Geometry::New();
211     mGeometry.AddVertexBuffer( vertexBuffer );
212     mGeometry.SetIndexBuffer( INDEX_CUBE,
213                               sizeof(INDEX_CUBE)/sizeof(INDEX_CUBE[0])
214         );
215     mGeometry.SetType( Geometry::TRIANGLES );
216   }
217
218   /**
219    * Creates a shader using inlined variable VERTEX_SHADER and FRAGMENT_SHADER
220    *
221    * Shaders are very basic and all they do is transforming vertices and interpolating
222    * input per-vertex color.
223    */
224   void CreateCubeShader()
225   {
226     mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
227   }
228
229   /**
230    * Function creates renderer. It turns on depth test and depth write.
231    */
232   void CreateRenderer()
233   {
234     mRenderer = Renderer::New( mGeometry, mShader );
235
236     // Face culling is enabled to hide the backwards facing sides of the cube
237     // This is sufficient to render a single object; for more complex scenes depth-testing might be required
238     mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK );
239   }
240
241   /**
242    * Creates new actor and attaches renderer.
243    */
244   void CreateActor()
245   {
246     Window window = mApplication.GetWindow();
247
248     float quarterWindowWidth = window.GetSize().GetWidth() * 0.25f;
249     mActor = Actor::New();
250     mActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
251     mActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
252     mActor.SetProperty( Actor::Property::POSITION, Vector3( 0.0f, 0.0f, 0.0f ) );
253     mActor.SetProperty( Actor::Property::SIZE, Vector3( quarterWindowWidth, quarterWindowWidth, quarterWindowWidth ) );
254     mActor.AddRenderer( mRenderer );
255     window.Add( mActor );
256   }
257
258   /**
259    * Plays animation
260    */
261   void PlayAnimation()
262   {
263     mAnimation = Animation::New( 5.0f );
264     mAnimation.SetLooping( true );
265     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::ZAXIS ) );
266     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::YAXIS ) );
267     mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::XAXIS ) );
268     mAnimation.Play();
269   }
270
271 private:
272   Application&  mApplication;
273
274   Renderer mRenderer;
275   Shader mShader;
276   Geometry mGeometry;
277   Actor mActor;
278   Animation mAnimation;
279 };
280
281 int DALI_EXPORT_API main( int argc, char **argv )
282 {
283   Application application = Application::New( &argc, &argv );
284   DrawCubeController test( application );
285   application.MainLoop();
286   return 0;
287 }