mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-04-22 22:20:01 +08:00
Store relative URI in Buffer serializer. Fixes #48.
Apply clang-format. Add simple saver sample.
This commit is contained in:
parent
20244e1e4e
commit
d42767e63f
2
examples/saver/Makefile.dev
Normal file
2
examples/saver/Makefile.dev
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
all:
|
||||||
|
clang++ -std=c++11 -I../../ -g -O1 -o saver main.cc
|
1
examples/saver/README.md
Normal file
1
examples/saver/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Simple serialization API sample.
|
33
examples/saver/main.cc
Normal file
33
examples/saver/main.cc
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "tiny_gltf.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cout << "Needs input.gltf output.gltf" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinygltf::Model model;
|
||||||
|
tinygltf::TinyGLTF loader;
|
||||||
|
std::string err;
|
||||||
|
std::string input_filename(argv[1]);
|
||||||
|
std::string output_filename(argv[2]);
|
||||||
|
|
||||||
|
// assume ascii glTF.
|
||||||
|
bool ret = loader.LoadASCIIFromFile(&model, &err, input_filename.c_str());
|
||||||
|
if (!ret) {
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
loader.WriteGltfSceneToFile(&model, output_filename);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
}
|
321
tiny_gltf.h
321
tiny_gltf.h
@ -37,13 +37,13 @@
|
|||||||
#ifndef TINY_GLTF_H_
|
#ifndef TINY_GLTF_H_
|
||||||
#define TINY_GLTF_H_
|
#define TINY_GLTF_H_
|
||||||
|
|
||||||
#include <cstdint>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace tinygltf {
|
namespace tinygltf {
|
||||||
|
|
||||||
@ -145,8 +145,7 @@ typedef enum {
|
|||||||
OBJECT_TYPE = 7
|
OBJECT_TYPE = 7
|
||||||
} Type;
|
} Type;
|
||||||
|
|
||||||
static inline int32_t GetComponentSizeInBytes(uint32_t componentType)
|
static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
|
||||||
{
|
|
||||||
if (componentType == TINYGLTF_COMPONENT_TYPE_BYTE) {
|
if (componentType == TINYGLTF_COMPONENT_TYPE_BYTE) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
|
} else if (componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
|
||||||
@ -169,8 +168,7 @@ static inline int32_t GetComponentSizeInBytes(uint32_t componentType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t GetTypeSizeInBytes(uint32_t ty)
|
static inline int32_t GetTypeSizeInBytes(uint32_t ty) {
|
||||||
{
|
|
||||||
if (ty == TINYGLTF_TYPE_SCALAR) {
|
if (ty == TINYGLTF_TYPE_SCALAR) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (ty == TINYGLTF_TYPE_VEC2) {
|
} else if (ty == TINYGLTF_TYPE_VEC2) {
|
||||||
@ -307,7 +305,6 @@ class Value {
|
|||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define TINYGLTF_VALUE_GET(ctype, var) \
|
#define TINYGLTF_VALUE_GET(ctype, var) \
|
||||||
template <> \
|
template <> \
|
||||||
inline const ctype &Value::Get<ctype>() const { \
|
inline const ctype &Value::Get<ctype>() const { \
|
||||||
@ -332,46 +329,44 @@ TINYGLTF_VALUE_GET(Value::Object, object_value_)
|
|||||||
#pragma clang diagnostic ignored "-Wpadded"
|
#pragma clang diagnostic ignored "-Wpadded"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
///Agregate object for representing a color
|
/// Agregate object for representing a color
|
||||||
using ColorValue = std::array<double, 4>;
|
using ColorValue = std::array<double, 4>;
|
||||||
|
|
||||||
struct Parameter {
|
struct Parameter {
|
||||||
bool bool_value;
|
bool bool_value;
|
||||||
std::string string_value;
|
std::string string_value;
|
||||||
std::vector<double> number_array;
|
std::vector<double> number_array;
|
||||||
std::map<std::string, double> json_double_value;
|
std::map<std::string, double> json_double_value;
|
||||||
|
|
||||||
//context sensitive methods. depending the type of the Parameter you are accessing, these are either valid or not
|
// context sensitive methods. depending the type of the Parameter you are
|
||||||
//If this parameter represent a texture map in a material, will return the texture index
|
// accessing, these are either valid or not
|
||||||
|
// If this parameter represent a texture map in a material, will return the
|
||||||
|
// texture index
|
||||||
|
|
||||||
///Return the index of a texture if this Parameter is a texture map.
|
/// Return the index of a texture if this Parameter is a texture map.
|
||||||
///Returned value is only valid if the parameter represent a texture from a material
|
/// Returned value is only valid if the parameter represent a texture from a
|
||||||
|
/// material
|
||||||
int TextureIndex() const {
|
int TextureIndex() const {
|
||||||
const auto it = json_double_value.find("index");
|
const auto it = json_double_value.find("index");
|
||||||
if (it != std::end(json_double_value))
|
if (it != std::end(json_double_value)) {
|
||||||
{
|
|
||||||
return int(it->second);
|
return int(it->second);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Material factor, like the roughness or metalness of a material
|
/// Material factor, like the roughness or metalness of a material
|
||||||
///Returned value is only valid if the parameter represent a texture from a material
|
/// Returned value is only valid if the parameter represent a texture from a
|
||||||
double Factor() const {
|
/// material
|
||||||
return number_array[0];
|
double Factor() const { return number_array[0]; }
|
||||||
}
|
|
||||||
|
|
||||||
///Return the color of a material
|
/// Return the color of a material
|
||||||
///Returned value is only valid if the parameter represent a texture from a material
|
/// Returned value is only valid if the parameter represent a texture from a
|
||||||
|
/// material
|
||||||
ColorValue ColorFactor() const {
|
ColorValue ColorFactor() const {
|
||||||
return {
|
return {
|
||||||
{ // this agregate intialize the std::array object, and uses C++11 RVO.
|
{// this agregate intialize the std::array object, and uses C++11 RVO.
|
||||||
number_array[0],
|
number_array[0], number_array[1], number_array[2],
|
||||||
number_array[1],
|
(number_array.size() > 3 ? number_array[3] : 1.0)}};
|
||||||
number_array[2],
|
|
||||||
(number_array.size() > 3 ? number_array[3] : 1.0)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -449,7 +444,8 @@ struct Image {
|
|||||||
int component;
|
int component;
|
||||||
std::vector<unsigned char> image;
|
std::vector<unsigned char> image;
|
||||||
int bufferView; // (required if no uri)
|
int bufferView; // (required if no uri)
|
||||||
std::string mimeType; // (required if no uri) ["image/jpeg", "image/png", "image/bmp", "image/gif"]
|
std::string mimeType; // (required if no uri) ["image/jpeg", "image/png",
|
||||||
|
// "image/bmp", "image/gif"]
|
||||||
std::string uri; // (required if no mimeType)
|
std::string uri; // (required if no mimeType)
|
||||||
Value extras;
|
Value extras;
|
||||||
|
|
||||||
@ -513,7 +509,8 @@ struct Accessor {
|
|||||||
int ByteStride(const BufferView &bufferViewObject) const {
|
int ByteStride(const BufferView &bufferViewObject) const {
|
||||||
if (bufferViewObject.byteStride == 0) {
|
if (bufferViewObject.byteStride == 0) {
|
||||||
// Assume data is tightly packed.
|
// Assume data is tightly packed.
|
||||||
int componentSizeInBytes = GetComponentSizeInBytes(static_cast<uint32_t>(componentType));
|
int componentSizeInBytes =
|
||||||
|
GetComponentSizeInBytes(static_cast<uint32_t>(componentType));
|
||||||
if (componentSizeInBytes <= 0) {
|
if (componentSizeInBytes <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -525,8 +522,10 @@ struct Accessor {
|
|||||||
|
|
||||||
return componentSizeInBytes * typeSizeInBytes;
|
return componentSizeInBytes * typeSizeInBytes;
|
||||||
} else {
|
} else {
|
||||||
// Check if byteStride is a mulple of the size of the accessor's component type.
|
// Check if byteStride is a mulple of the size of the accessor's component
|
||||||
int componentSizeInBytes = GetComponentSizeInBytes(static_cast<uint32_t>(componentType));
|
// type.
|
||||||
|
int componentSizeInBytes =
|
||||||
|
GetComponentSizeInBytes(static_cast<uint32_t>(componentType));
|
||||||
if (componentSizeInBytes <= 0) {
|
if (componentSizeInBytes <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -651,7 +650,7 @@ class Node {
|
|||||||
std::vector<double> weights; // The weights of the instantiated Morph Target
|
std::vector<double> weights; // The weights of the instantiated Morph Target
|
||||||
|
|
||||||
Value extras;
|
Value extras;
|
||||||
ParameterMap extLightsValues; // KHR_lights_cmn extension
|
ParameterMap extLightsValues; // KHR_lights_cmn extension
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -728,25 +727,24 @@ enum SectionCheck {
|
|||||||
///
|
///
|
||||||
/// LoadImageDataFunction type. Signature for custom image loading callbacks.
|
/// LoadImageDataFunction type. Signature for custom image loading callbacks.
|
||||||
///
|
///
|
||||||
typedef bool (*LoadImageDataFunction)(Image *, std::string *, int, int, const unsigned char *, int, void *);
|
typedef bool (*LoadImageDataFunction)(Image *, std::string *, int, int,
|
||||||
|
const unsigned char *, int, void *);
|
||||||
|
|
||||||
#ifndef TINYGLTF_NO_STB_IMAGE
|
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||||
// Declaration of default image loader callback
|
// Declaration of default image loader callback
|
||||||
static bool LoadImageData(Image *image, std::string *err, int req_width,
|
static bool LoadImageData(Image *image, std::string *err, int req_width,
|
||||||
int req_height, const unsigned char *bytes,
|
int req_height, const unsigned char *bytes, int size,
|
||||||
int size, void*);
|
void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class TinyGLTF {
|
class TinyGLTF {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wc++98-compat"
|
#pragma clang diagnostic ignored "-Wc++98-compat"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TinyGLTF() : bin_data_(nullptr), bin_size_(0), is_binary_(false) {
|
TinyGLTF() : bin_data_(nullptr), bin_size_(0), is_binary_(false) {}
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
@ -828,7 +826,7 @@ class TinyGLTF {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic pop // -Wpadded
|
#pragma clang diagnostic pop // -Wpadded
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace tinygltf
|
} // namespace tinygltf
|
||||||
@ -897,7 +895,7 @@ class TinyGLTF {
|
|||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include "TargetConditionals.h"
|
#include "TargetConditionals.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
@ -956,7 +954,8 @@ static std::string ExpandFilePath(const std::string &filepath) {
|
|||||||
return s;
|
return s;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || defined(__ANDROID__)
|
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR) || \
|
||||||
|
defined(__ANDROID__)
|
||||||
// no expansion
|
// no expansion
|
||||||
std::string s = filepath;
|
std::string s = filepath;
|
||||||
#else
|
#else
|
||||||
@ -1029,6 +1028,11 @@ static std::string GetBaseDir(const std::string &filepath) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/8520560/get-a-file-name-from-a-path
|
||||||
|
std::string GetBaseFilename(const std::string &filepath) {
|
||||||
|
return filepath.substr(filepath.find_last_of("/\\") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
// std::string base64_encode(unsigned char const* , unsigned int len);
|
// std::string base64_encode(unsigned char const* , unsigned int len);
|
||||||
std::string base64_decode(std::string const &s);
|
std::string base64_decode(std::string const &s);
|
||||||
|
|
||||||
@ -1188,14 +1192,14 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
|
void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
|
||||||
LoadImageData = func;
|
LoadImageData = func;
|
||||||
load_image_user_data_ = user_data;
|
load_image_user_data_ = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TINYGLTF_NO_STB_IMAGE
|
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||||
static bool LoadImageData(Image *image, std::string *err, int req_width,
|
static bool LoadImageData(Image *image, std::string *err, int req_width,
|
||||||
int req_height, const unsigned char *bytes,
|
int req_height, const unsigned char *bytes, int size,
|
||||||
int size, void*) {
|
void *) {
|
||||||
int w, h, comp;
|
int w, h, comp;
|
||||||
// if image cannot be decoded, ignore parsing and keep it by its path
|
// if image cannot be decoded, ignore parsing and keep it by its path
|
||||||
// don't break in this case
|
// don't break in this case
|
||||||
@ -1268,12 +1272,12 @@ static bool IsDataURI(const std::string &in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
header = "data:image/bmp;base64,";
|
header = "data:image/bmp;base64,";
|
||||||
if(in.find(header) == 0) {
|
if (in.find(header) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
header = "data:image/gif;base64,";
|
header = "data:image/gif;base64,";
|
||||||
if(in.find(header) == 0) {
|
if (in.find(header) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1401,8 +1405,7 @@ static bool ParseExtrasProperty(Value *ret, const json &o) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseBooleanProperty(bool *ret, std::string *err,
|
static bool ParseBooleanProperty(bool *ret, std::string *err, const json &o,
|
||||||
const json &o,
|
|
||||||
const std::string &property,
|
const std::string &property,
|
||||||
const bool required,
|
const bool required,
|
||||||
const std::string &parent_node = "") {
|
const std::string &parent_node = "") {
|
||||||
@ -1436,8 +1439,7 @@ static bool ParseBooleanProperty(bool *ret, std::string *err,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseNumberProperty(double *ret, std::string *err,
|
static bool ParseNumberProperty(double *ret, std::string *err, const json &o,
|
||||||
const json &o,
|
|
||||||
const std::string &property,
|
const std::string &property,
|
||||||
const bool required,
|
const bool required,
|
||||||
const std::string &parent_node = "") {
|
const std::string &parent_node = "") {
|
||||||
@ -1472,8 +1474,8 @@ static bool ParseNumberProperty(double *ret, std::string *err,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseNumberArrayProperty(std::vector<double> *ret, std::string *err,
|
static bool ParseNumberArrayProperty(std::vector<double> *ret, std::string *err,
|
||||||
const json &o,
|
const json &o, const std::string &property,
|
||||||
const std::string &property, bool required,
|
bool required,
|
||||||
const std::string &parent_node = "") {
|
const std::string &parent_node = "") {
|
||||||
json::const_iterator it = o.find(property);
|
json::const_iterator it = o.find(property);
|
||||||
if (it == o.end()) {
|
if (it == o.end()) {
|
||||||
@ -1503,7 +1505,8 @@ static bool ParseNumberArrayProperty(std::vector<double> *ret, std::string *err,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret->clear();
|
ret->clear();
|
||||||
for (json::const_iterator i = it.value().begin(); i != it.value().end(); i++) {
|
for (json::const_iterator i = it.value().begin(); i != it.value().end();
|
||||||
|
i++) {
|
||||||
if (!i.value().is_number()) {
|
if (!i.value().is_number()) {
|
||||||
if (required) {
|
if (required) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -1559,13 +1562,15 @@ static bool ParseStringProperty(
|
|||||||
|
|
||||||
static bool ParseStringIntProperty(std::map<std::string, int> *ret,
|
static bool ParseStringIntProperty(std::map<std::string, int> *ret,
|
||||||
std::string *err, const json &o,
|
std::string *err, const json &o,
|
||||||
const std::string &property, bool required, const std::string &parent = "") {
|
const std::string &property, bool required,
|
||||||
|
const std::string &parent = "") {
|
||||||
json::const_iterator it = o.find(property);
|
json::const_iterator it = o.find(property);
|
||||||
if (it == o.end()) {
|
if (it == o.end()) {
|
||||||
if (required) {
|
if (required) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (!parent.empty()) {
|
if (!parent.empty()) {
|
||||||
(*err) += "'" + property + "' property is missing in " + parent + ".\n";
|
(*err) +=
|
||||||
|
"'" + property + "' property is missing in " + parent + ".\n";
|
||||||
} else {
|
} else {
|
||||||
(*err) += "'" + property + "' property is missing.\n";
|
(*err) += "'" + property + "' property is missing.\n";
|
||||||
}
|
}
|
||||||
@ -1634,15 +1639,13 @@ static bool ParseJSONProperty(std::map<std::string, double> *ret,
|
|||||||
json::const_iterator itEnd(obj.end());
|
json::const_iterator itEnd(obj.end());
|
||||||
for (; it2 != itEnd; it2++) {
|
for (; it2 != itEnd; it2++) {
|
||||||
if (it2.value().is_number())
|
if (it2.value().is_number())
|
||||||
ret->insert(std::pair<std::string, double>(it2.key(),
|
ret->insert(std::pair<std::string, double>(it2.key(), it2.value()));
|
||||||
it2.value()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseAsset(Asset *asset, std::string *err,
|
static bool ParseAsset(Asset *asset, std::string *err, const json &o) {
|
||||||
const json &o) {
|
|
||||||
ParseStringProperty(&asset->version, err, o, "version", true, "Asset");
|
ParseStringProperty(&asset->version, err, o, "version", true, "Asset");
|
||||||
ParseStringProperty(&asset->generator, err, o, "generator", false, "Asset");
|
ParseStringProperty(&asset->generator, err, o, "generator", false, "Asset");
|
||||||
ParseStringProperty(&asset->minVersion, err, o, "minVersion", false, "Asset");
|
ParseStringProperty(&asset->minVersion, err, o, "minVersion", false, "Asset");
|
||||||
@ -1653,10 +1656,10 @@ static bool ParseAsset(Asset *asset, std::string *err,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseImage(Image *image, std::string *err,
|
static bool ParseImage(Image *image, std::string *err, const json &o,
|
||||||
const json &o, const std::string &basedir,
|
const std::string &basedir, bool is_binary,
|
||||||
bool is_binary, const unsigned char *bin_data,
|
const unsigned char *bin_data, size_t bin_size,
|
||||||
size_t bin_size, LoadImageDataFunction* LoadImageData = nullptr,
|
LoadImageDataFunction *LoadImageData = nullptr,
|
||||||
void *user_data = nullptr) {
|
void *user_data = nullptr) {
|
||||||
// A glTF image must either reference a bufferView or an image uri
|
// A glTF image must either reference a bufferView or an image uri
|
||||||
double bufferView = -1;
|
double bufferView = -1;
|
||||||
@ -1697,7 +1700,8 @@ static bool ParseImage(Image *image, std::string *err,
|
|||||||
}
|
}
|
||||||
|
|
||||||
double buffer_view = -1.0;
|
double buffer_view = -1.0;
|
||||||
if (!ParseNumberProperty(&buffer_view, err, o, "bufferView", true, "Image")) {
|
if (!ParseNumberProperty(&buffer_view, err, o, "bufferView", true,
|
||||||
|
"Image")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,11 +1760,10 @@ static bool ParseImage(Image *image, std::string *err,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (*LoadImageData)(image, err, 0, 0, &img.at(0),
|
return (*LoadImageData)(image, err, 0, 0, &img.at(0),
|
||||||
static_cast<int>(img.size()), user_data);
|
static_cast<int>(img.size()), user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseTexture(Texture *texture, std::string *err,
|
static bool ParseTexture(Texture *texture, std::string *err, const json &o,
|
||||||
const json &o,
|
|
||||||
const std::string &basedir) {
|
const std::string &basedir) {
|
||||||
(void)basedir;
|
(void)basedir;
|
||||||
double sampler = -1.0;
|
double sampler = -1.0;
|
||||||
@ -1775,9 +1778,8 @@ static bool ParseTexture(Texture *texture, std::string *err,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseBuffer(Buffer *buffer, std::string *err,
|
static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
|
||||||
const json &o, const std::string &basedir,
|
const std::string &basedir, bool is_binary = false,
|
||||||
bool is_binary = false,
|
|
||||||
const unsigned char *bin_data = nullptr,
|
const unsigned char *bin_data = nullptr,
|
||||||
size_t bin_size = 0) {
|
size_t bin_size = 0) {
|
||||||
double byteLength;
|
double byteLength;
|
||||||
@ -1849,7 +1851,8 @@ static bool ParseBuffer(Buffer *buffer, std::string *err,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Assume external .bin file.
|
// Assume external .bin file.
|
||||||
if (!LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes, true)) {
|
if (!LoadExternalFile(&buffer->data, err, buffer->uri, basedir, bytes,
|
||||||
|
true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1922,8 +1925,7 @@ static bool ParseBufferView(BufferView *bufferView, std::string *err,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseAccessor(Accessor *accessor, std::string *err,
|
static bool ParseAccessor(Accessor *accessor, std::string *err, const json &o) {
|
||||||
const json &o) {
|
|
||||||
double bufferView = -1.0;
|
double bufferView = -1.0;
|
||||||
if (!ParseNumberProperty(&bufferView, err, o, "bufferView", true,
|
if (!ParseNumberProperty(&bufferView, err, o, "bufferView", true,
|
||||||
"Accessor")) {
|
"Accessor")) {
|
||||||
@ -2032,9 +2034,9 @@ static bool ParsePrimitive(Primitive *primitive, std::string *err,
|
|||||||
|
|
||||||
// Look for morph targets
|
// Look for morph targets
|
||||||
json::const_iterator targetsObject = o.find("targets");
|
json::const_iterator targetsObject = o.find("targets");
|
||||||
if ((targetsObject != o.end()) &&
|
if ((targetsObject != o.end()) && targetsObject.value().is_array()) {
|
||||||
targetsObject.value().is_array()) {
|
for (json::const_iterator i = targetsObject.value().begin();
|
||||||
for (json::const_iterator i = targetsObject.value().begin(); i != targetsObject.value().end(); i++) {
|
i != targetsObject.value().end(); i++) {
|
||||||
std::map<std::string, int> targetAttribues;
|
std::map<std::string, int> targetAttribues;
|
||||||
|
|
||||||
const json &dict = i.value();
|
const json &dict = i.value();
|
||||||
@ -2042,8 +2044,7 @@ static bool ParsePrimitive(Primitive *primitive, std::string *err,
|
|||||||
json::const_iterator dictItEnd(dict.end());
|
json::const_iterator dictItEnd(dict.end());
|
||||||
|
|
||||||
for (; dictIt != dictItEnd; ++dictIt) {
|
for (; dictIt != dictItEnd; ++dictIt) {
|
||||||
targetAttribues[dictIt.key()] =
|
targetAttribues[dictIt.key()] = static_cast<int>(dictIt.value());
|
||||||
static_cast<int>(dictIt.value());
|
|
||||||
}
|
}
|
||||||
primitive->targets.push_back(targetAttribues);
|
primitive->targets.push_back(targetAttribues);
|
||||||
}
|
}
|
||||||
@ -2060,10 +2061,10 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) {
|
|||||||
mesh->primitives.clear();
|
mesh->primitives.clear();
|
||||||
json::const_iterator primObject = o.find("primitives");
|
json::const_iterator primObject = o.find("primitives");
|
||||||
if ((primObject != o.end()) && primObject.value().is_array()) {
|
if ((primObject != o.end()) && primObject.value().is_array()) {
|
||||||
for (json::const_iterator i = primObject.value().begin(); i != primObject.value().end(); i++) {
|
for (json::const_iterator i = primObject.value().begin();
|
||||||
|
i != primObject.value().end(); i++) {
|
||||||
Primitive primitive;
|
Primitive primitive;
|
||||||
if (ParsePrimitive(&primitive, err,
|
if (ParsePrimitive(&primitive, err, i.value())) {
|
||||||
i.value())) {
|
|
||||||
// Only add the primitive if the parsing succeeds.
|
// Only add the primitive if the parsing succeeds.
|
||||||
mesh->primitives.push_back(primitive);
|
mesh->primitives.push_back(primitive);
|
||||||
}
|
}
|
||||||
@ -2072,9 +2073,9 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) {
|
|||||||
|
|
||||||
// Look for morph targets
|
// Look for morph targets
|
||||||
json::const_iterator targetsObject = o.find("targets");
|
json::const_iterator targetsObject = o.find("targets");
|
||||||
if ((targetsObject != o.end()) &&
|
if ((targetsObject != o.end()) && targetsObject.value().is_array()) {
|
||||||
targetsObject.value().is_array()) {
|
for (json::const_iterator i = targetsObject.value().begin();
|
||||||
for (json::const_iterator i = targetsObject.value().begin(); i != targetsObject.value().end(); i++) {
|
i != targetsObject.value().end(); i++) {
|
||||||
std::map<std::string, int> targetAttribues;
|
std::map<std::string, int> targetAttribues;
|
||||||
|
|
||||||
const json &dict = i.value();
|
const json &dict = i.value();
|
||||||
@ -2082,8 +2083,7 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) {
|
|||||||
json::const_iterator dictItEnd(dict.end());
|
json::const_iterator dictItEnd(dict.end());
|
||||||
|
|
||||||
for (; dictIt != dictItEnd; ++dictIt) {
|
for (; dictIt != dictItEnd; ++dictIt) {
|
||||||
targetAttribues[dictIt.key()] =
|
targetAttribues[dictIt.key()] = static_cast<int>(dictIt.value());
|
||||||
static_cast<int>(dictIt.value());
|
|
||||||
}
|
}
|
||||||
mesh->targets.push_back(targetAttribues);
|
mesh->targets.push_back(targetAttribues);
|
||||||
}
|
}
|
||||||
@ -2098,8 +2098,8 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseParameterProperty(Parameter *param, std::string *err,
|
static bool ParseParameterProperty(Parameter *param, std::string *err,
|
||||||
const json &o,
|
const json &o, const std::string &prop,
|
||||||
const std::string &prop, bool required) {
|
bool required) {
|
||||||
double num_val;
|
double num_val;
|
||||||
|
|
||||||
// A parameter value can either be a string or an array of either a boolean or
|
// A parameter value can either be a string or an array of either a boolean or
|
||||||
@ -2163,17 +2163,16 @@ static bool ParseNode(Node *node, std::string *err, const json &o) {
|
|||||||
|
|
||||||
node->children.clear();
|
node->children.clear();
|
||||||
json::const_iterator childrenObject = o.find("children");
|
json::const_iterator childrenObject = o.find("children");
|
||||||
if ((childrenObject != o.end()) &&
|
if ((childrenObject != o.end()) && childrenObject.value().is_array()) {
|
||||||
childrenObject.value().is_array()) {
|
for (json::const_iterator i = childrenObject.value().begin();
|
||||||
for (json::const_iterator i = childrenObject.value().begin(); i != childrenObject.value().end(); i++) {
|
i != childrenObject.value().end(); i++) {
|
||||||
if (!i.value().is_number()) {
|
if (!i.value().is_number()) {
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) += "Invalid `children` array.\n";
|
(*err) += "Invalid `children` array.\n";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const int &childrenNode =
|
const int &childrenNode = static_cast<int>(i.value());
|
||||||
static_cast<int>(i.value());
|
|
||||||
node->children.push_back(childrenNode);
|
node->children.push_back(childrenNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2181,27 +2180,23 @@ static bool ParseNode(Node *node, std::string *err, const json &o) {
|
|||||||
ParseExtrasProperty(&(node->extras), o);
|
ParseExtrasProperty(&(node->extras), o);
|
||||||
|
|
||||||
json::const_iterator extensions_object = o.find("extensions");
|
json::const_iterator extensions_object = o.find("extensions");
|
||||||
if ((extensions_object != o.end()) &&
|
if ((extensions_object != o.end()) && extensions_object.value().is_object()) {
|
||||||
extensions_object.value().is_object()) {
|
const json &ext_values_object = extensions_object.value();
|
||||||
const json &ext_values_object =
|
|
||||||
extensions_object.value();
|
|
||||||
|
|
||||||
json::const_iterator it(ext_values_object.begin());
|
json::const_iterator it(ext_values_object.begin());
|
||||||
json::const_iterator itEnd(ext_values_object.end());
|
json::const_iterator itEnd(ext_values_object.end());
|
||||||
|
|
||||||
for (; it != itEnd; it++) {
|
for (; it != itEnd; it++) {
|
||||||
if ((it.key().compare("KHR_lights_cmn") == 0) &&
|
if ((it.key().compare("KHR_lights_cmn") == 0) && it.value().is_object()) {
|
||||||
it.value().is_object()) {
|
const json &light_values_object = it.value();
|
||||||
const json &light_values_object =
|
|
||||||
it.value();
|
|
||||||
|
|
||||||
json::const_iterator itVal(light_values_object.begin());
|
json::const_iterator itVal(light_values_object.begin());
|
||||||
json::const_iterator itValEnd(light_values_object.end());
|
json::const_iterator itValEnd(light_values_object.end());
|
||||||
|
|
||||||
for (; itVal != itValEnd; itVal++) {
|
for (; itVal != itValEnd; itVal++) {
|
||||||
Parameter param;
|
Parameter param;
|
||||||
if (ParseParameterProperty(¶m, err, light_values_object, itVal.key(),
|
if (ParseParameterProperty(¶m, err, light_values_object,
|
||||||
false)) {
|
itVal.key(), false)) {
|
||||||
node->extLightsValues[itVal.key()] = param;
|
node->extLightsValues[itVal.key()] = param;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2212,8 +2207,7 @@ static bool ParseNode(Node *node, std::string *err, const json &o) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseMaterial(Material *material, std::string *err,
|
static bool ParseMaterial(Material *material, std::string *err, const json &o) {
|
||||||
const json &o) {
|
|
||||||
material->values.clear();
|
material->values.clear();
|
||||||
material->extPBRValues.clear();
|
material->extPBRValues.clear();
|
||||||
material->additionalValues.clear();
|
material->additionalValues.clear();
|
||||||
@ -2224,8 +2218,7 @@ static bool ParseMaterial(Material *material, std::string *err,
|
|||||||
for (; it != itEnd; it++) {
|
for (; it != itEnd; it++) {
|
||||||
if (it.key() == "pbrMetallicRoughness") {
|
if (it.key() == "pbrMetallicRoughness") {
|
||||||
if (it.value().is_object()) {
|
if (it.value().is_object()) {
|
||||||
const json &values_object =
|
const json &values_object = it.value();
|
||||||
it.value();
|
|
||||||
|
|
||||||
json::const_iterator itVal(values_object.begin());
|
json::const_iterator itVal(values_object.begin());
|
||||||
json::const_iterator itValEnd(values_object.end());
|
json::const_iterator itValEnd(values_object.end());
|
||||||
@ -2240,14 +2233,12 @@ static bool ParseMaterial(Material *material, std::string *err,
|
|||||||
}
|
}
|
||||||
} else if (it.key() == "extensions") {
|
} else if (it.key() == "extensions") {
|
||||||
if (it.value().is_object()) {
|
if (it.value().is_object()) {
|
||||||
const json &extension =
|
const json &extension = it.value();
|
||||||
it.value();
|
|
||||||
|
|
||||||
json::const_iterator extIt = extension.begin();
|
json::const_iterator extIt = extension.begin();
|
||||||
if (!extIt.value().is_object()) continue;
|
if (!extIt.value().is_object()) continue;
|
||||||
|
|
||||||
const json &values_object =
|
const json &values_object = extIt.value();
|
||||||
extIt.value();
|
|
||||||
|
|
||||||
json::const_iterator itVal(values_object.begin());
|
json::const_iterator itVal(values_object.begin());
|
||||||
json::const_iterator itValEnd(values_object.end());
|
json::const_iterator itValEnd(values_object.end());
|
||||||
@ -2277,7 +2268,8 @@ static bool ParseAnimationChannel(AnimationChannel *channel, std::string *err,
|
|||||||
const json &o) {
|
const json &o) {
|
||||||
double samplerIndex = -1.0;
|
double samplerIndex = -1.0;
|
||||||
double targetIndex = -1.0;
|
double targetIndex = -1.0;
|
||||||
if (!ParseNumberProperty(&samplerIndex, err, o, "sampler", true, "AnimationChannel")) {
|
if (!ParseNumberProperty(&samplerIndex, err, o, "sampler", true,
|
||||||
|
"AnimationChannel")) {
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) += "`sampler` field is missing in animation channels\n";
|
(*err) += "`sampler` field is missing in animation channels\n";
|
||||||
}
|
}
|
||||||
@ -2286,8 +2278,7 @@ static bool ParseAnimationChannel(AnimationChannel *channel, std::string *err,
|
|||||||
|
|
||||||
json::const_iterator targetIt = o.find("target");
|
json::const_iterator targetIt = o.find("target");
|
||||||
if ((targetIt != o.end()) && targetIt.value().is_object()) {
|
if ((targetIt != o.end()) && targetIt.value().is_object()) {
|
||||||
const json &target_object =
|
const json &target_object = targetIt.value();
|
||||||
targetIt.value();
|
|
||||||
|
|
||||||
if (!ParseNumberProperty(&targetIndex, err, target_object, "node", true)) {
|
if (!ParseNumberProperty(&targetIndex, err, target_object, "node", true)) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -2318,10 +2309,10 @@ static bool ParseAnimation(Animation *animation, std::string *err,
|
|||||||
{
|
{
|
||||||
json::const_iterator channelsIt = o.find("channels");
|
json::const_iterator channelsIt = o.find("channels");
|
||||||
if ((channelsIt != o.end()) && channelsIt.value().is_array()) {
|
if ((channelsIt != o.end()) && channelsIt.value().is_array()) {
|
||||||
for (json::const_iterator i = channelsIt.value().begin(); i != channelsIt.value().end(); i++) {
|
for (json::const_iterator i = channelsIt.value().begin();
|
||||||
|
i != channelsIt.value().end(); i++) {
|
||||||
AnimationChannel channel;
|
AnimationChannel channel;
|
||||||
if (ParseAnimationChannel(&channel, err,
|
if (ParseAnimationChannel(&channel, err, i.value())) {
|
||||||
i.value())) {
|
|
||||||
// Only add the channel if the parsing succeeds.
|
// Only add the channel if the parsing succeeds.
|
||||||
animation->channels.push_back(channel);
|
animation->channels.push_back(channel);
|
||||||
}
|
}
|
||||||
@ -2332,8 +2323,7 @@ static bool ParseAnimation(Animation *animation, std::string *err,
|
|||||||
{
|
{
|
||||||
json::const_iterator samplerIt = o.find("samplers");
|
json::const_iterator samplerIt = o.find("samplers");
|
||||||
if ((samplerIt != o.end()) && samplerIt.value().is_array()) {
|
if ((samplerIt != o.end()) && samplerIt.value().is_array()) {
|
||||||
const json &sampler_array =
|
const json &sampler_array = samplerIt.value();
|
||||||
samplerIt.value();
|
|
||||||
|
|
||||||
json::const_iterator it = sampler_array.begin();
|
json::const_iterator it = sampler_array.begin();
|
||||||
json::const_iterator itEnd = sampler_array.end();
|
json::const_iterator itEnd = sampler_array.end();
|
||||||
@ -2377,8 +2367,7 @@ static bool ParseAnimation(Animation *animation, std::string *err,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseSampler(Sampler *sampler, std::string *err,
|
static bool ParseSampler(Sampler *sampler, std::string *err, const json &o) {
|
||||||
const json &o) {
|
|
||||||
ParseStringProperty(&sampler->name, err, o, "name", false);
|
ParseStringProperty(&sampler->name, err, o, "name", false);
|
||||||
|
|
||||||
double minFilter =
|
double minFilter =
|
||||||
@ -2458,8 +2447,7 @@ static bool ParsePerspectiveCamera(PerspectiveCamera *camera, std::string *err,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseOrthographicCamera(OrthographicCamera *camera,
|
static bool ParseOrthographicCamera(OrthographicCamera *camera,
|
||||||
std::string *err,
|
std::string *err, const json &o) {
|
||||||
const json &o) {
|
|
||||||
double xmag = 0.0;
|
double xmag = 0.0;
|
||||||
if (!ParseNumberProperty(&xmag, err, o, "xmag", true, "OrthographicCamera")) {
|
if (!ParseNumberProperty(&xmag, err, o, "xmag", true, "OrthographicCamera")) {
|
||||||
return false;
|
return false;
|
||||||
@ -2493,8 +2481,7 @@ static bool ParseOrthographicCamera(OrthographicCamera *camera,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParseCamera(Camera *camera, std::string *err,
|
static bool ParseCamera(Camera *camera, std::string *err, const json &o) {
|
||||||
const json &o) {
|
|
||||||
if (!ParseStringProperty(&camera->type, err, o, "type", true, "Camera")) {
|
if (!ParseStringProperty(&camera->type, err, o, "type", true, "Camera")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2519,8 +2506,7 @@ static bool ParseCamera(Camera *camera, std::string *err,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ParseOrthographicCamera(&camera->orthographic, err,
|
if (!ParseOrthographicCamera(&camera->orthographic, err, v.get<json>())) {
|
||||||
v.get<json>())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (camera->type.compare("perspective") == 0) {
|
} else if (camera->type.compare("perspective") == 0) {
|
||||||
@ -2543,8 +2529,7 @@ static bool ParseCamera(Camera *camera, std::string *err,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ParsePerspectiveCamera(&camera->perspective, err,
|
if (!ParsePerspectiveCamera(&camera->perspective, err, v.get<json>())) {
|
||||||
v.get<json>())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2576,7 +2561,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
|
|||||||
|
|
||||||
json v;
|
json v;
|
||||||
|
|
||||||
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(TINYGLTF_NOEXCEPTION)
|
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \
|
||||||
|
defined(_CPPUNWIND)) && \
|
||||||
|
not defined(TINYGLTF_NOEXCEPTION)
|
||||||
try {
|
try {
|
||||||
v = json::parse(str, str + length);
|
v = json::parse(str, str + length);
|
||||||
|
|
||||||
@ -2588,7 +2575,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
v = json::parse(str, str + length, nullptr, /* exception */false);
|
v = json::parse(str, str + length, nullptr, /* exception */ false);
|
||||||
|
|
||||||
if (!v.is_object()) {
|
if (!v.is_object()) {
|
||||||
// Assume parsing was failed.
|
// Assume parsing was failed.
|
||||||
@ -2728,8 +2715,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
if (!ParseBuffer(&buffer, err, it->get<json>(), base_dir,
|
if (!ParseBuffer(&buffer, err, it->get<json>(), base_dir, is_binary_,
|
||||||
is_binary_, bin_data_, bin_size_)) {
|
bin_data_, bin_size_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2844,7 +2831,6 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
|
|||||||
if ((rootIt != v.end()) && rootIt.value().is_array()) {
|
if ((rootIt != v.end()) && rootIt.value().is_array()) {
|
||||||
const json &root = rootIt.value();
|
const json &root = rootIt.value();
|
||||||
|
|
||||||
|
|
||||||
json::const_iterator it(root.begin());
|
json::const_iterator it(root.begin());
|
||||||
json::const_iterator itEnd(root.end());
|
json::const_iterator itEnd(root.end());
|
||||||
for (; it != itEnd; it++) {
|
for (; it != itEnd; it++) {
|
||||||
@ -2928,8 +2914,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Image image;
|
Image image;
|
||||||
if (!ParseImage(&image, err, it.value(), base_dir,
|
if (!ParseImage(&image, err, it.value(), base_dir, is_binary_,
|
||||||
is_binary_, bin_data_, bin_size_, &this->LoadImageData, load_image_user_data_)) {
|
bin_data_, bin_size_, &this->LoadImageData,
|
||||||
|
load_image_user_data_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2957,7 +2944,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
|
|||||||
}
|
}
|
||||||
bool ret = LoadImageData(&image, err, image.width, image.height,
|
bool ret = LoadImageData(&image, err, image.width, image.height,
|
||||||
&buffer.data[bufferView.byteOffset],
|
&buffer.data[bufferView.byteOffset],
|
||||||
static_cast<int>(bufferView.byteLength), load_image_user_data_);
|
static_cast<int>(bufferView.byteLength),
|
||||||
|
load_image_user_data_);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3103,7 +3091,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, const char *str,
|
|||||||
json::const_iterator itEnd(root.end());
|
json::const_iterator itEnd(root.end());
|
||||||
for (; it != itEnd; ++it) {
|
for (; it != itEnd; ++it) {
|
||||||
// parse KHR_lights_cmn extension
|
// parse KHR_lights_cmn extension
|
||||||
if ((it.key().compare("KHR_lights_cmn") == 0) && it.value().is_object()) {
|
if ((it.key().compare("KHR_lights_cmn") == 0) &&
|
||||||
|
it.value().is_object()) {
|
||||||
const json &object = it.value();
|
const json &object = it.value();
|
||||||
json::const_iterator itLight(object.find("lights"));
|
json::const_iterator itLight(object.find("lights"));
|
||||||
json::const_iterator itLightEnd(object.end());
|
json::const_iterator itLightEnd(object.end());
|
||||||
@ -3282,14 +3271,15 @@ bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
|
|||||||
// GLTF Serialization
|
// GLTF Serialization
|
||||||
///////////////////////
|
///////////////////////
|
||||||
|
|
||||||
//typedef std::pair<std::string, json> json_object_pair;
|
// typedef std::pair<std::string, json> json_object_pair;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void SerializeNumberProperty(const std::string &key, T number,
|
static void SerializeNumberProperty(const std::string &key, T number,
|
||||||
json &obj) {
|
json &obj) {
|
||||||
//obj.insert(
|
// obj.insert(
|
||||||
// json_object_pair(key, json(static_cast<double>(number))));
|
// json_object_pair(key, json(static_cast<double>(number))));
|
||||||
obj[key] = static_cast<double>(number);
|
// obj[key] = static_cast<double>(number);
|
||||||
|
obj[key] = number;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -3307,8 +3297,7 @@ static void SerializeNumberArrayProperty(const std::string &key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeStringProperty(const std::string &key,
|
static void SerializeStringProperty(const std::string &key,
|
||||||
const std::string &value,
|
const std::string &value, json &obj) {
|
||||||
json &obj) {
|
|
||||||
obj[key] = value;
|
obj[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3341,8 +3330,7 @@ static void SerializeValue(const std::string &key, const Value &value,
|
|||||||
for (unsigned int i = 0; i < valueKeys.size(); ++i) {
|
for (unsigned int i = 0; i < valueKeys.size(); ++i) {
|
||||||
Value elementValue = value.Get(valueKeys[i]);
|
Value elementValue = value.Get(valueKeys[i]);
|
||||||
if (elementValue.IsInt())
|
if (elementValue.IsInt())
|
||||||
jsonValue[valueKeys[i]] =
|
jsonValue[valueKeys[i]] = static_cast<double>(elementValue.Get<int>());
|
||||||
static_cast<double>(elementValue.Get<int>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obj[key] = jsonValue;
|
obj[key] = jsonValue;
|
||||||
@ -3350,8 +3338,8 @@ static void SerializeValue(const std::string &key, const Value &value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
|
static void SerializeGltfBufferData(const std::vector<unsigned char> &data,
|
||||||
const std::string &binFilePath) {
|
const std::string &binFilename) {
|
||||||
std::ofstream output(binFilePath.c_str(), std::ofstream::binary);
|
std::ofstream output(binFilename.c_str(), std::ofstream::binary);
|
||||||
output.write(reinterpret_cast<const char *>(&data[0]),
|
output.write(reinterpret_cast<const char *>(&data[0]),
|
||||||
std::streamsize(data.size()));
|
std::streamsize(data.size()));
|
||||||
output.close();
|
output.close();
|
||||||
@ -3419,8 +3407,7 @@ static void SerializeGltfAccessor(Accessor &accessor, json &o) {
|
|||||||
SerializeStringProperty("type", type, o);
|
SerializeStringProperty("type", type, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfAnimationChannel(AnimationChannel &channel,
|
static void SerializeGltfAnimationChannel(AnimationChannel &channel, json &o) {
|
||||||
json &o) {
|
|
||||||
SerializeNumberProperty("sampler", channel.sampler, o);
|
SerializeNumberProperty("sampler", channel.sampler, o);
|
||||||
json target;
|
json target;
|
||||||
SerializeNumberProperty("node", channel.target_node, target);
|
SerializeNumberProperty("node", channel.target_node, target);
|
||||||
@ -3429,8 +3416,7 @@ static void SerializeGltfAnimationChannel(AnimationChannel &channel,
|
|||||||
o["target"] = target;
|
o["target"] = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfAnimationSampler(AnimationSampler &sampler,
|
static void SerializeGltfAnimationSampler(AnimationSampler &sampler, json &o) {
|
||||||
json &o) {
|
|
||||||
SerializeNumberProperty("input", sampler.input, o);
|
SerializeNumberProperty("input", sampler.input, o);
|
||||||
SerializeNumberProperty("output", sampler.output, o);
|
SerializeNumberProperty("output", sampler.output, o);
|
||||||
SerializeStringProperty("interpolation", sampler.interpolation, o);
|
SerializeStringProperty("interpolation", sampler.interpolation, o);
|
||||||
@ -3473,16 +3459,16 @@ static void SerializeGltfAsset(Asset &asset, json &o) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfBuffer(Buffer &buffer, json &o,
|
static void SerializeGltfBuffer(Buffer &buffer, json &o,
|
||||||
const std::string &binFilePath) {
|
const std::string &binFilename,
|
||||||
SerializeGltfBufferData(buffer.data, binFilePath);
|
const std::string &binBaseFilename) {
|
||||||
|
SerializeGltfBufferData(buffer.data, binFilename);
|
||||||
SerializeNumberProperty("byteLength", buffer.data.size(), o);
|
SerializeNumberProperty("byteLength", buffer.data.size(), o);
|
||||||
SerializeStringProperty("uri", binFilePath, o);
|
SerializeStringProperty("uri", binBaseFilename, o);
|
||||||
|
|
||||||
if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
|
if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SerializeGltfBufferView(BufferView &bufferView,
|
static void SerializeGltfBufferView(BufferView &bufferView, json &o) {
|
||||||
json &o) {
|
|
||||||
SerializeNumberProperty("buffer", bufferView.buffer, o);
|
SerializeNumberProperty("buffer", bufferView.buffer, o);
|
||||||
SerializeNumberProperty<size_t>("byteLength", bufferView.byteLength, o);
|
SerializeNumberProperty<size_t>("byteLength", bufferView.byteLength, o);
|
||||||
SerializeNumberProperty<size_t>("byteStride", bufferView.byteStride, o);
|
SerializeNumberProperty<size_t>("byteStride", bufferView.byteStride, o);
|
||||||
@ -3613,7 +3599,6 @@ static void SerializeGltfNode(Node &node, json &o) {
|
|||||||
o["extensions"] = lightsExt;
|
o["extensions"] = lightsExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SerializeStringProperty("name", node.name, o);
|
SerializeStringProperty("name", node.name, o);
|
||||||
SerializeNumberArrayProperty<int>("children", node.children, o);
|
SerializeNumberArrayProperty<int>("children", node.children, o);
|
||||||
}
|
}
|
||||||
@ -3734,21 +3719,27 @@ bool TinyGLTF::WriteGltfSceneToFile(
|
|||||||
SerializeGltfAsset(model->asset, asset);
|
SerializeGltfAsset(model->asset, asset);
|
||||||
output["asset"] = asset;
|
output["asset"] = asset;
|
||||||
|
|
||||||
std::string binFilePath = filename;
|
std::string binFilename = GetBaseFilename(filename);
|
||||||
std::string ext = ".bin";
|
std::string ext = ".bin";
|
||||||
std::string::size_type pos = binFilePath.rfind('.', binFilePath.length());
|
std::string::size_type pos = binFilename.rfind('.', binFilename.length());
|
||||||
|
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
binFilePath = binFilePath.substr(0, pos) + ext;
|
binFilename = binFilename.substr(0, pos) + ext;
|
||||||
} else {
|
} else {
|
||||||
binFilePath = "./" + binFilePath + ".bin";
|
binFilename = binFilename + ".bin";
|
||||||
}
|
}
|
||||||
|
std::string binSaveFilePath = GetBaseDir(filename);
|
||||||
|
if (binSaveFilePath.empty()) {
|
||||||
|
binSaveFilePath = "./";
|
||||||
|
}
|
||||||
|
|
||||||
|
binSaveFilePath = JoinPath(binSaveFilePath, binFilename);
|
||||||
|
|
||||||
// BUFFERS (We expect only one buffer here)
|
// BUFFERS (We expect only one buffer here)
|
||||||
json buffers;
|
json buffers;
|
||||||
for (unsigned int i = 0; i < model->buffers.size(); ++i) {
|
for (unsigned int i = 0; i < model->buffers.size(); ++i) {
|
||||||
json buffer;
|
json buffer;
|
||||||
SerializeGltfBuffer(model->buffers[i], buffer, binFilePath);
|
SerializeGltfBuffer(model->buffers[i], buffer, binSaveFilePath, binFilename);
|
||||||
buffers.push_back(buffer);
|
buffers.push_back(buffer);
|
||||||
}
|
}
|
||||||
output["buffers"] = buffers;
|
output["buffers"] = buffers;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user