08cf1c7ec1759963aebe4d28c4548dd6a662307e
[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 #include "generated/rendering-cube-vert.h"
22 #include "generated/rendering-cube-frag.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
200     float quarterWindowWidth = window.GetSize().GetWidth() * 0.25f;
201     mActor                   = Actor::New();
202     mActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
203     mActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
204     mActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 0.0f));
205     mActor.SetProperty(Actor::Property::SIZE, Vector3(quarterWindowWidth, quarterWindowWidth, quarterWindowWidth));
206     mActor.AddRenderer(mRenderer);
207     window.Add(mActor);
208   }
209
210   /**
211    * Plays animation
212    */
213   void PlayAnimation()
214   {
215     mAnimation = Animation::New(5.0f);
216     mAnimation.SetLooping(true);
217     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::ZAXIS));
218     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::YAXIS));
219     mAnimation.AnimateBy(Property(mActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360)), Vector3::XAXIS));
220     mAnimation.Play();
221   }
222
223 private:
224   Application& mApplication;
225
226   Renderer  mRenderer;
227   Shader    mShader;
228   Geometry  mGeometry;
229   Actor     mActor;
230   Animation mAnimation;
231 };
232
233 int DALI_EXPORT_API main(int argc, char** argv)
234 {
235   Application        application = Application::New(&argc, &argv);
236   DrawCubeController test(application);
237   application.MainLoop();
238   return 0;
239 }