Use FileStream API in demo.
[platform/core/uifw/dali-demo.git] / examples / ray-marching / ray-marching-example.cpp
1 /*
2  * Copyright (c) 2017 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 "shared/view.h"
21 #include "shared/utility.h"
22 #include <stdio.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/devel-api/adaptor-framework/file-stream.h>
25
26 using namespace Dali;
27 using Dali::Toolkit::TextLabel;
28 using Dali::Toolkit::Control;
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
101   RayMarchingExample( Application& application )
102   : mApplication( application )
103   {
104     // Connect to the Application's Init signal
105     mApplication.InitSignal().Connect( this, &RayMarchingExample::Create );
106   }
107
108   ~RayMarchingExample()
109   {
110     // Nothing to do here;
111   }
112
113   // The Init signal is received once (only) during the Application lifetime
114   void Create( Application& application )
115   {
116     // Get a handle to the stage
117     Stage stage = Stage::GetCurrent();
118
119     stage.GetRootLayer().TouchSignal().Connect( this, &RayMarchingExample::OnTouch );
120
121     stage.KeyEventSignal().Connect(this, &RayMarchingExample::OnKeyEvent);
122
123     stage.SetBackgroundColor( Color::YELLOW );
124
125     // Hide the indicator bar
126     application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
127
128     // Creates a default view with a default tool bar.
129     // The view is added to the stage.
130     mContentLayer = DemoHelper::CreateView( application,
131                                             mView,
132                                             mToolBar,
133                                             BACKGROUND_IMAGE,
134                                             TOOLBAR_IMAGE,
135                                             APPLICATION_TITLE );
136
137     // Add an extra space on the right to center the title text.
138     mToolBar.AddControl( Actor::New(), DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight );
139
140     AddContentLayer();
141
142   }
143   bool OnTouch( Actor actor, const TouchData& touch )
144   {
145     // quit the application
146     mApplication.Quit();
147     return true;
148   }
149
150   /**
151    * Main key event handler
152    */
153   void OnKeyEvent(const KeyEvent& event)
154   {
155     if(event.state == KeyEvent::Down)
156     {
157       if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
158       {
159         mApplication.Quit();
160       }
161     }
162   }
163
164   /**
165    * Creates quad renderer
166    */
167   Renderer CreateQuadRenderer()
168   {
169     // Create shader & geometry needed by Renderer
170     Shader shader = LoadShaders( SHADER_NAME );
171
172     Property::Map vertexFormat;
173     vertexFormat["aPosition"] = Property::VECTOR2;
174     PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
175
176     const float P( 0.5f );
177     const Vector2 vertices[] = {
178       Vector2( -P, -P ),
179       Vector2( +P, -P ),
180       Vector2( -P, +P ),
181       Vector2( +P, +P )
182     };
183
184     vertexBuffer.SetData( vertices, 4 );
185
186     // Instantiate quad geometry
187     Geometry geometry = Geometry::New();
188     geometry.AddVertexBuffer( vertexBuffer );
189     geometry.SetType( Geometry::TRIANGLE_STRIP );
190
191     // Create renderer
192     Renderer renderer = Renderer::New( geometry, shader );
193
194     renderer.RegisterProperty("uRadius", 0.0f );
195     renderer.RegisterProperty("uAdjuster", -4.0f );
196
197     //  Animate the sphere radius uniform and a generic uAdjust uniform currently used to move the light around
198     Animation animation = Animation::New(8.0f);
199     animation.AnimateTo( Property(renderer,"uRadius"), 1.2f, AlphaFunction::BOUNCE);
200     animation.AnimateTo( Property(renderer,"uAdjuster"), 4.0f, AlphaFunction::BOUNCE);
201     animation.SetLooping( true );
202     animation.Play();
203
204     return renderer;
205   }
206
207   void AddContentLayer()
208   {
209     Stage stage = Stage::GetCurrent();
210
211      //Create all the renderers
212     Renderer renderer = CreateQuadRenderer();
213
214     Actor actor = Actor::New();
215     actor.AddRenderer( renderer );
216
217     actor.SetAnchorPoint( Dali::AnchorPoint::CENTER );
218     actor.SetParentOrigin( Dali::ParentOrigin::CENTER );
219     actor.SetResizePolicy( Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS );
220
221     mContentLayer.Add( actor );
222   }
223
224 private:
225   Application&  mApplication;
226   Control mView;
227   Layer mContentLayer;
228   ToolBar mToolBar;
229 };
230
231 int DALI_EXPORT_API main( int argc, char **argv )
232 {
233   Application application = Application::New( &argc, &argv );
234   RayMarchingExample test( application );
235   application.MainLoop();
236   return 0;
237 }