Let we allow to load bvh and facial animation from raw buffer stream.
Change-Id: I679539ce10e631101571dab95615404c41b9b2f3
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
/*
- * 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.
*
*/
-#include <dali-test-suite-utils.h>
#include <dali-scene3d/public-api/loader/bvh-loader.h>
+#include <dali-test-suite-utils.h>
+
+#include <fstream>
using namespace Dali;
using namespace Dali::Scene3D::Loader;
-int UtcDaliLoadBvh(void)
+namespace
{
- TestApplication application;
-
- AnimationDefinition animDef = LoadBvh(TEST_RESOURCE_DIR "/test.bvh", "testBvh");
-
- DALI_TEST_EQUAL(animDef.GetName(), "testBvh");
- DALI_TEST_EQUAL(animDef.GetDuration(), 0.3f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mNodeName, "root");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mPropertyName, "position");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mKeyFrames.GetType(), Property::Type::VECTOR3);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.durationSeconds, 0.3f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mNodeName, "root");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mPropertyName, "orientation");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mKeyFrames.GetType(), Property::Type::ROTATION);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mTimePeriod.durationSeconds, 0.3f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mNodeName, "first");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mPropertyName, "position");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mKeyFrames.GetType(), Property::Type::VECTOR3);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mTimePeriod.durationSeconds, 0.3f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mNodeName, "first");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mPropertyName, "orientation");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mKeyFrames.GetType(), Property::Type::ROTATION);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mTimePeriod.durationSeconds, 0.3f);
-
- Actor root = Actor::New();
- root.SetProperty(Actor::Property::NAME, "root");
-
- Actor first = Actor::New();
- first.SetProperty(Actor::Property::NAME, "first");
- root.Add(first);
-
- auto getActor = [&root](const Dali::Scene3D::Loader::AnimatedProperty& property) {
- return root.FindChildByName(property.mNodeName);
- };
-
- Animation animation = animDef.ReAnimate(getActor);
- DALI_TEST_EQUAL(animation.GetDuration(), animDef.GetDuration());
-
- application.GetScene().Add(root);
+std::string ReadBufferFromFile(const std::string& url)
+{
+ std::string rawString;
+ std::fstream fileStream;
- application.SendNotification();
- application.Render(20);
+ fileStream.open(url, std::ios::in | std::ios::binary);
+ if(!fileStream.is_open())
+ {
+ DALI_LOG_WARNING("stream open failed for: \"%s\", in mode: \"%d\".\n", url.c_str(), static_cast<int>(std::ios::in | std::ios::binary));
+ }
- DALI_TEST_EQUALS(Vector2(0, 0), root.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
- DALI_TEST_EQUALS(Vector2(0, 0), first.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
- Vector3 rootWorldPositionBefore = root.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
- Vector3 firstWorldPositionBefore = first.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ // get length of file:
+ fileStream.seekg(0, std::ios::end);
+ auto length = fileStream.tellg();
+ fileStream.seekg(0, std::ios::beg);
- animation.Play();
+ rawString.resize(length);
+ fileStream.read(rawString.data(), length);
- application.SendNotification();
- application.Render(1000);
+ fileStream.close();
- DALI_TEST_EQUALS(Vector2(0, 10), root.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
- DALI_TEST_EQUALS(Vector2(10, 0), first.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
+ return rawString;
+}
+} // namespace
- Vector3 rootWorldPositionAfter = root.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
- Vector3 firstWorldPositionAfter = first.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+int UtcDaliLoadBvh(void)
+{
+ TestApplication application;
- DALI_TEST_EQUALS(Vector3(0, 10, 0), rootWorldPositionAfter - rootWorldPositionBefore, TEST_LOCATION);
- DALI_TEST_EQUALS(Vector3(10, 10, 0), firstWorldPositionAfter - firstWorldPositionBefore, TEST_LOCATION);
+ for(uint32_t tc = 0; tc < 2; ++tc)
+ {
+ AnimationDefinition animDef;
+ tet_printf("UtcDaliLoadBvh testcase %u\n", tc);
+ switch(tc)
+ {
+ case 0: // Load bvh from url
+ {
+ animDef = LoadBvh(TEST_RESOURCE_DIR "/test.bvh", "testBvh");
+ break;
+ }
+ case 1: // Load bvh from buffer stream.
+ {
+ std::string rawString = ReadBufferFromFile(TEST_RESOURCE_DIR "/test.bvh");
+ animDef = LoadBvhFromBuffer(reinterpret_cast<uint8_t*>(rawString.data()), static_cast<int>(rawString.length()), "testBvh");
+ break;
+ }
+ }
+
+ DALI_TEST_EQUAL(animDef.GetName(), "testBvh");
+ DALI_TEST_EQUAL(animDef.GetDuration(), 0.3f);
+
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mNodeName, "root");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mPropertyName, "position");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mKeyFrames.GetType(), Property::Type::VECTOR3);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.durationSeconds, 0.3f);
+
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mNodeName, "root");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mPropertyName, "orientation");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mKeyFrames.GetType(), Property::Type::ROTATION);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(1).mTimePeriod.durationSeconds, 0.3f);
+
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mNodeName, "first");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mPropertyName, "position");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mKeyFrames.GetType(), Property::Type::VECTOR3);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(2).mTimePeriod.durationSeconds, 0.3f);
+
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mNodeName, "first");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mPropertyName, "orientation");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mKeyFrames.GetType(), Property::Type::ROTATION);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(3).mTimePeriod.durationSeconds, 0.3f);
+
+ Actor root = Actor::New();
+ root.SetProperty(Actor::Property::NAME, "root");
+
+ Actor first = Actor::New();
+ first.SetProperty(Actor::Property::NAME, "first");
+ root.Add(first);
+
+ auto getActor = [&root](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+ return root.FindChildByName(property.mNodeName);
+ };
+
+ Animation animation = animDef.ReAnimate(getActor);
+ DALI_TEST_EQUAL(animation.GetDuration(), animDef.GetDuration());
+
+ application.GetScene().Add(root);
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS(Vector2(0, 0), root.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2(0, 0), first.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
+ Vector3 rootWorldPositionBefore = root.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ Vector3 firstWorldPositionBefore = first.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+
+ animation.Play();
+
+ application.SendNotification();
+ application.Render(1000);
+
+ DALI_TEST_EQUALS(Vector2(0, 10), root.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2(10, 0), first.GetProperty<Vector2>(Actor::Property::POSITION), TEST_LOCATION);
+
+ Vector3 rootWorldPositionAfter = root.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ Vector3 firstWorldPositionAfter = first.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
+
+ DALI_TEST_EQUALS(Vector3(0, 10, 0), rootWorldPositionAfter - rootWorldPositionBefore, TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector3(10, 10, 0), firstWorldPositionAfter - firstWorldPositionBefore, TEST_LOCATION);
+ }
END_TEST;
}
-
-
-int UtcDaliLoadBvhFailed(void)
+int UtcDaliLoadBvhFailed01(void)
{
TestApplication application;
DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION);
END_TEST;
}
+
+int UtcDaliLoadBvhFailed02(void)
+{
+ TestApplication application;
+
+ AnimationDefinition animDef = LoadBvhFromBuffer(nullptr, 0, "testBvh");
+ DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION);
+ END_TEST;
+}
\ No newline at end of file
/*
- * 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.
*
*/
-#include <dali-test-suite-utils.h>
#include <dali-scene3d/public-api/loader/animation-definition.h>
#include <dali-scene3d/public-api/loader/facial-animation-loader.h>
+#include <dali-test-suite-utils.h>
+
+#include <fstream>
using namespace Dali;
using namespace Dali::Scene3D::Loader;
+namespace
+{
+std::string ReadBufferFromFile(const std::string& url)
+{
+ std::string rawString;
+ std::fstream fileStream;
+
+ fileStream.open(url, std::ios::in | std::ios::binary);
+ if(!fileStream.is_open())
+ {
+ DALI_LOG_WARNING("stream open failed for: \"%s\", in mode: \"%d\".\n", url.c_str(), static_cast<int>(std::ios::in | std::ios::binary));
+ }
+
+ // get length of file:
+ fileStream.seekg(0, std::ios::end);
+ auto length = fileStream.tellg();
+ fileStream.seekg(0, std::ios::beg);
+
+ rawString.resize(length);
+ fileStream.read(rawString.data(), length);
+
+ fileStream.close();
+
+ return rawString;
+}
+} // namespace
+
int UtcDaliLoadFacialAnimation(void)
{
TestApplication app;
- AnimationDefinition animDef = LoadFacialAnimation(TEST_RESOURCE_DIR "/facial-blendshape-animation.json");
-
- std::string name = animDef.GetName();
- DALI_TEST_EQUAL(name, "Facial_Blendshape_Animation");
- DALI_TEST_EQUAL(animDef.GetDuration(), 14.966001f);
- DALI_TEST_EQUAL(animDef.GetEndAction(), Animation::BAKE);
- DALI_TEST_EQUAL(animDef.GetSpeedFactor(), 1.0f);
- DALI_TEST_EQUAL(animDef.GetLoopCount(), 1);
- DALI_TEST_EQUAL(animDef.GetPropertyCount(), 122);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mNodeName, "GEO_1");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mPropertyName, "uBlendShapeWeight[0]");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.durationSeconds, 14.966001f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mNodeName, "GEO_2");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mPropertyName, "uBlendShapeWeight[1]");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mTimePeriod.durationSeconds, 14.966001f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mNodeName, "GEO_3");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mPropertyName, "uBlendShapeWeight[2]");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mTimePeriod.durationSeconds, 14.966001f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mNodeName, "GEO_4");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mPropertyName, "uBlendShapeWeight[7]");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mTimePeriod.durationSeconds, 14.966001f);
-
- DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mNodeName, "GEO_5");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mPropertyName, "uBlendShapeWeight[19]");
- DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mKeyFrames.GetType(), Property::Type::FLOAT);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mTimePeriod.delaySeconds, 0.0f);
- DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mTimePeriod.durationSeconds, 14.966001f);
-
- auto actor = Actor::New();
- actor.SetProperty(Actor::Property::NAME, "GEO_1");
-
- char weightNameBuffer[32];
- char* const pWeightName = weightNameBuffer + snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s", "uBlendShapeWeight");
- for(int i = 0; i < 122; i++)
+ for(uint32_t tc = 0; tc < 2; ++tc)
{
- snprintf(pWeightName, sizeof(weightNameBuffer) - (pWeightName - weightNameBuffer), "[%d]", i);
- std::string weightName{weightNameBuffer};
- actor.RegisterProperty(weightName, 0.0f);
- }
+ tet_printf("UtcDaliLoadFacialAnimation testcase %u\n", tc);
+ AnimationDefinition animDef;
+ switch(tc)
+ {
+ case 0: // Load bvh from url
+ {
+ animDef = LoadFacialAnimation(TEST_RESOURCE_DIR "/facial-blendshape-animation.json");
+ break;
+ }
+ case 1: // Load bvh from buffer stream.
+ {
+ std::string rawString = ReadBufferFromFile(TEST_RESOURCE_DIR "/facial-blendshape-animation.json");
+ animDef = LoadFacialAnimationFromBuffer(reinterpret_cast<uint8_t*>(rawString.data()), static_cast<int>(rawString.length()));
+ break;
+ }
+ }
+
+ std::string name = animDef.GetName();
+ DALI_TEST_EQUAL(name, "Facial_Blendshape_Animation");
+ DALI_TEST_EQUAL(animDef.GetDuration(), 14.966001f);
+ DALI_TEST_EQUAL(animDef.GetEndAction(), Animation::BAKE);
+ DALI_TEST_EQUAL(animDef.GetSpeedFactor(), 1.0f);
+ DALI_TEST_EQUAL(animDef.GetLoopCount(), 1);
+ DALI_TEST_EQUAL(animDef.GetPropertyCount(), 122);
+
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mNodeName, "GEO_1");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mPropertyName, "uBlendShapeWeight[0]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(0).mTimePeriod.durationSeconds, 14.966001f);
+
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mNodeName, "GEO_2");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mPropertyName, "uBlendShapeWeight[1]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(69).mTimePeriod.durationSeconds, 14.966001f);
- auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
- return actor.FindChildByName(property.mNodeName);
- };
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mNodeName, "GEO_3");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mPropertyName, "uBlendShapeWeight[2]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(86).mTimePeriod.durationSeconds, 14.966001f);
- auto anim = animDef.ReAnimate(getActor);
- DALI_TEST_EQUAL(anim.GetDuration(), animDef.GetDuration());
- DALI_TEST_EQUAL(anim.GetEndAction(), animDef.GetEndAction());
- DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.GetSpeedFactor());
- DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.GetLoopCount());
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mNodeName, "GEO_4");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mPropertyName, "uBlendShapeWeight[7]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(100).mTimePeriod.durationSeconds, 14.966001f);
+
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mNodeName, "GEO_5");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mPropertyName, "uBlendShapeWeight[19]");
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mKeyFrames.GetType(), Property::Type::FLOAT);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mTimePeriod.delaySeconds, 0.0f);
+ DALI_TEST_EQUAL(animDef.GetPropertyAt(121).mTimePeriod.durationSeconds, 14.966001f);
+
+ auto actor = Actor::New();
+ actor.SetProperty(Actor::Property::NAME, "GEO_1");
+
+ char weightNameBuffer[32];
+ char* const pWeightName = weightNameBuffer + snprintf(weightNameBuffer, sizeof(weightNameBuffer), "%s", "uBlendShapeWeight");
+ for(int i = 0; i < 122; i++)
+ {
+ snprintf(pWeightName, sizeof(weightNameBuffer) - (pWeightName - weightNameBuffer), "[%d]", i);
+ std::string weightName{weightNameBuffer};
+ actor.RegisterProperty(weightName, 0.0f);
+ }
+
+ auto getActor = [&actor](const Dali::Scene3D::Loader::AnimatedProperty& property) {
+ return actor.FindChildByName(property.mNodeName);
+ };
+
+ auto anim = animDef.ReAnimate(getActor);
+ DALI_TEST_EQUAL(anim.GetDuration(), animDef.GetDuration());
+ DALI_TEST_EQUAL(anim.GetEndAction(), animDef.GetEndAction());
+ DALI_TEST_EQUAL(anim.GetSpeedFactor(), animDef.GetSpeedFactor());
+ DALI_TEST_EQUAL(anim.GetLoopCount(), animDef.GetLoopCount());
+ }
END_TEST;
}
#include <dali-scene3d/public-api/loader/bvh-loader.h>
// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/file-stream.h>
+#include <dali/integration-api/debug.h>
+
#include <fstream>
#include <iostream>
#include <memory>
s.end());
}
-void ParseHierarchy(std::ifstream& file, std::shared_ptr<Joint>& joint)
+void ParseHierarchy(std::istream& file, std::shared_ptr<Joint>& joint)
{
std::string line;
while(std::getline(file, line))
}
}
-void ParseMotion(std::ifstream& file, std::shared_ptr<Joint>& hierarchy, uint32_t& frameCount, float& frameTime)
+void ParseMotion(std::istream& file, std::shared_ptr<Joint>& hierarchy, uint32_t& frameCount, float& frameTime)
{
std::vector<std::shared_ptr<Joint>> jointList;
MakeList(hierarchy, jointList);
}
}
- while(getline(file, line))
+ while(std::getline(file, line))
{
trim(line);
std::istringstream stream(line);
}
}
-bool ParseBvh(const std::string& path, uint32_t& frameCount, float& frameTime, std::shared_ptr<Joint>& rootJoint)
+bool ParseBvh(std::istream& file, uint32_t& frameCount, float& frameTime, std::shared_ptr<Joint>& rootJoint)
{
- std::ifstream file(path.data());
- if(!file.is_open())
- {
- return false;
- }
-
std::string line;
- while(getline(file, line))
+ while(std::getline(file, line))
{
trim(line);
std::istringstream stream(line);
if(token == TOKEN_HIERARCHY.data())
{
std::string line;
- while(getline(file, line))
+ while(std::getline(file, line))
{
trim(line);
std::istringstream stream(line);
animationDefinition.SetName(animationName);
animationDefinition.SetDuration(frameTime * (frameCount - 1));
- float keyFrameInterval = (frameCount > 1u) ? 1.0f / static_cast<float>(frameCount - 1u) : Dali::Math::MACHINE_EPSILON_10;
+ float keyFrameInterval = (frameCount > 1u) ? 1.0f / static_cast<float>(frameCount - 1u) : Dali::Math::MACHINE_EPSILON_10;
std::vector<std::shared_ptr<Joint>> jointList;
MakeList(hierarchy, jointList);
for(uint32_t i = 0; i < jointList.size(); ++i)
{
AnimatedProperty translationProperty;
- translationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());
- translationProperty.mNodeName = jointList[i]->name;
- translationProperty.mPropertyName = PROPERTY_NAME_POSITION.data();
+ translationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());
+ translationProperty.mNodeName = jointList[i]->name;
+ translationProperty.mPropertyName = PROPERTY_NAME_POSITION.data();
AnimatedProperty rotationProperty;
- rotationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());
- rotationProperty.mNodeName = jointList[i]->name;
- rotationProperty.mPropertyName = PROPERTY_NAME_ORIENTATION.data();
+ rotationProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());
+ rotationProperty.mNodeName = jointList[i]->name;
+ rotationProperty.mPropertyName = PROPERTY_NAME_ORIENTATION.data();
translationProperty.mKeyFrames = Dali::KeyFrames::New();
rotationProperty.mKeyFrames = Dali::KeyFrames::New();
return animationDefinition;
}
-} // namespace
-AnimationDefinition LoadBvh(const std::string& path, const std::string& animationName, const Vector3& scale)
+AnimationDefinition LoadBvhInternal(std::istream& stream, const std::string& animationName, const Vector3& scale)
{
uint32_t frameCount = 0;
float frameTime = 0.0f;
std::shared_ptr<Joint> rootJoint(new Joint);
- if(!ParseBvh(path, frameCount, frameTime, rootJoint))
+
+ if(!ParseBvh(stream, frameCount, frameTime, rootJoint))
{
AnimationDefinition animationDefinition;
return animationDefinition;
return GenerateAnimation(animationName, rootJoint, frameCount, frameTime, scale);
}
+} // namespace
+
+AnimationDefinition LoadBvh(const std::string& path, const std::string& animationName, const Vector3& scale)
+{
+ Dali::FileStream fileStream(path);
+ std::iostream& stream = fileStream.GetStream();
+
+ if(stream.fail())
+ {
+ DALI_LOG_ERROR("Fail to load bvh file : %s\n", path.c_str());
+ AnimationDefinition animationDefinition;
+ return animationDefinition;
+ }
+
+ return LoadBvhInternal(stream, animationName, scale);
+}
+
+AnimationDefinition LoadBvhFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, const std::string& animationName, const Vector3& scale)
+{
+ if(rawBuffer == nullptr || rawBufferLength == 0)
+ {
+ DALI_LOG_ERROR("Fail to load bvh buffer : buffer is empty!\n");
+ AnimationDefinition animationDefinition;
+ return animationDefinition;
+ }
+
+ Dali::FileStream fileStream(const_cast<uint8_t*>(rawBuffer), static_cast<size_t>(static_cast<uint32_t>(rawBufferLength)));
+ std::iostream& stream = fileStream.GetStream();
+
+ if(stream.fail())
+ {
+ DALI_LOG_ERROR("Fail to load bvh buffer : buffer length : %d\n", rawBufferLength);
+ AnimationDefinition animationDefinition;
+ return animationDefinition;
+ }
+
+ return LoadBvhInternal(stream, animationName, scale);
+}
} // namespace Dali::Scene3D::Loader
\ No newline at end of file
*/
DALI_SCENE3D_API AnimationDefinition LoadBvh(const std::string& path, const std::string& animationName, const Vector3& scale = Vector3::ONE);
+/**
+ * @brief Loads motion capture data from bvh data stream.
+ *
+ * @param[in] rawBuffer The bvh buffer.
+ * @param[in] rawBufferLength The length of buffer.
+ * @param[in] animationName Name of the motion capture animation
+ * @param[in] scale The scale factor to set on the position property manually.
+ * @return AnimationDefinition that includes joint animation information.
+ */
+DALI_SCENE3D_API AnimationDefinition LoadBvhFromBuffer(const uint8_t* rawBuffer, int rawBufferLength, const std::string& animationName, const Vector3& scale = Vector3::ONE);
+
} // namespace Dali::Scene3D::Loader
#endif // DALI_SCENE3D_LOADER_BVH_LOADER_H
\ No newline at end of file
/*\r
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
const js::Reader<BlendShape>& GetBlendShapeReader()\r
{\r
static const auto BLEND_SHAPE_READER = std::move(js::Reader<BlendShape>()\r
- .Register(*js::MakeProperty("key", ReadBlendShapeKeys, &BlendShape::mKeys))\r
- .Register(*new js::Property<BlendShape, std::string_view>("name", js::Read::StringView, &BlendShape::mNodeName))\r
- .Register(*js::MakeProperty("morphtarget", js::Read::Number<uint32_t>, &BlendShape::mNumberOfMorphTarget))\r
- .Register(*new js::Property<BlendShape, std::string_view>("blendShapeVersion", js::Read::StringView, &BlendShape::mVersion))\r
- .Register(*new js::Property<BlendShape, std::string_view>("fullName", js::Read::StringView, &BlendShape::mFullName))\r
- .Register(*js::MakeProperty("morphname", js::Read::Array<std::string_view, js::Read::StringView>, &BlendShape::mMorphNames)));\r
+ .Register(*js::MakeProperty("key", ReadBlendShapeKeys, &BlendShape::mKeys))\r
+ .Register(*new js::Property<BlendShape, std::string_view>("name", js::Read::StringView, &BlendShape::mNodeName))\r
+ .Register(*js::MakeProperty("morphtarget", js::Read::Number<uint32_t>, &BlendShape::mNumberOfMorphTarget))\r
+ .Register(*new js::Property<BlendShape, std::string_view>("blendShapeVersion", js::Read::StringView, &BlendShape::mVersion))\r
+ .Register(*new js::Property<BlendShape, std::string_view>("fullName", js::Read::StringView, &BlendShape::mFullName))\r
+ .Register(*js::MakeProperty("morphname", js::Read::Array<std::string_view, js::Read::StringView>, &BlendShape::mMorphNames)));\r
return BLEND_SHAPE_READER;\r
}\r
\r
const js::Reader<FacialAnimation>& GetFacialAnimationReader()\r
{\r
static const auto FACIAL_ANIMATION_READER = std::move(js::Reader<FacialAnimation>()\r
- .Register(*new js::Property<FacialAnimation, std::string_view>("name", js::Read::StringView, &FacialAnimation::mName))\r
- .Register(*js::MakeProperty("blendShapes", js::Read::Array<BlendShape, js::ObjectReader<BlendShape>::Read>, &FacialAnimation::mBlendShapes))\r
- .Register(*new js::Property<FacialAnimation, std::string_view>("version", js::Read::StringView, &FacialAnimation::mVersion))\r
- .Register(*js::MakeProperty("shapesAmount", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfShapes))\r
- .Register(*js::MakeProperty("time", js::Read::Array<uint32_t, js::Read::Number>, &FacialAnimation::mTime))\r
- .Register(*js::MakeProperty("frames", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfFrames)));\r
+ .Register(*new js::Property<FacialAnimation, std::string_view>("name", js::Read::StringView, &FacialAnimation::mName))\r
+ .Register(*js::MakeProperty("blendShapes", js::Read::Array<BlendShape, js::ObjectReader<BlendShape>::Read>, &FacialAnimation::mBlendShapes))\r
+ .Register(*new js::Property<FacialAnimation, std::string_view>("version", js::Read::StringView, &FacialAnimation::mVersion))\r
+ .Register(*js::MakeProperty("shapesAmount", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfShapes))\r
+ .Register(*js::MakeProperty("time", js::Read::Array<uint32_t, js::Read::Number>, &FacialAnimation::mTime))\r
+ .Register(*js::MakeProperty("frames", js::Read::Number<uint32_t>, &FacialAnimation::mNumberOfFrames)));\r
return FACIAL_ANIMATION_READER;\r
}\r
\r
-} // unnamed namespace\r
-\r
-namespace Scene3D\r
-{\r
-namespace Loader\r
+Dali::Scene3D::Loader::AnimationDefinition LoadFacialAnimationInternal(json::unique_ptr& root)\r
{\r
-AnimationDefinition LoadFacialAnimation(const std::string& url)\r
-{\r
- bool failed = false;\r
- auto js = LoadTextFile(url.c_str(), &failed);\r
- if(failed)\r
- {\r
- ExceptionFlinger(ASSERT_LOCATION) << "Failed to load " << url << ".";\r
- }\r
-\r
- json::unique_ptr root(json_parse(js.c_str(), js.size()));\r
- if(!root)\r
- {\r
- ExceptionFlinger(ASSERT_LOCATION) << "Failed to parse " << url << ".";\r
- }\r
-\r
static bool setObjectReaders = true;\r
if(setObjectReaders)\r
{\r
FacialAnimation facialAnimation;\r
GetFacialAnimationReader().Read(rootObj, facialAnimation);\r
\r
- AnimationDefinition animationDefinition;\r
+ Dali::Scene3D::Loader::AnimationDefinition animationDefinition;\r
animationDefinition.SetName(facialAnimation.mName.data());\r
animationDefinition.SetDuration(MILLISECONDS_TO_SECONDS * static_cast<float>(facialAnimation.mTime[facialAnimation.mNumberOfFrames - 1u]));\r
\r
{\r
for(uint32_t morphTargetIndex = 0u; morphTargetIndex < blendShape.mNumberOfMorphTarget; ++morphTargetIndex)\r
{\r
- AnimatedProperty animatedProperty;\r
+ Dali::Scene3D::Loader::AnimatedProperty animatedProperty;\r
animatedProperty.mTimePeriod = Dali::TimePeriod(animationDefinition.GetDuration());\r
- animatedProperty.mNodeName = blendShape.mNodeName;\r
+ animatedProperty.mNodeName = blendShape.mNodeName;\r
std::stringstream weightPropertyStream;\r
- weightPropertyStream << BlendShapes::WEIGHTS_UNIFORM << "[" << morphTargetIndex << "]";\r
+ weightPropertyStream << Dali::Scene3D::Loader::BlendShapes::WEIGHTS_UNIFORM << "[" << morphTargetIndex << "]";\r
animatedProperty.mPropertyName = weightPropertyStream.str();\r
\r
animatedProperty.mKeyFrames = Dali::KeyFrames::New();\r
\r
return animationDefinition;\r
}\r
+} // unnamed namespace\r
+\r
+namespace Scene3D\r
+{\r
+namespace Loader\r
+{\r
+AnimationDefinition LoadFacialAnimation(const std::string& url)\r
+{\r
+ bool failed = false;\r
+ auto jsonData = LoadTextFile(url.c_str(), &failed);\r
+ if(failed)\r
+ {\r
+ ExceptionFlinger(ASSERT_LOCATION) << "Failed to load " << url << ".";\r
+ }\r
+\r
+ json::unique_ptr root(json_parse(jsonData.c_str(), jsonData.size()));\r
+ if(!root)\r
+ {\r
+ ExceptionFlinger(ASSERT_LOCATION) << "Failed to parse json " << url << ".";\r
+ }\r
+\r
+ return LoadFacialAnimationInternal(root);\r
+}\r
+\r
+AnimationDefinition LoadFacialAnimationFromBuffer(const uint8_t* rawBuffer, int rawBufferLength)\r
+{\r
+ json::unique_ptr root(json_parse(rawBuffer, static_cast<size_t>(static_cast<uint32_t>(rawBufferLength))));\r
+ if(!root)\r
+ {\r
+ ExceptionFlinger(ASSERT_LOCATION) << "Failed to parse json from buffer.";\r
+ }\r
\r
+ return LoadFacialAnimationInternal(root);\r
+}\r
} // namespace Loader\r
} // namespace Scene3D\r
} // namespace Dali\r
#define DALI_SCENE3D_LOADER_FACIAL_ANIMATION_LOADER_H\r
\r
/*\r
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
* @return An animation definition.\r
*/\r
DALI_SCENE3D_API AnimationDefinition LoadFacialAnimation(const std::string& url);\r
+\r
+/**\r
+ * @brief Loads a facial animation encoded in a json file in the given data stream.\r
+ *\r
+ * Throws a DaliException on error.\r
+ *\r
+ * @param[in] rawBuffer The raw buffer containing the facial animation.\r
+ * @param[in] rawBufferLength The length of raw buffer.\r
+ *\r
+ * @return An animation definition.\r
+ */\r
+DALI_SCENE3D_API AnimationDefinition LoadFacialAnimationFromBuffer(const uint8_t* rawBuffer, int rawBufferLength);\r
} // namespace Dali::Scene3D::Loader\r
\r
#endif // DALI_SCENE3D_LOADER_FACIAL_ANIMATION_LOADER_H\r