Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / examples / ray-marching / ray-marching-example.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-toolkit/devel-api/controls/tool-bar/tool-bar.h>
20 #include <dali/devel-api/adaptor-framework/file-stream.h>
21 #include <dali/integration-api/debug.h>
22 #include <stdio.h>
23 #include "shared/utility.h"
24 #include "shared/view.h"
25
26 using namespace Dali;
27 using Dali::Toolkit::Control;
28 using Dali::Toolkit::TextLabel;
29 using Dali::Toolkit::ToolBar;
30
31 const char* BACKGROUND_IMAGE("");
32 const char* TOOLBAR_IMAGE(DEMO_IMAGE_DIR "top-bar.png");
33 const char* APPLICATION_TITLE("Ray Marching");
34 const char* SHADER_NAME("raymarch_sphere_shaded");
35
36 /**
37  * @brief LoadShaderCode
38  * @param filename
39  * @param output
40  * @return
41  */
42 bool LoadShaderCode(const char* path, const char* filename, std::vector<char>& output)
43 {
44   std::string fullpath(path);
45   fullpath += filename;
46
47   Dali::FileStream fileStream(fullpath, Dali::FileStream::READ | Dali::FileStream::BINARY);
48   FILE*            file = fileStream.GetFile();
49   if(!file)
50   {
51     return false;
52   }
53
54   bool retValue = false;
55   if(!fseek(file, 0, SEEK_END))
56   {
57     long int size = ftell(file);
58
59     if((size != -1L) &&
60        (!fseek(file, 0, SEEK_SET)))
61     {
62       output.resize(size + 1);
63       std::fill(output.begin(), output.end(), 0);
64       ssize_t result = fread(output.data(), size, 1, file);
65
66       retValue = (result >= 0);
67     }
68   }
69
70   return retValue;
71 }
72
73 /**
74  * @brief LoadShaders
75  * @param shaderName
76  * @return
77  */
78 Shader LoadShaders(const std::string& shaderName)
79 {
80   std::vector<char> bufV, bufF;
81   std::string       shaderVSH(shaderName);
82   std::string       shaderFSH(shaderName);
83   shaderVSH += ".vsh";
84   shaderFSH += ".fsh";
85
86   Shader shader;
87   if(LoadShaderCode(DEMO_SHADER_DIR, shaderVSH.c_str(), bufV) &&
88      LoadShaderCode(DEMO_SHADER_DIR, shaderFSH.c_str(), bufF))
89   {
90     shader = Shader::New(bufV.data(), bufF.data());
91   }
92   return shader;
93 }
94
95 // This example shows how to create a Ray Marching using a shader
96 //
97 class RayMarchingExample : public ConnectionTracker
98 {
99 public:
100   RayMarchingExample(Application& application)
101   : mApplication(application)
102   {
103     // Connect to the Application's Init signal
104     mApplication.InitSignal().Connect(this, &RayMarchingExample::Create);
105   }
106
107   ~RayMarchingExample()
108   {
109     // Nothing to do here;
110   }
111
112   // The Init signal is received once (only) during the Application lifetime
113   void Create(Application& application)
114   {
115     // Get a handle to the window
116     Window window = application.GetWindow();
117
118     window.GetRootLayer().TouchedSignal().Connect(this, &RayMarchingExample::OnTouch);
119
120     window.KeyEventSignal().Connect(this, &RayMarchingExample::OnKeyEvent);
121
122     window.SetBackgroundColor(Color::YELLOW);
123
124     // Creates a default view with a default tool bar.
125     // The view is added to the window.
126     mContentLayer = DemoHelper::CreateView(application,
127                                            mView,
128                                            mToolBar,
129                                            BACKGROUND_IMAGE,
130                                            TOOLBAR_IMAGE,
131                                            APPLICATION_TITLE);
132
133     // Add an extra space on the right to center the title text.
134     mToolBar.AddControl(Actor::New(), DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HORIZONTAL_RIGHT);
135
136     AddContentLayer();
137   }
138   bool OnTouch(Actor actor, const TouchEvent& touch)
139   {
140     // quit the application
141     mApplication.Quit();
142     return true;
143   }
144
145   /**
146    * Main key event handler
147    */
148   void OnKeyEvent(const KeyEvent& event)
149   {
150     if(event.GetState() == KeyEvent::DOWN)
151     {
152       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
153       {
154         mApplication.Quit();
155       }
156     }
157   }
158
159   /**
160    * Creates quad renderer
161    */
162   Renderer CreateQuadRenderer()
163   {
164     // Create shader & geometry needed by Renderer
165     Shader shader = LoadShaders(SHADER_NAME);
166
167     Property::Map vertexFormat;
168     vertexFormat["aPosition"] = Property::VECTOR2;
169     VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
170
171     const float   P(0.5f);
172     const Vector2 vertices[] = {
173       Vector2(-P, -P),
174       Vector2(+P, -P),
175       Vector2(-P, +P),
176       Vector2(+P, +P)};
177
178     vertexBuffer.SetData(vertices, 4);
179
180     // Instantiate quad geometry
181     Geometry geometry = Geometry::New();
182     geometry.AddVertexBuffer(vertexBuffer);
183     geometry.SetType(Geometry::TRIANGLE_STRIP);
184
185     // Create renderer
186     Renderer renderer = Renderer::New(geometry, shader);
187
188     renderer.RegisterProperty("uRadius", 0.0f);
189     renderer.RegisterProperty("uAdjuster", -4.0f);
190
191     //  Animate the sphere radius uniform and a generic uAdjust uniform currently used to move the light around
192     Animation animation = Animation::New(8.0f);
193     animation.AnimateTo(Property(renderer, "uRadius"), 1.2f, AlphaFunction::BOUNCE);
194     animation.AnimateTo(Property(renderer, "uAdjuster"), 4.0f, AlphaFunction::BOUNCE);
195     animation.SetLooping(true);
196     animation.Play();
197
198     return renderer;
199   }
200
201   void AddContentLayer()
202   {
203     Window window = mApplication.GetWindow();
204
205     //Create all the renderers
206     Renderer renderer = CreateQuadRenderer();
207
208     Actor actor = Actor::New();
209     actor.AddRenderer(renderer);
210
211     actor.SetProperty(Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::CENTER);
212     actor.SetProperty(Actor::Property::PARENT_ORIGIN, Dali::ParentOrigin::CENTER);
213     actor.SetResizePolicy(Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS);
214
215     mContentLayer.Add(actor);
216   }
217
218 private:
219   Application& mApplication;
220   Control      mView;
221   Layer        mContentLayer;
222   ToolBar      mToolBar;
223 };
224
225 int DALI_EXPORT_API main(int argc, char** argv)
226 {
227   Application        application = Application::New(&argc, &argv);
228   RayMarchingExample test(application);
229   application.MainLoop();
230   return 0;
231 }