mirror of
https://github.com/syoyo/tinygltf.git
synced 2026-06-08 11:13:50 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e8a7fd602 | ||
|
|
8098a9e8ed | ||
|
|
e0b393c695 | ||
|
|
c35819f0b7 | ||
|
|
4b9cfc8c1e | ||
|
|
c40c9c223e | ||
|
|
0067b4d941 | ||
|
|
35735bb686 | ||
|
|
4d119d7268 | ||
|
|
fe6a18269f | ||
|
|
bbc1eaeecf | ||
|
|
62cc92566e | ||
|
|
b2aca1ecef | ||
|
|
5a7b8278cd | ||
|
|
3d445cc65d | ||
|
|
51530ee500 | ||
|
|
759976e087 | ||
|
|
6e3d666cf3 | ||
|
|
bf7120f8a0 | ||
|
|
acf1e8a2b1 | ||
|
|
8c85d5e387 | ||
|
|
02e8b8da1e | ||
|
|
ddc76f7724 | ||
|
|
8e9aadf569 | ||
|
|
0eaa23fbfc | ||
|
|
2a5dc852cc |
45
.github/workflows/mingw-w64-msys2.yml
vendored
Normal file
45
.github/workflows/mingw-w64-msys2.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: MSYS2 MinGW-w64 Windows 64bit Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release
|
||||
- devel
|
||||
paths:
|
||||
- 'tiny_gltf.*'
|
||||
- 'CMakeLists.txt'
|
||||
- '.github/workflows/mingw-w64-msys2.yml'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
mingw-w64-msys2-build:
|
||||
name: MSYS2 MinGW-w64 Windows Build
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install core & build dependencies
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: UCRT64
|
||||
install: base-devel
|
||||
pacboy: >-
|
||||
cc:p cmake:p ninja:p
|
||||
update: true
|
||||
release: false
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake \
|
||||
-G"Ninja" \
|
||||
-S . \
|
||||
-B build
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build
|
||||
|
||||
@@ -109,6 +109,7 @@ WASI build example is located in [wasm](wasm) .
|
||||
* [SanityEngine](https://github.com/DethRaid/SanityEngine) - A C++/D3D12 renderer focused on the personal and professional development of its developer
|
||||
* [Open3D](http://www.open3d.org/) - A Modern Library for 3D Data Processing
|
||||
* [Supernova Engine](https://github.com/supernovaengine/supernova) - Game engine for 2D and 3D projects with Lua or C++ in data oriented design.
|
||||
* [Wicked Engine<img src="https://github.com/turanszkij/WickedEngine/blob/master/Content/logo_small.png" width="28px" align="center"/>](https://github.com/turanszkij/WickedEngine) - 3D engine with modern graphics
|
||||
* Your projects here! (Please send PR)
|
||||
|
||||
## TODOs
|
||||
|
||||
151
tiny_gltf.h
151
tiny_gltf.h
@@ -195,6 +195,11 @@ typedef enum {
|
||||
OBJECT_TYPE
|
||||
} Type;
|
||||
|
||||
typedef enum {
|
||||
Permissive,
|
||||
Strict
|
||||
} ParseStrictness;
|
||||
|
||||
static inline int32_t GetComponentSizeInBytes(uint32_t componentType) {
|
||||
if (componentType == TINYGLTF_COMPONENT_TYPE_BYTE) {
|
||||
return 1;
|
||||
@@ -832,7 +837,7 @@ struct Accessor {
|
||||
int count;
|
||||
bool isSparse;
|
||||
struct {
|
||||
int byteOffset;
|
||||
size_t byteOffset;
|
||||
int bufferView;
|
||||
int componentType; // a TINYGLTF_COMPONENT_TYPE_ value
|
||||
Value extras;
|
||||
@@ -842,7 +847,7 @@ struct Accessor {
|
||||
} indices;
|
||||
struct {
|
||||
int bufferView;
|
||||
int byteOffset;
|
||||
size_t byteOffset;
|
||||
Value extras;
|
||||
ExtensionMap extensions;
|
||||
std::string extras_json_string;
|
||||
@@ -1463,6 +1468,11 @@ class TinyGLTF {
|
||||
bool embedImages, bool embedBuffers,
|
||||
bool prettyPrint, bool writeBinary);
|
||||
|
||||
///
|
||||
/// Sets the parsing strictness.
|
||||
///
|
||||
void SetParseStrictness(ParseStrictness strictness);
|
||||
|
||||
///
|
||||
/// Set callback to use for loading image data
|
||||
///
|
||||
@@ -1552,6 +1562,8 @@ class TinyGLTF {
|
||||
size_t bin_size_ = 0;
|
||||
bool is_binary_ = false;
|
||||
|
||||
ParseStrictness strictness_ = ParseStrictness::Strict;
|
||||
|
||||
bool serialize_default_values_ = false; ///< Serialize default values?
|
||||
|
||||
bool store_original_json_for_extras_and_extensions_ = false;
|
||||
@@ -2553,6 +2565,10 @@ static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
||||
return true;
|
||||
}
|
||||
|
||||
void TinyGLTF::SetParseStrictness(ParseStrictness strictness) {
|
||||
strictness_ = strictness;
|
||||
}
|
||||
|
||||
void TinyGLTF::SetImageLoader(LoadImageDataFunction func, void *user_data) {
|
||||
LoadImageData = func;
|
||||
load_image_user_data_ = user_data;
|
||||
@@ -4632,24 +4648,26 @@ static bool ParseSparseAccessor(
|
||||
const detail::json &indices_obj = detail::GetValue(indices_iterator);
|
||||
const detail::json &values_obj = detail::GetValue(values_iterator);
|
||||
|
||||
int indices_buffer_view = 0, indices_byte_offset = 0, component_type = 0;
|
||||
int indices_buffer_view = 0, component_type = 0;
|
||||
size_t indices_byte_offset = 0;
|
||||
if (!ParseIntegerProperty(&indices_buffer_view, err, indices_obj,
|
||||
"bufferView", true, "SparseAccessor")) {
|
||||
return false;
|
||||
}
|
||||
ParseIntegerProperty(&indices_byte_offset, err, indices_obj, "byteOffset",
|
||||
ParseUnsignedProperty(&indices_byte_offset, err, indices_obj, "byteOffset",
|
||||
false);
|
||||
if (!ParseIntegerProperty(&component_type, err, indices_obj, "componentType",
|
||||
true, "SparseAccessor")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int values_buffer_view = 0, values_byte_offset = 0;
|
||||
int values_buffer_view = 0;
|
||||
size_t values_byte_offset = 0;
|
||||
if (!ParseIntegerProperty(&values_buffer_view, err, values_obj, "bufferView",
|
||||
true, "SparseAccessor")) {
|
||||
return false;
|
||||
}
|
||||
ParseIntegerProperty(&values_byte_offset, err, values_obj, "byteOffset",
|
||||
ParseUnsignedProperty(&values_byte_offset, err, values_obj, "byteOffset",
|
||||
false);
|
||||
|
||||
sparse->count = count;
|
||||
@@ -4857,8 +4875,9 @@ static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh *mesh,
|
||||
}
|
||||
|
||||
static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
||||
std::string *err,
|
||||
const Value &dracoExtensionValue) {
|
||||
std::string *err, std::string *warn,
|
||||
const Value &dracoExtensionValue,
|
||||
ParseStrictness strictness) {
|
||||
(void)err;
|
||||
auto bufferViewValue = dracoExtensionValue.Get("bufferView");
|
||||
if (!bufferViewValue.IsInt()) return false;
|
||||
@@ -4890,6 +4909,33 @@ static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
||||
|
||||
// create new bufferView for indices
|
||||
if (primitive->indices >= 0) {
|
||||
if (strictness == ParseStrictness::Permissive) {
|
||||
const draco::PointIndex::ValueType numPoint = mesh->num_points();
|
||||
// handle the situation where the stored component type does not match the
|
||||
// required type for the actual number of stored points
|
||||
int supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||
if (numPoint < static_cast<draco::PointIndex::ValueType>(
|
||||
std::numeric_limits<uint8_t>::max())) {
|
||||
supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
|
||||
} else if (
|
||||
numPoint < static_cast<draco::PointIndex::ValueType>(
|
||||
std::numeric_limits<uint16_t>::max())) {
|
||||
supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
|
||||
} else {
|
||||
supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
if (supposedComponentType > model->accessors[primitive->indices].componentType) {
|
||||
if (warn) {
|
||||
(*warn) +=
|
||||
"GLTF component type " + std::to_string(model->accessors[primitive->indices].componentType) +
|
||||
" is not sufficient for number of stored points,"
|
||||
" treating as " + std::to_string(supposedComponentType) + "\n";
|
||||
}
|
||||
model->accessors[primitive->indices].componentType = supposedComponentType;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t componentSize = GetComponentSizeInBytes(
|
||||
model->accessors[primitive->indices].componentType);
|
||||
Buffer decodedIndexBuffer;
|
||||
@@ -4955,9 +5001,11 @@ static bool ParseDracoExtension(Primitive *primitive, Model *model,
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ParsePrimitive(Primitive *primitive, Model *model, std::string *err,
|
||||
static bool ParsePrimitive(Primitive *primitive, Model *model,
|
||||
std::string *err, std::string *warn,
|
||||
const detail::json &o,
|
||||
bool store_original_json_for_extras_and_extensions) {
|
||||
bool store_original_json_for_extras_and_extensions,
|
||||
ParseStrictness strictness) {
|
||||
int material = -1;
|
||||
ParseIntegerProperty(&material, err, o, "material", false);
|
||||
primitive->material = material;
|
||||
@@ -5006,18 +5054,22 @@ static bool ParsePrimitive(Primitive *primitive, Model *model, std::string *err,
|
||||
auto dracoExtension =
|
||||
primitive->extensions.find("KHR_draco_mesh_compression");
|
||||
if (dracoExtension != primitive->extensions.end()) {
|
||||
ParseDracoExtension(primitive, model, err, dracoExtension->second);
|
||||
ParseDracoExtension(primitive, model, err, warn, dracoExtension->second, strictness);
|
||||
}
|
||||
#else
|
||||
(void)model;
|
||||
(void)warn;
|
||||
(void)strictness;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseMesh(Mesh *mesh, Model *model, std::string *err,
|
||||
static bool ParseMesh(Mesh *mesh, Model *model,
|
||||
std::string *err, std::string *warn,
|
||||
const detail::json &o,
|
||||
bool store_original_json_for_extras_and_extensions) {
|
||||
bool store_original_json_for_extras_and_extensions,
|
||||
ParseStrictness strictness) {
|
||||
ParseStringProperty(&mesh->name, err, o, "name", false);
|
||||
|
||||
mesh->primitives.clear();
|
||||
@@ -5030,8 +5082,9 @@ static bool ParseMesh(Mesh *mesh, Model *model, std::string *err,
|
||||
detail::ArrayBegin(detail::GetValue(primObject));
|
||||
i != primEnd; ++i) {
|
||||
Primitive primitive;
|
||||
if (ParsePrimitive(&primitive, model, err, *i,
|
||||
store_original_json_for_extras_and_extensions)) {
|
||||
if (ParsePrimitive(&primitive, model, err, warn, *i,
|
||||
store_original_json_for_extras_and_extensions,
|
||||
strictness)) {
|
||||
// Only add the primitive if the parsing succeeds.
|
||||
mesh->primitives.emplace_back(std::move(primitive));
|
||||
}
|
||||
@@ -5192,15 +5245,24 @@ static bool ParsePbrMetallicRoughness(
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ParseMaterial(Material *material, std::string *err,
|
||||
static bool ParseMaterial(Material *material, std::string *err, std::string *warn,
|
||||
const detail::json &o,
|
||||
bool store_original_json_for_extras_and_extensions) {
|
||||
bool store_original_json_for_extras_and_extensions,
|
||||
ParseStrictness strictness) {
|
||||
ParseStringProperty(&material->name, err, o, "name", /* required */ false);
|
||||
|
||||
if (ParseNumberArrayProperty(&material->emissiveFactor, err, o,
|
||||
"emissiveFactor",
|
||||
/* required */ false)) {
|
||||
if (material->emissiveFactor.size() != 3) {
|
||||
if (strictness==ParseStrictness::Permissive && material->emissiveFactor.size() == 4) {
|
||||
if (warn) {
|
||||
(*warn) +=
|
||||
"Array length of `emissiveFactor` parameter in "
|
||||
"material must be 3, but got 4\n";
|
||||
}
|
||||
material->emissiveFactor.resize(3);
|
||||
}
|
||||
else if (material->emissiveFactor.size() != 3) {
|
||||
if (err) {
|
||||
(*err) +=
|
||||
"Array length of `emissiveFactor` parameter in "
|
||||
@@ -6053,8 +6115,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
return false;
|
||||
}
|
||||
Mesh mesh;
|
||||
if (!ParseMesh(&mesh, model, err, o,
|
||||
store_original_json_for_extras_and_extensions_)) {
|
||||
if (!ParseMesh(&mesh, model, err, warn, o,
|
||||
store_original_json_for_extras_and_extensions_,
|
||||
strictness_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6082,20 +6145,22 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bufferView =
|
||||
const auto bufferView =
|
||||
model->accessors[size_t(primitive.indices)].bufferView;
|
||||
if (bufferView < 0 || size_t(bufferView) >= model->bufferViews.size()) {
|
||||
if (bufferView < 0) {
|
||||
// skip, bufferView could be null(-1) for certain extensions
|
||||
} else if (size_t(bufferView) >= model->bufferViews.size()) {
|
||||
if (err) {
|
||||
(*err) += "accessor[" + std::to_string(primitive.indices) +
|
||||
"] invalid bufferView";
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
model->bufferViews[size_t(bufferView)].target =
|
||||
TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
|
||||
// we could optionally check if accessors' bufferView type is Scalar, as
|
||||
// it should be
|
||||
}
|
||||
|
||||
model->bufferViews[size_t(bufferView)].target =
|
||||
TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER;
|
||||
// we could optionally check if accessors' bufferView type is Scalar, as
|
||||
// it should be
|
||||
}
|
||||
|
||||
for (auto &attribute : primitive.attributes) {
|
||||
@@ -6198,8 +6263,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
||||
Material material;
|
||||
ParseStringProperty(&material.name, err, o, "name", false);
|
||||
|
||||
if (!ParseMaterial(&material, err, o,
|
||||
store_original_json_for_extras_and_extensions_)) {
|
||||
if (!ParseMaterial(&material, err, warn, o,
|
||||
store_original_json_for_extras_and_extensions_,
|
||||
strictness_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -6644,8 +6710,8 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
|
||||
if (err) {
|
||||
(*err) =
|
||||
"Insufficient storage space for Chunk1(BIN data). At least Chunk1 "
|
||||
"Must have 4 bytes or more bytes, but got " +
|
||||
std::to_string((header_and_json_size + 12ull) - uint64_t(length)) +
|
||||
"Must have 4 or more bytes, but got " +
|
||||
std::to_string((header_and_json_size + 8ull) - uint64_t(length)) +
|
||||
".\n";
|
||||
}
|
||||
return false;
|
||||
@@ -6669,10 +6735,17 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
|
||||
}
|
||||
|
||||
if ((chunk1_length % 4) != 0) {
|
||||
if (err) {
|
||||
(*err) = "BIN Chunk end does not aligned to a 4-byte boundary.";
|
||||
if (strictness_==ParseStrictness::Permissive) {
|
||||
if (warn) {
|
||||
(*warn) += "BIN Chunk end is not aligned to a 4-byte boundary.\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (err) {
|
||||
(*err) = "BIN Chunk end is not aligned to a 4-byte boundary.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uint64_t(chunk1_length) + header_and_json_size > uint64_t(length)) {
|
||||
@@ -6697,10 +6770,6 @@ bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
|
||||
bin_size_ = size_t(chunk1_length);
|
||||
}
|
||||
|
||||
// Extract JSON string.
|
||||
std::string jsonString(reinterpret_cast<const char *>(&bytes[20]),
|
||||
chunk0_length);
|
||||
|
||||
is_binary_ = true;
|
||||
|
||||
bool ret = LoadFromString(model, err, warn,
|
||||
@@ -7098,7 +7167,7 @@ static void SerializeGltfAccessor(const Accessor &accessor, detail::json &o) {
|
||||
SerializeNumberProperty<int>("bufferView", accessor.bufferView, o);
|
||||
|
||||
if (accessor.byteOffset != 0)
|
||||
SerializeNumberProperty<int>("byteOffset", int(accessor.byteOffset), o);
|
||||
SerializeNumberProperty<size_t>("byteOffset", accessor.byteOffset, o);
|
||||
|
||||
SerializeNumberProperty<int>("componentType", accessor.componentType, o);
|
||||
SerializeNumberProperty<size_t>("count", accessor.count, o);
|
||||
@@ -7169,7 +7238,7 @@ static void SerializeGltfAccessor(const Accessor &accessor, detail::json &o) {
|
||||
detail::json indices;
|
||||
SerializeNumberProperty<int>("bufferView",
|
||||
accessor.sparse.indices.bufferView, indices);
|
||||
SerializeNumberProperty<int>("byteOffset",
|
||||
SerializeNumberProperty<size_t>("byteOffset",
|
||||
accessor.sparse.indices.byteOffset, indices);
|
||||
SerializeNumberProperty<int>(
|
||||
"componentType", accessor.sparse.indices.componentType, indices);
|
||||
@@ -7180,7 +7249,7 @@ static void SerializeGltfAccessor(const Accessor &accessor, detail::json &o) {
|
||||
detail::json values;
|
||||
SerializeNumberProperty<int>("bufferView",
|
||||
accessor.sparse.values.bufferView, values);
|
||||
SerializeNumberProperty<int>("byteOffset",
|
||||
SerializeNumberProperty<size_t>("byteOffset",
|
||||
accessor.sparse.values.byteOffset, values);
|
||||
SerializeExtrasAndExtensions(accessor.sparse.values, values);
|
||||
detail::JsonAddMember(sparse, "values", std::move(values));
|
||||
|
||||
Reference in New Issue
Block a user