From: seungho Date: Wed, 14 Sep 2022 07:51:43 +0000 (+0900) Subject: Change ModelView to Model X-Git-Tag: accepted/tizen/unified/20220922.062036~1^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=352af592adca3b68694d0d10552f490044005043;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git Change ModelView to Model - with several minor fix Change-Id: I3e4c99c8a30c3c9bfdc5bb0cb61f00a09720e34f Signed-off-by: seungho --- diff --git a/automated-tests/resources/beer_modelTest.dli b/automated-tests/resources/beer_modelTest.dli new file mode 100644 index 0000000000..20be585c64 --- /dev/null +++ b/automated-tests/resources/beer_modelTest.dli @@ -0,0 +1,181 @@ +{ + "asset": { "version": "1.0" }, + "scene": 0, + "scenes": [ { "nodes": [ 0 ] } ], + "nodes": [ + { + "name": "Scene", + "matrix": [ 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1 ], + "children": [ 1, 2 ] + }, + { + "name": "Cube", + "matrix": [ 2.5, 0, 0, 0, 0, 2.5, 0, 0, 0, 0, 2.5, 0, 0, 0, 0, 1 ], + "model": { + "mesh": 0, + "material": 0, + "shader": 0 + } + }, + { + "name": "bottle", + "matrix": [ 0.125, 0, 0, 0, 0, -0, 0.125, 0, 0, -0.125, -0, 0, -0, 0, -1.5, 1 ], + "children": [ 3, 4, 5, 6 ] + }, + { + "name": "bottle-cap", + "model": { + "mesh": 3, + "material": 2, + "shader": 1 + } + }, + { + "name": "bottle-alpha-front", + "model": { + "mesh": 1, + "material": 1, + "shader": 2 + } + }, + { + "name": "bottle-alpha-back", + "model": { + "mesh": 1, + "material": 1, + "shader": 3 + } + }, + { + "name": "bottle-label", + "model": { + "mesh": 2, + "material": 0, + "shader": 4 + } + } + ], + "meshes": [ + { + "uri": "cube.bin", + "attributes": 31, + "primitive": "TRIANGLES", + "indices": { "byteOffset": 0, "byteLength": 72 }, + "positions": { "byteOffset": 72, "byteLength": 288 }, + "normals": { "byteOffset": 360, "byteLength": 288 }, + "textures": { "byteOffset": 648, "byteLength": 192 }, + "tangents": { "byteOffset": 840, "byteLength": 288 } + }, + { + "uri": "beer.bin", + "attributes": 31, + "primitive": "TRIANGLES", + "indices": { "byteOffset": 0, "byteLength": 19920 }, + "positions": { "byteOffset": 19920, "byteLength": 54792 }, + "normals": { "byteOffset": 74712, "byteLength": 54792 }, + "textures": { "byteOffset": 129504, "byteLength": 36528 }, + "tangents": { "byteOffset": 166032, "byteLength": 54792 } + }, + { + "uri": "beer.bin", + "attributes": 31, + "primitive": "TRIANGLES", + "indices": { "byteOffset": 220824, "byteLength": 13200 }, + "positions": { "byteOffset": 234024, "byteLength": 14628 }, + "normals": { "byteOffset": 248652, "byteLength": 14628 }, + "textures": { "byteOffset": 263280, "byteLength": 9752 }, + "tangents": { "byteOffset": 273032, "byteLength": 14628 } + }, + { + "uri": "beer.bin", + "attributes": 31, + "primitive": "TRIANGLES", + "indices": { "byteOffset": 287660, "byteLength": 31440 }, + "positions": { "byteOffset": 319100, "byteLength": 121032 }, + "normals": { "byteOffset": 440132, "byteLength": 121032 }, + "textures": { "byteOffset": 561164, "byteLength": 80688 }, + "tangents": { "byteOffset": 641852, "byteLength": 121032 } + } + ], + "skeletons": [ + ], + "cameras": [ + { + "fov": 60, + "near": 0.1, + "far": 100, + "matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 3.5, 1 ] + } + ], + "lights": [ + ], + "materials": [ + { + "color": [ 1.0, 0.95, 0.5 ], + "metallic": 0.25, + "roughness": 1.0, + "environment": 1 + }, + { + "color": [ 0.1, 0.4, 0.0, 0.6 ], + "metallic": 0.4, + "roughness": 0.0, + "environment": 1 + }, + { + "color": [ 0.5, 0.5, 0.5 ], + "metallic": 1.0, + "roughness": 0.0, + "environment": 1 + } + ], + "environment": [ + { + }, + { + "cubeSpecular": "Studio/Radiance.ktx", + "cubeDiffuse": "Studio/Irradiance.ktx", + "iblIntensity": 0.75 + } + ], + "shaders": [ + { + "vertex": "dli_pbr.vsh", + "fragment": "dli_pbr.fsh", + "rendererState": "DEPTH_TEST|CULL_FRONT", + "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], + "uMaxLOD": 6 + }, + { + "vertex": "dli_pbr.vsh", + "fragment": "dli_pbr.fsh", + "rendererState": "DEPTH_TEST|DEPTH_WRITE", + "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], + "uMaxLOD": 6 + }, + { + "vertex": "dli_pbr.vsh", + "fragment": "dli_pbr.fsh", + "defines": [ "THREE_TEX" ], + "rendererState": "ALPHA_BLEND|DEPTH_TEST|CULL_FRONT", + "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], + "uMaxLOD": 6 + }, + { + "vertex": "dli_pbr.vsh", + "fragment": "dli_pbr.fsh", + "defines": [ "THREE_TEX" ], + "rendererState": "ALPHA_BLEND|DEPTH_TEST|CULL_BACK", + "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], + "uMaxLOD": 6 + }, + { + "vertex": "dli_pbr.vsh", + "fragment": "dli_pbr.fsh", + "defines": [ "FLIP_V" ], + "rendererState": "DEPTH_TEST|DEPTH_WRITE|CULL_BACK", + "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], + "uMaxLOD": 6 + } + ] +} diff --git a/automated-tests/resources/beer_modelViewTest.dli b/automated-tests/resources/beer_modelViewTest.dli deleted file mode 100644 index 20be585c64..0000000000 --- a/automated-tests/resources/beer_modelViewTest.dli +++ /dev/null @@ -1,181 +0,0 @@ -{ - "asset": { "version": "1.0" }, - "scene": 0, - "scenes": [ { "nodes": [ 0 ] } ], - "nodes": [ - { - "name": "Scene", - "matrix": [ 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1 ], - "children": [ 1, 2 ] - }, - { - "name": "Cube", - "matrix": [ 2.5, 0, 0, 0, 0, 2.5, 0, 0, 0, 0, 2.5, 0, 0, 0, 0, 1 ], - "model": { - "mesh": 0, - "material": 0, - "shader": 0 - } - }, - { - "name": "bottle", - "matrix": [ 0.125, 0, 0, 0, 0, -0, 0.125, 0, 0, -0.125, -0, 0, -0, 0, -1.5, 1 ], - "children": [ 3, 4, 5, 6 ] - }, - { - "name": "bottle-cap", - "model": { - "mesh": 3, - "material": 2, - "shader": 1 - } - }, - { - "name": "bottle-alpha-front", - "model": { - "mesh": 1, - "material": 1, - "shader": 2 - } - }, - { - "name": "bottle-alpha-back", - "model": { - "mesh": 1, - "material": 1, - "shader": 3 - } - }, - { - "name": "bottle-label", - "model": { - "mesh": 2, - "material": 0, - "shader": 4 - } - } - ], - "meshes": [ - { - "uri": "cube.bin", - "attributes": 31, - "primitive": "TRIANGLES", - "indices": { "byteOffset": 0, "byteLength": 72 }, - "positions": { "byteOffset": 72, "byteLength": 288 }, - "normals": { "byteOffset": 360, "byteLength": 288 }, - "textures": { "byteOffset": 648, "byteLength": 192 }, - "tangents": { "byteOffset": 840, "byteLength": 288 } - }, - { - "uri": "beer.bin", - "attributes": 31, - "primitive": "TRIANGLES", - "indices": { "byteOffset": 0, "byteLength": 19920 }, - "positions": { "byteOffset": 19920, "byteLength": 54792 }, - "normals": { "byteOffset": 74712, "byteLength": 54792 }, - "textures": { "byteOffset": 129504, "byteLength": 36528 }, - "tangents": { "byteOffset": 166032, "byteLength": 54792 } - }, - { - "uri": "beer.bin", - "attributes": 31, - "primitive": "TRIANGLES", - "indices": { "byteOffset": 220824, "byteLength": 13200 }, - "positions": { "byteOffset": 234024, "byteLength": 14628 }, - "normals": { "byteOffset": 248652, "byteLength": 14628 }, - "textures": { "byteOffset": 263280, "byteLength": 9752 }, - "tangents": { "byteOffset": 273032, "byteLength": 14628 } - }, - { - "uri": "beer.bin", - "attributes": 31, - "primitive": "TRIANGLES", - "indices": { "byteOffset": 287660, "byteLength": 31440 }, - "positions": { "byteOffset": 319100, "byteLength": 121032 }, - "normals": { "byteOffset": 440132, "byteLength": 121032 }, - "textures": { "byteOffset": 561164, "byteLength": 80688 }, - "tangents": { "byteOffset": 641852, "byteLength": 121032 } - } - ], - "skeletons": [ - ], - "cameras": [ - { - "fov": 60, - "near": 0.1, - "far": 100, - "matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 3.5, 1 ] - } - ], - "lights": [ - ], - "materials": [ - { - "color": [ 1.0, 0.95, 0.5 ], - "metallic": 0.25, - "roughness": 1.0, - "environment": 1 - }, - { - "color": [ 0.1, 0.4, 0.0, 0.6 ], - "metallic": 0.4, - "roughness": 0.0, - "environment": 1 - }, - { - "color": [ 0.5, 0.5, 0.5 ], - "metallic": 1.0, - "roughness": 0.0, - "environment": 1 - } - ], - "environment": [ - { - }, - { - "cubeSpecular": "Studio/Radiance.ktx", - "cubeDiffuse": "Studio/Irradiance.ktx", - "iblIntensity": 0.75 - } - ], - "shaders": [ - { - "vertex": "dli_pbr.vsh", - "fragment": "dli_pbr.fsh", - "rendererState": "DEPTH_TEST|CULL_FRONT", - "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], - "uMaxLOD": 6 - }, - { - "vertex": "dli_pbr.vsh", - "fragment": "dli_pbr.fsh", - "rendererState": "DEPTH_TEST|DEPTH_WRITE", - "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], - "uMaxLOD": 6 - }, - { - "vertex": "dli_pbr.vsh", - "fragment": "dli_pbr.fsh", - "defines": [ "THREE_TEX" ], - "rendererState": "ALPHA_BLEND|DEPTH_TEST|CULL_FRONT", - "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], - "uMaxLOD": 6 - }, - { - "vertex": "dli_pbr.vsh", - "fragment": "dli_pbr.fsh", - "defines": [ "THREE_TEX" ], - "rendererState": "ALPHA_BLEND|DEPTH_TEST|CULL_BACK", - "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], - "uMaxLOD": 6 - }, - { - "vertex": "dli_pbr.vsh", - "fragment": "dli_pbr.fsh", - "defines": [ "FLIP_V" ], - "rendererState": "DEPTH_TEST|DEPTH_WRITE|CULL_BACK", - "uCubeMatrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], - "uMaxLOD": 6 - } - ] -} diff --git a/automated-tests/src/dali-scene3d/CMakeLists.txt b/automated-tests/src/dali-scene3d/CMakeLists.txt index 6bc5e4058a..ef86b06832 100755 --- a/automated-tests/src/dali-scene3d/CMakeLists.txt +++ b/automated-tests/src/dali-scene3d/CMakeLists.txt @@ -19,7 +19,7 @@ SET(TC_SOURCES utc-Dali-FacialAnimation.cpp utc-Dali-Gltf2Loader.cpp utc-Dali-KtxLoader.cpp - utc-Dali-ModelView.cpp + utc-Dali-Model.cpp utc-Dali-SceneView.cpp utc-Dali-MatrixStack.cpp utc-Dali-MeshDefinition.cpp diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp new file mode 100644 index 0000000000..d6a73d8128 --- /dev/null +++ b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include + +using namespace Dali; +using namespace Dali::Toolkit; + +void model_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void model_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ +/** + * For the AnimatedCube.gltf and its Assets + * Donated by Norbert Nopper for glTF testing. + * Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnimatedCube + */ +const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf"; +const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf"; +const char* TEST_DLI_FILE_NAME = TEST_RESOURCE_DIR "/arc.dli"; +/** + * For the diffuse and specular cube map texture. + * These textures are based off version of Wave engine sample + * Take from https://github.com/WaveEngine/Samples + * + * Copyright (c) 2022 Wave Coorporation + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +const char* TEST_DIFFUSE_TEXTURE = TEST_RESOURCE_DIR "/forest_irradiance.ktx"; +const char* TEST_SPECULAR_TEXTURE = TEST_RESOURCE_DIR "/forest_radiance.ktx"; +} // namespace + +// Negative test case for a method +int UtcDaliModelUninitialized(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliModelUninitialized"); + + Scene3D::Model model; + + try + { + // New() must be called to create a Model or it wont be valid. + Actor a = Actor::New(); + model.Add(a); + DALI_TEST_CHECK(false); + } + catch(Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT(e); + DALI_TEST_CHECK(!model); + } + END_TEST; +} + +// Positive test case for a method +int UtcDaliModelNew(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliModelNew"); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + DALI_TEST_CHECK(model); + END_TEST; +} + +// Positive test case for a method +int UtcDaliModelDownCast(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliModelDownCast"); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + BaseHandle handle(model); + + Scene3D::Model model2 = Scene3D::Model::DownCast(handle); + DALI_TEST_CHECK(model); + DALI_TEST_CHECK(model2); + DALI_TEST_CHECK(model2 == model); + END_TEST; +} + +int UtcDaliModelTypeRegistry(void) +{ + ToolkitTestApplication application; + + TypeRegistry typeRegistry = TypeRegistry::Get(); + DALI_TEST_CHECK(typeRegistry); + + TypeInfo typeInfo = typeRegistry.GetTypeInfo("Model"); + DALI_TEST_CHECK(typeInfo); + + BaseHandle handle = typeInfo.CreateInstance(); + DALI_TEST_CHECK(handle); + + Scene3D::Model model = Scene3D::Model::DownCast(handle); + DALI_TEST_CHECK(model); + + END_TEST; +} + +// Positive test case for a method +int UtcDaliModelAddRemove(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliModelAddRemove"); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + DALI_TEST_CHECK(model); + + Actor actor = Actor::New(); + DALI_TEST_CHECK(!actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)); + + model.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + model.SetProperty(Actor::Property::SIZE, application.GetScene().GetSize()); + model.Add(actor); + application.GetScene().Add(model); + + DALI_TEST_CHECK(actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)); + + model.Remove(actor); + + DALI_TEST_CHECK(!actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)); + END_TEST; +} + +int UtcDaliModelCopyAndAssignment(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + DALI_TEST_CHECK(model); + + Scene3D::Model copy(model); + DALI_TEST_CHECK(model == copy); + + Scene3D::Model assign; + DALI_TEST_CHECK(!assign); + + assign = copy; + DALI_TEST_CHECK(assign == model); + + END_TEST; +} + +int UtcDaliModelMoveConstructor(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + DALI_TEST_EQUALS(1, model.GetBaseObject().ReferenceCount(), TEST_LOCATION); + model.SetProperty(Actor::Property::SENSITIVE, false); + DALI_TEST_CHECK(false == model.GetProperty(Actor::Property::SENSITIVE)); + + Scene3D::Model moved = std::move(model); + DALI_TEST_CHECK(moved); + DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION); + DALI_TEST_CHECK(false == moved.GetProperty(Actor::Property::SENSITIVE)); + DALI_TEST_CHECK(!model); + + END_TEST; +} + +int UtcDaliModelMoveAssignment(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + DALI_TEST_EQUALS(1, model.GetBaseObject().ReferenceCount(), TEST_LOCATION); + model.SetProperty(Actor::Property::SENSITIVE, false); + DALI_TEST_CHECK(false == model.GetProperty(Actor::Property::SENSITIVE)); + + Scene3D::Model moved; + moved = std::move(model); + DALI_TEST_CHECK(moved); + DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION); + DALI_TEST_CHECK(false == moved.GetProperty(Actor::Property::SENSITIVE)); + DALI_TEST_CHECK(!model); + + END_TEST; +} + +int UtcDaliModelOnScene01(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + uint32_t modelCount = model.GetModelRoot().GetChildCount(); + DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliModelOnScene02(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_DLI_FILE_NAME); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + uint32_t modelCount = model.GetModelRoot().GetChildCount(); + DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION); + + Actor rootActor = model.GetModelRoot(); + Vector3 rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); + DALI_TEST_EQUALS(Vector3(2, 2, 1), rootSize, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliModelOnSizeSet(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + Vector2 size(200.0f, 300.0f); + model.SetProperty(Actor::Property::SIZE, size); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(model.GetCurrentProperty(Actor::Property::SIZE), size, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliModelGetNaturalSize(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + Vector3 naturalSize = model.GetNaturalSize(); + + DALI_TEST_EQUALS(Vector3(2, 2, 2), naturalSize, TEST_LOCATION); + + Actor root = model.GetModelRoot(); + DALI_TEST_CHECK(root); + + END_TEST; +} + +int UtcDaliModelSetImageBasedLightSource01(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + Actor meshActor = model.FindChildByName("AnimatedCube"); + DALI_TEST_CHECK(meshActor); + + Renderer renderer = meshActor.GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + + TextureSet textureSet = renderer.GetTextures(); + DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION); + + Texture diffuseTexture = textureSet.GetTexture(5u); + Texture specularTexture = textureSet.GetTexture(6u); + + model.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE); + + Texture newDiffuseTexture = textureSet.GetTexture(5u); + Texture newSpecularTexture = textureSet.GetTexture(6u); + + DALI_TEST_NOT_EQUALS(diffuseTexture, newDiffuseTexture, 0.0f, TEST_LOCATION); + DALI_TEST_NOT_EQUALS(specularTexture, newSpecularTexture, 0.0f, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliModelSetImageBasedLightSource02(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + Actor meshActor = model.FindChildByName("AnimatedCube"); + DALI_TEST_CHECK(meshActor); + + Renderer renderer = meshActor.GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + + TextureSet textureSet = renderer.GetTextures(); + DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION); + + Texture diffuseTexture = textureSet.GetTexture(5u); + Texture specularTexture = textureSet.GetTexture(6u); + + model.SetImageBasedLightSource("", ""); + + Texture newDiffuseTexture = textureSet.GetTexture(5u); + Texture newSpecularTexture = textureSet.GetTexture(6u); + + DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION); + DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliModelSetImageBasedLightSource03(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + Actor meshActor = model.FindChildByName("AnimatedCube"); + DALI_TEST_CHECK(meshActor); + + Renderer renderer = meshActor.GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + + TextureSet textureSet = renderer.GetTextures(); + DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION); + + Texture diffuseTexture = textureSet.GetTexture(5u); + Texture specularTexture = textureSet.GetTexture(6u); + + model.SetImageBasedLightSource("dummy.ktx", "dummy.ktx"); + + Texture newDiffuseTexture = textureSet.GetTexture(5u); + Texture newSpecularTexture = textureSet.GetTexture(6u); + + DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION); + DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliModelImageBasedFactor(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + DALI_TEST_EQUALS(model.GetImageBasedLightScaleFactor(), 1.0f, TEST_LOCATION); + + model.SetImageBasedLightScaleFactor(0.5f); + DALI_TEST_EQUALS(model.GetImageBasedLightScaleFactor(), 0.5f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliModelAnimation01(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + uint32_t animationCount = model.GetAnimationCount(); + DALI_TEST_EQUALS(1, animationCount, TEST_LOCATION); + + Animation animationByIndex = model.GetAnimation(0u); + DALI_TEST_CHECK(animationByIndex); + + Animation animationByName = model.GetAnimation("animation_AnimatedCube"); + DALI_TEST_CHECK(animationByName); + DALI_TEST_EQUALS(animationByIndex, animationByName, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliModelAnimation02(void) +{ + ToolkitTestApplication application; + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_ANIMATION_TEST_FILE_NAME); + model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + uint32_t animationCount = model.GetAnimationCount(); + DALI_TEST_EQUALS(9, animationCount, TEST_LOCATION); + + Animation animation1 = model.GetAnimation("Step Scale"); + DALI_TEST_CHECK(animation1); + DALI_TEST_EQUALS(1.66667f, animation1.GetDuration(), 0.001f, TEST_LOCATION); + + Animation animation2 = model.GetAnimation("CubicSpline Scale"); + DALI_TEST_CHECK(animation2); + DALI_TEST_EQUALS(1.66667f, animation2.GetDuration(), 0.001f, TEST_LOCATION); + + DALI_TEST_NOT_EQUALS(animation1, animation2, 0.0f, TEST_LOCATION); + + END_TEST; +} + +// For ResourceReady +namespace +{ +static bool gOnRelayoutCallBackCalled = false; +void OnRelayoutCallback(Actor actor) +{ + gOnRelayoutCallBackCalled = true; +} + +static bool gResourceReadyCalled = false; +void OnResourceReady(Control control) +{ + gResourceReadyCalled = true; +} +} + +int UtcDaliModelResourceReady(void) +{ + ToolkitTestApplication application; + + gOnRelayoutCallBackCalled = false; + gResourceReadyCalled = false; + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_ANIMATION_TEST_FILE_NAME); + model.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f)); + model.OnRelayoutSignal().Connect(OnRelayoutCallback); + model.ResourceReadySignal().Connect(OnResourceReady); + DALI_TEST_EQUALS(model.IsResourceReady(), false, TEST_LOCATION); + + // Sanity check + DALI_TEST_CHECK(!gOnRelayoutCallBackCalled); + DALI_TEST_CHECK(!gResourceReadyCalled); + + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(gOnRelayoutCallBackCalled, false, TEST_LOCATION); + DALI_TEST_EQUALS(model.IsResourceReady(), true, TEST_LOCATION); + DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ModelView.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ModelView.cpp deleted file mode 100644 index fb9f4355f6..0000000000 --- a/automated-tests/src/dali-scene3d/utc-Dali-ModelView.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include - -#include - -using namespace Dali; -using namespace Dali::Toolkit; - -void model_view_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void model_view_cleanup(void) -{ - test_return_value = TET_PASS; -} - -namespace -{ -/** - * For the AnimatedCube.gltf and its Assets - * Donated by Norbert Nopper for glTF testing. - * Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnimatedCube - */ -const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf"; -const char* TEST_GLTF_TRIANGLE_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedTriangle.gltf"; -const char* TEST_GLTF_ANIMATION_TEST_FILE_NAME = TEST_RESOURCE_DIR "/animationTest.gltf"; -const char* TEST_DLI_FILE_NAME = TEST_RESOURCE_DIR "/arc.dli"; -const char* TEST_DLI_BEER_FILE_NAME = TEST_RESOURCE_DIR "/beer_modelViewTest.dli"; -/** - * For the diffuse and specular cube map texture. - * These textures are based off version of Wave engine sample - * Take from https://github.com/WaveEngine/Samples - * - * Copyright (c) 2022 Wave Coorporation - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -const char* TEST_DIFFUSE_TEXTURE = TEST_RESOURCE_DIR "/forest_irradiance.ktx"; -const char* TEST_SPECULAR_TEXTURE = TEST_RESOURCE_DIR "/forest_radiance.ktx"; -} // namespace - -// Negative test case for a method -int UtcDaliModelViewUninitialized(void) -{ - ToolkitTestApplication application; - tet_infoline(" UtcDaliModelViewUninitialized"); - - Scene3D::ModelView view; - - try - { - // New() must be called to create a ModelView or it wont be valid. - Actor a = Actor::New(); - view.Add(a); - DALI_TEST_CHECK(false); - } - catch(Dali::DaliException& e) - { - // Tests that a negative test of an assertion succeeds - DALI_TEST_PRINT_ASSERT(e); - DALI_TEST_CHECK(!view); - } - END_TEST; -} - -// Positive test case for a method -int UtcDaliModelViewNew(void) -{ - ToolkitTestApplication application; - tet_infoline(" UtcDaliModelViewNew"); - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - DALI_TEST_CHECK(view); - END_TEST; -} - -// Positive test case for a method -int UtcDaliModelViewDownCast(void) -{ - ToolkitTestApplication application; - tet_infoline(" UtcDaliModelViewDownCast"); - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - BaseHandle handle(view); - - Scene3D::ModelView modelView = Scene3D::ModelView::DownCast(handle); - DALI_TEST_CHECK(view); - DALI_TEST_CHECK(modelView); - DALI_TEST_CHECK(modelView == view); - END_TEST; -} - -int UtcDaliModelViewTypeRegistry(void) -{ - ToolkitTestApplication application; - - TypeRegistry typeRegistry = TypeRegistry::Get(); - DALI_TEST_CHECK(typeRegistry); - - TypeInfo typeInfo = typeRegistry.GetTypeInfo("ModelView"); - DALI_TEST_CHECK(typeInfo); - - BaseHandle handle = typeInfo.CreateInstance(); - DALI_TEST_CHECK(handle); - - Scene3D::ModelView modelView = Scene3D::ModelView::DownCast(handle); - DALI_TEST_CHECK(modelView); - - END_TEST; -} - -// Positive test case for a method -int UtcDaliModelViewAddRemove(void) -{ - ToolkitTestApplication application; - tet_infoline(" UtcDaliModelViewAddRemove"); - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - DALI_TEST_CHECK(view); - - Actor actor = Actor::New(); - DALI_TEST_CHECK(!actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)); - - view.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - view.SetProperty(Actor::Property::SIZE, application.GetScene().GetSize()); - view.Add(actor); - application.GetScene().Add(view); - - DALI_TEST_CHECK(actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)); - - view.Remove(actor); - - DALI_TEST_CHECK(!actor.GetProperty(Actor::Property::CONNECTED_TO_SCENE)); - END_TEST; -} - -int UtcDaliModelViewCopyAndAssignment(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - DALI_TEST_CHECK(view); - - Scene3D::ModelView copy(view); - DALI_TEST_CHECK(view == copy); - - Scene3D::ModelView assign; - DALI_TEST_CHECK(!assign); - - assign = copy; - DALI_TEST_CHECK(assign == view); - - END_TEST; -} - -int UtcDaliModelViewMoveConstructor(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - DALI_TEST_EQUALS(1, view.GetBaseObject().ReferenceCount(), TEST_LOCATION); - view.SetProperty(Actor::Property::SENSITIVE, false); - DALI_TEST_CHECK(false == view.GetProperty(Actor::Property::SENSITIVE)); - - Scene3D::ModelView moved = std::move(view); - DALI_TEST_CHECK(moved); - DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION); - DALI_TEST_CHECK(false == moved.GetProperty(Actor::Property::SENSITIVE)); - DALI_TEST_CHECK(!view); - - END_TEST; -} - -int UtcDaliModelViewMoveAssignment(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - DALI_TEST_EQUALS(1, view.GetBaseObject().ReferenceCount(), TEST_LOCATION); - view.SetProperty(Actor::Property::SENSITIVE, false); - DALI_TEST_CHECK(false == view.GetProperty(Actor::Property::SENSITIVE)); - - Scene3D::ModelView moved; - moved = std::move(view); - DALI_TEST_CHECK(moved); - DALI_TEST_EQUALS(1, moved.GetBaseObject().ReferenceCount(), TEST_LOCATION); - DALI_TEST_CHECK(false == moved.GetProperty(Actor::Property::SENSITIVE)); - DALI_TEST_CHECK(!view); - - END_TEST; -} - -int UtcDaliModelViewOnScene01(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - uint32_t modelCount = view.GetModelRoot().GetChildCount(); - DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewOnScene02(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_DLI_FILE_NAME); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - uint32_t modelCount = view.GetModelRoot().GetChildCount(); - DALI_TEST_EQUALS(1, modelCount, TEST_LOCATION); - - Actor rootActor = view.GetModelRoot(); - Vector3 rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); - DALI_TEST_EQUALS(Vector3(2, 2, 1), rootSize, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewOnSizeSet(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Vector2 size(200.0f, 300.0f); - view.SetProperty(Actor::Property::SIZE, size); - - application.SendNotification(); - application.Render(); - - DALI_TEST_EQUALS(view.GetCurrentProperty(Actor::Property::SIZE), size, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewGetNaturalSize(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - - Vector3 naturalSize = view.GetNaturalSize(); - - DALI_TEST_EQUALS(Vector3(2, 2, 2), naturalSize, TEST_LOCATION); - - Actor root = view.GetModelRoot(); - DALI_TEST_CHECK(root); - - END_TEST; -} - -int UtcDaliModelViewSetImageBasedLightSource01(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Actor meshActor = view.FindChildByName("AnimatedCube"); - DALI_TEST_CHECK(meshActor); - - Renderer renderer = meshActor.GetRendererAt(0u); - DALI_TEST_CHECK(renderer); - - TextureSet textureSet = renderer.GetTextures(); - DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION); - - Texture diffuseTexture = textureSet.GetTexture(5u); - Texture specularTexture = textureSet.GetTexture(6u); - - view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE); - - Texture newDiffuseTexture = textureSet.GetTexture(5u); - Texture newSpecularTexture = textureSet.GetTexture(6u); - - DALI_TEST_NOT_EQUALS(diffuseTexture, newDiffuseTexture, 0.0f, TEST_LOCATION); - DALI_TEST_NOT_EQUALS(specularTexture, newSpecularTexture, 0.0f, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewSetImageBasedLightSource02(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Actor meshActor = view.FindChildByName("AnimatedCube"); - DALI_TEST_CHECK(meshActor); - - Renderer renderer = meshActor.GetRendererAt(0u); - DALI_TEST_CHECK(renderer); - - TextureSet textureSet = renderer.GetTextures(); - DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION); - - Texture diffuseTexture = textureSet.GetTexture(5u); - Texture specularTexture = textureSet.GetTexture(6u); - - view.SetImageBasedLightSource("", ""); - - Texture newDiffuseTexture = textureSet.GetTexture(5u); - Texture newSpecularTexture = textureSet.GetTexture(6u); - - DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION); - DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewSetImageBasedLightSource03(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Actor meshActor = view.FindChildByName("AnimatedCube"); - DALI_TEST_CHECK(meshActor); - - Renderer renderer = meshActor.GetRendererAt(0u); - DALI_TEST_CHECK(renderer); - - TextureSet textureSet = renderer.GetTextures(); - DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION); - - Texture diffuseTexture = textureSet.GetTexture(5u); - Texture specularTexture = textureSet.GetTexture(6u); - - view.SetImageBasedLightSource("dummy.ktx", "dummy.ktx"); - - Texture newDiffuseTexture = textureSet.GetTexture(5u); - Texture newSpecularTexture = textureSet.GetTexture(6u); - - DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION); - DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewImageBasedFactor(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView modelView = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - - DALI_TEST_EQUALS(modelView.GetImageBasedLightScaleFactor(), 1.0f, TEST_LOCATION); - - modelView.SetImageBasedLightScaleFactor(0.5f); - DALI_TEST_EQUALS(modelView.GetImageBasedLightScaleFactor(), 0.5f, TEST_LOCATION); - END_TEST; -} - -int UtcDaliModelViewFitSize01(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Actor rootActor = view.GetModelRoot(); - Vector3 rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); - DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); - - Vector3 rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); - DALI_TEST_EQUALS(Vector3(25, -25, 25), rootScale, TEST_LOCATION); - - view.FitSize(false); - rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); - DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); - - rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); - DALI_TEST_EQUALS(Vector3(1, -1, 1), rootScale, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewFitSize02(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_DLI_BEER_FILE_NAME); - view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Actor rootActor = view.GetModelRoot(); - Vector3 rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); - DALI_TEST_EQUALS(Vector3(5, 5, 5), rootSize, TEST_LOCATION); - - Vector3 rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); - DALI_TEST_EQUALS(Vector3(10, -10, 10), rootScale, TEST_LOCATION); - - view.FitSize(false); - rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); - DALI_TEST_EQUALS(Vector3(5, 5, 5), rootSize, TEST_LOCATION); - - rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); - DALI_TEST_EQUALS(Vector3(1, -1, 1), rootScale, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewFitSize03(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - view.SetProperty(Dali::Actor::Property::SIZE, Vector2(0, 0)); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Actor rootActor = view.GetModelRoot(); - Vector3 rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); - DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); - - Vector3 rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); - DALI_TEST_EQUALS(Vector3(1, -1, 1), rootScale, TEST_LOCATION); - - view.FitSize(true); - rootSize = rootActor.GetProperty(Dali::Actor::Property::SIZE); - DALI_TEST_EQUALS(Vector3(2, 2, 2), rootSize, TEST_LOCATION); - - rootScale = rootActor.GetProperty(Dali::Actor::Property::SCALE); - DALI_TEST_EQUALS(Vector3(1, -1, 1), rootScale, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewFitCenter(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_TRIANGLE_FILE_NAME); - view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - Vector3 naturalSize = view.GetNaturalSize(); - DALI_TEST_EQUALS(Vector3(1, 1, 0), naturalSize, TEST_LOCATION); - - Actor rootActor = view.GetModelRoot(); - Vector3 anchorPoint = rootActor.GetProperty(Dali::Actor::Property::ANCHOR_POINT); - DALI_TEST_EQUALS(Vector3(1.0, 1.0, 0.5), anchorPoint, TEST_LOCATION); - - view.FitCenter(false); - anchorPoint = rootActor.GetProperty(Dali::Actor::Property::ANCHOR_POINT); - DALI_TEST_EQUALS(Vector3(0.5, 0.5, 0.5), anchorPoint, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewAnimation01(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - uint32_t animationCount = view.GetAnimationCount(); - DALI_TEST_EQUALS(1, animationCount, TEST_LOCATION); - - Animation animationByIndex = view.GetAnimation(0u); - DALI_TEST_CHECK(animationByIndex); - - Animation animationByName = view.GetAnimation("animation_AnimatedCube"); - DALI_TEST_CHECK(animationByName); - DALI_TEST_EQUALS(animationByIndex, animationByName, TEST_LOCATION); - - END_TEST; -} - -int UtcDaliModelViewAnimation02(void) -{ - ToolkitTestApplication application; - - Scene3D::ModelView view = Scene3D::ModelView::New(TEST_GLTF_ANIMATION_TEST_FILE_NAME); - view.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50)); - - application.GetScene().Add(view); - - application.SendNotification(); - application.Render(); - - uint32_t animationCount = view.GetAnimationCount(); - DALI_TEST_EQUALS(9, animationCount, TEST_LOCATION); - - Animation animation1 = view.GetAnimation("Step Scale"); - DALI_TEST_CHECK(animation1); - DALI_TEST_EQUALS(1.66667f, animation1.GetDuration(), 0.001f, TEST_LOCATION); - - Animation animation2 = view.GetAnimation("CubicSpline Scale"); - DALI_TEST_CHECK(animation2); - DALI_TEST_EQUALS(1.66667f, animation2.GetDuration(), 0.001f, TEST_LOCATION); - - DALI_TEST_NOT_EQUALS(animation1, animation2, 0.0f, TEST_LOCATION); - - END_TEST; -} - -// For ResourceReady -namespace -{ -static bool gOnRelayoutCallBackCalled = false; -void OnRelayoutCallback(Actor actor) -{ - gOnRelayoutCallBackCalled = true; -} - -static bool gResourceReadyCalled = false; -void OnResourceReady(Control control) -{ - gResourceReadyCalled = true; -} -} - -int UtcDaliModelViewResourceReady(void) -{ - ToolkitTestApplication application; - - gOnRelayoutCallBackCalled = false; - gResourceReadyCalled = false; - Scene3D::ModelView model = Scene3D::ModelView::New(TEST_GLTF_ANIMATION_TEST_FILE_NAME); - model.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f)); - model.OnRelayoutSignal().Connect(OnRelayoutCallback); - model.ResourceReadySignal().Connect(OnResourceReady); - DALI_TEST_EQUALS(model.IsResourceReady(), false, TEST_LOCATION); - - // Sanity check - DALI_TEST_CHECK(!gOnRelayoutCallBackCalled); - DALI_TEST_CHECK(!gResourceReadyCalled); - - application.GetScene().Add(model); - - application.SendNotification(); - application.Render(); - - DALI_TEST_EQUALS(gOnRelayoutCallBackCalled, false, TEST_LOCATION); - DALI_TEST_EQUALS(model.IsResourceReady(), true, TEST_LOCATION); - DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION); - - END_TEST; -} diff --git a/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp b/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp index 58bcab05af..8b89f63de7 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include using namespace Dali; @@ -73,11 +73,11 @@ const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf"; const char* TEST_DIFFUSE_TEXTURE = TEST_RESOURCE_DIR "/forest_irradiance.ktx"; const char* TEST_SPECULAR_TEXTURE = TEST_RESOURCE_DIR "/forest_radiance.ktx"; -Dali::Texture GetDiffuseTexture(Dali::Scene3D::ModelView modelView) +Dali::Texture GetDiffuseTexture(Dali::Scene3D::Model model) { Dali::Texture texture; - Actor meshActor = modelView.FindChildByName("AnimatedCube"); + Actor meshActor = model.FindChildByName("AnimatedCube"); if(meshActor) { Renderer renderer = meshActor.GetRendererAt(0u); @@ -94,11 +94,11 @@ Dali::Texture GetDiffuseTexture(Dali::Scene3D::ModelView modelView) return texture; } -Dali::Texture GetSpecularTexture(Dali::Scene3D::ModelView modelView) +Dali::Texture GetSpecularTexture(Dali::Scene3D::Model model) { Dali::Texture texture; - Actor meshActor = modelView.FindChildByName("AnimatedCube"); + Actor meshActor = model.FindChildByName("AnimatedCube"); if(meshActor) { Renderer renderer = meshActor.GetRendererAt(0u); @@ -126,7 +126,7 @@ int UtcDaliSceneViewUninitialized(void) try { - // New() must be called to create a ModelView or it wont be valid. + // New() must be called to create a Model or it wont be valid. Actor a = Actor::New(); view.Add(a); DALI_TEST_CHECK(false); @@ -181,8 +181,8 @@ int UtcDaliSceneViewTypeRegistry(void) BaseHandle handle = typeInfo.CreateInstance(); DALI_TEST_CHECK(handle); - Scene3D::SceneView modelView = Scene3D::SceneView::DownCast(handle); - DALI_TEST_CHECK(modelView); + Scene3D::SceneView model = Scene3D::SceneView::DownCast(handle); + DALI_TEST_CHECK(model); END_TEST; } @@ -425,9 +425,9 @@ int UtcDaliSceneViewImageBasedLight(void) application.SendNotification(); application.Render(); - Scene3D::ModelView modelView1 = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - Scene3D::ModelView modelView2 = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); - Scene3D::ModelView modelView3 = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); + Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + Scene3D::Model modelView2 = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + Scene3D::Model modelView3 = Scene3D::Model::New(TEST_GLTF_FILE_NAME); view.Add(modelView1); view.Add(modelView2); @@ -473,7 +473,7 @@ int UtcDaliSceneViewImageBasedFactor(void) application.SendNotification(); application.Render(); - Scene3D::ModelView modelView1 = Scene3D::ModelView::New(TEST_GLTF_FILE_NAME); + Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME); view.Add(modelView1); DALI_TEST_EQUALS(view.GetImageBasedLightScaleFactor(), 1.0f, TEST_LOCATION); diff --git a/dali-scene3d/internal/controls/model-view/model-view-impl.cpp b/dali-scene3d/internal/controls/model-view/model-view-impl.cpp deleted file mode 100644 index 5bf8ecedb5..0000000000 --- a/dali-scene3d/internal/controls/model-view/model-view-impl.cpp +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// CLASS HEADER -#include "model-view-impl.h" - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Dali; - -namespace Dali -{ -namespace Scene3D -{ -namespace Internal -{ -namespace -{ -BaseHandle Create() -{ - return Scene3D::ModelView::New(std::string()); -} - -// Setup properties, signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelView, Toolkit::Control, Create); -DALI_TYPE_REGISTRATION_END() - -static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u; -static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u; - -static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f); - -static constexpr std::string_view KTX_EXTENSION = ".ktx"; -static constexpr std::string_view OBJ_EXTENSION = ".obj"; -static constexpr std::string_view GLTF_EXTENSION = ".gltf"; -static constexpr std::string_view DLI_EXTENSION = ".dli"; - -struct BoundingVolume -{ - void Init() - { - pointMin = Vector3(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); - pointMax = Vector3(std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()); - } - - void ConsiderNewPointInVolume(const Vector3& position) - { - pointMin.x = std::min(position.x, pointMin.x); - pointMin.y = std::min(position.y, pointMin.y); - pointMin.z = std::min(position.z, pointMin.z); - - pointMax.x = std::max(position.x, pointMax.x); - pointMax.y = std::max(position.y, pointMax.y); - pointMax.z = std::max(position.z, pointMax.z); - } - - Vector3 CalculateSize() - { - return pointMax - pointMin; - } - - Vector3 CalculatePivot() - { - Vector3 pivot = pointMin / (pointMin - pointMax); - for(uint32_t i = 0; i < 3; ++i) - { - // To avoid divid by zero - if(pointMin[i] == pointMax[i]) - { - pivot[i] = 0.5f; - } - } - return pivot; - } - - Vector3 pointMin; - Vector3 pointMax; -}; - -void ConfigureBlendShapeShaders( - Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector&& requests) -{ - std::vector errors; - auto onError = [&errors](const std::string& msg) { errors.push_back(msg); }; - if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError)) - { - Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION); - for(auto& msg : errors) - { - flinger << msg << '\n'; - } - } -} - -void AddModelTreeToAABB(BoundingVolume& AABB, const Dali::Scene3D::Loader::SceneDefinition& scene, const Dali::Scene3D::Loader::Customization::Choices& choices, Dali::Scene3D::Loader::Index iNode, Dali::Scene3D::Loader::NodeDefinition::CreateParams& nodeParams, Matrix parentMatrix) -{ - static constexpr uint32_t BOX_POINT_COUNT = 8; - static uint32_t BBIndex[BOX_POINT_COUNT][3] = {{0, 0, 0}, {0, 1, 0}, {1, 0, 0}, {1, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1}}; - - Matrix nodeMatrix; - const Dali::Scene3D::Loader::NodeDefinition* node = scene.GetNode(iNode); - Matrix localMatrix = node->GetLocalSpace(); - Matrix::Multiply(nodeMatrix, localMatrix, parentMatrix); - - Vector3 volume[2]; - if(node->GetExtents(nodeParams.mResources, volume[0], volume[1])) - { - for(uint32_t i = 0; i < BOX_POINT_COUNT; ++i) - { - Vector4 position = Vector4(volume[BBIndex[i][0]].x, volume[BBIndex[i][1]].y, volume[BBIndex[i][2]].z, 1.0f); - Vector4 objectPosition = nodeMatrix * position; - objectPosition /= objectPosition.w; - - AABB.ConsiderNewPointInVolume(Vector3(objectPosition)); - } - } - - if(node->mCustomization) - { - if(!node->mChildren.empty()) - { - auto choice = choices.Get(node->mCustomization->mTag); - Dali::Scene3D::Loader::Index i = std::min(choice != Dali::Scene3D::Loader::Customization::NONE ? choice : 0, static_cast(node->mChildren.size() - 1)); - - AddModelTreeToAABB(AABB, scene, choices, node->mChildren[i], nodeParams, nodeMatrix); - } - } - else - { - for(auto i : node->mChildren) - { - AddModelTreeToAABB(AABB, scene, choices, i, nodeParams, nodeMatrix); - } - } -} - -} // anonymous namespace - -ModelView::ModelView(const std::string& modelPath, const std::string& resourcePath) -: Control(ControlBehaviour(DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS)), - mModelPath(modelPath), - mResourcePath(resourcePath), - mModelRoot(), - mNaturalSize(Vector3::ZERO), - mModelPivot(AnchorPoint::CENTER), - mIblScaleFactor(1.0f), - mFitSize(true), - mFitCenter(true), - mModelResourceReady(false), - mIBLResourceReady(true) -{ -} - -ModelView::~ModelView() -{ -} - -Dali::Scene3D::ModelView ModelView::New(const std::string& modelPath, const std::string& resourcePath) -{ - ModelView* impl = new ModelView(modelPath, resourcePath); - - Dali::Scene3D::ModelView handle = Dali::Scene3D::ModelView(*impl); - - // Second-phase init of the implementation - // This can only be done after the CustomActor connection has been made... - impl->Initialize(); - - return handle; -} - -const Actor ModelView::GetModelRoot() const -{ - return mModelRoot; -} - -void ModelView::FitSize(bool fit) -{ - mFitSize = fit; - ScaleModel(); -} - -void ModelView::FitCenter(bool fit) -{ - mFitCenter = fit; - FitModelPosition(); -} - -void ModelView::SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor) -{ - mIBLResourceReady = false; - Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuse); - Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specular); - SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor); - mIBLResourceReady = true; - - // If Model resource is already ready, then set resource ready. - // If Model resource is still not ready, wait for model resource ready. - if(IsResourceReady()) - { - SetResourceReady(false); - } -} - -void ModelView::SetImageBasedLightTexture(Dali::Texture diffuse, Dali::Texture specular, float scaleFactor) -{ - if(diffuse && specular) - { - if(mDiffuseTexture != diffuse || mSpecularTexture != specular) - { - mDiffuseTexture = diffuse; - mSpecularTexture = specular; - UpdateImageBasedLightTexture(); - } - if(mIblScaleFactor != scaleFactor) - { - mIblScaleFactor = scaleFactor; - UpdateImageBasedLightScaleFactor(); - } - - } -} - -void ModelView::SetImageBasedLightScaleFactor(float scaleFactor) -{ - mIblScaleFactor = scaleFactor; - if(mDiffuseTexture && mSpecularTexture) - { - UpdateImageBasedLightScaleFactor(); - } -} - -float ModelView::GetImageBasedLightScaleFactor() const -{ - return mIblScaleFactor; -} - -uint32_t ModelView::GetAnimationCount() const -{ - return mAnimations.size(); -} - -Dali::Animation ModelView::GetAnimation(uint32_t index) const -{ - Dali::Animation animation; - if(mAnimations.size() > index) - { - animation = mAnimations[index].second; - } - return animation; -} - -Dali::Animation ModelView::GetAnimation(const std::string& name) const -{ - Dali::Animation animation; - if(!name.empty()) - { - for(auto&& animationData : mAnimations) - { - if(animationData.first == name) - { - animation = animationData.second; - break; - } - } - } - return animation; -} - -/////////////////////////////////////////////////////////// -// -// Private methods -// - -void ModelView::OnSceneConnection(int depth) -{ - if(!mModelRoot) - { - LoadModel(); - } - - Actor parent = Self().GetParent(); - while(parent) - { - Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent); - if(sceneView) - { - GetImpl(sceneView).RegisterModelView(Scene3D::ModelView::DownCast(Self())); - mParentSceneView = sceneView; - break; - } - parent = parent.GetParent(); - } - - Control::OnSceneConnection(depth); -} - -void ModelView::OnSceneDisconnection() -{ - Scene3D::SceneView sceneView = mParentSceneView.GetHandle(); - if(sceneView) - { - GetImpl(sceneView).UnregisterModelView(Scene3D::ModelView::DownCast(Self())); - mParentSceneView.Reset(); - } - Control::OnSceneDisconnection(); -} - -Vector3 ModelView::GetNaturalSize() -{ - if(!mModelRoot) - { - LoadModel(); - } - - return mNaturalSize; -} - -float ModelView::GetHeightForWidth(float width) -{ - Extents padding; - padding = Self().GetProperty(Toolkit::Control::Property::PADDING); - return Control::GetHeightForWidth(width) + padding.top + padding.bottom; -} - -float ModelView::GetWidthForHeight(float height) -{ - Extents padding; - padding = Self().GetProperty(Toolkit::Control::Property::PADDING); - return Control::GetWidthForHeight(height) + padding.start + padding.end; -} - -void ModelView::OnRelayout(const Vector2& size, RelayoutContainer& container) -{ - Control::OnRelayout(size, container); - ScaleModel(); -} - -bool ModelView::IsResourceReady() const -{ - return mModelResourceReady && mIBLResourceReady; -} - -void ModelView::LoadModel() -{ - std::filesystem::path modelPath(mModelPath); - if(mResourcePath.empty()) - { - mResourcePath = std::string(modelPath.parent_path()) + "/"; - } - std::string extension = modelPath.extension(); - std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); - - Dali::Scene3D::Loader::ResourceBundle::PathProvider pathProvider = [&](Dali::Scene3D::Loader::ResourceType::Value type) { - return mResourcePath; - }; - - Dali::Scene3D::Loader::ResourceBundle resources; - Dali::Scene3D::Loader::SceneDefinition scene; - std::vector animGroups; - std::vector cameraParameters; - std::vector lights; - - std::vector animations; - animations.clear(); - - Dali::Scene3D::Loader::LoadResult output{resources, scene, animations, animGroups, cameraParameters, lights}; - - if(extension == DLI_EXTENSION) - { - Dali::Scene3D::Loader::DliLoader loader; - Dali::Scene3D::Loader::DliLoader::InputParams input{ - pathProvider(Dali::Scene3D::Loader::ResourceType::Mesh), - nullptr, - {}, - {}, - nullptr, - {}}; - Dali::Scene3D::Loader::DliLoader::LoadParams loadParams{input, output}; - if(!loader.LoadScene(mModelPath, loadParams)) - { - Dali::Scene3D::Loader::ExceptionFlinger(ASSERT_LOCATION) << "Failed to load scene from '" << mModelPath << "': " << loader.GetParseError(); - } - } - else if(extension == GLTF_EXTENSION) - { - Dali::Scene3D::Loader::ShaderDefinitionFactory sdf; - sdf.SetResources(resources); - Dali::Scene3D::Loader::LoadGltfScene(mModelPath, sdf, output); - - resources.mEnvironmentMaps.push_back({}); - } - else - { - DALI_LOG_ERROR("Unsupported model type.\n"); - } - - Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}}; - Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}}; - Dali::Scene3D::Loader::Customization::Choices choices; - - mModelRoot = Actor::New(); - - BoundingVolume AABB; - for(auto iRoot : scene.GetRoots()) - { - auto resourceRefs = resources.CreateRefCounter(); - scene.CountResourceRefs(iRoot, choices, resourceRefs); - resources.CountEnvironmentReferences(resourceRefs); - - resources.LoadResources(resourceRefs, pathProvider); - - // glTF Mesh is defined in right hand coordinate system, with positive Y for Up direction. - // Because DALi uses left hand system, Y direciton will be flipped for environment map sampling. - for(auto&& env : resources.mEnvironmentMaps) - { - env.first.mYDirection = Y_DIRECTION; - } - - if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) - { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); - scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); - ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); - - scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); - - mModelRoot.Add(actor); - } - - AddModelTreeToAABB(AABB, scene, choices, iRoot, nodeParams, Matrix::IDENTITY); - } - - if(!animations.empty()) - { - auto getActor = [&](const std::string& name) { - return mModelRoot.FindChildByName(name); - }; - - mAnimations.clear(); - for(auto&& animation : animations) - { - Dali::Animation anim = animation.ReAnimate(getActor); - - mAnimations.push_back({animation.mName, anim}); - } - } - - mRenderableActors.clear(); - CollectRenderableActor(mModelRoot); - UpdateImageBasedLightTexture(); - UpdateImageBasedLightScaleFactor(); - - mNaturalSize = AABB.CalculateSize(); - mModelPivot = AABB.CalculatePivot(); - mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); - Vector3 controlSize = Self().GetProperty(Dali::Actor::Property::SIZE); - if(controlSize.x == 0.0f || controlSize.y == 0.0f) - { - Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); - } - - FitModelPosition(); - ScaleModel(); - - Self().Add(mModelRoot); - - Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z)); - - mModelResourceReady = true; - - Control::SetResourceReady(false); -} - -void ModelView::ScaleModel() -{ - if(mModelRoot) - { - Vector3 size = Self().GetProperty(Dali::Actor::Property::SIZE); - if(mFitSize && size.x > 0.0f && size.y > 0.0f) - { - float scaleFactor = MAXFLOAT; - scaleFactor = std::min(size.x / mNaturalSize.x, scaleFactor); - scaleFactor = std::min(size.y / mNaturalSize.y, scaleFactor); - // Models in glTF and dli are defined as right hand coordinate system. - // DALi uses left hand coordinate system. Scaling negative is for change winding order. - mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scaleFactor); - } - else - { - // Models in glTF and dli are defined as right hand coordinate system. - // DALi uses left hand coordinate system. Scaling negative is for change winding order. - mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION); - } - } -} - -void ModelView::FitModelPosition() -{ - if(mModelRoot) - { - if(mFitCenter) - { - // Loaded model pivot is not the model center. - mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot); - } - else - { - mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); - } - } -} - -void ModelView::CollectRenderableActor(Actor actor) -{ - uint32_t rendererCount = actor.GetRendererCount(); - if(rendererCount) - { - mRenderableActors.push_back(actor); - } - - uint32_t childrenCount = actor.GetChildCount(); - for(uint32_t i = 0; i < childrenCount; ++i) - { - CollectRenderableActor(actor.GetChildAt(i)); - } -} - -void ModelView::UpdateImageBasedLightTexture() -{ - if(!mDiffuseTexture || !mSpecularTexture) - { - return; - } - - for(auto&& actor : mRenderableActors) - { - Actor renderableActor = actor.GetHandle(); - if(renderableActor) - { - uint32_t rendererCount = renderableActor.GetRendererCount(); - for(uint32_t i = 0; i < rendererCount; ++i) - { - Dali::Renderer renderer = renderableActor.GetRendererAt(i); - if(renderer) - { - Dali::TextureSet textures = renderer.GetTextures(); - if(textures) - { - uint32_t textureCount = textures.GetTextureCount(); - // EnvMap requires at least 2 texture, diffuse and specular - if(textureCount > 2u) - { - textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, mDiffuseTexture); - textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, mSpecularTexture); - } - } - } - } - } - } -} - -void ModelView::UpdateImageBasedLightScaleFactor() -{ - if(!mDiffuseTexture || !mSpecularTexture) - { - return; - } - for(auto&& actor : mRenderableActors) - { - Actor renderableActor = actor.GetHandle(); - if(renderableActor) - { - renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), mIblScaleFactor); - } - } -} - -} // namespace Internal -} // namespace Scene3D -} // namespace Dali diff --git a/dali-scene3d/internal/controls/model-view/model-view-impl.h b/dali-scene3d/internal/controls/model-view/model-view-impl.h deleted file mode 100644 index 77315e3310..0000000000 --- a/dali-scene3d/internal/controls/model-view/model-view-impl.h +++ /dev/null @@ -1,222 +0,0 @@ -#ifndef DALI_SCENE3D_INTERNAL_MODEL_VIEW_H -#define DALI_SCENE3D_INTERNAL_MODEL_VIEW_H - -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ -namespace Scene3D -{ -class ModelView; - -namespace Internal -{ -/** - * @brief Impl class for ModelView. - */ -class ModelView : public Dali::Toolkit::Internal::Control -{ -public: - using AnimationData = std::pair; - - /** - * @brief Creates a new ModelView. - * - * @return A public handle to the newly allocated ModelView. - */ - static Dali::Scene3D::ModelView New(const std::string& modelPath, const std::string& resourcePath); - - /** - * @copydoc ModelView::GetModelRoot() - */ - const Actor GetModelRoot() const; - - /** - * @copydoc ModelView::FitModel() - */ - void FitSize(bool fit); - - /** - * @copydoc ModelView::FitCenter() - */ - void FitCenter(bool fit); - - /** - * @copydoc ModelView::SetImageBasedLightSource() - */ - void SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor); - - /** - * @copydoc ModelView::SetImageBasedLightTexture() - */ - void SetImageBasedLightTexture(Dali::Texture diffuse, Dali::Texture specular, float scaleFactor); - - /** - * @copydoc ModelView::SetImageBasedLightScaleFactor() - */ - void SetImageBasedLightScaleFactor(float scaleFactor); - - /** - * @copydoc ModelView::GetImageBasedLightScaleFactor() - */ - float GetImageBasedLightScaleFactor() const; - - /** - * @copydoc ModelView::GetAnimationCount() - */ - uint32_t GetAnimationCount() const; - - /** - * @copydoc ModelView::GetAnimation() - */ - Dali::Animation GetAnimation(uint32_t index) const; - - /** - * @copydoc ModelView::GetAnimation() - */ - Dali::Animation GetAnimation(const std::string& name) const; - -protected: - /** - * @brief Constructs a new ModelView. - */ - ModelView(const std::string& modelPath, const std::string& resourcePath); - - /** - * A reference counted object may only be deleted by calling Unreference() - */ - virtual ~ModelView(); - -private: - /** - * @copydoc CustomActorImpl::OnSceneConnection() - */ - void OnSceneConnection(int depth) override; - - /** - * @copydoc CustomActorImpl::OnSceneDisconnection() - */ - void OnSceneDisconnection() override; - - /** - * @copydoc Toolkit::Control::GetNaturalSize - */ - Vector3 GetNaturalSize() override; - - /** - * @copydoc Toolkit::Control::GetHeightForWidth() - */ - float GetHeightForWidth(float width) override; - - /** - * @copydoc Toolkit::Control::GetWidthForHeight() - */ - float GetWidthForHeight(float height) override; - - /** - * @copydoc Toolkit::Control::OnRelayout() - */ - void OnRelayout(const Vector2& size, RelayoutContainer& container) override; - - /** - * @copydoc Toolkit::Control::IsResourceReady() - */ - bool IsResourceReady() const override; - - /** - * @brief Loads a model from file - */ - void LoadModel(); - - /** - * @brief Scales the model to fit the control or to return to original size. - */ - void ScaleModel(); - - /** - * @brief Changes model anchor point to set the model at center or returns to the original model pivot. - */ - void FitModelPosition(); - - /** - * @brief Changes IBL information of the input node. - */ - void CollectRenderableActor(Actor actor); - - /** - * @brief Changes IBL textures of the input node. - */ - void UpdateImageBasedLightTexture(); - - /** - * @brief Changes IBL scale factor of the input node. - */ - void UpdateImageBasedLightScaleFactor(); - -private: - std::string mModelPath; - std::string mResourcePath; - Dali::Actor mModelRoot; - std::vector mAnimations; - std::vector> mRenderableActors; - WeakHandle mParentSceneView; - - Dali::Texture mSpecularTexture; - Dali::Texture mDiffuseTexture; - Vector3 mNaturalSize; - Vector3 mModelPivot; - float mIblScaleFactor; - bool mFitSize; - bool mFitCenter; - bool mModelResourceReady; - bool mIBLResourceReady; -}; - -} // namespace Internal - -// Helpers for public-api forwarding methods -inline Dali::Scene3D::Internal::ModelView& GetImpl(Dali::Scene3D::ModelView& obj) -{ - DALI_ASSERT_ALWAYS(obj); - Dali::RefObject& handle = obj.GetImplementation(); - return static_cast(handle); -} - -inline const Dali::Scene3D::Internal::ModelView& GetImpl(const Dali::Scene3D::ModelView& obj) -{ - DALI_ASSERT_ALWAYS(obj); - const Dali::RefObject& handle = obj.GetImplementation(); - return static_cast(handle); -} - -} // namespace Scene3D - -} // namespace Dali - -#endif // DALI_SCENE3D_INTERNAL_MODEL_VIEW_H diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp new file mode 100644 index 0000000000..ed5d3bdc93 --- /dev/null +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal +{ +namespace +{ +BaseHandle Create() +{ + return Scene3D::Model::New(std::string()); +} + +// Setup properties, signals and actions using the type-registry. +DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Model, Toolkit::Control, Create); +DALI_TYPE_REGISTRATION_END() + +static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u; +static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u; + +static constexpr Vector3 Y_DIRECTION(1.0f, -1.0f, 1.0f); + +static constexpr std::string_view KTX_EXTENSION = ".ktx"; +static constexpr std::string_view OBJ_EXTENSION = ".obj"; +static constexpr std::string_view GLTF_EXTENSION = ".gltf"; +static constexpr std::string_view DLI_EXTENSION = ".dli"; + +struct BoundingVolume +{ + void Init() + { + pointMin = Vector3(std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()); + pointMax = Vector3(std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()); + } + + void ConsiderNewPointInVolume(const Vector3& position) + { + pointMin.x = std::min(position.x, pointMin.x); + pointMin.y = std::min(position.y, pointMin.y); + pointMin.z = std::min(position.z, pointMin.z); + + pointMax.x = std::max(position.x, pointMax.x); + pointMax.y = std::max(position.y, pointMax.y); + pointMax.z = std::max(position.z, pointMax.z); + } + + Vector3 CalculateSize() + { + return pointMax - pointMin; + } + + Vector3 CalculatePivot() + { + Vector3 pivot = pointMin / (pointMin - pointMax); + for(uint32_t i = 0; i < 3; ++i) + { + // To avoid divid by zero + if(pointMin[i] == pointMax[i]) + { + pivot[i] = 0.5f; + } + } + return pivot; + } + + Vector3 pointMin; + Vector3 pointMax; +}; + +void ConfigureBlendShapeShaders( + Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector&& requests) +{ + std::vector errors; + auto onError = [&errors](const std::string& msg) { errors.push_back(msg); }; + if(!scene.ConfigureBlendshapeShaders(resources, root, std::move(requests), onError)) + { + Dali::Scene3D::Loader::ExceptionFlinger flinger(ASSERT_LOCATION); + for(auto& msg : errors) + { + flinger << msg << '\n'; + } + } +} + +void AddModelTreeToAABB(BoundingVolume& AABB, const Dali::Scene3D::Loader::SceneDefinition& scene, const Dali::Scene3D::Loader::Customization::Choices& choices, Dali::Scene3D::Loader::Index iNode, Dali::Scene3D::Loader::NodeDefinition::CreateParams& nodeParams, Matrix parentMatrix) +{ + static constexpr uint32_t BOX_POINT_COUNT = 8; + static uint32_t BBIndex[BOX_POINT_COUNT][3] = {{0, 0, 0}, {0, 1, 0}, {1, 0, 0}, {1, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1}}; + + Matrix nodeMatrix; + const Dali::Scene3D::Loader::NodeDefinition* node = scene.GetNode(iNode); + Matrix localMatrix = node->GetLocalSpace(); + Matrix::Multiply(nodeMatrix, localMatrix, parentMatrix); + + Vector3 volume[2]; + if(node->GetExtents(nodeParams.mResources, volume[0], volume[1])) + { + for(uint32_t i = 0; i < BOX_POINT_COUNT; ++i) + { + Vector4 position = Vector4(volume[BBIndex[i][0]].x, volume[BBIndex[i][1]].y, volume[BBIndex[i][2]].z, 1.0f); + Vector4 objectPosition = nodeMatrix * position; + objectPosition /= objectPosition.w; + + AABB.ConsiderNewPointInVolume(Vector3(objectPosition)); + } + } + + if(node->mCustomization) + { + if(!node->mChildren.empty()) + { + auto choice = choices.Get(node->mCustomization->mTag); + Dali::Scene3D::Loader::Index i = std::min(choice != Dali::Scene3D::Loader::Customization::NONE ? choice : 0, static_cast(node->mChildren.size() - 1)); + + AddModelTreeToAABB(AABB, scene, choices, node->mChildren[i], nodeParams, nodeMatrix); + } + } + else + { + for(auto i : node->mChildren) + { + AddModelTreeToAABB(AABB, scene, choices, i, nodeParams, nodeMatrix); + } + } +} + +} // anonymous namespace + +Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl) +: Control(ControlBehaviour(DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS)), + mModelUrl(modelUrl), + mResourceDirectoryUrl(resourceDirectoryUrl), + mModelRoot(), + mNaturalSize(Vector3::ZERO), + mModelPivot(AnchorPoint::CENTER), + mIblScaleFactor(1.0f), + mModelResourceReady(false), + mIBLResourceReady(true) +{ +} + +Model::~Model() +{ +} + +Dali::Scene3D::Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl) +{ + Model* impl = new Model(modelUrl, resourceDirectoryUrl); + + Dali::Scene3D::Model handle = Dali::Scene3D::Model(*impl); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +const Actor Model::GetModelRoot() const +{ + return mModelRoot; +} + +void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor) +{ + mIBLResourceReady = false; + Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl); + Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl); + SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor); + mIBLResourceReady = true; + + // If Model resource is already ready, then set resource ready. + // If Model resource is still not ready, wait for model resource ready. + if(IsResourceReady()) + { + SetResourceReady(false); + } +} + +void Model::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) +{ + if(diffuseTexture && specularTexture) + { + if(mDiffuseTexture != diffuseTexture || mSpecularTexture != specularTexture) + { + mDiffuseTexture = diffuseTexture; + mSpecularTexture = specularTexture; + UpdateImageBasedLightTexture(); + } + if(mIblScaleFactor != scaleFactor) + { + mIblScaleFactor = scaleFactor; + UpdateImageBasedLightScaleFactor(); + } + + } +} + +void Model::SetImageBasedLightScaleFactor(float scaleFactor) +{ + mIblScaleFactor = scaleFactor; + if(mDiffuseTexture && mSpecularTexture) + { + UpdateImageBasedLightScaleFactor(); + } +} + +float Model::GetImageBasedLightScaleFactor() const +{ + return mIblScaleFactor; +} + +uint32_t Model::GetAnimationCount() const +{ + return mAnimations.size(); +} + +Dali::Animation Model::GetAnimation(uint32_t index) const +{ + Dali::Animation animation; + if(mAnimations.size() > index) + { + animation = mAnimations[index].second; + } + return animation; +} + +Dali::Animation Model::GetAnimation(const std::string& name) const +{ + Dali::Animation animation; + if(!name.empty()) + { + for(auto&& animationData : mAnimations) + { + if(animationData.first == name) + { + animation = animationData.second; + break; + } + } + } + return animation; +} + +/////////////////////////////////////////////////////////// +// +// Private methods +// + +void Model::OnSceneConnection(int depth) +{ + if(!mModelRoot) + { + LoadModel(); + } + + Actor parent = Self().GetParent(); + while(parent) + { + Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent); + if(sceneView) + { + GetImpl(sceneView).RegisterModel(Scene3D::Model::DownCast(Self())); + mParentSceneView = sceneView; + break; + } + parent = parent.GetParent(); + } + + Control::OnSceneConnection(depth); +} + +void Model::OnSceneDisconnection() +{ + Scene3D::SceneView sceneView = mParentSceneView.GetHandle(); + if(sceneView) + { + GetImpl(sceneView).UnregisterModel(Scene3D::Model::DownCast(Self())); + mParentSceneView.Reset(); + } + Control::OnSceneDisconnection(); +} + +Vector3 Model::GetNaturalSize() +{ + if(!mModelRoot) + { + LoadModel(); + } + + return mNaturalSize; +} + +float Model::GetHeightForWidth(float width) +{ + Extents padding; + padding = Self().GetProperty(Toolkit::Control::Property::PADDING); + return Control::GetHeightForWidth(width) + padding.top + padding.bottom; +} + +float Model::GetWidthForHeight(float height) +{ + Extents padding; + padding = Self().GetProperty(Toolkit::Control::Property::PADDING); + return Control::GetWidthForHeight(height) + padding.start + padding.end; +} + +void Model::OnRelayout(const Vector2& size, RelayoutContainer& container) +{ + Control::OnRelayout(size, container); + ScaleModel(); +} + +bool Model::IsResourceReady() const +{ + return mModelResourceReady && mIBLResourceReady; +} + +void Model::LoadModel() +{ + std::filesystem::path modelUrl(mModelUrl); + if(mResourceDirectoryUrl.empty()) + { + mResourceDirectoryUrl = std::string(modelUrl.parent_path()) + "/"; + } + std::string extension = modelUrl.extension(); + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + + Dali::Scene3D::Loader::ResourceBundle::PathProvider pathProvider = [&](Dali::Scene3D::Loader::ResourceType::Value type) { + return mResourceDirectoryUrl; + }; + + Dali::Scene3D::Loader::ResourceBundle resources; + Dali::Scene3D::Loader::SceneDefinition scene; + std::vector animGroups; + std::vector cameraParameters; + std::vector lights; + + std::vector animations; + animations.clear(); + + Dali::Scene3D::Loader::LoadResult output{resources, scene, animations, animGroups, cameraParameters, lights}; + + if(extension == DLI_EXTENSION) + { + Dali::Scene3D::Loader::DliLoader loader; + Dali::Scene3D::Loader::DliLoader::InputParams input{ + pathProvider(Dali::Scene3D::Loader::ResourceType::Mesh), + nullptr, + {}, + {}, + nullptr, + {}}; + Dali::Scene3D::Loader::DliLoader::LoadParams loadParams{input, output}; + if(!loader.LoadScene(mModelUrl, loadParams)) + { + Dali::Scene3D::Loader::ExceptionFlinger(ASSERT_LOCATION) << "Failed to load scene from '" << mModelUrl << "': " << loader.GetParseError(); + } + } + else if(extension == GLTF_EXTENSION) + { + Dali::Scene3D::Loader::ShaderDefinitionFactory sdf; + sdf.SetResources(resources); + Dali::Scene3D::Loader::LoadGltfScene(mModelUrl, sdf, output); + + resources.mEnvironmentMaps.push_back({}); + } + else + { + DALI_LOG_ERROR("Unsupported model type.\n"); + } + + Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}}; + Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}}; + Dali::Scene3D::Loader::Customization::Choices choices; + + mModelRoot = Actor::New(); + + BoundingVolume AABB; + for(auto iRoot : scene.GetRoots()) + { + auto resourceRefs = resources.CreateRefCounter(); + scene.CountResourceRefs(iRoot, choices, resourceRefs); + resources.CountEnvironmentReferences(resourceRefs); + + resources.LoadResources(resourceRefs, pathProvider); + + // glTF Mesh is defined in right hand coordinate system, with positive Y for Up direction. + // Because DALi uses left hand system, Y direciton will be flipped for environment map sampling. + for(auto&& env : resources.mEnvironmentMaps) + { + env.first.mYDirection = Y_DIRECTION; + } + + if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) + { + scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); + scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); + ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); + + scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); + + mModelRoot.Add(actor); + } + + AddModelTreeToAABB(AABB, scene, choices, iRoot, nodeParams, Matrix::IDENTITY); + } + + if(!animations.empty()) + { + auto getActor = [&](const std::string& name) { + return mModelRoot.FindChildByName(name); + }; + + mAnimations.clear(); + for(auto&& animation : animations) + { + Dali::Animation anim = animation.ReAnimate(getActor); + + mAnimations.push_back({animation.mName, anim}); + } + } + + mRenderableActors.clear(); + CollectRenderableActor(mModelRoot); + UpdateImageBasedLightTexture(); + UpdateImageBasedLightScaleFactor(); + + mNaturalSize = AABB.CalculateSize(); + mModelPivot = AABB.CalculatePivot(); + mModelRoot.SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); + Vector3 controlSize = Self().GetProperty(Dali::Actor::Property::SIZE); + if(controlSize.x == 0.0f || controlSize.y == 0.0f) + { + Self().SetProperty(Dali::Actor::Property::SIZE, mNaturalSize); + } + + FitModelPosition(); + ScaleModel(); + + Self().Add(mModelRoot); + + Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z)); + + mModelResourceReady = true; + + Control::SetResourceReady(false); +} + +void Model::ScaleModel() +{ + if(mModelRoot) + { + float scale = 1.0f; + Vector3 size = Self().GetProperty(Dali::Actor::Property::SIZE); + if(size.x > 0.0f && size.y > 0.0f) + { + scale = MAXFLOAT; + scale = std::min(size.x / mNaturalSize.x, scale); + scale = std::min(size.y / mNaturalSize.y, scale); + } + // Models in glTF and dli are defined as right hand coordinate system. + // DALi uses left hand coordinate system. Scaling negative is for change winding order. + mModelRoot.SetProperty(Dali::Actor::Property::SCALE, Y_DIRECTION * scale); + } +} + +void Model::FitModelPosition() +{ + if(mModelRoot) + { + // Loaded model pivot is not the model center. + mModelRoot.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + mModelRoot.SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3::ONE - mModelPivot); + } +} + +void Model::CollectRenderableActor(Actor actor) +{ + uint32_t rendererCount = actor.GetRendererCount(); + if(rendererCount) + { + mRenderableActors.push_back(actor); + } + + uint32_t childrenCount = actor.GetChildCount(); + for(uint32_t i = 0; i < childrenCount; ++i) + { + CollectRenderableActor(actor.GetChildAt(i)); + } +} + +void Model::UpdateImageBasedLightTexture() +{ + if(!mDiffuseTexture || !mSpecularTexture) + { + return; + } + + for(auto&& actor : mRenderableActors) + { + Actor renderableActor = actor.GetHandle(); + if(renderableActor) + { + uint32_t rendererCount = renderableActor.GetRendererCount(); + for(uint32_t i = 0; i < rendererCount; ++i) + { + Dali::Renderer renderer = renderableActor.GetRendererAt(i); + if(renderer) + { + Dali::TextureSet textures = renderer.GetTextures(); + if(textures) + { + uint32_t textureCount = textures.GetTextureCount(); + // EnvMap requires at least 2 texture, diffuse and specular + if(textureCount > 2u) + { + textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, mDiffuseTexture); + textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, mSpecularTexture); + } + } + } + } + } + } +} + +void Model::UpdateImageBasedLightScaleFactor() +{ + if(!mDiffuseTexture || !mSpecularTexture) + { + return; + } + for(auto&& actor : mRenderableActors) + { + Actor renderableActor = actor.GetHandle(); + if(renderableActor) + { + renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), mIblScaleFactor); + } + } +} + +} // namespace Internal +} // namespace Scene3D +} // namespace Dali diff --git a/dali-scene3d/internal/controls/model/model-impl.h b/dali-scene3d/internal/controls/model/model-impl.h new file mode 100644 index 0000000000..7e979774a4 --- /dev/null +++ b/dali-scene3d/internal/controls/model/model-impl.h @@ -0,0 +1,210 @@ +#ifndef DALI_SCENE3D_INTERNAL_MODEL_H +#define DALI_SCENE3D_INTERNAL_MODEL_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +class Model; + +namespace Internal +{ +/** + * @brief Impl class for Model. + */ +class Model : public Dali::Toolkit::Internal::Control +{ +public: + using AnimationData = std::pair; + + /** + * @brief Creates a new Model. + * + * @return A public handle to the newly allocated Model. + */ + static Dali::Scene3D::Model New(const std::string& modelUrl, const std::string& resourceDirectoryUrl); + + /** + * @copydoc Model::GetModelRoot() + */ + const Actor GetModelRoot() const; + + /** + * @copydoc Model::SetImageBasedLightSource() + */ + void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor); + + /** + * @copydoc Model::SetImageBasedLightTexture() + */ + void SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor); + + /** + * @copydoc Model::SetImageBasedLightScaleFactor() + */ + void SetImageBasedLightScaleFactor(float scaleFactor); + + /** + * @copydoc Model::GetImageBasedLightScaleFactor() + */ + float GetImageBasedLightScaleFactor() const; + + /** + * @copydoc Model::GetAnimationCount() + */ + uint32_t GetAnimationCount() const; + + /** + * @copydoc Model::GetAnimation() + */ + Dali::Animation GetAnimation(uint32_t index) const; + + /** + * @copydoc Model::GetAnimation() + */ + Dali::Animation GetAnimation(const std::string& name) const; + +protected: + /** + * @brief Constructs a new Model. + */ + Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~Model(); + +private: + /** + * @copydoc CustomActorImpl::OnSceneConnection() + */ + void OnSceneConnection(int depth) override; + + /** + * @copydoc CustomActorImpl::OnSceneDisconnection() + */ + void OnSceneDisconnection() override; + + /** + * @copydoc Toolkit::Control::GetNaturalSize + */ + Vector3 GetNaturalSize() override; + + /** + * @copydoc Toolkit::Control::GetHeightForWidth() + */ + float GetHeightForWidth(float width) override; + + /** + * @copydoc Toolkit::Control::GetWidthForHeight() + */ + float GetWidthForHeight(float height) override; + + /** + * @copydoc Toolkit::Control::OnRelayout() + */ + void OnRelayout(const Vector2& size, RelayoutContainer& container) override; + + /** + * @copydoc Toolkit::Control::IsResourceReady() + */ + bool IsResourceReady() const override; + + /** + * @brief Loads a model from file + */ + void LoadModel(); + + /** + * @brief Scales the model to fit the control or to return to original size. + */ + void ScaleModel(); + + /** + * @brief Changes model anchor point to set the model at center or returns to the original model pivot. + */ + void FitModelPosition(); + + /** + * @brief Changes IBL information of the input node. + */ + void CollectRenderableActor(Actor actor); + + /** + * @brief Changes IBL textures of the input node. + */ + void UpdateImageBasedLightTexture(); + + /** + * @brief Changes IBL scale factor of the input node. + */ + void UpdateImageBasedLightScaleFactor(); + +private: + std::string mModelUrl; + std::string mResourceDirectoryUrl; + Dali::Actor mModelRoot; + std::vector mAnimations; + std::vector> mRenderableActors; + WeakHandle mParentSceneView; + + Dali::Texture mSpecularTexture; + Dali::Texture mDiffuseTexture; + Vector3 mNaturalSize; + Vector3 mModelPivot; + float mIblScaleFactor; + bool mModelResourceReady; + bool mIBLResourceReady; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods +inline Dali::Scene3D::Internal::Model& GetImpl(Dali::Scene3D::Model& obj) +{ + DALI_ASSERT_ALWAYS(obj); + Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + +inline const Dali::Scene3D::Internal::Model& GetImpl(const Dali::Scene3D::Model& obj) +{ + DALI_ASSERT_ALWAYS(obj); + const Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + +} // namespace Scene3D + +} // namespace Dali + +#endif // DALI_SCENE3D_INTERNAL_MODEL_H diff --git a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp index f0afd0d65d..f35a0b0788 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp @@ -31,7 +31,7 @@ #include // INTERNAL INCLUDES -#include +#include #include #include @@ -162,22 +162,22 @@ void SceneView::SelectCamera(const std::string& name) UpdateCamera(GetCamera(name)); } -void SceneView::RegisterModelView(Scene3D::ModelView modelView) +void SceneView::RegisterModel(Scene3D::Model model) { - if(modelView) + if(model) { - modelView.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor); - mModels.push_back(modelView); + model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor); + mModels.push_back(model); } } -void SceneView::UnregisterModelView(Scene3D::ModelView modelView) +void SceneView::UnregisterModel(Scene3D::Model model) { - if(modelView) + if(model) { for(uint32_t i = 0; i < mModels.size(); ++i) { - if(mModels[i] == modelView) + if(mModels[i] == model) { mModels.erase(mModels.begin() + i); break; @@ -186,13 +186,13 @@ void SceneView::UnregisterModelView(Scene3D::ModelView modelView) } } -void SceneView::SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor) +void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor) { mIBLResourceReady = false; - Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuse); + Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl); if(diffuseTexture) { - Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specular); + Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl); if(specularTexture) { mDiffuseTexture = diffuseTexture; diff --git a/dali-scene3d/internal/controls/scene-view/scene-view-impl.h b/dali-scene3d/internal/controls/scene-view/scene-view-impl.h index f61ad8a226..ddd7319d8e 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.h +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.h @@ -30,8 +30,8 @@ #include // INTERNAL INCLUDES -#include #include +#include namespace Dali { @@ -95,25 +95,25 @@ public: void SelectCamera(const std::string& name); /** - * @brief Register a ModelView. - * Some works like ibl setting should be applied on the only ModelView not the all child actors. - * SceneView contains child ModelView list to apply the works effectively. + * @brief Register a Model. + * Some works like ibl setting should be applied on the only Model not the all child actors. + * SceneView contains child Model list to apply the works effectively. * - * @param[in] modelView ModelView to be registered. + * @param[in] model Model to be registered. */ - void RegisterModelView(Scene3D::ModelView modelView); + void RegisterModel(Scene3D::Model model); /** - * @brief Unregister a ModelView + * @brief Unregister a Model * - * @param[in] modelView ModelView to be unregistered. + * @param[in] model Model to be unregistered. */ - void UnregisterModelView(Scene3D::ModelView modelView); + void UnregisterModel(Scene3D::Model model); /** * @copydoc SceneView::SetImageBasedLightSource() */ - void SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor); + void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor); /** * @copydoc SceneView::SetImageBasedLightScaleFactor() @@ -209,13 +209,13 @@ private: ///////////////////////////////////////////////////////////// // FrameBuffer and Rendertask to render child objects as a 3D Scene - CameraActor mDefaultCamera; - CameraActor mSelectedCamera; - std::vector mCameras; - std::vector mModels; - Dali::FrameBuffer mRenderTarget; - Dali::Texture mTexture; - Dali::RenderTask mRenderTask; + CameraActor mDefaultCamera; + CameraActor mSelectedCamera; + std::vector mCameras; + std::vector mModels; + Dali::FrameBuffer mRenderTarget; + Dali::Texture mTexture; + Dali::RenderTask mRenderTask; Layer mRootLayer; diff --git a/dali-scene3d/internal/file.list b/dali-scene3d/internal/file.list index f1bcfd8cf3..2f9f7b3176 100644 --- a/dali-scene3d/internal/file.list +++ b/dali-scene3d/internal/file.list @@ -5,6 +5,6 @@ set(scene3d_src_files ${scene3d_src_files} ${scene3d_internal_dir}/loader/hash.cpp ${scene3d_internal_dir}/loader/json-reader.cpp ${scene3d_internal_dir}/loader/json-util.cpp - ${scene3d_internal_dir}/controls/model-view/model-view-impl.cpp + ${scene3d_internal_dir}/controls/model/model-impl.cpp ${scene3d_internal_dir}/controls/scene-view/scene-view-impl.cpp ) diff --git a/dali-scene3d/public-api/controls/model-view/model-view.cpp b/dali-scene3d/public-api/controls/model-view/model-view.cpp deleted file mode 100644 index 5d5ede59fd..0000000000 --- a/dali-scene3d/public-api/controls/model-view/model-view.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// CLASS HEADER -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ -namespace Scene3D -{ -ModelView::ModelView() -{ -} - -ModelView::ModelView(const ModelView& modelView) = default; - -ModelView::ModelView(ModelView&& rhs) = default; - -ModelView& ModelView::operator=(const ModelView& modelView) = default; - -ModelView& ModelView::operator=(ModelView&& rhs) = default; - -ModelView::~ModelView() -{ -} - -ModelView ModelView::New(const std::string& modelPath, const std::string& resourcePath) -{ - return Internal::ModelView::New(modelPath, resourcePath); -} - -ModelView ModelView::DownCast(BaseHandle handle) -{ - return Control::DownCast(handle); -} - -ModelView::ModelView(Internal::ModelView& implementation) -: Control(implementation) -{ -} - -ModelView::ModelView(Dali::Internal::CustomActor* internal) -: Control(internal) -{ - VerifyCustomActorPointer(internal); -} - -const Actor ModelView::GetModelRoot() const -{ - return GetImpl(*this).GetModelRoot(); -} - -void ModelView::FitSize(bool fit) -{ - GetImpl(*this).FitSize(fit); -} - -void ModelView::FitCenter(bool fit) -{ - GetImpl(*this).FitCenter(fit); -} - -void ModelView::SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor) -{ - GetImpl(*this).SetImageBasedLightSource(diffuse, specular, scaleFactor); -} - -void ModelView::SetImageBasedLightTexture(Texture diffuse, Texture specular, float scaleFactor) -{ - GetImpl(*this).SetImageBasedLightTexture(diffuse, specular, scaleFactor); -} - -void ModelView::SetImageBasedLightScaleFactor(float scaleFactor) -{ - GetImpl(*this).SetImageBasedLightScaleFactor(scaleFactor); -} - -float ModelView::GetImageBasedLightScaleFactor() const -{ - return GetImpl(*this).GetImageBasedLightScaleFactor(); -} - -uint32_t ModelView::GetAnimationCount() const -{ - return GetImpl(*this).GetAnimationCount(); -} - -Dali::Animation ModelView::GetAnimation(uint32_t index) const -{ - return GetImpl(*this).GetAnimation(index); -} - -Dali::Animation ModelView::GetAnimation(const std::string& name) const -{ - return GetImpl(*this).GetAnimation(name); -} - -} // namespace Scene3D - -} // namespace Dali diff --git a/dali-scene3d/public-api/controls/model-view/model-view.h b/dali-scene3d/public-api/controls/model-view/model-view.h deleted file mode 100644 index 19ea4c33ae..0000000000 --- a/dali-scene3d/public-api/controls/model-view/model-view.h +++ /dev/null @@ -1,243 +0,0 @@ -#ifndef DALI_SCENE3D_MODEL_VIEW_H -#define DALI_SCENE3D_MODEL_VIEW_H - -/* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// INTERNAL INCLUDES -#include - -// EXTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ -namespace Scene3D -{ -namespace Internal DALI_INTERNAL -{ -class ModelView; -} - -/** - * @addtogroup dali_toolkit_controls_model_view - * @{ - */ - -/** - * @brief ModelView is a control to show 3D model objects. - * ModelView supports to load glTF 2.0 and DLI models for the input format - * and also supports Physically Based Rendering with Image Based Lighting. - * - * The Animations defined in the glTF or DLI models are also loaded and can be retrieved by using GetAnimation() method. - * The number of animation is also retrieved by GetAnimationCount() method. - * - * By default, The loaded model has it's own position and size which are defined in vertex buffer regardless of the Control size. - * The model can be resized and repositioned to fit to the ModelView Control with FitSize() and FitCenter() methods. - * - * @code - * - * ModelView modelView = ModelView::New(modelUrl); - * modelView.SetProperty(Dali::Actor::Property::SIZE, Vector2(width, height)); - * modelView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); - * modelView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - * modelView.SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor); - * modelView.FitSize(true); - * modelView.FitCenter(true); - * window.Add(modelView); - * uint32_t animationCount = modelView.GetAnimationCount(); - * Dali::Animation animation = modelView.GetAnimation(0); - * animation.Play(); - * - * @endcode - */ -class DALI_SCENE3D_API ModelView : public Dali::Toolkit::Control -{ -public: - /** - * @brief Create an initialized ModelView. - * @param[in] modelPath model file path.(e.g., glTF, and DLI). - * @param[in] resourcePath resource file path that includes binary, image etc. - * @note If resourcePath is empty, the parent directory path of modelPath is used for resource path. - * @return A handle to a newly allocated Dali resource - */ - static ModelView New(const std::string& modelPath, const std::string& resourcePath = std::string()); - - /** - * @brief Creates an uninitialized ModelView. - * - * Only derived versions can be instantiated. Calling member - * functions with an uninitialized Dali::Object is not allowed. - */ - ModelView(); - - /** - * @brief Destructor. - * - * This is non-virtual since derived Handle types must not contain data or virtual methods. - */ - ~ModelView(); - - /** - * @brief Copy constructor. - * @param[in] modelView Handle to an object - */ - ModelView(const ModelView& modelView); - - /** - * @brief Move constructor - * - * @param[in] rhs A reference to the moved handle - */ - ModelView(ModelView&& rhs); - - /** - * @brief Assignment operator. - * @param[in] modelView Handle to an object - * @return reference to this - */ - ModelView& operator=(const ModelView& modelView); - - /** - * @brief Move assignment - * - * @param[in] rhs A reference to the moved handle - * @return A reference to this - */ - ModelView& operator=(ModelView&& rhs); - - /** - * @brief Downcasts an Object handle to ModelView. - * - * If handle points to a ModelView, the downcast produces valid handle. - * If not, the returned handle is left uninitialized. - * - * @param[in] handle Handle to an object - * @return Handle to a ModelView or an uninitialized handle - */ - static ModelView DownCast(BaseHandle handle); - - /** - * @brief Retrieves model root Actor. - * @return Root Actor of the model. - */ - const Actor GetModelRoot() const; - - /** - * @brief Fits the model to the Control size. - * @param[in] fit true to fit model size to control. - * @note This method makes model fit to the Control size by keeping original model ratio. - * It means If model size is (2, 2, 2) and ModelView size is (10, 8), then the model become looks (8, 8, 8). - * If ModelView Size x or y is 0, this method don't work anything. - * If ModelView Size z is 0, this method considers only x and y values of ModelView Size. - */ - void FitSize(bool fit); - - /** - * @brief Moves the model to the center of control. - * @param[in] fit true to fit model to center of control. - * @note This method doesn't changes size of model. - */ - void FitCenter(bool fit); - - /** - * @brief Changes Image Based Light as the input textures. - * @param[in] diffuse cube map that can be used as a diffuse IBL source. - * @param[in] specular cube map that can be used as a specular IBL source. - * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f. - */ - void SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor = 1.0f); - - /** - * @brief Sets Image Based Light Texture. - * - * @param[in] diffuse cube map texture that can be used as a diffuse IBL source. - * @param[in] specular cube map texture that can be used as a specular IBL source. - * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f. - * - * @note Both of diffuse and specular should be available. If not, nothing applied. - */ - void SetImageBasedLightTexture(Texture diffuse, Texture specular, float scaleFactor = 1.0f); - - /** - * @brief Sets Scale Factor of Image Based Light Source. - * - * @note If SetImageBasedLightSource() or SetImageBasedLightTexture() method is called after this method, scaleFactor is overrided. - * - * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. - */ - void SetImageBasedLightScaleFactor(float scaleFactor); - - /** - * @brief Gets Scale Factor of Image Based Light Source. - * Default value is 1.0f. - * - * @return scale factor that controls light source intensity. - */ - float GetImageBasedLightScaleFactor() const; - - /** - * @brief Gets number of animations those loaded from model file. - * @return The number of loaded animations. - * @note This method should be called after Model load finished. - */ - uint32_t GetAnimationCount() const; - - /** - * @brief Gets animation at the index. - * @param[in] index Index of animation to be retrieved. - * @return Animation at the index. - * @note This method should be called after Model load finished. - */ - Dali::Animation GetAnimation(uint32_t index) const; - - /** - * @brief Retrieves animation with the given name. - * @param[in] name string name of animation to be retrieved. - * @return Animation that has the given name. - * @note This method should be called after Model load finished. - */ - Dali::Animation GetAnimation(const std::string& name) const; - -public: // Not intended for application developers - /// @cond internal - /** - * @brief Creates a handle using the Toolkit::Internal implementation. - * - * @param[in] implementation The Control implementation - */ - DALI_INTERNAL ModelView(Internal::ModelView& implementation); - - /** - * @brief Allows the creation of this Control from an Internal::CustomActor pointer. - * - * @param[in] internal A pointer to the internal CustomActor - */ - DALI_INTERNAL ModelView(Dali::Internal::CustomActor* internal); - /// @endcond -}; - -/** - * @} - */ -} // namespace Scene3D - -} // namespace Dali - -#endif // DALI_SCENE3D_MODEL_VIEW_H diff --git a/dali-scene3d/public-api/controls/model/model.cpp b/dali-scene3d/public-api/controls/model/model.cpp new file mode 100644 index 0000000000..e315cb9c07 --- /dev/null +++ b/dali-scene3d/public-api/controls/model/model.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Scene3D +{ +Model::Model() +{ +} + +Model::Model(const Model& model) = default; + +Model::Model(Model&& rhs) = default; + +Model& Model::operator=(const Model& model) = default; + +Model& Model::operator=(Model&& rhs) = default; + +Model::~Model() +{ +} + +Model Model::New(const std::string& modelUrl, const std::string& resourceDirectoryUrl) +{ + return Internal::Model::New(modelUrl, resourceDirectoryUrl); +} + +Model Model::DownCast(BaseHandle handle) +{ + return Control::DownCast(handle); +} + +Model::Model(Internal::Model& implementation) +: Control(implementation) +{ +} + +Model::Model(Dali::Internal::CustomActor* internal) +: Control(internal) +{ + VerifyCustomActorPointer(internal); +} + +const Actor Model::GetModelRoot() const +{ + return GetImpl(*this).GetModelRoot(); +} + +void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor) +{ + GetImpl(*this).SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor); +} + +void Model::SetImageBasedLightTexture(Texture diffuseTexture, Texture specularTexture, float scaleFactor) +{ + GetImpl(*this).SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor); +} + +void Model::SetImageBasedLightScaleFactor(float scaleFactor) +{ + GetImpl(*this).SetImageBasedLightScaleFactor(scaleFactor); +} + +float Model::GetImageBasedLightScaleFactor() const +{ + return GetImpl(*this).GetImageBasedLightScaleFactor(); +} + +uint32_t Model::GetAnimationCount() const +{ + return GetImpl(*this).GetAnimationCount(); +} + +Dali::Animation Model::GetAnimation(uint32_t index) const +{ + return GetImpl(*this).GetAnimation(index); +} + +Dali::Animation Model::GetAnimation(const std::string& name) const +{ + return GetImpl(*this).GetAnimation(name); +} + +} // namespace Scene3D + +} // namespace Dali diff --git a/dali-scene3d/public-api/controls/model/model.h b/dali-scene3d/public-api/controls/model/model.h new file mode 100644 index 0000000000..6678d9fe59 --- /dev/null +++ b/dali-scene3d/public-api/controls/model/model.h @@ -0,0 +1,223 @@ +#ifndef DALI_SCENE3D_MODEL_H +#define DALI_SCENE3D_MODEL_H + +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Scene3D +{ +namespace Internal DALI_INTERNAL +{ +class Model; +} + +/** + * @addtogroup dali_toolkit_controls_model + * @{ + */ + +/** + * @brief Model is a control to show 3D model objects. + * Model supports to load glTF 2.0 and DLI models for the input format + * and also supports Physically Based Rendering with Image Based Lighting. + * + * The Animations defined in the glTF or DLI models are also loaded and can be retrieved by using GetAnimation() method. + * The number of animation is also retrieved by GetAnimationCount() method. + * + * By default, The loaded model has its own position and size which are defined in vertex buffer regardless of the Control size. + * + * @code + * + * Model model = Model::New(modelUrl); + * model.SetProperty(Dali::Actor::Property::SIZE, Vector2(width, height)); + * model.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + * model.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + * model.SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor); + * window.Add(model); + * uint32_t animationCount = model.GetAnimationCount(); + * Dali::Animation animation = model.GetAnimation(0); + * animation.Play(); + * + * @endcode + */ +class DALI_SCENE3D_API Model : public Dali::Toolkit::Control +{ +public: + /** + * @brief Create an initialized Model. + * @param[in] modelUrl model file path.(e.g., glTF, and DLI). + * @param[in] resourceDirectoryUrl resource file path that includes binary, image etc. + * @note If resourceDirectoryUrl is empty, the parent directory path of modelUrl is used for resource path. + * @return A handle to a newly allocated Dali resource + */ + static Model New(const std::string& modelUrl, const std::string& resourceDirectoryUrl = std::string()); + + /** + * @brief Creates an uninitialized Model. + * + * Only derived versions can be instantiated. Calling member + * functions with an uninitialized Dali::Object is not allowed. + */ + Model(); + + /** + * @brief Destructor. + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~Model(); + + /** + * @brief Copy constructor. + * @param[in] model Handle to an object + */ + Model(const Model& model); + + /** + * @brief Move constructor + * + * @param[in] rhs A reference to the moved handle + */ + Model(Model&& rhs); + + /** + * @brief Assignment operator. + * @param[in] model Handle to an object + * @return reference to this + */ + Model& operator=(const Model& model); + + /** + * @brief Move assignment + * + * @param[in] rhs A reference to the moved handle + * @return A reference to this + */ + Model& operator=(Model&& rhs); + + /** + * @brief Downcasts an Object handle to Model. + * + * If handle points to a Model, the downcast produces valid handle. + * If not, the returned handle is left uninitialized. + * + * @param[in] handle Handle to an object + * @return Handle to a Model or an uninitialized handle + */ + static Model DownCast(BaseHandle handle); + + /** + * @brief Retrieves model root Actor. + * @return Root Actor of the model. + */ + const Actor GetModelRoot() const; + + /** + * @brief Changes Image Based Light as the input textures. + * @param[in] diffuseUrl cube map that can be used as a diffuse IBL source. + * @param[in] specularUrl cube map that can be used as a specular IBL source. + * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f. + */ + void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor = 1.0f); + + /** + * @brief Sets Image Based Light Texture. + * + * @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source. + * @param[in] specularTexture cube map texture that can be used as a specular IBL source. + * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f. + * + * @note Both of diffuse texture and specular texture should be available. If not, nothing applied. + */ + void SetImageBasedLightTexture(Texture diffuseTexture, Texture specularTexture, float scaleFactor = 1.0f); + + /** + * @brief Sets Scale Factor of Image Based Light Source. + * + * @note If SetImageBasedLightSource() or SetImageBasedLightTexture() method is called after this method, scaleFactor is overrided. + * + * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. + */ + void SetImageBasedLightScaleFactor(float scaleFactor); + + /** + * @brief Gets Scale Factor of Image Based Light Source. + * Default value is 1.0f. + * + * @return scale factor that controls light source intensity. + */ + float GetImageBasedLightScaleFactor() const; + + /** + * @brief Gets number of animations those loaded from model file. + * @return The number of loaded animations. + * @note This method should be called after Model load finished. + */ + uint32_t GetAnimationCount() const; + + /** + * @brief Gets animation at the index. + * @param[in] index Index of animation to be retrieved. + * @return Animation at the index. + * @note This method should be called after Model load finished. + */ + Dali::Animation GetAnimation(uint32_t index) const; + + /** + * @brief Retrieves animation with the given name. + * @param[in] name string name of animation to be retrieved. + * @return Animation that has the given name. + * @note This method should be called after Model load finished. + */ + Dali::Animation GetAnimation(const std::string& name) const; + +public: // Not intended for application developers + /// @cond internal + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation + */ + DALI_INTERNAL Model(Internal::Model& implementation); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor + */ + DALI_INTERNAL Model(Dali::Internal::CustomActor* internal); + /// @endcond +}; + +/** + * @} + */ +} // namespace Scene3D + +} // namespace Dali + +#endif // DALI_SCENE3D_MODEL_H diff --git a/dali-scene3d/public-api/controls/scene-view/scene-view.cpp b/dali-scene3d/public-api/controls/scene-view/scene-view.cpp index 530d4f1a46..1aea71ceef 100644 --- a/dali-scene3d/public-api/controls/scene-view/scene-view.cpp +++ b/dali-scene3d/public-api/controls/scene-view/scene-view.cpp @@ -102,9 +102,9 @@ void SceneView::SelectCamera(const std::string& name) GetImpl(*this).SelectCamera(name); } -void SceneView::SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor) +void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor) { - GetImpl(*this).SetImageBasedLightSource(diffuse, specular, scaleFactor); + GetImpl(*this).SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor); } void SceneView::SetImageBasedLightScaleFactor(float scaleFactor) diff --git a/dali-scene3d/public-api/controls/scene-view/scene-view.h b/dali-scene3d/public-api/controls/scene-view/scene-view.h index 0e4f10ec26..b1923c303e 100644 --- a/dali-scene3d/public-api/controls/scene-view/scene-view.h +++ b/dali-scene3d/public-api/controls/scene-view/scene-view.h @@ -91,7 +91,7 @@ class SceneView; * sceneView.SetProperty(Dali::Actor::Property::SIZE, Vector2(400, 400)); * mWindow.Add(sceneView); * - * Dali::Scene3D::ModelView model = Dali::Scene3D::ModelView::New(...); + * Dali::Scene3D::Model model = Dali::Scene3D::Model::New(...); * sceneView.Add(model); * * CameraActor cameraActor = CameraActor::New(); @@ -243,11 +243,11 @@ public: * If SceneView has IBL, IBL of newly added Model is also overridden. * To set indivisual IBL for each Model, the Model's IBL should be set after the SceneView's IBL. * - * @param[in] diffuse cube map that can be used as a diffuse IBL source. - * @param[in] specular cube map that can be used as a specular IBL source. + * @param[in] diffuseUrl cube map that can be used as a diffuse IBL source. + * @param[in] specularUrl cube map that can be used as a specular IBL source. * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f. */ - void SetImageBasedLightSource(const std::string& diffuse, const std::string& specular, float scaleFactor = 1.0f); + void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor = 1.0f); /** * @brief Sets Scale Factor of Image Based Light Source. diff --git a/dali-scene3d/public-api/file.list b/dali-scene3d/public-api/file.list index c80e43ff2c..1ce931fb6f 100644 --- a/dali-scene3d/public-api/file.list +++ b/dali-scene3d/public-api/file.list @@ -1,7 +1,7 @@ set(scene3d_public_api_dir "${scene3d_dir}/public-api") set(scene3d_src_files ${scene3d_src_files} - ${scene3d_public_api_dir}/controls/model-view/model-view.cpp + ${scene3d_public_api_dir}/controls/model/model.cpp ${scene3d_public_api_dir}/controls/scene-view/scene-view.cpp ${scene3d_public_api_dir}/loader/alpha-function-helper.cpp ${scene3d_public_api_dir}/loader/animated-property.cpp