[dali_2.3.25] Merge branch 'devel/master'
[platform/core/uifw/dali-demo.git] / examples / rendering-cube / rendering-cube.cpp
1 /*
2  * Copyright (c) 2022 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 #include "generated/rendering-cube-frag.h"
22 #include "generated/rendering-cube-vert.h"
23
24 using namespace Dali;
25 using namespace Toolkit;
26
27 // This example shows how to create a cube with colors on each side
28 //
29 class DrawCubeController : public ConnectionTracker
30 {
31 public:
32   DrawCubeController(Application& application)
33   : mApplication(application)
34   {
35     // Connect to the Application's Init signal
36     mApplication.InitSignal().Connect(this, &DrawCubeController::Create);
37   }
38
39   ~DrawCubeController()
40   {
41     // Nothing to do here;
42   }
43
44   // The Init signal is received once (only) during the Application lifetime
45   void Create(Application& application)
46   {
47     // Get a handle to the window
48     Window window = application.GetWindow();
49     window.SetBackgroundColor(Color::WHITE);
50
51     // Step 1. Create shader
52     CreateCubeShader();
53
54     // Step 2. Prepare geometry
55     CreateCubeGeometry();
56
57     // Step 3. Create a renderer
58     CreateRenderer();
59
60     // Step 4. Create an Actor
61     CreateActor();
62
63     // Step 5. Play animation to rotate the cube
64     PlayAnimation();
65
66     // Respond to a click anywhere on the window
67     window.GetRootLayer().TouchedSignal().Connect(this, &DrawCubeController::OnTouch);
68
69     // Respond to key events
70     window.KeyEventSignal().Connect(this, &DrawCubeController::OnKeyEvent);
71   }
72
73   bool OnTouch(Actor actor, const TouchEvent& touch)
74   {
75     // quit the application
76     mApplication.Quit();
77     return true;
78   }
79
80   /**
81    * @brief Called when any key event is received
82    *
83    * Will use this to quit the application if Back or the Escape key is received
84    * @param[in] event The key event information
85    */
86   void OnKeyEvent(const KeyEvent& event)
87   {
88     if(event.GetState() == KeyEvent::DOWN)
89     {
90       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
91       {
92         mApplication.Quit();
93       }
94     }
95   }
96
97   /**
98    * This function creates a cube geometry including texture coordinates.
99    * Also it demonstrates using the indexed draw feature by setting an index array.
100    */
101   void CreateCubeGeometry()
102   {
103     struct Vertex
104     {
105       Vector3 aPosition;
106       Vector3 aColor;
107     };
108
109     const Vector3 COLOR0(1.0f, 1.0f, 0.0f);
110     const Vector3 COLOR1(0.0f, 1.0f, 1.0f);
111     const Vector3 COLOR2(1.0f, 0.0f, 1.0f);
112     const Vector3 COLOR3(0.0f, 1.0f, 0.0f);
113     const Vector3 COLOR4(0.0f, 0.0f, 1.0f);
114     const Vector3 COLOR5(1.0f, 0.0f, 0.0f);
115
116     Vertex vertices[] = {
117       {Vector3(1.0f, -1.0f, -1.0f), COLOR5},
118       {Vector3(-1.0f, 1.0f, -1.0f), COLOR5},
119       {Vector3(1.0f, 1.0f, -1.0f), COLOR5},
120       {Vector3(-1.0f, 1.0f, 1.0f), COLOR3},
121       {Vector3(1.0f, -1.0f, 1.0f), COLOR3},
122       {Vector3(1.0f, 1.0f, 1.0f), COLOR3},
123       {Vector3(1.0f, 1.0f, 1.0f), COLOR4},
124       {Vector3(1.0f, -1.0f, -1.0f), COLOR4},
125       {Vector3(1.0f, 1.0f, -1.0f), COLOR4},
126       {Vector3(1.0f, -1.0f, 1.0f), COLOR1},
127       {Vector3(-1.0f, -1.0f, -1.0f), COLOR1},
128       {Vector3(1.0f, -1.0f, -1.0f), COLOR1},
129       {Vector3(-1.0f, -1.0f, -1.0f), COLOR0},
130       {Vector3(-1.0f, 1.0f, 1.0f), COLOR0},
131       {Vector3(-1.0f, 1.0f, -1.0f), COLOR0},
132       {Vector3(1.0f, 1.0f, -1.0f), COLOR2},
133       {Vector3(-1.0f, 1.0f, 1.0f), COLOR2},
134       {Vector3(1.0f, 1.0f, 1.0f), COLOR2},
135       {Vector3(1.0f, -1.0f, -1.0f), COLOR5},
136       {Vector3(-1.0f, -1.0f, -1.0f), COLOR5},
137       {Vector3(-1.0f, 1.0f, -1.0f), COLOR5},
138       {Vector3(-1.0f, 1.0f, 1.0f), COLOR3},
139       {Vector3(-1.0f, -1.0f, 1.0f), COLOR3},
140       {Vector3(1.0f, -1.0f, 1.0f), COLOR3},
141       {Vector3(1.0f, 1.0f, 1.0f), COLOR4},
142       {Vector3(1.0f, -1.0f, 1.0f), COLOR4},
143       {Vector3(1.0f, -1.0f, -1.0f), COLOR4},
144       {Vector3(1.0f, -1.0f, 1.0f), COLOR1},
145       {Vector3(-1.0f, -1.0f, 1.0f), COLOR1},
146       {Vector3(-1.0f, -1.0f, -1.0f), COLOR1},
147       {Vector3(-1.0f, -1.0f, -1.0f), COLOR0},
148       {Vector3(-1.0f, -1.0f, 1.0f), COLOR0},
149       {Vector3(-1.0f, 1.0f, 1.0f), COLOR0},
150       {Vector3(1.0f, 1.0f, -1.0f), COLOR2},
151       {Vector3(-1.0f, 1.0f, -1.0f), COLOR2},
152       {Vector3(-1.0f, 1.0f, 1.0f), COLOR2},
153     };
154
155     VertexBuffer vertexBuffer = VertexBuffer::New(Property::Map()
156                                                     .Add("aPosition", Property::VECTOR3)
157                                                     .Add("aColor", Property::VECTOR3));
158     vertexBuffer.SetData(vertices, sizeof(vertices) / sizeof(Vertex));
159
160     // create indices
161     const unsigned short INDEX_CUBE[] = {
162       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};
163     mGeometry = Geometry::New();
164     mGeometry.AddVertexBuffer(vertexBuffer);
165     mGeometry.SetIndexBuffer(INDEX_CUBE,
166                              sizeof(INDEX_CUBE) / sizeof(INDEX_CUBE[0]));
167     mGeometry.SetType(Geometry::TRIANGLES);
168   }
169
170   /**
171    * Creates a shader using inlined variable SHADER_RENDERING_CUBE_VERT and SHADER_RENDERING_CUBE_FRAG
172    *
173    * Shaders are very basic and all they do is transforming vertices and interpolating
174    * input per-vertex color.
175    */
176   void CreateCubeShader()
177   {
178     mShader = Shader::New(SHADER_RENDERING_CUBE_VERT, SHADER_RENDERING_CUBE_FRAG);
179   }
180
181   /**
182    * Function creates renderer. It turns on depth test and depth write.
183    */
184   void CreateRenderer()
185   {
186     mRenderer = Renderer::New(mGeometry, mShader);
187
188     // Face culling is enabled to hide the backwards facing sides of the cube
189     // This is sufficient to render a single object; for more complex scenes depth-testing might be required
190     mRenderer.SetProperty(Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK);
191   }
192
193   /**
194    * Creates new actor and attaches renderer.
195    */
196   void CreateActor()
197   {
198     Window window = mApplication.GetWindow();
199     const auto windowSize = window.GetSize();
200
201     float quarterWindowSize = std::min(windowSize.GetWidth(), windowSize.GetHeight()) * 0.25f;
202     mActor                  = Actor::New();
203     mActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
204     mActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
205     mActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 0.0f));
206     mActor.SetProperty(Actor::Property::SIZE, Vector3(quarterWindowSize, quarterWindowSize, quarterWindowSize));
207     mActor.AddRenderer(mRenderer);
208     window.Add(mActor);
209   }
210
211   /**
212    * Plays animation
213    */
214   void PlayAnimation()
215   {
216     mAnimation = Animation::New(5.0f);
217     mAnimation.SetLooping(true);
218     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::ZAXIS));
219     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::YAXIS));
220     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::XAXIS));
221     mAnimation.Play();
222   }
223
224 private:
225   Application& mApplication;
226
227   Renderer  mRenderer;
228   Shader    mShader;
229   Geometry  mGeometry;
230   Actor     mActor;
231   Animation mAnimation;
232 };
233
234 int DALI_EXPORT_API main(int argc, char** argv)
235 {
236   Application        application = Application::New(&argc, &argv);
237   DrawCubeController test(application);
238   application.MainLoop();
239   return 0;
240 }