Compare commits

..

6 Commits

Author SHA1 Message Date
Syoyo Fujita
1b7994a4f4 Make lodepng optional. 2019-01-14 21:33:56 +09:00
Syoyo Fujita
c91b6468e8 Merge pull request #133 from Ybalrid/lodepng
fix ci build of example
2019-01-11 02:29:29 +09:00
Arthur Brainville (Ybalrid)
d4f8fcea10 fix ci build of example 2019-01-10 18:19:20 +00:00
Syoyo Fujita
ab069ffb40 Initial support of loading 16bit PNG using lodepng. 2019-01-07 02:27:28 +09:00
Syoyo Fujita
cbf13fef62 Merge branch 'master' into lodepng 2019-01-07 01:05:12 +09:00
Syoyo Fujita
57074aee04 Add single file version of lodepng. 2019-01-07 01:04:37 +09:00
15 changed files with 7959 additions and 320 deletions

21
LICENSE.lodepng Normal file
View File

@@ -0,0 +1,21 @@
Copyright (c) 2005-2018 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

View File

@@ -46,14 +46,11 @@ v2.0.0 release(22 Aug, 2018)!
* Load from memory
* Custom callback handler
* [x] Image load
* Extensions
* [x] Draco mesh decoding
## Examples
* [glview](examples/glview) : Simple glTF geometry viewer.
* [validator](examples/validator) : Simple glTF validator with JSON schema.
* [basic](examples/basic) : Basic glTF viewer with texturing support.
## Projects using TinyGLTF
@@ -67,8 +64,7 @@ v2.0.0 release(22 Aug, 2018)!
* [ ] Write C++ code generator which emits C++ code from JSON schema for robust parsing.
* [ ] Mesh Compression/decompression(Open3DGC, etc)
* [x] Load Draco compressed mesh
* [x] Save Draco compressed mesh
* [ ] Load Draco compressed mesh
* [ ] Support `extensions` and `extras` property
* [ ] HDR image?
* [ ] OpenEXR extension through TinyEXR.
@@ -86,6 +82,7 @@ TinyGLTF uses the following third party libraries.
* base64 : Copyright (C) 2004-2008 René Nyffenegger
* stb_image.h : v2.08 - public domain image loader - [Github link](https://github.com/nothings/stb/blob/master/stb_image.h)
* stb_image_write.h : v1.09 - public domain image writer - [Github link](https://github.com/nothings/stb/blob/master/stb_image_write.h)
* lodepng : Copyright (c) 2005-2018 Lode Vandevenne. zlib license. https://lodev.org/lodepng/
## Build and example
@@ -133,7 +130,7 @@ if (!ret) {
* `TINYGLTF_NO_STB_IMAGE_WRITE` : Do not write images with stb_image_write. Instead use `TinyGLTF::SetImageWriter(WriteimageDataFunction WriteImageData, void *user_data)` to set a callback for writing images.
* `TINYGLTF_NO_EXTERNAL_IMAGE` : Do not try to load external image file. This option woulde be helpful if you do not want load image file during glTF parsing.
* `TINYGLTF_ANDROID_LOAD_FROM_ASSETS`: Load all files from packaged app assets instead of the regular file system. **Note:** You must pass a valid asset manager from your android app to `tinygltf::asset_manager` beforehand.
* `TINYGLTF_ENABLE_DRACO`: Enable Draco compression. User must provide include path and link correspnding libraries in your project file.
* `TINYGLTF_USE_LODEPNG` : Load 16bit PNG image with lodepng(Valid when `TINYGLTF_NO_STB_IMAGE` was **not** defined). Must defined `LODEPNG_IMPLEMENTATION` in one .cc.
### Saving gltTF 2.0 model
* [ ] Buffers.
@@ -175,4 +172,5 @@ $ ./tester_noexcept
* json.hpp : Licensed under the MIT License <http://opensource.org/licenses/MIT>. Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
* stb_image : Public domain.
* lodepng : zlib license
* catch : Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. Distributed under the Boost Software License, Version 1.0.

View File

@@ -1,21 +0,0 @@
# Basic glTF viewer
## Requirements
* glew
* glfw3
* premake5(linux)
* OpenGL 3.3+ GPU
## Build on Linux and macOS
```
$ premake5 gmake
$ make
```
## Build on Visual Studio
Plese use solution file located at `basic` folder.

Binary file not shown.

View File

@@ -1,44 +0,0 @@
solution "basic_viewer"
-- location ( "build" )
configurations { "Debug", "Release" }
platforms {"native", "x64", "x32"}
project "basic_viewer"
kind "ConsoleApp"
language "C++"
cppdialect "C++11"
files { "main.cpp", "shaders.cpp", "window.cpp" }
includedirs { "./" }
includedirs { "../../" }
includedirs { "../common/glm" }
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 { "glfw", "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"

View File

@@ -19,7 +19,7 @@ uniform vec3 sun_color; \n\
out vec4 color;\n\
void main() {\n\
float lum = max(dot(normal, normalize(sun_position)), 0.0);\n\
color = texture(tex, texcoord) * vec4((0.3 + 0.7 * lum) * sun_color, 1.0);\n\
color = texture2D(tex, texcoord) * vec4((0.3 + 0.7 * lum) * sun_color, 1.0);\n\
}\n\
";

View File

@@ -1,10 +1,8 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.6)
project(glview)
set ( CMAKE_PREFIX_PATH cmake )
set ( DRACO_DIR "" CACHE STRING "Path to draco" )
find_package ( GLEW REQUIRED )
find_package ( GLFW3 REQUIRED )
find_package ( OpenGL REQUIRED )
@@ -23,16 +21,6 @@ endif (APPLE)
set(CMAKE_CXX_STANDARD 11)
if (${DRACO_DIR} STREQUAL "")
else ()
# TODO(syoyo): better CMake script for draco
add_definitions(-DTINYGLTF_ENABLE_DRACO)
include_directories(${DRACO_DIR}/include)
link_directories(${DRACO_DIR}/lib)
set(DRACO_LIBRARY draco)
endif ()
include_directories(
../../
../common
@@ -47,7 +35,6 @@ add_executable(glview
)
target_link_libraries ( glview
${DRACO_LIBRARY}
${GLFW3_UNIX_LINK_LIBRARIES}
${GLEW_LIBRARY}
${GLFW3_glfw_LIBRARY}

View File

@@ -27,17 +27,6 @@ Open .sln in Visual Studio 2013
When running .exe, glew and glfw dll must exist in the working directory.
#### Build with Draco(optional)
Assume CMake build.
```
$ mkdir build
$ cd build
$ cmake -DDRACO_DIR=/path/to/draco ../
$ make
```
## TODO
* [ ] PBR Material

View File

@@ -677,14 +677,10 @@ static void DrawNode(tinygltf::Model &model, const tinygltf::Node &node) {
// std::cout << it->first << std::endl;
// FIXME(syoyo): Refactor.
// DrawCurves(scene, it->second);
if (node.mesh > -1) {
assert(node.mesh < model.meshes.size());
DrawMesh(model, model.meshes[node.mesh]);
}
DrawMesh(model, model.meshes[node.mesh]);
// Draw child nodes.
for (size_t i = 0; i < node.children.size(); i++) {
assert(node.children[i] < model.nodes.size());
DrawNode(model, model.nodes[node.children[i]]);
}
@@ -790,12 +786,10 @@ int main(int argc, char **argv) {
return -1;
}
std::stringstream ss;
ss << "Simple glTF viewer: " << input_filename;
char title[1024];
sprintf(title, "Simple glTF viewer: %s", input_filename.c_str());
std::string title = ss.str();
window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);
window = glfwCreateWindow(width, height, title, NULL, NULL);
if (window == NULL) {
std::cerr << "Failed to open GLFW window. " << std::endl;
glfwTerminate();

View File

@@ -0,0 +1,6 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define LODEPNG_IMPLEMENTATION
#include "lodepng.h"

View File

@@ -1,3 +1,5 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define LODEPNG_IMPLEMENTATION
#include "lodepng.h"

View File

@@ -9,7 +9,7 @@ newoption {
}
sources = {
"stbi-impl.cc",
"img-loaders.cc",
"main.cc",
"render.cc",
"render-config.cc",

View File

@@ -4,6 +4,7 @@
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define LODEPNG_IMPLEMENTATION
#include "tiny_gltf.h"
#include <cstdio>

7866
lodepng.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,6 @@
// THE SOFTWARE.
// Version:
// - v2.1.0 Add draco compression.
// - v2.0.1 Add comparsion feature(Thanks to @Selmar).
// - v2.0.0 glTF 2.0!.
//
@@ -35,6 +34,7 @@
// - jsonhpp: C++ JSON library.
// - base64: base64 decode/encode library.
// - stb_image: Image loading library.
// - lodepng: Load 16bit PNG.
//
#ifndef TINY_GLTF_H_
#define TINY_GLTF_H_
@@ -477,8 +477,10 @@ struct Image {
std::string name;
int width;
int height;
int component;
std::vector<unsigned char> image;
int component; // channels. e.g. RGB=3, RGBA=4
int bits; // bit depth per channel. 8(byte), 16 or 32.
int pixel_type; // pixel type(TINYGLTF_COMPONENT_TYPE_***). usually UBYTE(bits = 8) or USHORT(bits = 16)
std::vector<unsigned char> image; // width * height * component * (bits/8)
int bufferView; // (required if no uri)
std::string mimeType; // (required if no uri) ["image/jpeg", "image/png",
// "image/bmp", "image/gif"]
@@ -499,6 +501,8 @@ struct Image {
width = -1;
height = -1;
component = -1;
bits = -1;
pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
}
bool operator==(const Image &) const;
};
@@ -539,9 +543,8 @@ struct BufferView {
// understood to be tightly packed
int target; // ["ARRAY_BUFFER", "ELEMENT_ARRAY_BUFFER"]
Value extras;
bool dracoDecoded; // Flag indicating this has been draco decoded
BufferView() : byteOffset(0), byteStride(0), dracoDecoded(false) {}
BufferView() : byteOffset(0), byteStride(0) {}
bool operator==(const BufferView &) const;
};
@@ -660,7 +663,6 @@ struct Primitive {
// where each target is a dict with attribues in ["POSITION, "NORMAL",
// "TANGENT"] pointing
// to their corresponding accessors
ExtensionMap extensions;
Value extras;
Primitive() {
@@ -1063,19 +1065,18 @@ class TinyGLTF {
#endif
#endif
#include "json.hpp"
#ifdef TINYGLTF_ENABLE_DRACO
#include "draco/core/decoder_buffer.h"
#include "draco/compression/decode.h"
#endif
#include "./json.hpp"
#ifndef TINYGLTF_NO_STB_IMAGE
#include "stb_image.h"
#include "./stb_image.h"
#endif
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
#include "stb_image_write.h"
#include "./stb_image_write.h"
#endif
#if defined(TINYGLTF_USE_LODEPNG)
#include "./lodepng.h"
#endif
#ifdef __clang__
@@ -1200,8 +1201,7 @@ bool BufferView::operator==(const BufferView &other) const {
return this->buffer == other.buffer && this->byteLength == other.byteLength &&
this->byteOffset == other.byteOffset &&
this->byteStride == other.byteStride && this->name == other.name &&
this->target == other.target && this->extras == other.extras &&
this->dracoDecoded == other.dracoDecoded;
this->target == other.target && this->extras == other.extras;
}
bool Camera::operator==(const Camera &other) const {
return this->name == other.name && this->extensions == other.extensions &&
@@ -1212,6 +1212,7 @@ bool Camera::operator==(const Camera &other) const {
bool Image::operator==(const Image &other) const {
return this->bufferView == other.bufferView &&
this->component == other.component && this->extras == other.extras &&
this->bits == other.bits &&
this->height == other.height && this->image == other.image &&
this->mimeType == other.mimeType && this->name == other.name &&
this->uri == other.uri && this->width == other.width;
@@ -1608,6 +1609,9 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err, std::str
// some GPU drivers do not support 24-bit images for Vulkan
req_comp = 4;
int bits = 8;
int pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
// if image cannot be decoded, ignore parsing and keep it by its path
// don't break in this case
// FIXME we should only enter this function if the image is embedded. If
@@ -1617,11 +1621,28 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err, std::str
unsigned char *data =
stbi_load_from_memory(bytes, size, &w, &h, &comp, req_comp);
if (!data) {
#if defined(TINYGLTF_USE_LODEPNG)
// try to load as 16bit PNG RGBA
unsigned ret = lodepng_decode_memory(&data, reinterpret_cast<unsigned *>(&w), reinterpret_cast<unsigned *>(&h), bytes, size, LCT_RGBA, /* bitdepth*/16);
if (ret != 0) {
// NOTE: you can use `warn` instead of `err`
if (err) {
(*err) += "Unknown image format. STB and LodePNG cannot decode image data for image[" + std::to_string(image_idx) + "] name = \"" + image->name + "\".\n";
}
return false;
}
bits = 16;
pixel_type = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
#else
// NOTE: you can use `warn` instead of `err`
if (err) {
(*err) += "Unknown image format. STB cannot decode image data for image[" + std::to_string(image_idx) + "] name = \"" + image->name + "\". Proably 16bit PNG?\n";
}
return false;
#endif
}
if (w < 1 || h < 1) {
@@ -1655,8 +1676,10 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err, std::str
image->width = w;
image->height = h;
image->component = req_comp;
image->image.resize(static_cast<size_t>(w * h * req_comp));
std::copy(data, data + w * h * req_comp, image->image.begin());
image->bits = bits;
image->pixel_type = pixel_type;
image->image.resize(static_cast<size_t>(w * h * req_comp * (bits/8)));
std::copy(data, data + w * h * req_comp * (bits/8), image->image.begin());
free(data);
@@ -2523,6 +2546,7 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err, std:
// Keep texture path (for textures that cannot be decoded)
image->uri = uri;
#ifdef TINYGLTF_NO_EXTERNAL_IMAGE
// TODO(syoyo): Call LoadImageData callback?
return true;
#endif
if (!LoadExternalFile(&img, err, warn, uri, basedir, false, 0, false, fs)) {
@@ -2737,7 +2761,10 @@ static bool ParseBufferView(BufferView *bufferView, std::string *err,
static bool ParseAccessor(Accessor *accessor, std::string *err, const json &o) {
double bufferView = -1.0;
ParseNumberProperty(&bufferView, err, o, "bufferView", false, "Accessor");
if (!ParseNumberProperty(&bufferView, err, o, "bufferView", true,
"Accessor")) {
return false;
}
double byteOffset = 0.0;
ParseNumberProperty(&byteOffset, err, o, "byteOffset", false, "Accessor");
@@ -2819,184 +2846,7 @@ static bool ParseAccessor(Accessor *accessor, std::string *err, const json &o) {
return true;
}
#ifdef TINYGLTF_ENABLE_DRACO
static void DecodeIndexBuffer(draco::Mesh* mesh, size_t componentSize, std::vector<uint8_t>& outBuffer)
{
if (componentSize == 4)
{
assert(sizeof(mesh->face(draco::FaceIndex(0))[0]) == componentSize);
memcpy(outBuffer.data(), &mesh->face(draco::FaceIndex(0))[0], outBuffer.size());
}
else
{
size_t faceStride = componentSize * 3;
for (draco::FaceIndex f(0); f < mesh->num_faces(); ++f)
{
const draco::Mesh::Face& face = mesh->face(f);
if (componentSize == 2)
{
uint16_t indices[3] = { (uint16_t)face[0].value(), (uint16_t)face[1].value(), (uint16_t)face[2].value() };
memcpy(outBuffer.data() + f.value() * faceStride, &indices[0], faceStride);
}
else
{
uint8_t indices[3] = { (uint8_t)face[0].value(), (uint8_t)face[1].value(), (uint8_t)face[2].value() };
memcpy(outBuffer.data() + f.value() * faceStride, &indices[0], faceStride);
}
}
}
}
template<typename T>
static bool GetAttributeForAllPoints(draco::Mesh* mesh, const draco::PointAttribute* pAttribute, std::vector<uint8_t>& outBuffer)
{
size_t byteOffset = 0;
T values[4] = { 0, 0, 0, 0 };
for (draco::PointIndex i(0); i < mesh->num_points(); ++i)
{
const draco::AttributeValueIndex val_index = pAttribute->mapped_index(i);
if (!pAttribute->ConvertValue<T>(val_index, pAttribute->num_components(), values))
return false;
memcpy(outBuffer.data() + byteOffset, &values[0], sizeof(T) * pAttribute->num_components());
byteOffset += sizeof(T) * pAttribute->num_components();
}
return true;
}
static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh* mesh, const draco::PointAttribute* pAttribute, std::vector<uint8_t>& outBuffer)
{
bool decodeResult = false;
switch (componentType)
{
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
decodeResult = GetAttributeForAllPoints<uint8_t>(mesh, pAttribute, outBuffer);
break;
case TINYGLTF_COMPONENT_TYPE_BYTE:
decodeResult = GetAttributeForAllPoints<int8_t>(mesh, pAttribute, outBuffer);
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
decodeResult = GetAttributeForAllPoints<uint16_t>(mesh, pAttribute, outBuffer);
break;
case TINYGLTF_COMPONENT_TYPE_SHORT:
decodeResult = GetAttributeForAllPoints<int16_t>(mesh, pAttribute, outBuffer);
break;
case TINYGLTF_COMPONENT_TYPE_INT:
decodeResult = GetAttributeForAllPoints<int32_t>(mesh, pAttribute, outBuffer);
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
decodeResult = GetAttributeForAllPoints<uint32_t>(mesh, pAttribute, outBuffer);
break;
case TINYGLTF_COMPONENT_TYPE_FLOAT:
decodeResult = GetAttributeForAllPoints<float>(mesh, pAttribute, outBuffer);
break;
case TINYGLTF_COMPONENT_TYPE_DOUBLE:
decodeResult = GetAttributeForAllPoints<double>(mesh, pAttribute, outBuffer);
break;
default:
return false;
}
return decodeResult;
}
static bool ParseDracoExtension(Primitive *primitive, Model *model, std::string *err, const Value &dracoExtensionValue)
{
auto bufferViewValue = dracoExtensionValue.Get("bufferView");
if (!bufferViewValue.IsInt())
return false;
auto attributesValue = dracoExtensionValue.Get("attributes");
if (!attributesValue.IsObject())
return false;
auto attributesObject = attributesValue.Get<Value::Object>();
int bufferView = bufferViewValue.Get<int>();
BufferView& view = model->bufferViews[bufferView];
Buffer& buffer = model->buffers[view.buffer];
// BufferView has already been decoded
if (view.dracoDecoded)
return true;
view.dracoDecoded = true;
const char* bufferViewData = reinterpret_cast<const char*>(buffer.data.data() + view.byteOffset);
size_t bufferViewSize = view.byteLength;
// decode draco
draco::DecoderBuffer decoderBuffer;
decoderBuffer.Init(bufferViewData, bufferViewSize);
draco::Decoder decoder;
auto decodeResult = decoder.DecodeMeshFromBuffer(&decoderBuffer);
if (!decodeResult.ok()) {
return false;
}
const std::unique_ptr<draco::Mesh>& mesh = decodeResult.value();
// create new bufferView for indices
if (primitive->indices >= 0)
{
int32_t componentSize = GetComponentSizeInBytes(model->accessors[primitive->indices].componentType);
Buffer decodedIndexBuffer;
decodedIndexBuffer.data.resize(mesh->num_faces() * 3 * componentSize);
DecodeIndexBuffer(mesh.get(), componentSize, decodedIndexBuffer.data);
model->buffers.emplace_back(std::move(decodedIndexBuffer));
BufferView decodedIndexBufferView;
decodedIndexBufferView.buffer = int(model->buffers.size() - 1);
decodedIndexBufferView.byteLength = int(mesh->num_faces() * 3 * componentSize);
decodedIndexBufferView.byteOffset = 0;
decodedIndexBufferView.byteStride = 0;
decodedIndexBufferView.target = TINYGLTF_TARGET_ARRAY_BUFFER;
model->bufferViews.emplace_back(std::move(decodedIndexBufferView));
model->accessors[primitive->indices].bufferView = int(model->bufferViews.size() - 1);
model->accessors[primitive->indices].count = int(mesh->num_faces() * 3);
}
for (const auto& attribute : attributesObject)
{
if (!attribute.second.IsInt())
return false;
auto primitiveAttribute = primitive->attributes.find(attribute.first);
if (primitiveAttribute == primitive->attributes.end())
return false;
int dracoAttributeIndex = attribute.second.Get<int>();
const auto pAttribute = mesh->GetAttributeByUniqueId(dracoAttributeIndex);
const auto pBuffer = pAttribute->buffer();
const auto componentType = model->accessors[primitiveAttribute->second].componentType;
// Create a new buffer for this decoded buffer
Buffer decodedBuffer;
size_t bufferSize = mesh->num_points() * pAttribute->num_components() * GetComponentSizeInBytes(componentType);
decodedBuffer.data.resize(bufferSize);
if (!GetAttributeForAllPoints(componentType, mesh.get(), pAttribute, decodedBuffer.data))
return false;
model->buffers.emplace_back(std::move(decodedBuffer));
BufferView decodedBufferView;
decodedBufferView.buffer = int(model->buffers.size() - 1);
decodedBufferView.byteLength = bufferSize;
decodedBufferView.byteOffset = pAttribute->byte_offset();
decodedBufferView.byteStride = pAttribute->byte_stride();
decodedBufferView.target = primitive->indices >= 0 ? TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER : TINYGLTF_TARGET_ARRAY_BUFFER;
model->bufferViews.emplace_back(std::move(decodedBufferView));
model->accessors[primitiveAttribute->second].bufferView = int(model->bufferViews.size() - 1);
model->accessors[primitiveAttribute->second].count = int(mesh->num_points());
}
return true;
}
#endif
static bool ParsePrimitive(Primitive *primitive, Model *model, std::string *err,
static bool ParsePrimitive(Primitive *primitive, std::string *err,
const json &o) {
double material = -1.0;
ParseNumberProperty(&material, err, o, "material", false);
@@ -3036,20 +2886,10 @@ static bool ParsePrimitive(Primitive *primitive, Model *model, std::string *err,
ParseExtrasProperty(&(primitive->extras), o);
ParseExtensionsProperty(&primitive->extensions, err, o);
#ifdef TINYGLTF_ENABLE_DRACO
auto dracoExtension = primitive->extensions.find("KHR_draco_mesh_compression");
if (dracoExtension != primitive->extensions.end())
{
ParseDracoExtension(primitive, model, err, dracoExtension->second);
}
#endif
return true;
}
static bool ParseMesh(Mesh *mesh, Model *model, std::string *err, const json &o) {
static bool ParseMesh(Mesh *mesh, std::string *err, const json &o) {
ParseStringProperty(&mesh->name, err, o, "name", false);
mesh->primitives.clear();
@@ -3058,7 +2898,7 @@ static bool ParseMesh(Mesh *mesh, Model *model, std::string *err, const json &o)
for (json::const_iterator i = primObject.value().begin();
i != primObject.value().end(); i++) {
Primitive primitive;
if (ParsePrimitive(&primitive, model, err, i.value())) {
if (ParsePrimitive(&primitive, err, i.value())) {
// Only add the primitive if the parsing succeeds.
mesh->primitives.push_back(primitive);
}
@@ -3717,7 +3557,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
return false;
}
Mesh mesh;
if (!ParseMesh(&mesh, model, err, it->get<json>())) {
if (!ParseMesh(&mesh, err, it->get<json>())) {
return false;
}
@@ -4823,14 +4663,14 @@ static void WriteBinaryGltfFile(const std::string &output,
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 + int(content.size()) + padding_size;
const int length = 12 + 8 + content.size() + padding_size;
gltfFile.write(header.c_str(), 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 = int(content.size()) + padding_size;
const int model_length = 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));