syoyo / tinygltf Goto Github PK
View Code? Open in Web Editor NEWHeader only C++11 tiny glTF 2.0 library
License: MIT License
Header only C++11 tiny glTF 2.0 library
License: MIT License
Add GLSL PBR shader into glview
example.
ran into this likely rare case, where a data uri was used for a buffer inside of a glb file. the parser skipped over it.
suggested change, inside of ParseBuffer right after the !uri.empty() check,
make sure to try to parse a datauri first,
see below.
snip---------------------------------------
if (is_binary) {
// Still binary glTF accepts external dataURI. First try external resources.
if (!uri.empty()) {
if (IsDataURI(uri)) { // <--- Here
if (!DecodeDataURI(&buffer->data, uri, bytes, true)) {
if (err) {
(*err) += "Failed to decode 'uri' : " + uri + " in Buffer\n";
}
return false;
}
}
else {
// Assume external .bin file.
LoadExternalFile(&buffer->data, err, uri, basedir, bytes, true);
}
} else {
// load data from (embedded) binary data
snip--------------------------------------------
I just noticed this when looking at the branch tree, master
was recently (June 4th) modified with some fixes, but it was last changed a very long time before that. Was this a mistake?
Hi,
I have some problems with value objects. This is only really a concern when it comes to extensions, because just the definition of an extension may change behaviour, even if the object is empty (e.g. all parameters are default values).
Right now, when reading the gltf file, any empty objects are completely ignored, which results in their type being TYPE_NULL
.
The same goes for writing. When writing a Value::Object
, if the object is empty, it is not written to the output.
This makes a lot of sense for normal gltf objects, however for extensions this poses a problem. Extensions can (and often will) modify the default behaviour if they are present, even if they do not define any of their properties (e.g. their properties are all default values).
The spec defines the extensions
object like this: Dictionary object with extension-specific objects.
Strictly speaking, this means all values contained by the extensions
object should be objects themselves.
I suggest we modify the ParseExtensionsProperty
and SerializeExtensionMap
to always serialize the top-level values in the extensions
object as objects.
This means we will be able to read and subsequently write this, which is currently not possible:
"materials": [
{
"name": "WHITE",
"extensions": {
"VENDOR_material_some_ext": {
}
}
},
Line 3282 in 1e94d05
std::vectorstd::string valueKeys;
should be
std::vectorstd::string valueKeys = value.Keys();
Support HDR image format for the texture as an extension.
This seems inconsistent with loading images. In addition, we actually need the uri for caching purposes.
Is there a specific reason for this, or can we perhaps save it? : )
Hey there! Really cool library! Been using it to great success in the last few days. C:
But I was just about to cross-compile a Windows build for someone using MinGW on a Linux box when I got an error about Windows.h not being found in tiny_gltf.h. Looking online, I saw people using lowercase windows.h rather than uppercase Windows.h, so I tried making the change, and the compilation was successful.
Probably the compiler on Windows is case-insensitive and so it works either way, but it has to be lowercase on MinGW on Linux at least. Too quick a fix for me to do the whole pull request routine for, since it's just a matter of one letter in one file, but it's on line 683. c;
Fixed it myself for myself, but might as well fix it for others in the future. Thanks!
It takes a template parameter, but doesn't use it. Mistake?
Hi,
I bumped into a small problem while implementing the loading of glTF assets into a project via this library.
When the byteStride of a buffer view is not defined inside the glTF file, the glTF standard states that this means "the data is tightly packed".
The current way tinygltf handle this is by putting the byteStride member of the bufferView object to zero.
I think a saner thing to do as a loading library, would be to actually put there the value it should have when reading the buffer as just a plain array of the underlying datatype.
This permit the library user to just iterate through the data with the same code, with no regards into checking if the byteStride is 0, and thus making this kind of code work all the time.
In that case, making byteStride be sizeof(component_type) * countOfElementsInType
Where countOfElementsInType
is equal to the number of variable you need to get one element in the array (e.g. for a buffer of FLOAT that represent a VEC3, be equal to sizeof(float) * 3
)
for(size_t i = 0; i < bufferLenghtInElements; ++i)
{
//Access the data of each element of the buffer
buffer.data[(bufferView.byteOffset + accessor.byteOffset) + i * bufferView.byteStride]
}
Strictly speaking, this is okay according to the representation of the file we do here in C++ in regards to the data that was in the JSON file, and how the specification say we should interpret it.
Here's where the standard defines what not setting the byteStride means : https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment
What do you think about this ?
Thanks again for the awesome work on this "tiny" library ;-)
Hi,
I'm trying to bind tinygltf to my graphics engine but there something I either don't understand or isn't supported.
According to this spec:
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
I should be able to get the vertex buffer from the Mesh. I was expecting to do something like:
model->accessors[mesh.primitives[i].BufferViewIndex]
and then getting the buffer to call glBufferStorage
/glBufferData
but the Primitive only contain "indices" and "material".
I cannot just loop through all model_->bufferViews
because I need to know which bufferView is owned to which mesh.
loading a simple cube GLTF with embedded mesh data (no additional files) leaks 2 allocations. works fine with GLB equivalent.
i detected this using a custom memory allocator which asserts if every alloc isnt freed on exit.
tested with vs2015
Line 64 in 05e0bf1
The only example I see is the saver, which just loads a model and re-saves it. For someone writing an exporter it would be great to have an example that creates a simple model from scratch.
This happens when you supply a full file path to save to. I did not try using a relative file path.
To support embedded devices or environments where RTTI and exception are not available.
Hi,
I'm wondering if there is currently any way to validate that serialization is working correctly? The project I'm working on has many and rather large models, so any mismatch is a potentially large time-waster. There have been a few errors before (as I've seen and submitted pull requests to fix them), so this could help in both catching mistakes and testing new implementations.
E.g. I would like to compare model data using the equals ==
operator. If it is a wanted feature, I could make a pull request.
Alternatively, I imagine the json parser implements the equals operator, so perhaps we could refactor to make use of that?
Any ideas and concerns are welcome.
Forwarding from a colleague.
In addition to not passing the header size check, accessors, bufferviews and buffers are still flagged as required in the loading process, but in fact are not present in this scenario and should be skipped.
The GLB file format specification specifies that the Bin header & data of a GLB file are not mandatory (it says the number of BIN headers can be 0 or 1). However, if I try to load a GLB from memory with no Bin buffer, the loader fails.
This is due to the “LoadBinaryFromMemory” methods that checks the size of the binary data. In case the Bin buffer is not present, the size is exactly 20 + size of JSON contents. The test is done with a greater or equal operator, and so it passes and returns false.
The suggested fix is to change this operator to a “greater than” operator.That is:
if ((20 + model_length >= size) || (model_length < 1) || (model_format != 0x4E4F534A)) { // 0x4E4F534A = JSON format. if (err) { (*err) = "Invalid glTF binary."; } return false; }
Would become:
if ((20 + model_length > size) || (model_length < 1) || // specification allows a GLB file with no bin buffer (model_format != 0x4E4F534A)) { // 0x4E4F534A = JSON format. if (err) { (*err) = "Invalid glTF binary."; } return false; }
Hi,
The "glview" project runs fine on Windows, but I noticed that there were some errors when building using the "premake4.lua" script with Premake 5. I've changed some of the flags based on the following logs:
This version of "premake5.lua" generates a project without errors, which might be useful to copy:
solution "glview"
-- location ( "build" )
configurations { "Debug", "Release" }
platforms {"native", "x64", "x32"}
project "glview"
kind "ConsoleApp"
language "C++"
cppdialect "C++11"
files { "glview.cc", "trackball.cc" }
includedirs { "./" }
includedirs { "../../" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" }
configuration { "windows" }
-- Edit path to glew and GLFW3 fit to your environment.
includedirs { "../../../../local/glew-1.13.0/include/" }
includedirs { "../../../../local/glfw-3.2.bin.WIN32/include/" }
libdirs { "../../../../local/glew-1.13.0/lib/Release/Win32/" }
libdirs { "../../../../local/glfw-3.2.bin.WIN32/lib-vc2013/" }
links { "glfw3", "gdi32", "winmm", "user32", "glew32", "glu32","opengl32", "kernel32" }
defines { "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
includedirs { "/usr/local/include" }
buildoptions { "-Wno-deprecated-declarations" }
libdirs { "/usr/local/lib" }
links { "glfw3", "GLEW" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }
configuration "Debug"
defines { "DEBUG" }
symbols "On"
warnings "Extra"
configuration "Release"
defines { "NDEBUG" }
optimize "On"
warnings "Extra"
Hi,
Currently, if I want to develop and use a custom extension, I would have to add parsing of this extension to the code.
Instead, would it not be more convenient to put every ParameterMap inside... well.. another map, indexing by string?
Something like this:
typedef std::map<std::string, ParameterMap> ExtensionMap;
ParseExtensions(...)
struct Material {
...
ExtensionMap extensions;
...
}
... {
if (it.key() == "extensions")
{
ExtensionMap extensions;
if(ParseExtensions(...)) {
material->extensions = extensions;
}
}
}
I tried to load a model with your example but the visual gave me this compile errors for TinyGLTF class declaration:
everity Code Description Project File Line Suppression State Error LNK2019 unresolved external symbol "bool __cdecl tinygltf::LoadImageData(struct tinygltf::Image *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > *,int,int,unsigned char const *,int,void *)" (?LoadImageData@tinygltf@@YA_NPAUImage@1@PAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HHPBEHPAX@Z) referenced in function "public: __thiscall tinygltf::TinyGLTF::TinyGLTF(void)" (??0TinyGLTF@tinygltf@@QAE@XZ)
and
Severity Code Description Project File Line Suppression State Error LNK2019 unresolved external symbol "bool __cdecl tinygltf::WriteImageData(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const *,struct tinygltf::Image *,bool,void *)" (?WriteImageData@tinygltf@@YA_NPBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@0PAUImage@1@_NPAX@Z) referenced in function "public: __thiscall tinygltf::TinyGLTF::TinyGLTF(void)" (??0TinyGLTF@tinygltf@@QAE@XZ)
I am using MSV 2015
Given the example below, I'm not sure how to get the Index values of both the normal and base textures. Is there an example showing this?
"materials" : [
{
"name" : "Material",
"normalTexture" : {
"index" : 1
},
"pbrMetallicRoughness" : {
"baseColorFactor" : [
0.800000011920929,
0.800000011920929,
0.800000011920929,
1.0
],
"baseColorTexture" : {
"index" : 0
},
"metallicFactor" : 0.0
}
}
],
Offending line of code: ParseNumberProperty(&byteLength, err, o, "byteStride", false);
Since many glTF files exclude this property, many files will load fine. One example asset I found which will cause this issue is "GearboxAssy.glb" from glTF-Sample-Models.
https://github.com/syoyo/tinygltf/blob/devel/tiny_gltf.h#L1582
Spec says:
When byteStride of referenced bufferView is not defined, it means that accessor elements are tightly packed, i.e., effective stride equals the size of the element.
Reported by @Teybeo
As far As I understand the tiny_gltf I should use the camera index Node::camera and use it to find the good camera in corresponding std::vector in tinygltf::Model.
The problem is there is no std::vector in Model, grep -i "Camera" only give me the class definition of Camera and there is no reference to camera loading in the examples that I could find.
On my engine I will assume that the camera position/rotation is the node position/rotation but I can't get more information from the node (fov, aspect ratio, zfar/znear etc...)
Did I missed something or it isn't implemented ?
Add parsing option to specify the preferred number of texture channels(e.g. want to load texture always as 32bit RGBA)
Gltf models with separate images and buffers, with a space in the filename will not load.
The bug only occurs in Linux build, (it can not be reproduced on windows.)
How to reproduce:
I have attached a model, duck with spaces.zip, that fails when loaded by loader_example.
tinygltf/examples/raytrace/gltf-loader.cc
Line 48 in 6602560
Seams like it should return true here.
I tried running after that and it crashed :( (on windows)
I've got some warning at beginning also which I just disabled :|
I want to print all of the vertex positions of the mesh to the screen, but I have no idea how. Can someone help me out please ?
What I have already done:
https://pastebin.com/PiGencLV
sry for the pastebin but that "Insert code" is useless (my first part of the code is out of the highlight box)
I cannot figure out how to use this to draw models. Is it possible to have a more simple example, I'm finding the glview example is difficult to follow.
As an example I have so far a basic work in progress https://gist.github.com/viperscape/989cf91ecbd42a2dd89780e30a166c0a
I think my drawMesh is to blame: https://gist.github.com/viperscape/989cf91ecbd42a2dd89780e30a166c0a#file-main-cpp-L88
I was able to render a triangle of vertex points using the same shader and model-view functions. So I must be missing something inherent with how gltf works and how the example was laid out.
Any help is appreciated! If this is too off-topic for an issue, feel free to close
Implement glTF 2.0 serializer(saver)
@AurL, I have refactored devel
branch and now devel
branch will be ready to accept serializer PR from you. Could you please send your serializer PR to devel
branch?
Some configuration failed in TravisCI and AppVeyor.
It would be nice to add an option not decoding pixels(e.g. jpg/png) during glTF parsing for example faster glTF parsing.
For that purpose, easiest way is add an option something raw
or undecoded
flag to Image
.
tinygltf currently assumes that external files physically reside on the host's filesystem. In many game engines and similiar programs, however, files are packed in virtual "container" files and/or managed by libraries such as PhysicsFS that do not directly access the physical filesystem.
A simple way to solve this issue would be making the prototypes ofFileExists
, LoadExternalFile
, ExpandFilePath
and any other file I/O functions be visible to the user and letting their default implementations be disabled by #define TINYGLTF_NO_FS_IMPLEMENTATION
.
I could try implementing this functionality and pushing it to the repo if you would like.
I used tinygltf in a project, and one thing I think most will need are sanity checks done on the loaded tinyglt::Model object, beyond the basics already provided. A few things which would be useful:
Now this project is self-described as "tiny" so one question I have is where does this functionality belong? Possible locations:
To me option three feels right by keeping the functionality completely optional but readily available. I'd be interested in getting the ball rolling on this. Thoughts?
Hello again! I have another quick fix to suggest after another cross-compiling adventure. c:
I got errors compiling to iOS because the checks for TARGET_OS_IPHONE
failed and the library ended up trying to do things it was not meant to try to do on iOS; this is because you forgot to do this in order to include the definition (which in my experience is not meant to be set by the IDE for an iOS project but by including this file):
#if __APPLE__
#include "TargetConditionals.h"
#endif
I added it right before namespace gltf
but feel free to put it where you think makes sense and that should fix it. c:
Unless there is a better parsing method idk about, it seems very useful to have the ability to self-identify which index an item is. For example, if I pass in a tinygltf::Node
to a function I am finding myself also passing its index as a 2nd parameter. I also will pass in the top tinygltf::Model
but then I need to transverse the entire list of Nodes to check if its the same if I am trying to match an animation sampler up to it.
Not sure if this is outside scope of tinygltf, but seems like the simplest fix for an issue I keep reincurring.
Latest AMD drivers does not support RGB format in textures. Only R, RG, or RGBA.
Implement writing glTF data to memory(std::string)
I'm trying to integrate tinygltf in my framework. A simple way to manage all the resources loaded is storing them in a map container using strings. On any string tag like material name, mesh name, texture name etc i am always getting empty string "".
By default there will be a compile error in most Visual Studio projects due to a Windows macro for min and max. You can fix this by replacing this line in picojson.h:
if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() &&
With this:
if (errno == 0 && (std::numeric_limits<int64_t>::min)() <= ival && ival <= (std::numeric_limits<int64_t>::max)() &&
I notice that some type like Buffer is a typedef in h. This makes forward declearation in other header files not possible (https://stackoverflow.com/questions/18501993/struct-forward-declaration-error-typedef-redefinition-with-different-types).
Is that a special feature in tiny_gltf to avoid user directly define functions to use these types? Or should we just makes all typedef to struct?
Thank you.
i think there is logic error in line 1709?
// Write image to disc
FsCallbacks *fs = reinterpret_cast<FsCallbacks *>(fsPtr);
if (fs != nullptr && fs->WriteWholeFile == nullptr) {
......
Hi,
I used afl-fuzz (American Fuzzy Lop) to fuzz test input to the loader_example program. It triggered assertions (abort behavior, I believe to be intentional) but no major issues were found. I wanted to let you know in case these are worth your time to fix. If not, then please close this issue at your leasire.
Input files and a few example stack traces can be found here: https://github.com/rwhitworth/tinygltf-fuzz/tree/master/2017-07-31
static void SerializeGltfImage(Image &image, json &o)
{
if (!image.mimeType.empty())
{
// (required if no uri)
// (required if no uri) ["image/jpeg", "image/png",
// "image/bmp", "image/gif"]
SerializeStringProperty("mimeType", image.mimeType, o);
SerializeNumberProperty("bufferview", image.bufferView, o);
}
else if (!image.uri.empty())
{
SerializeStringProperty("uri", image.uri, o);
}
Last time, last updates (after MSVC fix) glTF not loading correctly (texcoords). I also, loading images by FreeImage. Here is model https://sketchfab.com/features/gltf
tinygltf/examples/raytrace/gltf-loader.cc
Line 47 in dac2a89
Somewhere here should be a code which translates data from model to meshes/materials/textures
right now it returns true but actually there is nothing in the output buffers.
After that it crashed inside nanort when it calculates BoundingBox with 0 elements inside mesh(This looks like a separate issue).
Translate Model to output buffers or log message about TODO.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.