Merge "Allow to load uint32_t as indices" into devel/master
authorDavid Steele <david.steele@samsung.com>
Mon, 27 Feb 2023 11:09:45 +0000 (11:09 +0000)
committerGerrit Code Review <gerrit@review>
Mon, 27 Feb 2023 11:09:45 +0000 (11:09 +0000)
15 files changed:
automated-tests/resources/AnimatedCube.gltf
automated-tests/src/dali-scene3d/utc-Dali-CameraParameters.cpp
automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp
automated-tests/src/dali-scene3d/utc-Dali-Model.cpp
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/model/model-impl.h
dali-scene3d/internal/loader/gltf2-asset.h
dali-scene3d/public-api/controls/model/model.cpp
dali-scene3d/public-api/controls/model/model.h
dali-scene3d/public-api/loader/camera-parameters.cpp
dali-scene3d/public-api/loader/camera-parameters.h
dali-scene3d/public-api/loader/dli-loader.cpp
dali-scene3d/public-api/loader/gltf2-loader.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 7787c04..807c07e 100644 (file)
         "camera" : 1,
         "translation" : [ 0.5, 0.5, 3.0 ],
         "children": [
-          4
+          4, 5, 6, 7
         ]
       },
       {
             0.0,
             1.0
         ]
+      },
+      {
+        "camera" : 3,
+        "translation" : [ 0.0, 0.0, 0.0 ]
+      },
+      {
+        "camera" : 4,
+        "translation" : [ 0.0, 0.0, 0.0 ]
+      },
+      {
+        "camera" : 5,
+        "translation" : [ 0.0, 0.0, 0.0 ]
       }
    ],
    "scene" : 0,
         "zfar": 100.0,
         "znear": 0.01
       }
+    },
+    {
+      "type": "perspective",
+      "perspective": {
+        "aspectRatio": 1.0,
+        "yfov": 0.7,
+        "znear": 0.01
+      }
+    },
+    {
+      "type": "perspective",
+      "perspective": {
+        "aspectRatio": 1.0,
+        "zfar": 100.0,
+        "znear": 0.01
+      }
+    },
+    {
+      "type": "orthographic",
+      "orthographic": {
+        "xmag": 1.0,
+        "ymag": 1.0,
+        "znear": 0.01
+      }
     }
    ],
    "samplers": [
index 5fec8f2..83f345c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -35,7 +35,7 @@ int UtcDaliCameraParameters(void)
                                           Vector3::ZAXIS * -100.f);
   camParams.orthographicSize = 3.0f;
   camParams.aspectRatio      = 1.0f;
-  camParams.yFov             = Degree(Radian(M_PI * .5)).degree;
+  camParams.yFovDegree       = Degree(Radian(M_PI * .5));
   camParams.zNear            = 1.f;
   camParams.zFar             = 1000.f;
 
@@ -70,7 +70,7 @@ int UtcDaliCameraParameters(void)
 
     if(camParams.isPerspective)
     {
-      DALI_TEST_EQUAL(camera.GetProperty(Dali::CameraActor::Property::FIELD_OF_VIEW).Get<float>(), Radian(Degree(camParams.yFov)).radian);
+      DALI_TEST_EQUAL(camera.GetProperty(Dali::CameraActor::Property::FIELD_OF_VIEW).Get<float>(), Radian(camParams.yFovDegree).radian);
     }
     else
     {
index a485f0f..bcb61b5 100644 (file)
@@ -179,7 +179,7 @@ int UtcDaliGltfLoaderSuccess1(void)
   LoadGltfScene(TEST_RESOURCE_DIR "/AnimatedCube.gltf", sdf, ctx.loadResult);
 
   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
-  DALI_TEST_EQUAL(6u, ctx.scene.GetNodeCount());
+  DALI_TEST_EQUAL(9u, ctx.scene.GetNodeCount());
 
   // Default envmap is used
   DALI_TEST_EQUAL(1u, ctx.resources.mEnvironmentMaps.size());
@@ -452,7 +452,7 @@ int UtcDaliGltfLoaderSuccess1(void)
   DALI_TEST_EQUAL(2u, ctx.resources.mShaders.size());
   DALI_TEST_EQUAL(0u, ctx.resources.mSkeletons.size());
 
-  DALI_TEST_EQUAL(3u, ctx.cameras.size());
+  DALI_TEST_EQUAL(6u, ctx.cameras.size());
   DALI_TEST_EQUAL(0u, ctx.lights.size());
   DALI_TEST_EQUAL(1u, ctx.animations.size());
   DALI_TEST_EQUAL(0u, ctx.animationGroups.size());
index 5d2c344..18bd46c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -26,6 +26,8 @@
 
 #include <dali-scene3d/public-api/controls/model/model.h>
 
+#include <dali/devel-api/actors/camera-actor-devel.h>
+
 using namespace Dali;
 using namespace Dali::Toolkit;
 
@@ -58,7 +60,7 @@ const char* TEST_DLI_EXERCISE_FILE_NAME            = TEST_RESOURCE_DIR "/exercis
  * These textures are based off version of Wave engine sample
  * Take from https://github.com/WaveEngine/Samples
  *
- * Copyright (c) 2022 Wave Coorporation
+ * Copyright (c) 2023 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
@@ -1035,6 +1037,114 @@ int UtcDaliModelAnimation03(void)
   END_TEST;
 }
 
+int UtcDaliModelCameraGenerate01(void)
+{
+  ToolkitTestApplication application;
+
+  Scene3D::Model model = Scene3D::Model::New(TEST_DLI_EXERCISE_FILE_NAME);
+  model.SetProperty(Dali::Actor::Property::SIZE, Vector2(50, 50));
+  application.GetScene().Add(model);
+
+  gResourceReadyCalled = false;
+  model.ResourceReadySignal().Connect(&OnResourceReady);
+  DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+  uint32_t cameraCount = model.GetCameraCount();
+  DALI_TEST_EQUALS(1, cameraCount, TEST_LOCATION);
+
+  CameraActor generatedCamera = model.GenerateCamera(0u);
+  DALI_TEST_CHECK(generatedCamera);
+
+  generatedCamera = model.GenerateCamera(1u); // Fail to generate camera
+  DALI_TEST_CHECK(!generatedCamera);
+
+  END_TEST;
+}
+
+int UtcDaliModelCameraGenerate02(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);
+
+  gResourceReadyCalled = false;
+  model.ResourceReadySignal().Connect(&OnResourceReady);
+  DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
+
+  uint32_t cameraCount = model.GetCameraCount();
+  DALI_TEST_EQUALS(6, cameraCount, TEST_LOCATION);
+
+  CameraActor generatedCamera0 = model.GenerateCamera(0u);
+  DALI_TEST_CHECK(generatedCamera0);
+  CameraActor generatedCamera1 = model.GenerateCamera(1u);
+  DALI_TEST_CHECK(generatedCamera1);
+  CameraActor generatedCamera2 = model.GenerateCamera(2u);
+  DALI_TEST_CHECK(generatedCamera2);
+  CameraActor generatedCamera3 = model.GenerateCamera(3u); // Infinity far camera
+  DALI_TEST_CHECK(generatedCamera3);
+  CameraActor generatedCamera4 = model.GenerateCamera(4u); // Broken camera 1
+  DALI_TEST_CHECK(!generatedCamera4);
+  CameraActor generatedCamera5 = model.GenerateCamera(5u); // Broken camera 2
+  DALI_TEST_CHECK(!generatedCamera5);
+  CameraActor generatedCamera6 = model.GenerateCamera(6u); // Out of bound
+  DALI_TEST_CHECK(!generatedCamera6);
+
+  CameraActor appliedCamera;
+  DALI_TEST_EQUALS(model.ApplyCamera(0u, appliedCamera), false, TEST_LOCATION); // Cannot apply into empty camera.
+
+  auto CompareCameraProperties = [](CameraActor lhs, CameraActor rhs, const char* location) {
+    DALI_TEST_EQUALS(lhs.GetProperty<int>(Dali::CameraActor::Property::PROJECTION_MODE), rhs.GetProperty<int>(Dali::CameraActor::Property::PROJECTION_MODE), TEST_LOCATION);
+    DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), rhs.GetProperty<float>(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE), TEST_LOCATION);
+
+    if(lhs.GetProperty<int>(Dali::CameraActor::Property::PROJECTION_MODE) == static_cast<int>(Dali::Camera::ProjectionMode::PERSPECTIVE_PROJECTION))
+    {
+      DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::FIELD_OF_VIEW), rhs.GetProperty<float>(Dali::CameraActor::Property::FIELD_OF_VIEW), TEST_LOCATION);
+      // TODO : Open this test when infinity far projection implement.
+      //DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), rhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), TEST_LOCATION);
+    }
+    else
+    {
+      DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE), rhs.GetProperty<float>(Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE), TEST_LOCATION);
+      DALI_TEST_EQUALS(lhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), rhs.GetProperty<float>(Dali::CameraActor::Property::FAR_PLANE_DISTANCE), TEST_LOCATION);
+    }
+  };
+
+  appliedCamera = CameraActor::New();
+  DALI_TEST_EQUALS(model.ApplyCamera(0u, appliedCamera), true, TEST_LOCATION);
+  CompareCameraProperties(generatedCamera0, appliedCamera, TEST_LOCATION);
+  DALI_TEST_EQUALS(model.ApplyCamera(1u, appliedCamera), true, TEST_LOCATION);
+  CompareCameraProperties(generatedCamera1, appliedCamera, TEST_LOCATION);
+  DALI_TEST_EQUALS(model.ApplyCamera(2u, appliedCamera), true, TEST_LOCATION);
+  CompareCameraProperties(generatedCamera2, appliedCamera, TEST_LOCATION);
+  DALI_TEST_EQUALS(model.ApplyCamera(3u, appliedCamera), true, TEST_LOCATION);
+  CompareCameraProperties(generatedCamera3, appliedCamera, TEST_LOCATION);
+  DALI_TEST_EQUALS(model.ApplyCamera(4u, appliedCamera), false, TEST_LOCATION); // Broken camera 1
+  DALI_TEST_EQUALS(model.ApplyCamera(5u, appliedCamera), false, TEST_LOCATION); // Broken camera 2
+  DALI_TEST_EQUALS(model.ApplyCamera(6u, appliedCamera), false, TEST_LOCATION); // Cannot apply over the index.
+
+  END_TEST;
+}
+
 int UtcDaliModelMultiplePrimitives(void)
 {
   ToolkitTestApplication application;
@@ -1082,8 +1192,8 @@ int UtcDaliModelColorMode(void)
   application.SendNotification();
   application.Render();
 
-  Actor actor = model.FindChildByName("AnimatedCube");
-  Vector4 childColor = actor[Dali::Actor::Property::COLOR];
+  Actor   actor           = model.FindChildByName("AnimatedCube");
+  Vector4 childColor      = actor[Dali::Actor::Property::COLOR];
   Vector4 childWorldColor = actor[Dali::Actor::Property::WORLD_COLOR];
 
   DALI_TEST_EQUALS(childColor, Color::WHITE, TEST_LOCATION);
index 31e75e5..e5d5e78 100644 (file)
@@ -116,8 +116,7 @@ void ConfigureBlendShapeShaders(
   Dali::Scene3D::Loader::ResourceBundle& resources, const Dali::Scene3D::Loader::SceneDefinition& scene, Actor root, std::vector<Dali::Scene3D::Loader::BlendshapeShaderConfigurationRequest>&& requests)
 {
   std::vector<std::string> errors;
-  auto                     onError = [&errors](const std::string& msg)
-  { errors.push_back(msg); };
+  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);
@@ -384,6 +383,45 @@ Dali::Animation Model::GetAnimation(const std::string& name) const
   return animation;
 }
 
+uint32_t Model::GetCameraCount() const
+{
+  return mCameraParameters.size();
+}
+
+Dali::CameraActor Model::GenerateCamera(uint32_t index) const
+{
+  Dali::CameraActor camera;
+  if(mCameraParameters.size() > index)
+  {
+    camera = Dali::CameraActor::New3DCamera();
+    if(!mCameraParameters[index].ConfigureCamera(camera, false))
+    {
+      DALI_LOG_ERROR("Fail to generate %u's camera actor : Some property was not defined. Please check model file.\n", index);
+      camera.Reset();
+      return camera;
+    }
+
+    ApplyCameraTransform(camera);
+  }
+  return camera;
+}
+
+bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const
+{
+  if(camera && mCameraParameters.size() > index)
+  {
+    if(!mCameraParameters[index].ConfigureCamera(camera, false))
+    {
+      DALI_LOG_ERROR("Fail to apply %u's camera actor : Some property was not defined. Please check model file.\n", index);
+      return false;
+    }
+
+    ApplyCameraTransform(camera);
+    return true;
+  }
+  return false;
+}
+
 ///////////////////////////////////////////////////////////
 //
 // Private methods
@@ -583,6 +621,45 @@ void Model::UpdateImageBasedLightScaleFactor()
   }
 }
 
+void Model::ApplyCameraTransform(Dali::CameraActor camera) const
+{
+  Vector3    selfPosition    = Self().GetProperty<Vector3>(Actor::Property::POSITION);
+  Quaternion selfOrientation = Self().GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+  Vector3    selfScale       = Self().GetProperty<Vector3>(Actor::Property::SCALE);
+
+  Vector3    cameraPosition    = camera.GetProperty<Vector3>(Actor::Property::POSITION);
+  Quaternion cameraOrientation = camera.GetProperty<Quaternion>(Actor::Property::ORIENTATION);
+  Vector3    cameraScale       = camera.GetProperty<Vector3>(Actor::Property::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.
+  if(!Dali::Equals(Y_DIRECTION.Dot(Vector3::YAXIS), 1.0f))
+  {
+    // Reflect by XZ plane
+    cameraPosition.y = -cameraPosition.y;
+    Quaternion yDirectionQuaternion;
+    yDirectionQuaternion.mVector = Vector3::YAXIS;
+    // Reflect orientation
+    cameraOrientation = yDirectionQuaternion * cameraOrientation * yDirectionQuaternion;
+  }
+
+  Vector3    resultPosition;
+  Quaternion resultOrientation;
+  Vector3    resultScale;
+
+  Matrix selfMatrix(false);
+  Matrix cameraMatrix(false);
+  Matrix resultMatrix(false);
+  selfMatrix.SetTransformComponents(selfScale, selfOrientation, selfPosition);
+  cameraMatrix.SetTransformComponents(cameraScale, cameraOrientation, cameraPosition);
+  Matrix::Multiply(resultMatrix, cameraMatrix, selfMatrix);
+  resultMatrix.GetTransformComponents(resultPosition, resultOrientation, resultScale);
+
+  camera.SetProperty(Actor::Property::POSITION, resultPosition);
+  camera.SetProperty(Actor::Property::ORIENTATION, resultOrientation);
+  camera.SetProperty(Actor::Property::SCALE, resultScale);
+}
+
 void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
 {
   if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
@@ -622,6 +699,8 @@ void Model::OnModelLoadComplete()
   auto* resources = &(mModelLoadTask->mResources);
   auto* scene     = &(mModelLoadTask->mScene);
   CreateAnimations(*scene);
+  ResetCameraParameters();
+
   if(!resources->mEnvironmentMaps.empty())
   {
     mDefaultDiffuseTexture  = resources->mEnvironmentMaps.front().second.mDiffuse;
@@ -745,10 +824,10 @@ void Model::CreateModel()
 
 void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene)
 {
+  mAnimations.clear();
   if(!mModelLoadTask->mAnimations.empty())
   {
-    auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property)
-    {
+    auto getActor = [&](const Scene3D::Loader::AnimatedProperty& property) {
       if(property.mNodeIndex == Scene3D::Loader::INVALID_INDEX)
       {
         return mModelRoot.FindChildByName(property.mNodeName);
@@ -761,7 +840,6 @@ void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene)
       return mModelRoot.FindChildById(node->mNodeId);
     };
 
-    mAnimations.clear();
     for(auto&& animation : mModelLoadTask->mAnimations)
     {
       Dali::Animation anim = animation.ReAnimate(getActor);
@@ -770,6 +848,16 @@ void Model::CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene)
   }
 }
 
+void Model::ResetCameraParameters()
+{
+  mCameraParameters.clear();
+  if(!mModelLoadTask->mCameraParameters.empty())
+  {
+    // Copy camera parameters.
+    std::copy(mModelLoadTask->mCameraParameters.begin(), mModelLoadTask->mCameraParameters.end(), std::back_inserter(mCameraParameters));
+  }
+}
+
 } // namespace Internal
 } // namespace Scene3D
 } // namespace Dali
index 36e3a9a..fea5d60 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_SCENE3D_INTERNAL_MODEL_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -20,6 +20,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali/public-api/actors/camera-actor.h>
 #include <dali/public-api/actors/layer.h>
 #include <dali/public-api/animation/animation.h>
 #include <dali/public-api/object/weak-handle.h>
@@ -47,6 +48,7 @@ class Model : public Dali::Toolkit::Internal::Control, public ImageBasedLightObs
 {
 public:
   using AnimationData = std::pair<std::string, Dali::Animation>;
+  using CameraData    = Loader::CameraParameters;
 
   /**
    * @brief Creates a new Model.
@@ -115,6 +117,21 @@ public:
    */
   Dali::Animation GetAnimation(const std::string& name) const;
 
+  /**
+   * @copydoc Model::GetCameraCount()
+   */
+  uint32_t GetCameraCount() const;
+
+  /**
+   * @copydoc Model::GenerateCamera()
+   */
+  Dali::CameraActor GenerateCamera(uint32_t index) const;
+
+  /**
+   * @copydoc Model::ApplyCamera()
+   */
+  bool ApplyCamera(uint32_t index, Dali::CameraActor camera) const;
+
 protected:
   /**
    * @brief Constructs a new Model.
@@ -167,6 +184,7 @@ private:
    */
   bool IsResourceReady() const override;
 
+private:
   /**
    * @brief Scales the model to fit the control or to return to original size.
    */
@@ -192,6 +210,15 @@ private:
    */
   void UpdateImageBasedLightScaleFactor();
 
+  /**
+   * @brief Apply self transform into inputed camera.
+   * Inputed camera must be configured by CameraParameter. Mean, inputed camera coordinate depend on Model.
+   * After this API finished, CameraActor coordinate system converted as DALi coordinate system.
+   *
+   * @param[in,out] camera CameraActor who need to apply model itself's transform
+   */
+  void ApplyCameraTransform(Dali::CameraActor camera) const;
+
 public: // Overrides ImageBasedLightObserver Methods.
   /**
    * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightTexture()
@@ -254,11 +281,17 @@ private:
    */
   void CreateAnimations(Dali::Scene3D::Loader::SceneDefinition& scene);
 
+  /**
+   * @brief Reset CameraData from loaded CameraParameters.
+   */
+  void ResetCameraParameters();
+
 private:
   std::string                    mModelUrl;
   std::string                    mResourceDirectoryUrl;
   Dali::Actor                    mModelRoot;
   std::vector<AnimationData>     mAnimations;
+  std::vector<CameraData>        mCameraParameters;
   std::vector<WeakHandle<Actor>> mRenderableActors;
   WeakHandle<Scene3D::SceneView> mParentSceneView;
 
index 2a1392a..6576803 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_SCENE3D_LOADER_GLTF2_ASSET_H_
 #define DALI_SCENE3D_LOADER_GLTF2_ASSET_H_
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
  */
 
 // INTERNAL INCLUDES
-#include "dali-scene3d/internal/loader/json-reader.h"
-#include "dali-scene3d/public-api/loader/index.h"
+#include <dali-scene3d/internal/loader/json-reader.h>
+#include <dali-scene3d/public-api/loader/index.h>
 
 // EXTERNAL INCLUDES
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/vector4.h>
 #include <cstdint>
 #include <memory>
-#include "dali/devel-api/common/map-wrapper.h"
-#include "dali/public-api/common/vector-wrapper.h"
-#include "dali/public-api/math/quaternion.h"
-#include "dali/public-api/math/vector4.h"
 
 #define ENUM_STRING_MAPPING(t, x) \
   {                               \
@@ -50,7 +50,8 @@
 
 namespace gltf2
 {
-using Index = Dali::Scene3D::Loader::Index;
+using Index                           = Dali::Scene3D::Loader::Index;
+constexpr float UNDEFINED_FLOAT_VALUE = -1.0f; ///< Special marker for some non-negative only float values.
 
 template<typename T>
 class Ref
@@ -350,7 +351,7 @@ struct TextureInfo
  */
 struct MaterialIor
 {
-  float mIor = MAXFLOAT;
+  float mIor = UNDEFINED_FLOAT_VALUE;
 };
 
 /**
@@ -446,20 +447,20 @@ struct Camera : Named
 {
   struct Perspective
   {
-    float mAspectRatio;
-    float mYFov;
-    float mZFar;
-    float mZNear;
+    float mAspectRatio = UNDEFINED_FLOAT_VALUE;
+    float mYFov        = UNDEFINED_FLOAT_VALUE;
+    float mZFar        = UNDEFINED_FLOAT_VALUE;
+    float mZNear       = UNDEFINED_FLOAT_VALUE;
     //TODO: extras
     //TODO: extensions
   };
 
   struct Orthographic
   {
-    float mXMag;
-    float mYMag;
-    float mZFar;
-    float mZNear;
+    float mXMag  = UNDEFINED_FLOAT_VALUE;
+    float mYMag  = UNDEFINED_FLOAT_VALUE;
+    float mZFar  = UNDEFINED_FLOAT_VALUE;
+    float mZNear = UNDEFINED_FLOAT_VALUE;
     //TODO: extras
     //TODO: extensions
   };
index c0369ab..fa792f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -122,6 +122,21 @@ Dali::Animation Model::GetAnimation(const std::string& name) const
   return GetImpl(*this).GetAnimation(name);
 }
 
+uint32_t Model::GetCameraCount() const
+{
+  return GetImpl(*this).GetCameraCount();
+}
+
+Dali::CameraActor Model::GenerateCamera(uint32_t index) const
+{
+  return GetImpl(*this).GenerateCamera(index);
+}
+
+bool Model::ApplyCamera(uint32_t index, Dali::CameraActor camera) const
+{
+  return GetImpl(*this).ApplyCamera(index, camera);
+}
+
 } // namespace Scene3D
 
 } // namespace Dali
index 45ceca1..ce723ea 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_SCENE3D_MODEL_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -23,6 +23,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control.h>
+#include <dali/public-api/actors/camera-actor.h>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/rendering/texture.h>
 
@@ -270,6 +271,43 @@ public:
    */
   Dali::Animation GetAnimation(const std::string& name) const;
 
+  /**
+   * @brief Gets number of camera parameters those loaded from model file.
+   *
+   * @SINCE_2_2.15
+   * @return The number of loaded camera parameters.
+   * @note This method should be called after Model load finished.
+   */
+  uint32_t GetCameraCount() const;
+
+  /**
+   * @brief Generate camera actor using camera parameters at the index.
+   * If camera parameter is valid, create new CameraActor.
+   * Camera parameter decide at initialized time and
+   * didn't apply model node's current position (like Animation).
+   *
+   * @SINCE_2_2.15
+   * @param[in] index Index of camera to be used for generation camera.
+   * @return Generated CameraActor by the index, or empty Handle if generation failed.
+   * @note This method should be called after Model load finished.
+   */
+  Dali::CameraActor GenerateCamera(uint32_t index) const;
+
+  /**
+   * @brief Apply camera parameters at the index to inputed camera actor.
+   * If camera parameter is valid and camera actor is not empty, apply parameters.
+   * It will change camera's transform and near / far / fov or orthographic size / aspect ratio (if defined)
+   * Camera parameter decide at initialized time and
+   * didn't apply model node's current position (like Animation).
+   *
+   * @SINCE_2_2.15
+   * @param[in] index Index of camera to be used for generation camera.
+   * @param[in,out] camera Index of camera to be used for generation camera.
+   * @return True if apply successed. False otherwise.
+   * @note This method should be called after Model load finished.
+   */
+  bool ApplyCamera(uint32_t index, Dali::CameraActor camera) const;
+
 public: // Not intended for application developers
   /// @cond internal
   /**
index 270f84b..cc9a351 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
  * limitations under the License.
  *
  */
-#include "dali-scene3d/public-api/loader/camera-parameters.h"
-#include "dali-scene3d/public-api/loader/utils.h"
-#include "dali/devel-api/actors/camera-actor-devel.h"
-#include "dali/integration-api/debug.h"
-#include "dali/public-api/actors/camera-actor.h"
-#include "dali/public-api/math/quaternion.h"
+
+// CLASS HEADER
+#include <dali-scene3d/public-api/loader/camera-parameters.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/actors/camera-actor-devel.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/camera-actor.h>
+#include <dali/public-api/math/quaternion.h>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/loader/gltf2-asset.h> // for gltf2::UNDEFINED_FLOAT_VALUE
+#include <dali-scene3d/public-api/loader/utils.h>
 
 namespace Dali
 {
@@ -143,11 +150,12 @@ void Orthographic(Matrix& result, float left, float right, float bottom, float t
 ViewProjection CameraParameters::GetViewProjection() const
 {
   ViewProjection viewProjection;
+
   // The projection matrix.
   if(isPerspective)
   {
     Perspective(viewProjection.GetProjection(),
-                Radian(Degree(yFov)),
+                Radian(yFovDegree),
                 1.f,
                 zNear,
                 zFar,
@@ -191,36 +199,75 @@ void CameraParameters::CalculateTransformComponents(Vector3& position, Quaternio
   orientation *= viewQuaternion;
 }
 
-void CameraParameters::ConfigureCamera(CameraActor& camera) const
+bool CameraParameters::ConfigureCamera(CameraActor& camera, bool invertY) const
 {
-  SetActorCentered(camera);
-
   if(isPerspective)
   {
+    if(Dali::Equals(zNear, gltf2::UNDEFINED_FLOAT_VALUE) ||
+       Dali::Equals(yFovDegree.degree, gltf2::UNDEFINED_FLOAT_VALUE))
+    {
+      return false;
+    }
+
     camera.SetProjectionMode(Camera::PERSPECTIVE_PROJECTION);
     camera.SetNearClippingPlane(zNear);
-    camera.SetFarClippingPlane(zFar);
-    camera.SetFieldOfView(Radian(Degree(yFov)));
+    camera.SetFieldOfView(Radian(yFovDegree));
+
+    if(!Dali::Equals(zFar, gltf2::UNDEFINED_FLOAT_VALUE))
+    {
+      camera.SetFarClippingPlane(zFar);
+    }
+    else
+    {
+      // TODO : Infinite perspective projection didn't support yet. Just set big enough value now
+      camera.SetFarClippingPlane(1000.0f);
+    }
+
+    if(!Dali::Equals(aspectRatio, gltf2::UNDEFINED_FLOAT_VALUE))
+    {
+      // TODO: By gltf 2.0 spec, we should not 'crop' and 'non-uniform scaling' by viewport.
+      // If we skip to setup this value, 'non-uniform scaling' problem fixed.
+      // But we need to resolve 'crop' case in future.
+      //camera.SetAspectRatio(aspectRatio);
+    }
   }
   else
   {
+    if(Dali::Equals(zNear, gltf2::UNDEFINED_FLOAT_VALUE) ||
+       Dali::Equals(zFar, gltf2::UNDEFINED_FLOAT_VALUE) ||
+       Dali::Equals(orthographicSize, gltf2::UNDEFINED_FLOAT_VALUE))
+    {
+      return false;
+    }
+
     camera.SetProjectionMode(Camera::ORTHOGRAPHIC_PROJECTION);
     camera.SetNearClippingPlane(zNear);
     camera.SetFarClippingPlane(zFar);
-    camera.SetAspectRatio(aspectRatio);
     camera.SetProperty(Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE, orthographicSize);
+
+    if(!Dali::Equals(aspectRatio, gltf2::UNDEFINED_FLOAT_VALUE))
+    {
+      // TODO: By gltf 2.0 spec, we should not 'crop' and 'non-uniform scaling' by viewport.
+      // If we skip to setup this value, 'non-uniform scaling' problem fixed.
+      // But we need to resolve 'crop' case in future.
+      //camera.SetAspectRatio(aspectRatio);
+    }
   }
 
+  SetActorCentered(camera);
+
   // model
   Vector3    camTranslation;
   Vector3    camScale;
   Quaternion camOrientation;
   CalculateTransformComponents(camTranslation, camOrientation, camScale);
 
-  camera.SetInvertYAxis(true);
+  camera.SetInvertYAxis(invertY);
   camera.SetProperty(Actor::Property::POSITION, camTranslation);
   camera.SetProperty(Actor::Property::ORIENTATION, camOrientation);
   camera.SetProperty(Actor::Property::SCALE, camScale);
+
+  return true;
 }
 
 } // namespace Loader
index 70060e5..9fde071 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_SCENE3D_LOADER_CAMERA_PARAMETERS_H
 #define DALI_SCENE3D_LOADER_CAMERA_PARAMETERS_H
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
  */
 
 // INTERNAL INCLUDES
-#include "dali-scene3d/public-api/api.h"
-#include "dali-scene3d/public-api/loader/view-projection.h"
+#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/loader/view-projection.h>
 
 // EXTERNAL INCLUDES
-#include "dali/public-api/math/matrix.h"
-#include "dali/public-api/math/vector3.h"
+#include <dali/public-api/math/degree.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector3.h>
 
 namespace Dali
 {
@@ -35,10 +36,11 @@ namespace Loader
 {
 struct DALI_SCENE3D_API CameraParameters
 {
+  // TODO : Is these default value has is meaning?
   Matrix matrix           = Matrix::IDENTITY;
   float  orthographicSize = 1.f;
   float  aspectRatio      = 1.f;
-  float  yFov             = 60.f;
+  Degree yFovDegree       = Degree(60.f);
   float  zNear            = 0.1f;
   float  zFar             = 1000.f;
   bool   isPerspective    = true;
@@ -58,8 +60,10 @@ struct DALI_SCENE3D_API CameraParameters
    * @brief Configures the camera in the way that it is supposed to be used with
    *        scene3d scenes. This means inverted Y and a rotation of 180 degrees
    *        along the Y axis, plus whatever the parameters define.
+   *
+   * @return True if success to generate camera. False otherwise.
    */
-  void ConfigureCamera(CameraActor& camera) const;
+  bool ConfigureCamera(CameraActor& camera, bool invertY = true) const;
 };
 
 } // namespace Loader
index 8953f1a..1a087c9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -57,12 +57,12 @@ namespace rs = RendererState;
 
 namespace
 {
-const char* NODES         = "nodes";
-const char* SCENES        = "scenes";
-const char* NODE          = "node";
-const char* URI           = "uri";
-const char* URL           = "url";
-const char* HINTS         = "hints";
+const char* NODES  = "nodes";
+const char* SCENES = "scenes";
+const char* NODE   = "node";
+const char* URI    = "uri";
+const char* URL    = "url";
+const char* HINTS  = "hints";
 const char* NAME("name");
 const char* BLEND_SHAPE_HEADER("blendShapeHeader");
 const char* BLEND_SHAPES("blendShapes");
@@ -1729,7 +1729,7 @@ void DliLoader::Impl::GetCameraParameters(std::vector<CameraParameters>& cameras
       {
         auto& jsonCamera = (*i0).second;
 
-        ReadFloat(jsonCamera.GetChild("fov"), iCamera->yFov);
+        ReadFloat(jsonCamera.GetChild("fov"), iCamera->yFovDegree.degree);
         ReadFloat(jsonCamera.GetChild("near"), iCamera->zNear);
         ReadFloat(jsonCamera.GetChild("far"), iCamera->zFar);
         if(ReadVector(jsonCamera.GetChild("orthographic"), dummyFloatArray, 4u))
index 9068b7f..05bd72c 100644 (file)
@@ -47,13 +47,13 @@ namespace
 Dali::Mutex gInitializeMutex;
 Dali::Mutex gReadMutex;
 
-const char* POSITION_PROPERTY("position");
-const char* ORIENTATION_PROPERTY("orientation");
-const char* SCALE_PROPERTY("scale");
-const char* BLEND_SHAPE_WEIGHTS_UNIFORM("uBlendShapeWeight");
-const char* MRENDERER_MODEL_IDENTIFICATION("M-Renderer");
-const char* ROOT_NODE_NAME("RootNode");
-const Vector3     SCALE_TO_ADJUST(100.0f, 100.0f, 100.0f);
+const char*   POSITION_PROPERTY("position");
+const char*   ORIENTATION_PROPERTY("orientation");
+const char*   SCALE_PROPERTY("scale");
+const char*   BLEND_SHAPE_WEIGHTS_UNIFORM("uBlendShapeWeight");
+const char*   MRENDERER_MODEL_IDENTIFICATION("M-Renderer");
+const char*   ROOT_NODE_NAME("RootNode");
+const Vector3 SCALE_TO_ADJUST(100.0f, 100.0f, 100.0f);
 
 const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{
   Geometry::POINTS,
@@ -263,7 +263,7 @@ const auto CAMERA_PERSPECTIVE_READER = std::move(js::Reader<gt::Camera::Perspect
 
 const auto CAMERA_ORTHOGRAPHIC_READER = std::move(js::Reader<gt::Camera::Orthographic>()
                                                     .Register(*js::MakeProperty("xmag", js::Read::Number<float>, &gt::Camera::Orthographic::mXMag))
-                                                    .Register(*js::MakeProperty("ymag", js::Read::Number<float>, &gt::Camera::Orthographic::mXMag))
+                                                    .Register(*js::MakeProperty("ymag", js::Read::Number<float>, &gt::Camera::Orthographic::mYMag))
                                                     .Register(*js::MakeProperty("zfar", js::Read::Number<float>, &gt::Camera::Orthographic::mZFar))
                                                     .Register(*js::MakeProperty("znear", js::Read::Number<float>, &gt::Camera::Orthographic::mZNear)));
 
@@ -578,7 +578,7 @@ void ConvertMaterial(const gt::Material& material, const std::unordered_map<std:
     matDef.mEmissiveFactor = material.mEmissiveFactor;
   }
 
-  if(material.mMaterialExtensions.mMaterialIor.mIor < MAXFLOAT)
+  if(!Dali::Equals(material.mMaterialExtensions.mMaterialIor.mIor, gltf2::UNDEFINED_FLOAT_VALUE))
   {
     float ior                  = material.mMaterialExtensions.mMaterialIor.mIor;
     matDef.mDielectricSpecular = powf((ior - 1.0f) / (ior + 1.0f), 2.0f);
@@ -812,18 +812,33 @@ void ConvertCamera(const gt::Camera& camera, CameraParameters& camParams)
   if(camParams.isPerspective)
   {
     auto& perspective = camera.mPerspective;
-    camParams.yFov    = Degree(Radian(perspective.mYFov)).degree;
-    camParams.zNear   = perspective.mZNear;
-    camParams.zFar    = perspective.mZFar;
+    if(!Dali::Equals(perspective.mYFov, gltf2::UNDEFINED_FLOAT_VALUE))
+    {
+      camParams.yFovDegree = Degree(Radian(perspective.mYFov));
+    }
+    else
+    {
+      camParams.yFovDegree = Degree(gltf2::UNDEFINED_FLOAT_VALUE);
+    }
+    camParams.zNear = perspective.mZNear;
+    camParams.zFar  = perspective.mZFar;
     // TODO: yes, we seem to ignore aspectRatio in CameraParameters.
   }
   else
   {
-    auto& ortho                = camera.mOrthographic;
-    camParams.orthographicSize = ortho.mYMag * .5f;
-    camParams.aspectRatio      = ortho.mXMag / ortho.mYMag;
-    camParams.zNear            = ortho.mZNear;
-    camParams.zFar             = ortho.mZFar;
+    auto& ortho = camera.mOrthographic;
+    if(!Dali::Equals(ortho.mYMag, gltf2::UNDEFINED_FLOAT_VALUE) && !Dali::Equals(ortho.mXMag, gltf2::UNDEFINED_FLOAT_VALUE))
+    {
+      camParams.orthographicSize = ortho.mYMag * .5f;
+      camParams.aspectRatio      = ortho.mXMag / ortho.mYMag;
+    }
+    else
+    {
+      camParams.orthographicSize = gltf2::UNDEFINED_FLOAT_VALUE;
+      camParams.aspectRatio      = gltf2::UNDEFINED_FLOAT_VALUE;
+    }
+    camParams.zNear = ortho.mZNear;
+    camParams.zFar  = ortho.mZFar;
   }
 }
 
index 7b52284..3b6a6fc 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 14;
+const unsigned int TOOLKIT_MICRO_VERSION = 15;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 38e80df..f6ebe63 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.2.14
+Version:    2.2.15
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT