Introduce tiny_gltf_util.h header file which contains some useful helper/util functions.
diff --git a/examples/anim-dump/anim-dump.cc b/examples/anim-dump/anim-dump.cc
index 40537dc..022f077 100644
--- a/examples/anim-dump/anim-dump.cc
+++ b/examples/anim-dump/anim-dump.cc
@@ -1,11 +1,14 @@
//
// TODO(syoyo): Print extensions and extras for each glTF object.
//
+#include "tiny_gltf_util.h"
+
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "tiny_gltf.h"
+
#include <cstdio>
#include <fstream>
#include <iostream>
@@ -16,187 +19,6 @@
return "";
}
-static std::string PrintMode(int mode) {
- if (mode == TINYGLTF_MODE_POINTS) {
- return "POINTS";
- } else if (mode == TINYGLTF_MODE_LINE) {
- return "LINE";
- } else if (mode == TINYGLTF_MODE_LINE_LOOP) {
- return "LINE_LOOP";
- } else if (mode == TINYGLTF_MODE_TRIANGLES) {
- return "TRIANGLES";
- } else if (mode == TINYGLTF_MODE_TRIANGLE_FAN) {
- return "TRIANGLE_FAN";
- } else if (mode == TINYGLTF_MODE_TRIANGLE_STRIP) {
- return "TRIANGLE_STRIP";
- }
- return "**UNKNOWN**";
-}
-
-static std::string PrintTarget(int target) {
- if (target == 34962) {
- return "GL_ARRAY_BUFFER";
- } else if (target == 34963) {
- return "GL_ELEMENT_ARRAY_BUFFER";
- } else {
- return "**UNKNOWN**";
- }
-}
-
-static std::string PrintType(int ty) {
- if (ty == TINYGLTF_TYPE_SCALAR) {
- return "SCALAR";
- } else if (ty == TINYGLTF_TYPE_VECTOR) {
- return "VECTOR";
- } else if (ty == TINYGLTF_TYPE_VEC2) {
- return "VEC2";
- } else if (ty == TINYGLTF_TYPE_VEC3) {
- return "VEC3";
- } else if (ty == TINYGLTF_TYPE_VEC4) {
- return "VEC4";
- } else if (ty == TINYGLTF_TYPE_MATRIX) {
- return "MATRIX";
- } else if (ty == TINYGLTF_TYPE_MAT2) {
- return "MAT2";
- } else if (ty == TINYGLTF_TYPE_MAT3) {
- return "MAT3";
- } else if (ty == TINYGLTF_TYPE_MAT4) {
- return "MAT4";
- }
- return "**UNKNOWN**";
-}
-
-static std::string PrintComponentType(int ty) {
- if (ty == TINYGLTF_COMPONENT_TYPE_BYTE) {
- return "BYTE";
- } else if (ty == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
- return "UNSIGNED_BYTE";
- } else if (ty == TINYGLTF_COMPONENT_TYPE_SHORT) {
- return "SHORT";
- } else if (ty == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
- return "UNSIGNED_SHORT";
- } else if (ty == TINYGLTF_COMPONENT_TYPE_INT) {
- return "INT";
- } else if (ty == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) {
- return "UNSIGNED_INT";
- } else if (ty == TINYGLTF_COMPONENT_TYPE_FLOAT) {
- return "FLOAT";
- } else if (ty == TINYGLTF_COMPONENT_TYPE_DOUBLE) {
- return "DOUBLE";
- }
-
- return "**UNKNOWN**";
-}
-
-#if 0
-static std::string PrintParameterType(int ty) {
- if (ty == TINYGLTF_PARAMETER_TYPE_BYTE) {
- return "BYTE";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_UNSIGNED_BYTE) {
- return "UNSIGNED_BYTE";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_SHORT) {
- return "SHORT";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_UNSIGNED_SHORT) {
- return "UNSIGNED_SHORT";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_INT) {
- return "INT";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_UNSIGNED_INT) {
- return "UNSIGNED_INT";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_FLOAT) {
- return "FLOAT";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_FLOAT_VEC2) {
- return "FLOAT_VEC2";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_FLOAT_VEC3) {
- return "FLOAT_VEC3";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_FLOAT_VEC4) {
- return "FLOAT_VEC4";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_INT_VEC2) {
- return "INT_VEC2";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_INT_VEC3) {
- return "INT_VEC3";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_INT_VEC4) {
- return "INT_VEC4";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_BOOL) {
- return "BOOL";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_BOOL_VEC2) {
- return "BOOL_VEC2";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_BOOL_VEC3) {
- return "BOOL_VEC3";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_BOOL_VEC4) {
- return "BOOL_VEC4";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_FLOAT_MAT2) {
- return "FLOAT_MAT2";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_FLOAT_MAT3) {
- return "FLOAT_MAT3";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_FLOAT_MAT4) {
- return "FLOAT_MAT4";
- } else if (ty == TINYGLTF_PARAMETER_TYPE_SAMPLER_2D) {
- return "SAMPLER_2D";
- }
-
- return "**UNKNOWN**";
-}
-#endif
-
-static std::string PrintWrapMode(int mode) {
- if (mode == TINYGLTF_TEXTURE_WRAP_REPEAT) {
- return "REPEAT";
- } else if (mode == TINYGLTF_TEXTURE_WRAP_CLAMP_TO_EDGE) {
- return "CLAMP_TO_EDGE";
- } else if (mode == TINYGLTF_TEXTURE_WRAP_MIRRORED_REPEAT) {
- return "MIRRORED_REPEAT";
- }
-
- return "**UNKNOWN**";
-}
-
-static std::string PrintFilterMode(int mode) {
- if (mode == TINYGLTF_TEXTURE_FILTER_NEAREST) {
- return "NEAREST";
- } else if (mode == TINYGLTF_TEXTURE_FILTER_LINEAR) {
- return "LINEAR";
- } else if (mode == TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST) {
- return "NEAREST_MIPMAP_NEAREST";
- } else if (mode == TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR) {
- return "NEAREST_MIPMAP_LINEAR";
- } else if (mode == TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST) {
- return "LINEAR_MIPMAP_NEAREST";
- } else if (mode == TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR) {
- return "LINEAR_MIPMAP_LINEAR";
- }
- return "**UNKNOWN**";
-}
-
-static std::string PrintIntArray(const std::vector<int> &arr) {
- if (arr.size() == 0) {
- return "";
- }
-
- std::stringstream ss;
- ss << "[ ";
- for (size_t i = 0; i < arr.size(); i++) {
- ss << arr[i] << ((i != arr.size() - 1) ? ", " : "");
- }
- ss << " ]";
-
- return ss.str();
-}
-
-static std::string PrintFloatArray(const std::vector<double> &arr) {
- if (arr.size() == 0) {
- return "";
- }
-
- std::stringstream ss;
- ss << "[ ";
- for (size_t i = 0; i < arr.size(); i++) {
- ss << arr[i] << ((i != arr.size() - 1) ? ", " : "");
- }
- ss << " ]";
-
- return ss.str();
-}
-
static std::string Indent(const int indent) {
std::string s;
for (int i = 0; i < indent; i++) {
@@ -206,168 +28,7 @@
return s;
}
-static std::string PrintParameterValue(const tinygltf::Parameter ¶m) {
- if (!param.number_array.empty()) {
- return PrintFloatArray(param.number_array);
- } else {
- return param.string_value;
- }
-}
-#if 0
-static std::string PrintParameterMap(const tinygltf::ParameterMap &pmap) {
- std::stringstream ss;
-
- ss << pmap.size() << std::endl;
- for (auto &kv : pmap) {
- ss << kv.first << " : " << PrintParameterValue(kv.second) << std::endl;
- }
-
- return ss.str();
-}
-#endif
-
-static std::string PrintValue(const std::string &name,
- const tinygltf::Value &value, const int indent, const bool tag = true) {
- std::stringstream ss;
-
- if (value.IsObject()) {
- const tinygltf::Value::Object &o = value.Get<tinygltf::Value::Object>();
- tinygltf::Value::Object::const_iterator it(o.begin());
- tinygltf::Value::Object::const_iterator itEnd(o.end());
- for (; it != itEnd; it++) {
- ss << PrintValue(it->first, it->second, indent + 1) << std::endl;
- }
- } else if (value.IsString()) {
- if (tag) {
- ss << Indent(indent) << name << " : " << value.Get<std::string>();
- } else {
- ss << " " << value.Get<std::string>() << " ";
- }
- } else if (value.IsBool()) {
- if (tag) {
- ss << Indent(indent) << name << " : " << value.Get<bool>();
- } else {
- ss << " " << value.Get<bool>() << " ";
- }
- } else if (value.IsNumber()) {
- if (tag) {
- ss << Indent(indent) << name << " : " << value.Get<double>();
- } else {
- ss << " " << value.Get<double>() << " ";
- }
- } else if (value.IsInt()) {
- if (tag) {
- ss << Indent(indent) << name << " : " << value.Get<int>();
- } else {
- ss << " " << value.Get<int>() << " ";
- }
- } else if (value.IsArray()) {
- ss << Indent(indent) << name << " [ ";
- for (size_t i = 0; i < value.Size(); i++) {
- ss << PrintValue("", value.Get(int(i)), indent + 1, /* tag */false);
- if (i != (value.ArrayLen()-1)) {
- ss << ", ";
- }
-
- }
- ss << Indent(indent) << "] ";
- }
-
- // @todo { binary }
-
- return ss.str();
-}
-
-static void DumpNode(const tinygltf::Node &node, int indent) {
- std::cout << Indent(indent) << "name : " << node.name << std::endl;
- std::cout << Indent(indent) << "camera : " << node.camera << std::endl;
- std::cout << Indent(indent) << "mesh : " << node.mesh << std::endl;
- if (!node.rotation.empty()) {
- std::cout << Indent(indent)
- << "rotation : " << PrintFloatArray(node.rotation)
- << std::endl;
- }
- if (!node.scale.empty()) {
- std::cout << Indent(indent)
- << "scale : " << PrintFloatArray(node.scale) << std::endl;
- }
- if (!node.translation.empty()) {
- std::cout << Indent(indent)
- << "translation : " << PrintFloatArray(node.translation)
- << std::endl;
- }
-
- if (!node.matrix.empty()) {
- std::cout << Indent(indent)
- << "matrix : " << PrintFloatArray(node.matrix) << std::endl;
- }
-
- std::cout << Indent(indent)
- << "children : " << PrintIntArray(node.children) << std::endl;
-}
-
-static void DumpStringIntMap(const std::map<std::string, int> &m, int indent) {
- std::map<std::string, int>::const_iterator it(m.begin());
- std::map<std::string, int>::const_iterator itEnd(m.end());
- for (; it != itEnd; it++) {
- std::cout << Indent(indent) << it->first << ": " << it->second << std::endl;
- }
-}
-
-static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) {
- std::cout << Indent(indent) << "material : " << primitive.material
- << std::endl;
- std::cout << Indent(indent) << "indices : " << primitive.indices << std::endl;
- std::cout << Indent(indent) << "mode : " << PrintMode(primitive.mode)
- << "(" << primitive.mode << ")" << std::endl;
- std::cout << Indent(indent)
- << "attributes(items=" << primitive.attributes.size() << ")"
- << std::endl;
- DumpStringIntMap(primitive.attributes, indent + 1);
-
- std::cout << Indent(indent) << "extras :" << std::endl
- << PrintValue("extras", primitive.extras, indent + 1) << std::endl;
-}
-
-static void DumpExtensions(const tinygltf::ExtensionMap &extension, const int indent)
-{
- // TODO(syoyo): pritty print Value
- for (auto &e : extension) {
- std::cout << Indent(indent) << e.first << std::endl;
- std::cout << PrintValue("extensions", e.second, indent+1) << std::endl;
- }
-}
-
-static float DecodeScalarAnimationValue(const size_t i, const tinygltf::Accessor &accessor, const tinygltf::Model &model)
-{
- const tinygltf::BufferView &bufferView = model.bufferViews[accessor.bufferView];
- const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer];
-
- const uint8_t *addr = GetBufferAddress(i, accessor, bufferView, buffer);
- if (addr == nullptr) {
- std::cerr << "Invalid glTF data?" << std::endl;
- return 0.0f;
- }
-
- float value = 0.0f;
-
- if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_BYTE) {
- value = tinygltf::DecodeAnimationChannelValue(*(reinterpret_cast<const int8_t*>(addr)));
- } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
- value = tinygltf::DecodeAnimationChannelValue(*(reinterpret_cast<const uint8_t*>(addr)));
- } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_SHORT) {
- value = tinygltf::DecodeAnimationChannelValue(*(reinterpret_cast<const int16_t*>(addr)));
- } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
- value = tinygltf::DecodeAnimationChannelValue(*(reinterpret_cast<const uint16_t*>(addr)));
- } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) {
- value = *(reinterpret_cast<const float*>(addr));
- } else {
- std::cerr << "??? Unknown componentType : " << PrintComponentType(accessor.componentType) << std::endl;
- }
-
- return value;
-}
static void ProcessAnimation(const tinygltf::Animation &animation, const tinygltf::Model &model)
{
@@ -401,8 +62,10 @@
for (size_t i = 0; i < accessor.count; i++) {
if (accessor.type == TINYGLTF_TYPE_SCALAR) {
- float v = DecodeScalarAnimationValue(i, accessor, model);
- std::cout << Indent(2) << "input value[" << i << "] = " << v << std::endl;
+ float v;
+ if (tinygltf::util::DecodeScalarAnimationValue(i, accessor, model, &v)) {
+ std::cout << Indent(2) << "input value[" << i << "] = " << v << std::endl;
+ }
}
}
diff --git a/tiny_gltf.h b/tiny_gltf.h
index 8608501..21bf527 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -196,20 +196,6 @@
}
}
-// Utility function for decoding animation value
-static inline float DecodeAnimationChannelValue(int8_t c) {
- return std::max(float(c) / 127.0f, -1.0f);
-}
-static inline float DecodeAnimationChannelValue(uint8_t c) {
- return float(c) / 255.0f;
-}
-static inline float DecodeAnimationChannelValue(int16_t c) {
- return std::max(float(c) / 32767.0f, -1.0f);
-}
-static inline float DecodeAnimationChannelValue(uint16_t c) {
- return float(c) / 65525.0f;
-}
-
bool IsDataURI(const std::string &in);
bool DecodeDataURI(std::vector<unsigned char> *out, std::string &mime_type,
const std::string &in, size_t reqBytes, bool checkSize);
@@ -2036,7 +2022,7 @@
const uint8_t *GetBufferAddress(const int i, const Accessor &accessor, const BufferView &bufferViewObject, const Buffer &buffer) {
- if (i >= accessor.count) return nullptr;
+ if (i >= int(accessor.count)) return nullptr;
int byte_stride = accessor.ByteStride(bufferViewObject);
if (byte_stride == -1) {
@@ -3529,7 +3515,7 @@
{
if (primitive.indices > -1) // has indices from parsing step, must be Element Array Buffer
{
- model->bufferViews[model->accessors[primitive.indices].bufferView]
+ model->bufferViews[size_t(model->accessors[size_t(primitive.indices)].bufferView)]
.target = TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
// we could optionally check if acessors' bufferView type is Scalar, as it should be
}
@@ -4616,23 +4602,23 @@
const int padding_size = content.size() % 4;
// 12 bytes for header, JSON content length, 8 bytes for JSON chunk info, padding
- const int length = 12 + 8 + content.size() + padding_size;
+ const int length = 12 + 8 + int(content.size()) + padding_size;
- gltfFile.write(header.c_str(), header.size());
+ gltfFile.write(header.c_str(), std::streamsize(header.size()));
gltfFile.write(reinterpret_cast<const char *>(&version), sizeof(version));
gltfFile.write(reinterpret_cast<const char *>(&length), sizeof(length));
// JSON chunk info, then JSON data
- const int model_length = content.size() + padding_size;
+ const int model_length = int(content.size()) + padding_size;
const int model_format = 0x4E4F534A;
gltfFile.write(reinterpret_cast<const char *>(&model_length), sizeof(model_length));
gltfFile.write(reinterpret_cast<const char *>(&model_format), sizeof(model_format));
- gltfFile.write(content.c_str(), content.size());
+ gltfFile.write(content.c_str(), std::streamsize(content.size()));
// Chunk must be multiplies of 4, so pad with spaces
if (padding_size > 0) {
- const std::string padding = std::string(padding_size, ' ');
- gltfFile.write(padding.c_str(), padding.size());
+ const std::string padding = std::string(size_t(padding_size), ' ');
+ gltfFile.write(padding.c_str(), std::streamsize(padding.size()));
}
}
diff --git a/tiny_gltf_util.h b/tiny_gltf_util.h
new file mode 100644
index 0000000..64fc6ca
--- /dev/null
+++ b/tiny_gltf_util.h
@@ -0,0 +1,294 @@
+//
+// TinyGLTF utility functions
+//
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 - 2018 Syoyo Fujita, Aurélien Chatelain and many
+// contributors.
+//
+
+#include <iostream>
+
+#include "tiny_gltf.h"
+
+namespace tinygltf {
+
+namespace util {
+
+static std::string PrintMode(int mode) {
+ if (mode == TINYGLTF_MODE_POINTS) {
+ return "POINTS";
+ } else if (mode == TINYGLTF_MODE_LINE) {
+ return "LINE";
+ } else if (mode == TINYGLTF_MODE_LINE_LOOP) {
+ return "LINE_LOOP";
+ } else if (mode == TINYGLTF_MODE_TRIANGLES) {
+ return "TRIANGLES";
+ } else if (mode == TINYGLTF_MODE_TRIANGLE_FAN) {
+ return "TRIANGLE_FAN";
+ } else if (mode == TINYGLTF_MODE_TRIANGLE_STRIP) {
+ return "TRIANGLE_STRIP";
+ }
+ return "**UNKNOWN**";
+}
+
+static std::string PrintTarget(int target) {
+ if (target == 34962) {
+ return "GL_ARRAY_BUFFER";
+ } else if (target == 34963) {
+ return "GL_ELEMENT_ARRAY_BUFFER";
+ } else {
+ return "**UNKNOWN**";
+ }
+}
+
+static std::string PrintType(int ty) {
+ if (ty == TINYGLTF_TYPE_SCALAR) {
+ return "SCALAR";
+ } else if (ty == TINYGLTF_TYPE_VECTOR) {
+ return "VECTOR";
+ } else if (ty == TINYGLTF_TYPE_VEC2) {
+ return "VEC2";
+ } else if (ty == TINYGLTF_TYPE_VEC3) {
+ return "VEC3";
+ } else if (ty == TINYGLTF_TYPE_VEC4) {
+ return "VEC4";
+ } else if (ty == TINYGLTF_TYPE_MATRIX) {
+ return "MATRIX";
+ } else if (ty == TINYGLTF_TYPE_MAT2) {
+ return "MAT2";
+ } else if (ty == TINYGLTF_TYPE_MAT3) {
+ return "MAT3";
+ } else if (ty == TINYGLTF_TYPE_MAT4) {
+ return "MAT4";
+ }
+ return "**UNKNOWN**";
+}
+
+static std::string PrintComponentType(int ty) {
+ if (ty == TINYGLTF_COMPONENT_TYPE_BYTE) {
+ return "BYTE";
+ } else if (ty == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
+ return "UNSIGNED_BYTE";
+ } else if (ty == TINYGLTF_COMPONENT_TYPE_SHORT) {
+ return "SHORT";
+ } else if (ty == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
+ return "UNSIGNED_SHORT";
+ } else if (ty == TINYGLTF_COMPONENT_TYPE_INT) {
+ return "INT";
+ } else if (ty == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) {
+ return "UNSIGNED_INT";
+ } else if (ty == TINYGLTF_COMPONENT_TYPE_FLOAT) {
+ return "FLOAT";
+ } else if (ty == TINYGLTF_COMPONENT_TYPE_DOUBLE) {
+ return "DOUBLE";
+ }
+
+ return "**UNKNOWN**";
+}
+
+static std::string PrintWrapMode(int mode) {
+ if (mode == TINYGLTF_TEXTURE_WRAP_REPEAT) {
+ return "REPEAT";
+ } else if (mode == TINYGLTF_TEXTURE_WRAP_CLAMP_TO_EDGE) {
+ return "CLAMP_TO_EDGE";
+ } else if (mode == TINYGLTF_TEXTURE_WRAP_MIRRORED_REPEAT) {
+ return "MIRRORED_REPEAT";
+ }
+
+ return "**UNKNOWN**";
+}
+
+static std::string PrintFilterMode(int mode) {
+ if (mode == TINYGLTF_TEXTURE_FILTER_NEAREST) {
+ return "NEAREST";
+ } else if (mode == TINYGLTF_TEXTURE_FILTER_LINEAR) {
+ return "LINEAR";
+ } else if (mode == TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST) {
+ return "NEAREST_MIPMAP_NEAREST";
+ } else if (mode == TINYGLTF_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR) {
+ return "NEAREST_MIPMAP_LINEAR";
+ } else if (mode == TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST) {
+ return "LINEAR_MIPMAP_NEAREST";
+ } else if (mode == TINYGLTF_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR) {
+ return "LINEAR_MIPMAP_LINEAR";
+ }
+ return "**UNKNOWN**";
+}
+
+static int GetAnimationSamplerInputCount(const tinygltf::AnimationSampler &sampler, const tinygltf::Model &model)
+{
+ const tinygltf::Accessor &accessor = model.accessors[sampler.input];
+ return accessor.count;
+}
+
+static int GetAnimationSamplerOutputCount(const tinygltf::AnimationSampler &sampler, const tinygltf::Model &model)
+{
+ const tinygltf::Accessor &accessor = model.accessors[sampler.output];
+ return accessor.count;
+}
+
+static bool GetAnimationSamplerInputMinMax(const tinygltf::AnimationSampler &sampler, const tinygltf::Model &model, float *min_value, float *max_value)
+{
+ const tinygltf::Accessor &accessor = model.accessors[sampler.input];
+
+ // Assume scalar value.
+ if ((accessor.minValues.size() > 0) &&
+ (accessor.maxValues.size() > 0)) {
+ (*min_value) = accessor.minValues[0];
+ (*max_value) = accessor.maxValues[0];
+ return true;
+ } else {
+ (*min_value) = 0.0f;
+ (*max_value) = 0.0f;
+ return false;
+ }
+}
+
+// Utility function for decoding animation value
+static inline float DecodeAnimationChannelValue(int8_t c) {
+ return std::max(float(c) / 127.0f, -1.0f);
+}
+static inline float DecodeAnimationChannelValue(uint8_t c) {
+ return float(c) / 255.0f;
+}
+static inline float DecodeAnimationChannelValue(int16_t c) {
+ return std::max(float(c) / 32767.0f, -1.0f);
+}
+static inline float DecodeAnimationChannelValue(uint16_t c) {
+ return float(c) / 65525.0f;
+}
+
+static bool DecodeScalarAnimationValue(const size_t i, const tinygltf::Accessor &accessor, const tinygltf::Model &model, float *scalar)
+{
+ const BufferView &bufferView = model.bufferViews[accessor.bufferView];
+ const Buffer &buffer = model.buffers[bufferView.buffer];
+
+ const uint8_t *addr = GetBufferAddress(i, accessor, bufferView, buffer);
+ if (addr == nullptr) {
+ std::cerr << "Invalid glTF data?" << std::endl;
+ return false;
+ }
+
+ float value = 0.0f;
+
+ if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_BYTE) {
+ value = DecodeAnimationChannelValue(*(reinterpret_cast<const int8_t*>(addr)));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
+ value = DecodeAnimationChannelValue(*(reinterpret_cast<const uint8_t*>(addr)));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_SHORT) {
+ value = DecodeAnimationChannelValue(*(reinterpret_cast<const int16_t*>(addr)));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
+ value = DecodeAnimationChannelValue(*(reinterpret_cast<const uint16_t*>(addr)));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) {
+ value = *(reinterpret_cast<const float*>(addr));
+ } else {
+ std::cerr << "??? Unknown componentType : " << PrintComponentType(accessor.componentType) << std::endl;
+ return false;
+ }
+
+ (*scalar) = value;
+
+ return true;
+}
+
+static bool DecodeTranslationAnimationValue(const size_t i, const tinygltf::Accessor &accessor, const tinygltf::Model &model, float *xyz)
+{
+ if (accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) {
+ std::cerr << "`translation` must be float type." << std::endl;
+ return false;
+ }
+
+ const BufferView &bufferView = model.bufferViews[accessor.bufferView];
+ const Buffer &buffer = model.buffers[bufferView.buffer];
+
+ const uint8_t *addr = GetBufferAddress(i, accessor, bufferView, buffer);
+ if (addr == nullptr) {
+ std::cerr << "Invalid glTF data?" << std::endl;
+ return 0.0f;
+ }
+
+ const float *ptr = reinterpret_cast<const float*>(addr);
+
+ xyz[0] = *(ptr + 0);
+ xyz[1] = *(ptr + 1);
+ xyz[2] = *(ptr + 2);
+
+ return true;
+}
+
+static bool DecodeScaleAnimationValue(const size_t i, const tinygltf::Accessor &accessor, const tinygltf::Model &model, float *xyz)
+{
+ if (accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) {
+ std::cerr << "`scale` must be float type." << std::endl;
+ return false;
+ }
+
+ const BufferView &bufferView = model.bufferViews[accessor.bufferView];
+ const Buffer &buffer = model.buffers[bufferView.buffer];
+
+ const uint8_t *addr = GetBufferAddress(i, accessor, bufferView, buffer);
+ if (addr == nullptr) {
+ std::cerr << "Invalid glTF data?" << std::endl;
+ return 0.0f;
+ }
+
+ const float *ptr = reinterpret_cast<const float*>(addr);
+
+ xyz[0] = *(ptr + 0);
+ xyz[1] = *(ptr + 1);
+ xyz[2] = *(ptr + 2);
+
+ return true;
+}
+
+static bool DecodeRotationAnimationValue(const size_t i, const tinygltf::Accessor &accessor, const tinygltf::Model &model, float *xyzw)
+{
+ const BufferView &bufferView = model.bufferViews[accessor.bufferView];
+ const Buffer &buffer = model.buffers[bufferView.buffer];
+
+ const uint8_t *addr = GetBufferAddress(i, accessor, bufferView, buffer);
+ if (addr == nullptr) {
+ std::cerr << "Invalid glTF data?" << std::endl;
+ return false;
+ }
+
+ float value = 0.0f;
+
+ if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_BYTE) {
+ xyzw[0] = DecodeAnimationChannelValue(*(reinterpret_cast<const int8_t*>(addr) + 0));
+ xyzw[1] = DecodeAnimationChannelValue(*(reinterpret_cast<const int8_t*>(addr) + 1));
+ xyzw[2] = DecodeAnimationChannelValue(*(reinterpret_cast<const int8_t*>(addr) + 2));
+ xyzw[3] = DecodeAnimationChannelValue(*(reinterpret_cast<const int8_t*>(addr) + 3));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
+ xyzw[0] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint8_t*>(addr) + 0));
+ xyzw[1] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint8_t*>(addr) + 1));
+ xyzw[2] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint8_t*>(addr) + 2));
+ xyzw[3] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint8_t*>(addr) + 3));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_SHORT) {
+ xyzw[0] = DecodeAnimationChannelValue(*(reinterpret_cast<const int16_t*>(addr) + 0));
+ xyzw[1] = DecodeAnimationChannelValue(*(reinterpret_cast<const int16_t*>(addr) + 1));
+ xyzw[2] = DecodeAnimationChannelValue(*(reinterpret_cast<const int16_t*>(addr) + 2));
+ xyzw[3] = DecodeAnimationChannelValue(*(reinterpret_cast<const int16_t*>(addr) + 3));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) {
+ xyzw[0] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint16_t*>(addr) + 0));
+ xyzw[1] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint16_t*>(addr) + 1));
+ xyzw[2] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint16_t*>(addr) + 2));
+ xyzw[3] = DecodeAnimationChannelValue(*(reinterpret_cast<const uint16_t*>(addr) + 3));
+ } else if (accessor.componentType == TINYGLTF_COMPONENT_TYPE_FLOAT) {
+ xyzw[0] = *(reinterpret_cast<const float*>(addr) + 0);
+ xyzw[1] = *(reinterpret_cast<const float*>(addr) + 1);
+ xyzw[2] = *(reinterpret_cast<const float*>(addr) + 2);
+ xyzw[3] = *(reinterpret_cast<const float*>(addr) + 3);
+ } else {
+ std::cerr << "??? Unknown componentType : " << PrintComponentType(accessor.componentType) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace util
+
+} // namespace tinygltf