Updated demos to use DALi clang-format
[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-toolkit/dali-toolkit.h>
19 #include <dali/dali.h>
20
21 using namespace Dali;
22 using namespace Toolkit;
23
24 namespace
25 {
26 // clang-format off
27
28 /*
29  * Vertex shader
30  */
31 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
32 attribute mediump vec3 aPosition;\n // DALi shader builtin
33 attribute mediump vec3 aColor;\n // DALi shader builtin
34 uniform   mediump mat4 uMvpMatrix;\n // DALi shader builtin
35 uniform   mediump vec3 uSize;\n // DALi shader builtin
36 \n
37 varying mediump vec4 vColor;\n
38 \n
39 void main()\n
40 {\n
41   mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
42   vertexPosition.xyz *= uSize;\n
43   vColor = vec4( aColor, 1.0 );\n
44   gl_Position = uMvpMatrix * vertexPosition;\n
45 }\n
46 );
47
48 /*
49  * Fragment shader
50  */
51 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
52 varying mediump vec4 vColor;\n
53 \n
54 void main()\n
55 {\n
56   gl_FragColor = vColor;\n
57 }\n
58 );
59 // clang-format on
60
61 } // namespace
62
63 // This example shows how to create a cube with colors on each side
64 //
65 class DrawCubeController : public ConnectionTracker
66 {
67 public:
68   DrawCubeController(Application& application)
69   : mApplication(application)
70   {
71     // Connect to the Application's Init signal
72     mApplication.InitSignal().Connect(this, &DrawCubeController::Create);
73   }
74
75   ~DrawCubeController()
76   {
77     // Nothing to do here;
78   }
79
80   // The Init signal is received once (only) during the Application lifetime
81   void Create(Application& application)
82   {
83     // Get a handle to the window
84     Window window = application.GetWindow();
85     window.SetBackgroundColor(Color::WHITE);
86
87     // Step 1. Create shader
88     CreateCubeShader();
89
90     // Step 2. Prepare geometry
91     CreateCubeGeometry();
92
93     // Step 3. Create a renderer
94     CreateRenderer();
95
96     // Step 4. Create an Actor
97     CreateActor();
98
99     // Step 5. Play animation to rotate the cube
100     PlayAnimation();
101
102     // Respond to a click anywhere on the window
103     window.GetRootLayer().TouchedSignal().Connect(this, &DrawCubeController::OnTouch);
104
105     // Respond to key events
106     window.KeyEventSignal().Connect(this, &DrawCubeController::OnKeyEvent);
107   }
108
109   bool OnTouch(Actor actor, const TouchEvent& touch)
110   {
111     // quit the application
112     mApplication.Quit();
113     return true;
114   }
115
116   /**
117    * @brief Called when any key event is received
118    *
119    * Will use this to quit the application if Back or the Escape key is received
120    * @param[in] event The key event information
121    */
122   void OnKeyEvent(const KeyEvent& event)
123   {
124     if(event.GetState() == KeyEvent::DOWN)
125     {
126       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
127       {
128         mApplication.Quit();
129       }
130     }
131   }
132
133   /**
134    * This function creates a cube geometry including texture coordinates.
135    * Also it demonstrates using the indexed draw feature by setting an index array.
136    */
137   void CreateCubeGeometry()
138   {
139     struct Vertex
140     {
141       Vector3 aPosition;
142       Vector3 aColor;
143     };
144
145     const Vector3 COLOR0(1.0f, 1.0f, 0.0f);
146     const Vector3 COLOR1(0.0f, 1.0f, 1.0f);
147     const Vector3 COLOR2(1.0f, 0.0f, 1.0f);
148     const Vector3 COLOR3(0.0f, 1.0f, 0.0f);
149     const Vector3 COLOR4(0.0f, 0.0f, 1.0f);
150     const Vector3 COLOR5(1.0f, 0.0f, 0.0f);
151
152     Vertex vertices[] = {
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), COLOR5},
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), COLOR3},
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), COLOR4},
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), COLOR1},
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), COLOR0},
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), COLOR2},
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), COLOR5},
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), COLOR3},
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), COLOR4},
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), COLOR1},
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), COLOR0},
186       {Vector3(1.0f, 1.0f, -1.0f), COLOR2},
187       {Vector3(-1.0f, 1.0f, -1.0f), COLOR2},
188       {Vector3(-1.0f, 1.0f, 1.0f), COLOR2},
189     };
190
191     VertexBuffer vertexBuffer = VertexBuffer::New(Property::Map()
192                                                     .Add("aPosition", Property::VECTOR3)
193                                                     .Add("aColor", Property::VECTOR3));
194     vertexBuffer.SetData(vertices, sizeof(vertices) / sizeof(Vertex));
195
196     // create indices
197     const unsigned short INDEX_CUBE[] = {
198       2, 1, 0, 5, 4, 3, 8, 7, 6, 11, 10, 9, 14, 13, 12, 17, 16, 15, 20, 19, 18, 23, 22, 21, 26, 25, 24, 29, 28, 27, 32, 31, 30, 35, 34, 33};
199     mGeometry = Geometry::New();
200     mGeometry.AddVertexBuffer(vertexBuffer);
201     mGeometry.SetIndexBuffer(INDEX_CUBE,
202                              sizeof(INDEX_CUBE) / sizeof(INDEX_CUBE[0]));
203     mGeometry.SetType(Geometry::TRIANGLES);
204   }
205
206   /**
207    * Creates a shader using inlined variable VERTEX_SHADER and FRAGMENT_SHADER
208    *
209    * Shaders are very basic and all they do is transforming vertices and interpolating
210    * input per-vertex color.
211    */
212   void CreateCubeShader()
213   {
214     mShader = Shader::New(VERTEX_SHADER, FRAGMENT_SHADER);
215   }
216
217   /**
218    * Function creates renderer. It turns on depth test and depth write.
219    */
220   void CreateRenderer()
221   {
222     mRenderer = Renderer::New(mGeometry, mShader);
223
224     // Face culling is enabled to hide the backwards facing sides of the cube
225     // This is sufficient to render a single object; for more complex scenes depth-testing might be required
226     mRenderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK);
227   }
228
229   /**
230    * Creates new actor and attaches renderer.
231    */
232   void CreateActor()
233   {
234     Window window = mApplication.GetWindow();
235
236     float quarterWindowWidth = window.GetSize().GetWidth() * 0.25f;
237     mActor                   = Actor::New();
238     mActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
239     mActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
240     mActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 0.0f));
241     mActor.SetProperty(Actor::Property::SIZE, Vector3(quarterWindowWidth, quarterWindowWidth, quarterWindowWidth));
242     mActor.AddRenderer(mRenderer);
243     window.Add(mActor);
244   }
245
246   /**
247    * Plays animation
248    */
249   void PlayAnimation()
250   {
251     mAnimation = Animation::New(5.0f);
252     mAnimation.SetLooping(true);
253     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::ZAXIS));
254     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::YAXIS));
255     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::XAXIS));
256     mAnimation.Play();
257   }
258
259 private:
260   Application& mApplication;
261
262   Renderer  mRenderer;
263   Shader    mShader;
264   Geometry  mGeometry;
265   Actor     mActor;
266   Animation mAnimation;
267 };
268
269 int DALI_EXPORT_API main(int argc, char** argv)
270 {
271   Application        application = Application::New(&argc, &argv);
272   DrawCubeController test(application);
273   application.MainLoop();
274   return 0;
275 }