2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali/devel-api/actors/camera-actor-devel.h>
20 #include <dali/devel-api/adaptor-framework/file-stream.h>
24 #include "gltf-scene.h"
32 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
33 attribute mediump vec3 aPosition;\n
34 attribute mediump vec3 aNormal;\n
35 attribute mediump vec2 aTexCoord;\n
36 uniform mediump mat4 uMvpMatrix;\n
37 uniform mediump mat3 uNormalMatrix;\n
38 uniform mediump vec3 uSize;\n
40 varying mediump vec2 vTexCoord; \n
41 varying mediump vec3 vNormal; \n
42 varying mediump vec3 vPosition; \n
45 mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
46 vertexPosition.xyz *= uSize;\n
47 vTexCoord = aTexCoord;\n
48 vNormal = normalize(uNormalMatrix * aNormal);\n
49 vPosition = aPosition; \n
50 gl_Position = uMvpMatrix * vertexPosition;\n
54 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
55 uniform lowp vec4 uColor;\n
56 uniform sampler2D sTexture; \n
57 varying mediump vec3 vNormal;\n
58 varying mediump vec3 vPosition; \n
59 varying mediump vec2 vTexCoord; \n
63 gl_FragColor = texture2D(sTexture, vTexCoord) * 50.0;\n
67 const char* FRAGMENT_SIMPLE_SHADER = DALI_COMPOSE_SHADER(
68 uniform lowp vec4 uColor;\n
69 uniform sampler2D sTexture; \n
70 varying mediump vec3 vNormal;\n
71 varying mediump vec3 vPosition; \n
72 varying mediump vec2 vTexCoord; \n
76 gl_FragColor = texture2D(sTexture, vTexCoord) * 2.0;\n
80 const char* TEXTURED_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
81 uniform lowp vec4 uColor;\n
82 uniform sampler2D sTexture; \n
83 uniform mediump vec2 uScreenSize;\n
85 uniform mediump vec3 eyePos;\n
86 uniform mediump vec3 lightDir;\n
88 varying mediump vec3 vNormal;\n
89 varying mediump vec3 vPosition; \n
90 varying mediump vec2 vTexCoord; \n
94 mediump vec3 n = normalize( vNormal );\n
95 mediump vec3 l = normalize( lightDir );\n
96 mediump vec3 e = normalize( eyePos );\n
97 mediump float intensity = max(dot(n,l), 0.0);\n
98 gl_FragColor = texture2D(sTexture, vTexCoord) * intensity;\n
102 const char* PLASMA_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
103 precision mediump float;\n
104 uniform sampler2D sTexture; \n
107 uniform float uKFactor;
108 uniform mediump vec3 eyePos;\n
109 uniform mediump vec3 lightDir;\n
110 varying mediump vec3 vNormal;\n
111 varying mediump vec3 vPosition; \n
112 varying mediump vec2 vTexCoord; \n
116 mediump vec3 n = normalize( vNormal );\n
117 mediump vec3 l = normalize( lightDir );\n
118 mediump vec3 e = normalize( eyePos );\n
119 mediump float intensity = max(dot(n,l), 0.0);\n
121 const mediump float PI = 3.1415926535897932384626433832795;\n
122 mediump float v = 0.0;\n
123 mediump vec2 c = vTexCoord * uKFactor - uKFactor/2.0;\n
124 v += sin((c.x+uTime));\n
125 v += sin((c.y+uTime)/2.0);\n
126 v += sin((c.x+c.y+uTime)/2.0);\n
127 c += uKFactor/2.0 * vec2(sin(uTime/3.0), cos(uTime/2.0));\n
128 v += sin(sqrt(c.x*c.x+c.y*c.y+1.0)+uTime);\n
130 mediump vec3 col = vec3(1, sin(PI*v), cos(PI*v));\n
131 gl_FragColor = (texture2D(sTexture, vTexCoord)) * (((col.r+col.g+col.b)/3.0)+1.0+intensity);\n
135 const char* TEX_FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
136 uniform lowp vec4 uColor;\n
137 uniform sampler2D sTexture0; \n
138 uniform sampler2D sTexture1; \n
139 uniform mediump vec3 eyePos;\n
140 uniform mediump vec3 lightDir;\n
141 uniform mediump vec2 uScreenSize;\n
142 varying mediump vec3 vNormal;\n
143 varying mediump vec3 vPosition; \n
144 varying mediump vec2 vTexCoord; \n
147 mediump float rand(mediump vec2 co){\n
148 return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n
153 mediump vec2 tx = (gl_FragCoord.xy / uScreenSize.xy);\n
154 mediump vec3 n = normalize( vNormal );\n
155 mediump vec3 l = normalize( lightDir );\n
156 mediump vec3 e = normalize( eyePos );\n
157 mediump float factor = gl_FragCoord.y / uScreenSize.y;\n
158 mediump float intensity = max(dot(n,l), 0.0);\n
159 mediump vec2 uv = tx;\n
160 gl_FragColor = ((texture2D(sTexture0, vTexCoord) * factor ) + \n
161 (texture2D(sTexture1, uv))) * intensity;\n
171 using ModelPtr = std::unique_ptr<Model>;
173 using ActorContainer = std::vector<Actor>;
174 using CameraContainer = std::vector<CameraActor>;
175 using ModelContainer = std::vector<ModelPtr>;
176 using TextureSetContainer = std::vector<TextureSet>;
178 const Vector3 DEFAULT_LIGHT_DIRECTION(0.5, 0.5, -1);
181 bool LoadFile(const std::string& filename, std::vector<T>& bytes)
183 Dali::FileStream fileStream(filename, Dali::FileStream::READ | Dali::FileStream::BINARY);
184 FILE* fin = fileStream.GetFile();
188 if(fseek(fin, 0, SEEK_END))
192 bytes.resize(uint32_t(ftell(fin)));
193 std::fill(bytes.begin(), bytes.end(), 0);
194 if(fseek(fin, 0, SEEK_SET))
198 size_t result = fread(bytes.data(), 1, bytes.size(), fin);
199 return (result != 0);
205 Shader CreateShader(const std::string& vsh, const std::string& fsh)
207 std::vector<char> vshShaderSource;
208 std::vector<char> fshShaderSource;
213 std::string vshPath(DEMO_GAME_DIR);
216 LoadFile(vshPath, vshShaderSource);
220 vshShaderSource.insert(vshShaderSource.end(), vsh.begin(), vsh.end());
226 std::string fshPath(DEMO_GAME_DIR);
229 LoadFile(fshPath, fshShaderSource);
233 fshShaderSource.insert(fshShaderSource.end(), fsh.begin(), fsh.end());
236 vshShaderSource.emplace_back(0);
237 fshShaderSource.emplace_back(0);
238 return Shader::New(std::string(vshShaderSource.data()), std::string(fshShaderSource.data()));
241 ModelPtr CreateModel(
243 const glTF_Mesh* mesh,
244 const std::string& vertexShaderSource,
245 const std::string& fragmentShaderSource)
248 * Obtain interleaved buffer for first mesh with position and normal attributes
250 auto positionBuffer = gltf.GetMeshAttributeBuffer(*mesh,
251 {glTFAttributeType::POSITION,
252 glTFAttributeType::NORMAL,
253 glTFAttributeType::TEXCOORD_0});
255 auto attributeCount = gltf.GetMeshAttributeCount(mesh);
257 * Create matching property buffer
259 auto vertexBuffer = VertexBuffer::New(Property::Map()
260 .Add("aPosition", Property::VECTOR3)
261 .Add("aNormal", Property::VECTOR3)
262 .Add("aTexCoord", Property::VECTOR2));
265 vertexBuffer.SetData(positionBuffer.data(), attributeCount);
267 auto geometry = Geometry::New();
268 geometry.AddVertexBuffer(vertexBuffer);
269 auto indexBuffer = gltf.GetMeshIndexBuffer(mesh);
270 geometry.SetIndexBuffer(indexBuffer.data(), indexBuffer.size());
271 geometry.SetType(Geometry::Type::TRIANGLES);
272 ModelPtr retval(new Model());
273 retval->shader = CreateShader(vertexShaderSource, fragmentShaderSource);
274 retval->geometry = geometry;
278 void ReplaceShader(Actor& actor, const std::string& vsh, const std::string& fsh)
280 auto renderer = actor.GetRendererAt(0);
281 auto shader = CreateShader(vsh, fsh);
282 renderer.SetShader(shader);
285 void CreateTextureSetsFromGLTF(glTF* gltf, const std::string& basePath, TextureSetContainer& textureSets)
287 const auto& materials = gltf->GetMaterials();
288 const auto& textures = gltf->GetTextures();
290 std::map<std::string, Texture> textureCache{};
292 for(const auto& material : materials)
294 TextureSet textureSet;
295 if(material.pbrMetallicRoughness.enabled)
297 textureSet = TextureSet::New();
298 std::string filename(basePath);
300 filename += textures[material.pbrMetallicRoughness.baseTextureColor.index].uri;
301 Dali::PixelData pixelData = Dali::Toolkit::SyncImageLoader::Load(filename);
303 auto cacheKey = textures[material.pbrMetallicRoughness.baseTextureColor.index].uri;
304 auto iter = textureCache.find(cacheKey);
306 if(iter == textureCache.end())
308 texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
309 texture.Upload(pixelData);
310 texture.GenerateMipmaps();
311 textureCache[cacheKey] = texture;
315 texture = iter->second;
317 textureSet.SetTexture(0, texture);
318 Dali::Sampler sampler = Dali::Sampler::New();
319 sampler.SetWrapMode(Dali::WrapMode::REPEAT, Dali::WrapMode::REPEAT, Dali::WrapMode::REPEAT);
320 sampler.SetFilterMode(Dali::FilterMode::LINEAR_MIPMAP_LINEAR, Dali::FilterMode::LINEAR);
321 textureSet.SetSampler(0, sampler);
323 textureSets.emplace_back(textureSet);
328 * Creates models from glTF
330 void CreateModelsFromGLTF(glTF* gltf, ModelContainer& models)
332 const auto& meshes = gltf->GetMeshes();
333 for(const auto& mesh : meshes)
335 // change shader to use texture if material indicates that
336 if(mesh->material != 0xffffffff && gltf->GetMaterials()[mesh->material].pbrMetallicRoughness.enabled)
338 models.emplace_back(CreateModel(*gltf, mesh, VERTEX_SHADER, TEXTURED_FRAGMENT_SHADER));
342 models.emplace_back(CreateModel(*gltf, mesh, VERTEX_SHADER, FRAGMENT_SHADER));
347 Actor CreateSceneFromGLTF(
350 ModelContainer& models,
351 ActorContainer& actors,
352 CameraContainer& cameras,
353 TextureSetContainer& textureSets)
355 const auto& nodes = gltf->GetNodes();
357 Vector3 cameraPosition;
359 // for each node create nodes and children
360 // resolve parents later
361 actors.reserve(nodes.size());
362 for(const auto& node : nodes)
364 auto actor = node.cameraId != 0xffffffff ? CameraActor::New(window.GetSize()) : Actor::New();
366 actor.SetProperty(Actor::Property::SIZE, Vector3(1, 1, 1));
367 actor.SetProperty(Dali::Actor::Property::NAME, node.name);
368 actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
369 actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
370 actor.SetProperty(Actor::Property::POSITION, Vector3(node.translation[0], node.translation[1], node.translation[2]));
371 actor.SetProperty(Actor::Property::SCALE, Vector3(node.scale[0], node.scale[1], node.scale[2]));
372 actor.SetProperty(Actor::Property::ORIENTATION, Quaternion(node.rotationQuaternion[3], node.rotationQuaternion[0], node.rotationQuaternion[1], node.rotationQuaternion[2]));
374 actors.emplace_back(actor);
376 // Initially add each actor to the very first one
377 if(actors.size() > 1)
379 actors[0].Add(actor);
382 // If mesh, create and add renderer
383 if(node.meshId != 0xffffffff)
385 const auto& model = models[node.meshId].get();
386 auto renderer = Renderer::New(model->geometry, model->shader);
388 // if textured, add texture set
389 auto materialId = gltf->GetMeshes()[node.meshId]->material;
390 if(materialId != 0xffffffff)
392 if(gltf->GetMaterials()[materialId].pbrMetallicRoughness.enabled)
394 renderer.SetTextures(textureSets[materialId]);
398 actor.AddRenderer(renderer);
401 // Reset and attach main camera
402 if(node.cameraId != 0xffffffff)
404 cameraPosition = Vector3(node.translation[0], node.translation[1], node.translation[2]);
405 auto quatY = Quaternion(Degree(180.0f), Vector3(0.0, 1.0, 0.0));
406 auto cameraActor = CameraActor::DownCast(actor);
407 cameraActor.SetProperty(Actor::Property::ORIENTATION, Quaternion(node.rotationQuaternion[3], node.rotationQuaternion[0], node.rotationQuaternion[1], node.rotationQuaternion[2]) * quatY);
408 cameraActor.SetProjectionMode(Camera::PERSPECTIVE_PROJECTION);
410 const auto camera = gltf->GetCameras()[node.cameraId];
411 cameraActor.SetNearClippingPlane(camera->znear);
412 cameraActor.SetFarClippingPlane(camera->zfar);
413 cameraActor.SetFieldOfView(camera->yfov);
415 cameraActor.SetProperty(CameraActor::Property::INVERT_Y_AXIS, true);
416 cameraActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
417 cameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
419 cameras.emplace_back(cameraActor);
423 // Resolve hierarchy dependencies
425 for(const auto& node : nodes)
427 if(!node.children.empty())
429 for(const auto& childId : node.children)
431 actors[i].Add(actors[childId + 1]);
437 for(auto& actor : actors)
439 actor.RegisterProperty("lightDir", DEFAULT_LIGHT_DIRECTION);
440 actor.RegisterProperty("eyePos", cameraPosition);
446 } // unnamed namespace
448 // This example shows how to create and display mirrored reflection using CameraActor
450 class ReflectionExample : public ConnectionTracker
453 ReflectionExample(Application& application)
454 : mApplication(application)
456 // Connect to the Application's Init signal
457 mApplication.InitSignal().Connect(this, &ReflectionExample::Create);
460 ~ReflectionExample() = default;
463 // The Init signal is received once (only) during the Application lifetime
464 void Create(Application& application)
466 // Get a handle to the window
467 Window window = application.GetWindow();
468 uint32_t windowWidth = uint32_t(window.GetSize().GetWidth());
469 uint32_t windowHeight = uint32_t(window.GetSize().GetHeight());
471 window.GetRenderTaskList().GetTask(0).SetClearEnabled(false);
472 mLayer3D = Layer::New();
473 mLayer3D.SetProperty(Actor::Property::SIZE, Vector2(windowWidth, windowHeight));
474 window.Add(mLayer3D);
476 mLayer3D.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
477 mLayer3D.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
478 mLayer3D.SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
479 mLayer3D.SetProperty(Layer::Property::DEPTH_TEST, true);
481 auto gltf = glTF(DEMO_GAME_DIR "/reflection");
483 // Define direction of light
486 * Instantiate texture sets
488 CreateTextureSetsFromGLTF(&gltf, DEMO_GAME_DIR, mTextureSets);
493 CreateModelsFromGLTF(&gltf, mModels);
496 * Create scene nodes & add to 3D Layer
498 mLayer3D.Add(CreateSceneFromGLTF(window, &gltf, mModels, mActors, mCameras, mTextureSets));
500 auto planeActor = mLayer3D.FindChildByName("Plane");
501 auto solarActor = mLayer3D.FindChildByName("solar_root");
502 auto backgroundActor = mLayer3D.FindChildByName("background");
503 ReplaceShader(backgroundActor, VERTEX_SHADER, FRAGMENT_SIMPLE_SHADER);
504 mCenterActor = mLayer3D.FindChildByName("center");
505 mCenterHorizActor = mLayer3D.FindChildByName("center2");
508 auto sun = mLayer3D.FindChildByName("sun");
509 ReplaceShader(sun, VERTEX_SHADER, PLASMA_FRAGMENT_SHADER);
510 mSunTimeUniformIndex = sun.RegisterProperty("uTime", 0.0f);
511 mSunKFactorUniformIndex = sun.RegisterProperty("uKFactor", 0.0f);
513 mTickTimer = Timer::New(16);
514 mTickTimer.TickSignal().Connect(this, &ReflectionExample::TickTimerSignal);
517 auto milkyway = mLayer3D.FindChildByName("milkyway");
518 ReplaceShader(milkyway, VERTEX_SHADER, FRAGMENT_SHADER);
520 auto renderTaskSourceActor = mLayer3D.FindChildByName("RenderTaskSource");
523 * Access camera (it's a child of "Camera" node)
525 auto camera = mLayer3D.FindChildByName("Camera_Orientation");
526 auto cameraRef = mLayer3D.FindChildByName("CameraReflection_Orientation");
528 auto cameraActor = CameraActor::DownCast(camera);
529 mCamera3D = cameraActor;
531 auto cameraRefActor = CameraActor::DownCast(cameraRef);
532 cameraRefActor.SetProperty(DevelCameraActor::Property::REFLECTION_PLANE, Vector4(0.0f, -1.0f, 0.0f, 0.0f));
533 mReflectionCamera3D = cameraRefActor;
535 auto task3D = window.GetRenderTaskList().CreateTask();
536 task3D.SetSourceActor(mLayer3D);
537 task3D.SetViewport(Rect<int>(0, 0, windowWidth, windowHeight));
538 task3D.SetCameraActor(cameraActor);
539 task3D.SetClearColor(Color::BLACK);
540 task3D.SetClearEnabled(true);
541 task3D.SetExclusive(false);
542 task3D.SetCameraActor(cameraActor);
545 * Change shader to textured
547 Shader texShader = CreateShader(VERTEX_SHADER, TEX_FRAGMENT_SHADER);
548 planeActor.RegisterProperty("uScreenSize", Vector2(windowWidth, windowHeight));
549 auto renderer = planeActor.GetRendererAt(0);
550 auto textureSet = renderer.GetTextures();
551 renderer.SetShader(texShader);
553 Texture fbTexture = Texture::New(TextureType::TEXTURE_2D, Pixel::Format::RGBA8888, windowWidth, windowHeight);
554 textureSet.SetTexture(1u, fbTexture);
556 auto fb = FrameBuffer::New(windowWidth, windowHeight, FrameBuffer::Attachment::DEPTH);
558 fb.AttachColorTexture(fbTexture);
560 auto renderTask = window.GetRenderTaskList().CreateTask();
561 renderTask.SetFrameBuffer(fb);
562 renderTask.SetSourceActor(renderTaskSourceActor);
563 renderTask.SetViewport(Rect<int>(0, 0, windowWidth, windowHeight));
564 renderTask.SetCameraActor(cameraRefActor);
565 renderTask.SetClearColor(Color::BLACK);
566 renderTask.SetClearEnabled(true);
567 renderTask.SetExclusive(false);
569 mAnimation = Animation::New(30.0f);
570 mAnimation.AnimateBy(Property(solarActor, Actor::Property::ORIENTATION),
571 Quaternion(Degree(359), Vector3(0.0, 1.0, 0.0)));
572 mAnimation.AnimateBy(Property(milkyway, Actor::Property::ORIENTATION),
573 Quaternion(Degree(-359), Vector3(0.0, 1.0, 0.0)));
574 mAnimation.SetLooping(true);
577 Actor panScreen = Actor::New();
578 Vector2 windowSize = window.GetSize();
579 panScreen.SetProperty(Actor::Property::SIZE, windowSize);
580 panScreen.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
581 panScreen.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
582 auto camera2d = window.GetRenderTaskList().GetTask(0).GetCameraActor();
583 panScreen.SetProperty(Actor::Property::POSITION, Vector3(0, 0, camera2d.GetNearClippingPlane()));
584 camera2d.Add(panScreen);
585 camera2d.RotateBy(Degree(180.0f), Vector3(0.0, 1.0, 0.0));
586 mPanGestureDetector = PanGestureDetector::New();
587 mPanGestureDetector.Attach(panScreen);
588 mPanGestureDetector.DetectedSignal().Connect(this, &ReflectionExample::OnPan);
590 // Respond to key events
591 window.KeyEventSignal().Connect(this, &ReflectionExample::OnKeyEvent);
596 void OnPan(Actor actor, const PanGesture& panGesture)
598 Vector2 displacement = panGesture.GetScreenDisplacement();
600 displacement.y * -0.1f,
601 displacement.x * 0.1f
604 Quaternion q(Degree(0.f), Degree(rotation.y), Degree(rotation.x));
605 Quaternion q0 = mCenterActor.GetProperty(Actor::Property::ORIENTATION).Get<Quaternion>();
606 mCenterActor.SetProperty(Actor::Property::ORIENTATION, q * q0);
608 Matrix m = Matrix::IDENTITY;
609 m.SetTransformComponents(Vector3::ONE, q0, Vector3::ZERO);
610 auto yAxis = m.GetYAxis() * -1.0f;
613 mReflectionCamera3D.SetProperty(DevelCameraActor::Property::REFLECTION_PLANE, Vector4(yAxis.x, yAxis.y, yAxis.z, 0.0f));
616 void OnKeyEvent(const KeyEvent& event)
618 if(event.GetState() == KeyEvent::DOWN)
620 if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
627 bool TickTimerSignal()
629 auto root = mLayer3D;
630 static float rotationAngle = 0.0f;
632 const auto ROTATION_ANGLE_STEP = 0.05f;
633 const auto FRAME_DELTA_TIME = 0.016f;
634 const auto PLASMA_K_FACTOR = 12.0f; // 'granularity' of plasma effect
636 rotationAngle += ROTATION_ANGLE_STEP;
637 mMockTime += FRAME_DELTA_TIME;
638 mKFactor = PLASMA_K_FACTOR;
640 auto sun = root.FindChildByName("sun");
641 sun.SetProperty(mSunTimeUniformIndex, mMockTime);
642 sun.SetProperty(mSunKFactorUniformIndex, mKFactor);
643 sun.SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(Degree(rotationAngle)), Vector3(0.0, 1.0, 0.0)));
648 Application& mApplication;
652 ActorContainer mActors{};
653 CameraContainer mCameras{};
654 ModelContainer mModels{};
655 TextureSetContainer mTextureSets{};
657 Animation mAnimation{};
658 float mMockTime{0.0f};
659 float mKFactor{0.0f};
660 Property::Index mSunTimeUniformIndex{};
661 Property::Index mSunKFactorUniformIndex{};
662 PanGestureDetector mPanGestureDetector{};
666 CameraActor mCamera3D{};
667 CameraActor mReflectionCamera3D{};
668 Actor mCenterActor{};
669 Actor mCenterHorizActor{};
672 int DALI_EXPORT_API main(int argc, char** argv)
674 Application application = Application::New(&argc, &argv);
675 ReflectionExample test(application);
676 application.MainLoop();