Keep up with loader_example.cc

Update picojson.h
This commit is contained in:
Syoyo Fujita 2017-05-27 23:51:23 +09:00
parent 2057b1ae6e
commit f612015ac2
4 changed files with 1150 additions and 1494 deletions

267
box.gltf
View File

@ -1,267 +0,0 @@
{
"accessors": {
"accessor_21": {
"bufferView": "bufferView_29",
"byteOffset": 0,
"byteStride": 0,
"componentType": 5123,
"count": 36,
"type": "SCALAR"
},
"accessor_23": {
"bufferView": "bufferView_30",
"byteOffset": 0,
"byteStride": 12,
"componentType": 5126,
"count": 24,
"max": [
0.5,
0.5,
0.5
],
"min": [
-0.5,
-0.5,
-0.5
],
"type": "VEC3"
},
"accessor_25": {
"bufferView": "bufferView_30",
"byteOffset": 288,
"byteStride": 12,
"componentType": 5126,
"count": 24,
"max": [
1,
1,
1
],
"min": [
-1,
-1,
-1
],
"type": "VEC3"
},
"accessor_27": {
"bufferView": "bufferView_30",
"byteOffset": 576,
"byteStride": 8,
"componentType": 5126,
"count": 24,
"max": [
1,
1
],
"min": [
0,
0
],
"type": "VEC2"
}
},
"animations": {},
"asset": {
"generator": "collada2gltf@ceec062e3d5793f2f249f53cbd843aee382ad40b",
"premultipliedAlpha": true,
"profile": {
"api": "WebGL",
"version": "1.0.2"
},
"version": 1
},
"bufferViews": {
"bufferView_29": {
"buffer": "box",
"byteLength": 72,
"byteOffset": 0,
"target": 34963
},
"bufferView_30": {
"buffer": "box",
"byteLength": 768,
"byteOffset": 72,
"target": 34962
}
},
"buffers": {
"box": {
"byteLength": 840,
"type": "arraybuffer",
"uri": "data:application/octet-stream;base64,AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUAAAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPgAAAAAAAIA+oKqqPgAAAD8AAAAAAAAAP6Cqqj4AAIA+oKqqPgAAAACgqqo+AACAPrCqKj8AAAAAsKoqPwAAAD+gqqo+AACAPqCqqj4AAAA/sKoqPwAAgD6wqio/AABAP6Cqqj4AAAA/oKqqPgAAQD+wqio/AAAAP7CqKj8AAIA/oKqqPgAAQD+gqqo+AACAP7CqKj8AAEA/sKoqPwAAgD4AAIA/AAAAPwAAgD8AAIA+sKoqPwAAAD+wqio/"
}
},
"materials": {
"Effect-Red": {
"name": "Red",
"technique": "technique0",
"values": {
"diffuse": [
0.8,
0,
0,
1
],
"shininess": 256,
"specular": [
0.2,
0.2,
0.2,
1
]
}
}
},
"meshes": {
"Geometry-mesh002": {
"name": "Mesh",
"primitives": [
{
"attributes": {
"NORMAL": "accessor_25",
"POSITION": "accessor_23",
"TEXCOORD_0": "accessor_27"
},
"indices": "accessor_21",
"material": "Effect-Red",
"mode": 4
}
]
}
},
"nodes": {
"Geometry-mesh002Node": {
"children": [],
"matrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
],
"meshes": [
"Geometry-mesh002"
],
"name": "Mesh"
},
"node_1": {
"children": [
"Geometry-mesh002Node"
],
"matrix": [
1,
0,
0,
0,
0,
0,
-1,
0,
0,
1,
0,
0,
0,
0,
0,
1
],
"name": "Y_UP_Transform"
}
},
"programs": {
"program_0": {
"attributes": [
"a_normal",
"a_position"
],
"fragmentShader": "box0FS",
"vertexShader": "box0VS"
}
},
"scene": "defaultScene",
"scenes": {
"defaultScene": {
"nodes": [
"node_1"
]
}
},
"shaders": {
"box0FS": {
"type": 35632,
"uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Owp2YXJ5aW5nIHZlYzMgdl9ub3JtYWw7CnVuaWZvcm0gdmVjNCB1X2RpZmZ1c2U7CnVuaWZvcm0gdmVjNCB1X3NwZWN1bGFyOwp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOwp2b2lkIG1haW4odm9pZCkgewp2ZWMzIG5vcm1hbCA9IG5vcm1hbGl6ZSh2X25vcm1hbCk7CnZlYzQgY29sb3IgPSB2ZWM0KDAuLCAwLiwgMC4sIDAuKTsKdmVjNCBkaWZmdXNlID0gdmVjNCgwLiwgMC4sIDAuLCAxLik7CnZlYzQgc3BlY3VsYXI7CmRpZmZ1c2UgPSB1X2RpZmZ1c2U7CnNwZWN1bGFyID0gdV9zcGVjdWxhcjsKZGlmZnVzZS54eXogKj0gbWF4KGRvdChub3JtYWwsdmVjMygwLiwwLiwxLikpLCAwLik7CmNvbG9yLnh5eiArPSBkaWZmdXNlLnh5ejsKY29sb3IgPSB2ZWM0KGNvbG9yLnJnYiAqIGRpZmZ1c2UuYSwgZGlmZnVzZS5hKTsKZ2xfRnJhZ0NvbG9yID0gY29sb3I7Cn0K"
},
"box0VS": {
"type": 35633,
"uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0OwphdHRyaWJ1dGUgdmVjMyBhX3Bvc2l0aW9uOwphdHRyaWJ1dGUgdmVjMyBhX25vcm1hbDsKdmFyeWluZyB2ZWMzIHZfbm9ybWFsOwp1bmlmb3JtIG1hdDMgdV9ub3JtYWxNYXRyaXg7CnVuaWZvcm0gbWF0NCB1X21vZGVsVmlld01hdHJpeDsKdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsKdm9pZCBtYWluKHZvaWQpIHsKdmVjNCBwb3MgPSB1X21vZGVsVmlld01hdHJpeCAqIHZlYzQoYV9wb3NpdGlvbiwxLjApOwp2X25vcm1hbCA9IHVfbm9ybWFsTWF0cml4ICogYV9ub3JtYWw7CmdsX1Bvc2l0aW9uID0gdV9wcm9qZWN0aW9uTWF0cml4ICogcG9zOwp9Cg=="
}
},
"skins": {},
"techniques": {
"technique0": {
"attributes": {
"a_normal": "normal",
"a_position": "position"
},
"parameters": {
"diffuse": {
"type": 35666
},
"modelViewMatrix": {
"semantic": "MODELVIEW",
"type": 35676
},
"normal": {
"semantic": "NORMAL",
"type": 35665
},
"normalMatrix": {
"semantic": "MODELVIEWINVERSETRANSPOSE",
"type": 35675
},
"position": {
"semantic": "POSITION",
"type": 35665
},
"projectionMatrix": {
"semantic": "PROJECTION",
"type": 35676
},
"shininess": {
"type": 5126
},
"specular": {
"type": 35666
}
},
"program": "program_0",
"states": {
"enable": [
2929,
2884
]
},
"uniforms": {
"u_diffuse": "diffuse",
"u_modelViewMatrix": "modelViewMatrix",
"u_normalMatrix": "normalMatrix",
"u_projectionMatrix": "projectionMatrix",
"u_shininess": "shininess",
"u_specular": "specular"
}
}
}
}

View File

@ -62,15 +62,6 @@ static std::string PrintType(int ty) {
return "**UNKNOWN**"; return "**UNKNOWN**";
} }
static std::string PrintShaderType(int ty) {
if (ty == TINYGLTF_SHADER_TYPE_VERTEX_SHADER) {
return "VERTEX_SHADER";
} else if (ty == TINYGLTF_SHADER_TYPE_FRAGMENT_SHADER) {
return "FRAGMENT_SHADER";
}
return "**UNKNOWN**";
}
static std::string PrintComponentType(int ty) { static std::string PrintComponentType(int ty) {
if (ty == TINYGLTF_COMPONENT_TYPE_BYTE) { if (ty == TINYGLTF_COMPONENT_TYPE_BYTE) {
return "BYTE"; return "BYTE";
@ -93,6 +84,7 @@ static std::string PrintComponentType(int ty) {
return "**UNKNOWN**"; return "**UNKNOWN**";
} }
#if 0
static std::string PrintParameterType(int ty) { static std::string PrintParameterType(int ty) {
if (ty == TINYGLTF_PARAMETER_TYPE_BYTE) { if (ty == TINYGLTF_PARAMETER_TYPE_BYTE) {
return "BYTE"; return "BYTE";
@ -140,6 +132,7 @@ static std::string PrintParameterType(int ty) {
return "**UNKNOWN**"; return "**UNKNOWN**";
} }
#endif
static std::string PrintWrapMode(int mode) { static std::string PrintWrapMode(int mode) {
if (mode == TINYGLTF_TEXTURE_WRAP_RPEAT) { if (mode == TINYGLTF_TEXTURE_WRAP_RPEAT) {
@ -170,7 +163,7 @@ static std::string PrintFilterMode(int mode) {
return "**UNKNOWN**"; return "**UNKNOWN**";
} }
static std::string PrintFloatArray(const std::vector<double> &arr) { static std::string PrintIntArray(const std::vector<int> &arr) {
if (arr.size() == 0) { if (arr.size() == 0) {
return ""; return "";
} }
@ -185,7 +178,7 @@ static std::string PrintFloatArray(const std::vector<double> &arr) {
return ss.str(); return ss.str();
} }
static std::string PrintStringArray(const std::vector<std::string> &arr) { static std::string PrintFloatArray(const std::vector<double> &arr) {
if (arr.size() == 0) { if (arr.size() == 0) {
return ""; return "";
} }
@ -244,6 +237,7 @@ static std::string PrintValue(const std::string& name, const tinygltf::Value &va
static void DumpNode(const tinygltf::Node &node, int indent) { static void DumpNode(const tinygltf::Node &node, int indent) {
std::cout << Indent(indent) << "name : " << node.name << std::endl; std::cout << Indent(indent) << "name : " << node.name << std::endl;
std::cout << Indent(indent) << "camera : " << node.camera << std::endl; std::cout << Indent(indent) << "camera : " << node.camera << std::endl;
std::cout << Indent(indent) << "mesh : " << node.mesh << std::endl;
if (!node.rotation.empty()) { if (!node.rotation.empty()) {
std::cout << Indent(indent) std::cout << Indent(indent)
<< "rotation : " << PrintFloatArray(node.rotation) << "rotation : " << PrintFloatArray(node.rotation)
@ -265,16 +259,13 @@ static void DumpNode(const tinygltf::Node &node, int indent) {
} }
std::cout << Indent(indent) std::cout << Indent(indent)
<< "meshes : " << PrintStringArray(node.meshes) << std::endl; << "children : " << PrintIntArray(node.children) << std::endl;
std::cout << Indent(indent)
<< "children : " << PrintStringArray(node.children) << std::endl;
} }
static void DumpStringMap(const std::map<std::string, std::string> &map, static void DumpStringIntMap(const std::map<std::string, int> &m,
int indent) { int indent) {
std::map<std::string, std::string>::const_iterator it(map.begin()); std::map<std::string, int>::const_iterator it(m.begin());
std::map<std::string, std::string>::const_iterator itEnd(map.end()); std::map<std::string, int>::const_iterator itEnd(m.end());
for (; it != itEnd; it++) { for (; it != itEnd; it++) {
std::cout << Indent(indent) << it->first << ": " << it->second << std::endl; std::cout << Indent(indent) << it->first << ": " << it->second << std::endl;
} }
@ -289,110 +280,79 @@ static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) {
std::cout << Indent(indent) std::cout << Indent(indent)
<< "attributes(items=" << primitive.attributes.size() << ")" << "attributes(items=" << primitive.attributes.size() << ")"
<< std::endl; << std::endl;
DumpStringMap(primitive.attributes, indent + 1); DumpStringIntMap(primitive.attributes, indent + 1);
std::cout << Indent(indent) std::cout << Indent(indent)
<< "extras :" << std::endl << "extras :" << std::endl
<< PrintValue("extras", primitive.extras, indent+1) << std::endl; << PrintValue("extras", primitive.extras, indent+1) << std::endl;
} }
static void DumpTechniqueParameter(const tinygltf::TechniqueParameter &param, static void Dump(const tinygltf::Model &model) {
int indent) {
std::cout << Indent(indent) << "count : " << param.count << std::endl;
std::cout << Indent(indent) << "node : " << param.node << std::endl;
std::cout << Indent(indent) << "semantic : " << param.semantic << std::endl;
std::cout << Indent(indent) << "type : " << PrintParameterType(param.type)
<< std::endl;
std::cout << Indent(indent)
<< "value : " << PrintParameterValue(param.value) << std::endl;
}
static void Dump(const tinygltf::Scene &scene) {
std::cout << "=== Dump glTF ===" << std::endl; std::cout << "=== Dump glTF ===" << std::endl;
std::cout << "asset.generator : " << scene.asset.generator std::cout << "asset.copyright : " << model.asset.copyright
<< std::endl; << std::endl;
std::cout << "asset.premultipliedAlpha : " << scene.asset.premultipliedAlpha std::cout << "asset.generator : " << model.asset.generator
<< std::endl; << std::endl;
std::cout << "asset.version : " << scene.asset.version std::cout << "asset.version : " << model.asset.version
<< std::endl; << std::endl;
std::cout << "asset.profile.api : " << scene.asset.profile_api std::cout << "asset.minVersion : " << model.asset.minVersion
<< std::endl;
std::cout << "asset.profile.version : " << scene.asset.profile_version
<< std::endl; << std::endl;
std::cout << std::endl; std::cout << std::endl;
std::cout << "=== Dump scene ===" << std::endl; std::cout << "=== Dump scene ===" << std::endl;
std::cout << "defaultScene: " << scene.defaultScene << std::endl; std::cout << "defaultScene: " << model.defaultScene << std::endl;
{ {
std::map<std::string, std::vector<std::string> >::const_iterator it( std::cout << "scenes(items=" << model.scenes.size() << ")" << std::endl;
scene.scenes.begin()); for (size_t i = 0; i < model.scenes.size(); i++) {
std::map<std::string, std::vector<std::string> >::const_iterator itEnd( std::cout << Indent(1) << "scene[" << i << "] name : " << model.scenes[i].name << std::endl;
scene.scenes.end());
std::cout << "scenes(items=" << scene.scenes.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
std::cout << Indent(2) << "nodes : [ ";
for (size_t i = 0; i < it->second.size(); i++) {
std::cout << it->second[i]
<< ((i != (it->second.size() - 1)) ? ", " : "");
}
std::cout << " ] " << std::endl;
} }
} }
{ {
std::map<std::string, tinygltf::Mesh>::const_iterator it( std::cout << "meshes(item=" << model.meshes.size() << ")" << std::endl;
scene.meshes.begin()); for (size_t i = 0; i < model.meshes.size(); i++) {
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd( std::cout << Indent(1) << "name : " << model.meshes[i].name << std::endl;
scene.meshes.end());
std::cout << "meshes(item=" << scene.meshes.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->second.name << std::endl;
std::cout << Indent(1) std::cout << Indent(1)
<< "primitives(items=" << it->second.primitives.size() << "primitives(items=" << model.meshes[i].primitives.size()
<< "): " << std::endl; << "): " << std::endl;
for (size_t i = 0; i < it->second.primitives.size(); i++) { for (size_t k = 0; k < model.meshes[i].primitives.size(); k++) {
DumpPrimitive(it->second.primitives[i], 2); DumpPrimitive(model.meshes[i].primitives[k], 2);
} }
} }
} }
{ {
std::map<std::string, tinygltf::Accessor>::const_iterator it( for (size_t i = 0; i < model.accessors.size(); i++) {
scene.accessors.begin()); const tinygltf::Accessor &accessor = model.accessors[i];
std::map<std::string, tinygltf::Accessor>::const_iterator itEnd( std::cout << Indent(1) << "name : " << accessor.name << std::endl;
scene.accessors.end()); std::cout << Indent(2) << "bufferView : " << accessor.bufferView
std::cout << "accessors(items=" << scene.accessors.size() << ")"
<< std::endl; << std::endl;
for (; it != itEnd; it++) { std::cout << Indent(2) << "byteOffset : " << accessor.byteOffset
std::cout << Indent(1) << "name : " << it->first << std::endl;
std::cout << Indent(2) << "bufferView : " << it->second.bufferView
<< std::endl; << std::endl;
std::cout << Indent(2) << "byteOffset : " << it->second.byteOffset std::cout << Indent(2) << "byteStride : " << accessor.byteStride
<< std::endl;
std::cout << Indent(2) << "byteStride : " << it->second.byteStride
<< std::endl; << std::endl;
std::cout << Indent(2) << "componentType: " std::cout << Indent(2) << "componentType: "
<< PrintComponentType(it->second.componentType) << "(" << PrintComponentType(accessor.componentType) << "("
<< it->second.componentType << ")" << std::endl; << accessor.componentType << ")" << std::endl;
std::cout << Indent(2) << "count : " << it->second.count std::cout << Indent(2) << "count : " << accessor.count
<< std::endl; << std::endl;
std::cout << Indent(2) << "type : " << PrintType(it->second.type) std::cout << Indent(2) << "type : " << PrintType(accessor.type)
<< std::endl; << std::endl;
if (!it->second.minValues.empty()) { if (!accessor.minValues.empty()) {
std::cout << Indent(2) << "min : ["; std::cout << Indent(2) << "min : [";
for (size_t i = 0; i < it->second.minValues.size(); i++) { for (size_t k = 0; k < accessor.minValues.size(); k++) {
std::cout << it->second.minValues[i] std::cout << accessor.minValues[k]
<< ((i != it->second.minValues.size() - 1) ? ", " : ""); << ((i != accessor.minValues.size() - 1) ? ", " : "");
} }
std::cout << "]" << std::endl; std::cout << "]" << std::endl;
} }
if (!it->second.maxValues.empty()) { if (!accessor.maxValues.empty()) {
std::cout << Indent(2) << "max : ["; std::cout << Indent(2) << "max : [";
for (size_t i = 0; i < it->second.maxValues.size(); i++) { for (size_t k = 0; k < accessor.maxValues.size(); k++) {
std::cout << it->second.maxValues[i] std::cout << accessor.maxValues[k]
<< ((i != it->second.maxValues.size() - 1) ? ", " : ""); << ((i != accessor.maxValues.size() - 1) ? ", " : "");
} }
std::cout << "]" << std::endl; std::cout << "]" << std::endl;
} }
@ -400,113 +360,82 @@ static void Dump(const tinygltf::Scene &scene) {
} }
{ {
std::map<std::string, tinygltf::Animation>::const_iterator it( std::cout << "animations(items=" << model.animations.size() << ")"
scene.animations.begin());
std::map<std::string, tinygltf::Animation>::const_iterator itEnd(
scene.animations.end());
std::cout << "animations(items=" << scene.animations.size() << ")"
<< std::endl; << std::endl;
for (; it != itEnd; it++) { for (size_t i = 0; i < model.animations.size(); i++) {
std::cout << Indent(1) << "name : " << it->first << std::endl; const tinygltf::Animation &animation = model.animations[i];
std::cout << Indent(1) << "name : " << animation.name << std::endl;
std::cout << Indent(1) << "channels : [ " << std::endl; std::cout << Indent(1) << "channels : [ " << std::endl;
for (size_t i = 0; i < it->second.channels.size(); i++) { for (size_t j = 0; i < animation.channels.size(); i++) {
std::cout << Indent(2) std::cout << Indent(2)
<< "sampler : " << it->second.channels[i].sampler << "sampler : " << animation.channels[j].sampler
<< std::endl; << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "target.id : " << it->second.channels[i].target_id << "target.id : " << animation.channels[j].target_node
<< std::endl; << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "target.path : " << it->second.channels[i].target_path << "target.path : " << animation.channels[j].target_path
<< std::endl; << std::endl;
std::cout << ((i != (it->second.channels.size() - 1)) ? " , " : ""); std::cout << ((i != (animation.channels.size() - 1)) ? " , " : "");
} }
std::cout << " ]" << std::endl; std::cout << " ]" << std::endl;
std::map<std::string, tinygltf::AnimationSampler>::const_iterator std::cout << Indent(1) << "samplers(items=" << animation.samplers.size()
samplerIt(it->second.samplers.begin());
std::map<std::string, tinygltf::AnimationSampler>::const_iterator
samplerItEnd(it->second.samplers.end());
std::cout << Indent(1) << "samplers(items=" << it->second.samplers.size()
<< ")" << std::endl; << ")" << std::endl;
for (; samplerIt != samplerItEnd; samplerIt++) { for (size_t j = 0; j < animation.samplers.size(); j++) {
std::cout << Indent(1) << "name : " << samplerIt->first const tinygltf::AnimationSampler &sampler = animation.samplers[i];
<< std::endl; std::cout << Indent(2) << "input : " << sampler.input
std::cout << Indent(2) << "input : " << samplerIt->second.input
<< std::endl; << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "interpolation : " << samplerIt->second.interpolation << "interpolation : " << sampler.interpolation
<< std::endl; << std::endl;
std::cout << Indent(2) << "output : " << samplerIt->second.output std::cout << Indent(2) << "output : " << sampler.output
<< std::endl; << std::endl;
} }
{
std::cout << Indent(1)
<< "parameters(items=" << it->second.parameters.size() << ")"
<< std::endl;
tinygltf::ParameterMap::const_iterator p(it->second.parameters.begin());
tinygltf::ParameterMap::const_iterator pEnd(
it->second.parameters.end());
for (; p != pEnd; p++) {
std::cout << Indent(2) << p->first << ": "
<< PrintParameterValue(p->second) << std::endl;
}
}
} }
} }
{ {
std::map<std::string, tinygltf::BufferView>::const_iterator it( std::cout << "bufferViews(items=" << model.bufferViews.size() << ")"
scene.bufferViews.begin());
std::map<std::string, tinygltf::BufferView>::const_iterator itEnd(
scene.bufferViews.end());
std::cout << "bufferViews(items=" << scene.bufferViews.size() << ")"
<< std::endl; << std::endl;
for (; it != itEnd; it++) { for (size_t i = 0; i < model.bufferViews.size(); i++) {
std::cout << Indent(1) << "name : " << it->first << std::endl; const tinygltf::BufferView &bufferView = model.bufferViews[i];
std::cout << Indent(2) << "buffer : " << it->second.buffer std::cout << Indent(1) << "name : " << bufferView.name << std::endl;
std::cout << Indent(2) << "buffer : " << bufferView.buffer
<< std::endl; << std::endl;
std::cout << Indent(2) << "byteLength : " << it->second.byteLength std::cout << Indent(2) << "byteLength : " << bufferView.byteLength
<< std::endl; << std::endl;
std::cout << Indent(2) << "byteOffset : " << it->second.byteOffset std::cout << Indent(2) << "byteOffset : " << bufferView.byteOffset
<< std::endl; << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "target : " << PrintTarget(it->second.target) << "target : " << PrintTarget(bufferView.target)
<< std::endl; << std::endl;
} }
} }
{ {
std::map<std::string, tinygltf::Buffer>::const_iterator it( std::cout << "buffers(items=" << model.buffers.size() << ")" << std::endl;
scene.buffers.begin()); for (size_t i = 0; i < model.buffers.size(); i++) {
std::map<std::string, tinygltf::Buffer>::const_iterator itEnd( const tinygltf::Buffer &buffer = model.buffers[i];
scene.buffers.end()); std::cout << Indent(1) << "name : " << buffer.name << std::endl;
std::cout << "buffers(items=" << scene.buffers.size() << ")" << std::endl; std::cout << Indent(2) << "byteLength : " << buffer.data.size()
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
std::cout << Indent(2) << "byteLength : " << it->second.data.size()
<< std::endl; << std::endl;
} }
} }
{ {
std::map<std::string, tinygltf::Material>::const_iterator it( std::cout << "materials(items=" << model.materials.size() << ")"
scene.materials.begin());
std::map<std::string, tinygltf::Material>::const_iterator itEnd(
scene.materials.end());
std::cout << "materials(items=" << scene.materials.size() << ")"
<< std::endl; << std::endl;
for (; it != itEnd; it++) { for (size_t i = 0; i < model.materials.size(); i++) {
std::cout << Indent(1) << "name : " << it->first << std::endl; const tinygltf::Material &material = model.materials[i];
std::cout << Indent(1) << "technique : " << it->second.technique std::cout << Indent(1) << "name : " << material.name << std::endl;
<< std::endl; std::cout << Indent(1) << "values(items=" << material.values.size()
std::cout << Indent(1) << "values(items=" << it->second.values.size()
<< ")" << std::endl; << ")" << std::endl;
tinygltf::ParameterMap::const_iterator p(it->second.values.begin()); tinygltf::ParameterMap::const_iterator p(material.values.begin());
tinygltf::ParameterMap::const_iterator pEnd(it->second.values.end()); tinygltf::ParameterMap::const_iterator pEnd(material.values.end());
for (; p != pEnd; p++) { for (; p != pEnd; p++) {
std::cout << Indent(2) << p->first << ": " std::cout << Indent(2) << p->first << ": "
<< PrintParameterValue(p->second) << std::endl; << PrintParameterValue(p->second) << std::endl;
@ -515,179 +444,57 @@ static void Dump(const tinygltf::Scene &scene) {
} }
{ {
std::map<std::string, tinygltf::Node>::const_iterator it( std::cout << "nodes(items=" << model.nodes.size() << ")" << std::endl;
scene.nodes.begin()); for (size_t i = 0; i < model.nodes.size(); i++) {
std::map<std::string, tinygltf::Node>::const_iterator itEnd( const tinygltf::Node &node = model.nodes[i];
scene.nodes.end()); std::cout << Indent(1) << "name : " << node.name << std::endl;
std::cout << "nodes(items=" << scene.nodes.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
DumpNode(it->second, 2); DumpNode(node, 2);
} }
} }
{ {
std::map<std::string, tinygltf::Image>::const_iterator it( std::cout << "images(items=" << model.images.size() << ")" << std::endl;
scene.images.begin()); for (size_t i = 0; i < model.images.size(); i++) {
std::map<std::string, tinygltf::Image>::const_iterator itEnd( const tinygltf::Image &image = model.images[i];
scene.images.end()); std::cout << Indent(1) << "name : " << image.name << std::endl;
std::cout << "images(items=" << scene.images.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
std::cout << Indent(2) << "width : " << it->second.width << std::endl; std::cout << Indent(2) << "width : " << image.width << std::endl;
std::cout << Indent(2) << "height : " << it->second.height std::cout << Indent(2) << "height : " << image.height
<< std::endl; << std::endl;
std::cout << Indent(2) << "component : " << it->second.component std::cout << Indent(2) << "component : " << image.component
<< std::endl;
std::cout << Indent(2) << "name : " << it->second.name << std::endl;
}
}
{
std::map<std::string, tinygltf::Texture>::const_iterator it(
scene.textures.begin());
std::map<std::string, tinygltf::Texture>::const_iterator itEnd(
scene.textures.end());
std::cout << "textures(items=" << scene.textures.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
std::cout << Indent(1) << "format : " << it->second.format
<< std::endl;
std::cout << Indent(1) << "internalFormat : " << it->second.internalFormat
<< std::endl;
std::cout << Indent(1) << "sampler : " << it->second.sampler
<< std::endl;
std::cout << Indent(1) << "source : " << it->second.source
<< std::endl;
std::cout << Indent(1) << "target : " << it->second.target
<< std::endl;
std::cout << Indent(1) << "type : " << it->second.type
<< std::endl; << std::endl;
} }
} }
{ {
std::map<std::string, tinygltf::Shader>::const_iterator it( std::cout << "textures(items=" << model.textures.size() << ")" << std::endl;
scene.shaders.begin()); for (size_t i = 0; i < model.textures.size(); i++) {
std::map<std::string, tinygltf::Shader>::const_iterator itEnd( const tinygltf::Texture &texture = model.textures[i];
scene.shaders.end()); std::cout << Indent(1) << "sampler : " << texture.sampler
std::cout << "shaders(items=" << scene.shaders.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name (id) : " << it->first << std::endl;
std::cout << Indent(2)
<< "type : " << PrintShaderType(it->second.type)
<< std::endl; << std::endl;
std::cout << Indent(1) << "source : " << texture.source
std::cout << Indent(2) << "name (json) : " << it->second.name
<< std::endl;
// Indent shader source nicely.
std::string shader_source(Indent(3));
shader_source.resize(shader_source.size() + it->second.source.size());
std::vector<unsigned char>::const_iterator sourceIt(
it->second.source.begin());
std::vector<unsigned char>::const_iterator sourceItEnd(
it->second.source.end());
for (; sourceIt != sourceItEnd; ++sourceIt) {
shader_source += static_cast<char>(*sourceIt);
if (*sourceIt == '\n') {
shader_source += Indent(3);
}
}
std::cout << Indent(2) << "source :\n"
<< shader_source << std::endl;
}
}
{
std::map<std::string, tinygltf::Program>::const_iterator it(
scene.programs.begin());
std::map<std::string, tinygltf::Program>::const_iterator itEnd(
scene.programs.end());
std::cout << "programs(items=" << scene.programs.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
std::cout << Indent(2) << "vertexShader : " << it->second.vertexShader
<< std::endl;
std::cout << Indent(2) << "fragmentShader : " << it->second.fragmentShader
<< std::endl;
std::cout << Indent(2) << "attributes : "
<< PrintStringArray(it->second.attributes) << std::endl;
std::cout << Indent(2) << "name : " << it->second.name
<< std::endl; << std::endl;
} }
} }
{ {
std::map<std::string, tinygltf::Technique>::const_iterator it( std::cout << "samplers(items=" << model.samplers.size() << ")" << std::endl;
scene.techniques.begin());
std::map<std::string, tinygltf::Technique>::const_iterator itEnd(
scene.techniques.end());
std::cout << "techniques(items=" << scene.techniques.size() << ")"
<< std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name (id) : " << it->first << std::endl;
std::cout << Indent(2) << "program : " << it->second.program
<< std::endl;
std::cout << Indent(2) << "name (json) : " << it->second.name
<< std::endl;
for (size_t i = 0; i < model.samplers.size(); i++) {
const tinygltf::Sampler &sampler = model.samplers[i];
std::cout << Indent(1) << "name (id) : " << sampler.name << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "parameters(items=" << it->second.parameters.size() << ")" << "minFilter : " << PrintFilterMode(sampler.minFilter)
<< std::endl;
std::map<std::string, tinygltf::TechniqueParameter>::const_iterator
paramIt(it->second.parameters.begin());
std::map<std::string, tinygltf::TechniqueParameter>::const_iterator
paramItEnd(it->second.parameters.end());
for (; paramIt != paramItEnd; ++paramIt) {
std::cout << Indent(3) << "name : " << paramIt->first << std::endl;
DumpTechniqueParameter(paramIt->second, 4);
}
std::cout << Indent(2)
<< "attributes(items=" << it->second.attributes.size() << ")"
<< std::endl;
DumpStringMap(it->second.attributes, 3);
std::cout << Indent(2) << "uniforms(items=" << it->second.uniforms.size()
<< ")" << std::endl;
DumpStringMap(it->second.uniforms, 3);
}
}
{
std::map<std::string, tinygltf::Sampler>::const_iterator it(
scene.samplers.begin());
std::map<std::string, tinygltf::Sampler>::const_iterator itEnd(
scene.samplers.end());
std::cout << "samplers(items=" << scene.samplers.size() << ")" << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name (id) : " << it->first << std::endl;
std::cout << Indent(2)
<< "minFilter : " << PrintFilterMode(it->second.minFilter)
<< std::endl; << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "magFilter : " << PrintFilterMode(it->second.magFilter) << "magFilter : " << PrintFilterMode(sampler.magFilter)
<< std::endl; << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "wrapS : " << PrintWrapMode(it->second.wrapS) << "wrapS : " << PrintWrapMode(sampler.wrapS)
<< std::endl; << std::endl;
std::cout << Indent(2) std::cout << Indent(2)
<< "wrapT : " << PrintWrapMode(it->second.wrapT) << "wrapT : " << PrintWrapMode(sampler.wrapT)
<< std::endl; << std::endl;
} }
} }
@ -699,7 +506,7 @@ int main(int argc, char **argv) {
exit(1); exit(1);
} }
tinygltf::Scene scene; tinygltf::Model model;
tinygltf::TinyGLTFLoader loader; tinygltf::TinyGLTFLoader loader;
std::string err; std::string err;
std::string input_filename(argv[1]); std::string input_filename(argv[1]);
@ -708,10 +515,10 @@ int main(int argc, char **argv) {
bool ret = false; bool ret = false;
if (ext.compare("glb") == 0) { if (ext.compare("glb") == 0) {
// assume binary glTF. // assume binary glTF.
ret = loader.LoadBinaryFromFile(&scene, &err, input_filename.c_str()); ret = loader.LoadBinaryFromFile(&model, &err, input_filename.c_str());
} else { } else {
// assume ascii glTF. // assume ascii glTF.
ret = loader.LoadASCIIFromFile(&scene, &err, input_filename.c_str()); ret = loader.LoadASCIIFromFile(&model, &err, input_filename.c_str());
} }
if (!err.empty()) { if (!err.empty()) {
@ -723,7 +530,7 @@ int main(int argc, char **argv) {
return -1; return -1;
} }
Dump(scene); Dump(model);
return 0; return 0;
} }

View File

@ -40,6 +40,7 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <vector> #include <vector>
#include <utility>
// for isnan/isinf // for isnan/isinf
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
@ -64,7 +65,6 @@ extern "C" {
#endif #endif
#endif // PICOJSON_USE_RVALUE_REFERENCE #endif // PICOJSON_USE_RVALUE_REFERENCE
// experimental support for int64_t (see README.mkdn for detail) // experimental support for int64_t (see README.mkdn for detail)
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
#define __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS
@ -83,7 +83,11 @@ extern "C" {
#endif #endif
#ifndef PICOJSON_ASSERT #ifndef PICOJSON_ASSERT
# define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0) #define PICOJSON_ASSERT(e) \
do { \
if (!(e)) \
throw std::runtime_error(#e); \
} while (0)
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
@ -106,13 +110,12 @@ namespace picojson {
array_type, array_type,
object_type object_type
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
, int64_type ,
int64_type
#endif #endif
}; };
enum { enum { INDENT_WIDTH = 2 };
INDENT_WIDTH = 2
};
struct null {}; struct null {};
@ -130,9 +133,11 @@ namespace picojson {
array *array_; array *array_;
object *object_; object *object_;
}; };
protected: protected:
int type_; int type_;
_storage u_; _storage u_;
public: public:
value(); value();
value(int type, bool); value(int type, bool);
@ -144,6 +149,11 @@ namespace picojson {
explicit value(const std::string &s); explicit value(const std::string &s);
explicit value(const array &a); explicit value(const array &a);
explicit value(const object &o); explicit value(const object &o);
#if PICOJSON_USE_RVALUE_REFERENCE
explicit value(std::string &&s);
explicit value(array &&a);
explicit value(object &&o);
#endif
explicit value(const char *s); explicit value(const char *s);
value(const char *s, size_t len); value(const char *s, size_t len);
~value(); ~value();
@ -157,32 +167,42 @@ namespace picojson {
template <typename T> bool is() const; template <typename T> bool is() const;
template <typename T> const T &get() const; template <typename T> const T &get() const;
template <typename T> T &get(); template <typename T> T &get();
template <typename T> void set(const T &);
#if PICOJSON_USE_RVALUE_REFERENCE
template <typename T> void set(T &&);
#endif
bool evaluate_as_boolean() const; bool evaluate_as_boolean() const;
const value& get(size_t idx) const; const value &get(const size_t idx) const;
const value &get(const std::string &key) const; const value &get(const std::string &key) const;
value& get(size_t idx); value &get(const size_t idx);
value &get(const std::string &key); value &get(const std::string &key);
bool contains(size_t idx) const; bool contains(const size_t idx) const;
bool contains(const std::string &key) const; bool contains(const std::string &key) const;
std::string to_str() const; std::string to_str() const;
template <typename Iter> void serialize(Iter os, bool prettify = false) const; template <typename Iter> void serialize(Iter os, bool prettify = false) const;
std::string serialize(bool prettify = false) const; std::string serialize(bool prettify = false) const;
private: private:
template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool
template <typename Iter> static void _indent(Iter os, int indent); template <typename Iter> static void _indent(Iter os, int indent);
template <typename Iter> void _serialize(Iter os, int indent) const; template <typename Iter> void _serialize(Iter os, int indent) const;
std::string _serialize(int indent) const; std::string _serialize(int indent) const;
void clear();
}; };
typedef value::array array; typedef value::array array;
typedef value::object object; typedef value::object object;
inline value::value() : type_(null_type) {} inline value::value() : type_(null_type), u_() {
}
inline value::value(int type, bool) : type_(type) { inline value::value(int type, bool) : type_(type), u_() {
switch (type) { switch (type) {
#define INIT(p, v) case p##type: u_.p = v; break #define INIT(p, v) \
case p##type: \
u_.p = v; \
break
INIT(boolean_, false); INIT(boolean_, false);
INIT(number_, 0.0); INIT(number_, 0.0);
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
@ -192,21 +212,22 @@ namespace picojson {
INIT(array_, new array()); INIT(array_, new array());
INIT(object_, new object()); INIT(object_, new object());
#undef INIT #undef INIT
default: break; default:
break;
} }
} }
inline value::value(bool b) : type_(boolean_type) { inline value::value(bool b) : type_(boolean_type), u_() {
u_.boolean_ = b; u_.boolean_ = b;
} }
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
inline value::value(int64_t i) : type_(int64_type) { inline value::value(int64_t i) : type_(int64_type), u_() {
u_.int64_ = i; u_.int64_ = i;
} }
#endif #endif
inline value::value(double n) : type_(number_type) { inline value::value(double n) : type_(number_type), u_() {
if ( if (
#ifdef _MSC_VER #ifdef _MSC_VER
!_finite(n) !_finite(n)
@ -221,40 +242,65 @@ namespace picojson {
u_.number_ = n; u_.number_ = n;
} }
inline value::value(const std::string& s) : type_(string_type) { inline value::value(const std::string &s) : type_(string_type), u_() {
u_.string_ = new std::string(s); u_.string_ = new std::string(s);
} }
inline value::value(const array& a) : type_(array_type) { inline value::value(const array &a) : type_(array_type), u_() {
u_.array_ = new array(a); u_.array_ = new array(a);
} }
inline value::value(const object& o) : type_(object_type) { inline value::value(const object &o) : type_(object_type), u_() {
u_.object_ = new object(o); u_.object_ = new object(o);
} }
inline value::value(const char* s) : type_(string_type) { #if PICOJSON_USE_RVALUE_REFERENCE
inline value::value(std::string &&s) : type_(string_type), u_() {
u_.string_ = new std::string(std::move(s));
}
inline value::value(array &&a) : type_(array_type), u_() {
u_.array_ = new array(std::move(a));
}
inline value::value(object &&o) : type_(object_type), u_() {
u_.object_ = new object(std::move(o));
}
#endif
inline value::value(const char *s) : type_(string_type), u_() {
u_.string_ = new std::string(s); u_.string_ = new std::string(s);
} }
inline value::value(const char* s, size_t len) : type_(string_type) { inline value::value(const char *s, size_t len) : type_(string_type), u_() {
u_.string_ = new std::string(s, len); u_.string_ = new std::string(s, len);
} }
inline value::~value() { inline void value::clear() {
switch (type_) { switch (type_) {
#define DEINIT(p) case p##type: delete u_.p; break #define DEINIT(p) \
case p##type: \
delete u_.p; \
break
DEINIT(string_); DEINIT(string_);
DEINIT(array_); DEINIT(array_);
DEINIT(object_); DEINIT(object_);
#undef DEINIT #undef DEINIT
default: break; default:
break;
} }
} }
inline value::value(const value& x) : type_(x.type_) { inline value::~value() {
clear();
}
inline value::value(const value &x) : type_(x.type_), u_() {
switch (type_) { switch (type_) {
#define INIT(p, v) case p##type: u_.p = v; break #define INIT(p, v) \
case p##type: \
u_.p = v; \
break
INIT(string_, new std::string(*x.u_.string_)); INIT(string_, new std::string(*x.u_.string_));
INIT(array_, new array(*x.u_.array_)); INIT(array_, new array(*x.u_.array_));
INIT(object_, new object(*x.u_.object_)); INIT(object_, new object(*x.u_.object_));
@ -274,7 +320,7 @@ namespace picojson {
} }
#if PICOJSON_USE_RVALUE_REFERENCE #if PICOJSON_USE_RVALUE_REFERENCE
inline value::value(value&& x)throw() : type_(null_type) { inline value::value(value &&x) throw() : type_(null_type), u_() {
swap(x); swap(x);
} }
inline value &value::operator=(value &&x) throw() { inline value &value::operator=(value &&x) throw() {
@ -310,13 +356,11 @@ namespace picojson {
#define GET(ctype, var) \ #define GET(ctype, var) \
template <> inline const ctype &value::get<ctype>() const { \ template <> inline const ctype &value::get<ctype>() const { \
PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
&& is<ctype>()); \
return var; \ return var; \
} \ } \
template <> inline ctype &value::get<ctype>() { \ template <> inline ctype &value::get<ctype>() { \
PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \ PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
&& is<ctype>()); \
return var; \ return var; \
} }
GET(bool, u_.boolean_) GET(bool, u_.boolean_)
@ -324,13 +368,44 @@ namespace picojson {
GET(array, *u_.array_) GET(array, *u_.array_)
GET(object, *u_.object_) GET(object, *u_.object_)
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
GET(double, (type_ == int64_type && (const_cast<value*>(this)->type_ = number_type, const_cast<value*>(this)->u_.number_ = u_.int64_), u_.number_)) GET(double,
(type_ == int64_type && (const_cast<value *>(this)->type_ = number_type, const_cast<value *>(this)->u_.number_ = u_.int64_),
u_.number_))
GET(int64_t, u_.int64_) GET(int64_t, u_.int64_)
#else #else
GET(double, u_.number_) GET(double, u_.number_)
#endif #endif
#undef GET #undef GET
#define SET(ctype, jtype, setter) \
template <> inline void value::set<ctype>(const ctype &_val) { \
clear(); \
type_ = jtype##_type; \
setter \
}
SET(bool, boolean, u_.boolean_ = _val;)
SET(std::string, string, u_.string_ = new std::string(_val);)
SET(array, array, u_.array_ = new array(_val);)
SET(object, object, u_.object_ = new object(_val);)
SET(double, number, u_.number_ = _val;)
#ifdef PICOJSON_USE_INT64
SET(int64_t, int64, u_.int64_ = _val;)
#endif
#undef SET
#if PICOJSON_USE_RVALUE_REFERENCE
#define MOVESET(ctype, jtype, setter) \
template <> inline void value::set<ctype>(ctype && _val) { \
clear(); \
type_ = jtype##_type; \
setter \
}
MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
MOVESET(array, array, u_.array_ = new array(std::move(_val));)
MOVESET(object, object, u_.object_ = new object(std::move(_val));)
#undef MOVESET
#endif
inline bool value::evaluate_as_boolean() const { inline bool value::evaluate_as_boolean() const {
switch (type_) { switch (type_) {
case null_type: case null_type:
@ -350,13 +425,13 @@ namespace picojson {
} }
} }
inline const value& value::get(size_t idx) const { inline const value &value::get(const size_t idx) const {
static value s_null; static value s_null;
PICOJSON_ASSERT(is<array>()); PICOJSON_ASSERT(is<array>());
return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
} }
inline value& value::get(size_t idx) { inline value &value::get(const size_t idx) {
static value s_null; static value s_null;
PICOJSON_ASSERT(is<array>()); PICOJSON_ASSERT(is<array>());
return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
@ -376,7 +451,7 @@ namespace picojson {
return i != u_.object_->end() ? i->second : s_null; return i != u_.object_->end() ? i->second : s_null;
} }
inline bool value::contains(size_t idx) const { inline bool value::contains(const size_t idx) const {
PICOJSON_ASSERT(is<array>()); PICOJSON_ASSERT(is<array>());
return idx < u_.array_->size(); return idx < u_.array_->size();
} }
@ -389,8 +464,10 @@ namespace picojson {
inline std::string value::to_str() const { inline std::string value::to_str() const {
switch (type_) { switch (type_) {
case null_type: return "null"; case null_type:
case boolean_type: return u_.boolean_ ? "true" : "false"; return "null";
case boolean_type:
return u_.boolean_ ? "true" : "false";
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
case int64_type: { case int64_type: {
char buf[sizeof("-9223372036854775808")]; char buf[sizeof("-9223372036854775808")];
@ -415,10 +492,14 @@ namespace picojson {
#endif #endif
return buf; return buf;
} }
case string_type: return *u_.string_; case string_type:
case array_type: return "array"; return *u_.string_;
case object_type: return "object"; case array_type:
default: PICOJSON_ASSERT(0); return "array";
case object_type:
return "object";
default:
PICOJSON_ASSERT(0);
#ifdef _MSC_VER #ifdef _MSC_VER
__assume(0); __assume(0);
#endif #endif
@ -430,11 +511,14 @@ namespace picojson {
std::copy(s.begin(), s.end(), oi); std::copy(s.begin(), s.end(), oi);
} }
template <typename Iter> void serialize_str(const std::string& s, Iter oi) { template <typename Iter> struct serialize_str_char {
*oi++ = '"'; Iter oi;
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { void operator()(char c) {
switch (*i) { switch (c) {
#define MAP(val, sym) case val: copy(sym, oi); break #define MAP(val, sym) \
case val: \
copy(sym, oi); \
break
MAP('"', "\\\""); MAP('"', "\\\"");
MAP('\\', "\\\\"); MAP('\\', "\\\\");
MAP('/', "\\/"); MAP('/', "\\/");
@ -445,16 +529,22 @@ namespace picojson {
MAP('\t', "\\t"); MAP('\t', "\\t");
#undef MAP #undef MAP
default: default:
if (static_cast<unsigned char>(*i) < 0x20 || *i == 0x7f) { if (static_cast<unsigned char>(c) < 0x20 || c == 0x7f) {
char buf[7]; char buf[7];
SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff); SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff);
copy(buf, buf + 6, oi); copy(buf, buf + 6, oi);
} else { } else {
*oi++ = *i; *oi++ = c;
} }
break; break;
} }
} }
};
template <typename Iter> void serialize_str(const std::string &s, Iter oi) {
*oi++ = '"';
serialize_str_char<Iter> process_char = {oi};
std::for_each(s.begin(), s.end(), process_char);
*oi++ = '"'; *oi++ = '"';
} }
@ -483,9 +573,7 @@ namespace picojson {
if (indent != -1) { if (indent != -1) {
++indent; ++indent;
} }
for (array::const_iterator i = u_.array_->begin(); for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) {
i != u_.array_->end();
++i) {
if (i != u_.array_->begin()) { if (i != u_.array_->begin()) {
*oi++ = ','; *oi++ = ',';
} }
@ -508,9 +596,7 @@ namespace picojson {
if (indent != -1) { if (indent != -1) {
++indent; ++indent;
} }
for (object::const_iterator i = u_.object_->begin(); for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) {
i != u_.object_->end();
++i) {
if (i != u_.object_->begin()) { if (i != u_.object_->begin()) {
*oi++ = ','; *oi++ = ',';
} }
@ -551,35 +637,40 @@ namespace picojson {
template <typename Iter> class input { template <typename Iter> class input {
protected: protected:
Iter cur_, end_; Iter cur_, end_;
int last_ch_; bool consumed_;
bool ungot_;
int line_; int line_;
public: public:
input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {} input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) {
}
int getc() { int getc() {
if (ungot_) { if (consumed_) {
ungot_ = false; if (*cur_ == '\n') {
return last_ch_; ++line_;
}
++cur_;
} }
if (cur_ == end_) { if (cur_ == end_) {
last_ch_ = -1; consumed_ = false;
return -1; return -1;
} }
if (last_ch_ == '\n') { consumed_ = true;
line_++; return *cur_ & 0xff;
}
last_ch_ = *cur_ & 0xff;
++cur_;
return last_ch_;
} }
void ungetc() { void ungetc() {
if (last_ch_ != -1) { consumed_ = false;
PICOJSON_ASSERT(! ungot_);
ungot_ = true;
} }
Iter cur() const {
if (consumed_) {
input<Iter> *self = const_cast<input<Iter> *>(this);
self->consumed_ = false;
++self->cur_;
}
return cur_;
}
int line() const {
return line_;
} }
Iter cur() const { return cur_; }
int line() const { return line_; }
void skip_ws() { void skip_ws() {
while (1) { while (1) {
int ch = getc(); int ch = getc();
@ -589,18 +680,16 @@ namespace picojson {
} }
} }
} }
bool expect(int expect) { bool expect(const int expected) {
skip_ws(); skip_ws();
if (getc() != expect) { if (getc() != expected) {
ungetc(); ungetc();
return false; return false;
} }
return true; return true;
} }
bool match(const std::string &pattern) { bool match(const std::string &pattern) {
for (std::string::const_iterator pi(pattern.begin()); for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) {
pi != pattern.end();
++pi) {
if (getc() != *pi) { if (getc() != *pi) {
ungetc(); ungetc();
return false; return false;
@ -654,20 +743,20 @@ namespace picojson {
uni_ch += 0x10000; uni_ch += 0x10000;
} }
if (uni_ch < 0x80) { if (uni_ch < 0x80) {
out.push_back(uni_ch); out.push_back(static_cast<char>(uni_ch));
} else { } else {
if (uni_ch < 0x800) { if (uni_ch < 0x800) {
out.push_back(0xc0 | (uni_ch >> 6)); out.push_back(static_cast<char>(0xc0 | (uni_ch >> 6)));
} else { } else {
if (uni_ch < 0x10000) { if (uni_ch < 0x10000) {
out.push_back(0xe0 | (uni_ch >> 12)); out.push_back(static_cast<char>(0xe0 | (uni_ch >> 12)));
} else { } else {
out.push_back(0xf0 | (uni_ch >> 18)); out.push_back(static_cast<char>(0xf0 | (uni_ch >> 18)));
out.push_back(0x80 | ((uni_ch >> 12) & 0x3f)); out.push_back(static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f)));
} }
out.push_back(0x80 | ((uni_ch >> 6) & 0x3f)); out.push_back(static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f)));
} }
out.push_back(0x80 | (uni_ch & 0x3f)); out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f)));
} }
return true; return true;
} }
@ -685,7 +774,10 @@ namespace picojson {
return false; return false;
} }
switch (ch) { switch (ch) {
#define MAP(sym, val) case sym: out.push_back(val); break #define MAP(sym, val) \
case sym: \
out.push_back(val); \
break
MAP('"', '\"'); MAP('"', '\"');
MAP('\\', '\\'); MAP('\\', '\\');
MAP('/', '/'); MAP('/', '/');
@ -704,7 +796,7 @@ namespace picojson {
return false; return false;
} }
} else { } else {
out.push_back(ch); out.push_back(static_cast<char>(ch));
} }
} }
return false; return false;
@ -736,9 +828,7 @@ namespace picojson {
} }
do { do {
std::string key; std::string key;
if (! in.expect('"') if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) {
|| ! _parse_string(key, in)
|| ! in.expect(':')) {
return false; return false;
} }
if (!ctx.parse_object_item(in, key)) { if (!ctx.parse_object_item(in, key)) {
@ -752,9 +842,8 @@ namespace picojson {
std::string num_str; std::string num_str;
while (1) { while (1) {
int ch = in.getc(); int ch = in.getc();
if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') {
|| ch == 'e' || ch == 'E') { num_str.push_back(static_cast<char>(ch));
num_str.push_back(ch);
} else if (ch == '.') { } else if (ch == '.') {
#if PICOJSON_USE_LOCALE #if PICOJSON_USE_LOCALE
num_str += localeconv()->decimal_point; num_str += localeconv()->decimal_point;
@ -773,7 +862,8 @@ namespace picojson {
in.skip_ws(); in.skip_ws();
int ch = in.getc(); int ch = in.getc();
switch (ch) { switch (ch) {
#define IS(ch, text, op) case ch: \ #define IS(ch, text, op) \
case ch: \
if (in.match(text) && op) { \ if (in.match(text) && op) { \
return true; \ return true; \
} else { \ } else { \
@ -794,7 +884,7 @@ namespace picojson {
double f; double f;
char *endp; char *endp;
in.ungetc(); in.ungetc();
std::string num_str = _parse_number(in); std::string num_str(_parse_number(in));
if (num_str.empty()) { if (num_str.empty()) {
return false; return false;
} }
@ -802,10 +892,8 @@ namespace picojson {
{ {
errno = 0; errno = 0;
intmax_t ival = strtoimax(num_str.c_str(), &endp, 10); intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
if (errno == 0 if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() &&
&& std::numeric_limits<int64_t>::min() <= ival endp == num_str.c_str() + num_str.size()) {
&& ival <= std::numeric_limits<int64_t>::max()
&& endp == num_str.c_str() + num_str.size()) {
ctx.set_int64(ival); ctx.set_int64(ival);
return true; return true;
} }
@ -826,19 +914,35 @@ namespace picojson {
class deny_parse_context { class deny_parse_context {
public: public:
bool set_null() { return false; } bool set_null() {
bool set_bool(bool) { return false; } return false;
}
bool set_bool(bool) {
return false;
}
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
bool set_int64(int64_t) { return false; } bool set_int64(int64_t) {
return false;
}
#endif #endif
bool set_number(double) { return false; } bool set_number(double) {
template <typename Iter> bool parse_string(input<Iter>&) { return false; } return false;
bool parse_array_start() { return false; } }
template <typename Iter> bool parse_string(input<Iter> &) {
return false;
}
bool parse_array_start() {
return false;
}
template <typename Iter> bool parse_array_item(input<Iter> &, size_t) { template <typename Iter> bool parse_array_item(input<Iter> &, size_t) {
return false; return false;
} }
bool parse_array_stop(size_t) { return false; } bool parse_array_stop(size_t) {
bool parse_object_start() { return false; } return false;
}
bool parse_object_start() {
return false;
}
template <typename Iter> bool parse_object_item(input<Iter> &, const std::string &) { template <typename Iter> bool parse_object_item(input<Iter> &, const std::string &) {
return false; return false;
} }
@ -847,8 +951,10 @@ namespace picojson {
class default_parse_context { class default_parse_context {
protected: protected:
value *out_; value *out_;
public: public:
default_parse_context(value* out) : out_(out) {} default_parse_context(value *out) : out_(out) {
}
bool set_null() { bool set_null() {
*out_ = value(); *out_ = value();
return true; return true;
@ -881,7 +987,9 @@ namespace picojson {
default_parse_context ctx(&a.back()); default_parse_context ctx(&a.back());
return _parse(ctx, in); return _parse(ctx, in);
} }
bool parse_array_stop(size_t) { return true; } bool parse_array_stop(size_t) {
return true;
}
bool parse_object_start() { bool parse_object_start() {
*out_ = value(object_type, false); *out_ = value(object_type, false);
return true; return true;
@ -891,6 +999,7 @@ namespace picojson {
default_parse_context ctx(&o[key]); default_parse_context ctx(&o[key]);
return _parse(ctx, in); return _parse(ctx, in);
} }
private: private:
default_parse_context(const default_parse_context &); default_parse_context(const default_parse_context &);
default_parse_context &operator=(const default_parse_context &); default_parse_context &operator=(const default_parse_context &);
@ -899,29 +1008,47 @@ namespace picojson {
class null_parse_context { class null_parse_context {
public: public:
struct dummy_str { struct dummy_str {
void push_back(int) {} void push_back(int) {
}
}; };
public: public:
null_parse_context() {} null_parse_context() {
bool set_null() { return true; } }
bool set_bool(bool) { return true; } bool set_null() {
return true;
}
bool set_bool(bool) {
return true;
}
#ifdef PICOJSON_USE_INT64 #ifdef PICOJSON_USE_INT64
bool set_int64(int64_t) { return true; } bool set_int64(int64_t) {
return true;
}
#endif #endif
bool set_number(double) { return true; } bool set_number(double) {
return true;
}
template <typename Iter> bool parse_string(input<Iter> &in) { template <typename Iter> bool parse_string(input<Iter> &in) {
dummy_str s; dummy_str s;
return _parse_string(s, in); return _parse_string(s, in);
} }
bool parse_array_start() { return true; } bool parse_array_start() {
return true;
}
template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) { template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
return _parse(*this, in); return _parse(*this, in);
} }
bool parse_array_stop(size_t) { return true; } bool parse_array_stop(size_t) {
bool parse_object_start() { return true; } return true;
}
bool parse_object_start() {
return true;
}
template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &) { template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &) {
return _parse(*this, in); return _parse(*this, in);
} }
private: private:
null_parse_context(const null_parse_context &); null_parse_context(const null_parse_context &);
null_parse_context &operator=(const null_parse_context &); null_parse_context &operator=(const null_parse_context &);
@ -945,7 +1072,7 @@ namespace picojson {
if (ch == -1 || ch == '\n') { if (ch == -1 || ch == '\n') {
break; break;
} else if (ch >= ' ') { } else if (ch >= ' ') {
err->push_back(ch); err->push_back(static_cast<char>(ch));
} }
} }
} }
@ -965,14 +1092,11 @@ namespace picojson {
inline std::string parse(value &out, std::istream &is) { inline std::string parse(value &out, std::istream &is) {
std::string err; std::string err;
parse(out, std::istreambuf_iterator<char>(is.rdbuf()), parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err);
std::istreambuf_iterator<char>(), &err);
return err; return err;
} }
template <typename T> struct last_error_t { template <typename T> struct last_error_t { static std::string s; };
static std::string s;
};
template <typename T> std::string last_error_t<T>::s; template <typename T> std::string last_error_t<T>::s;
inline void set_last_error(const std::string &s) { inline void set_last_error(const std::string &s) {
@ -1009,17 +1133,15 @@ namespace picojson {
#if !PICOJSON_USE_RVALUE_REFERENCE #if !PICOJSON_USE_RVALUE_REFERENCE
namespace std { namespace std {
template<> inline void swap(picojson::value& x, picojson::value& y) template <> inline void swap(picojson::value &x, picojson::value &y) {
{
x.swap(y); x.swap(y);
} }
} }
#endif #endif
inline std::istream& operator>>(std::istream& is, picojson::value& x) inline std::istream &operator>>(std::istream &is, picojson::value &x) {
{
picojson::set_last_error(std::string()); picojson::set_last_error(std::string());
std::string err = picojson::parse(x, is); const std::string err(picojson::parse(x, is));
if (!err.empty()) { if (!err.empty()) {
picojson::set_last_error(err); picojson::set_last_error(err);
is.setstate(std::ios::failbit); is.setstate(std::ios::failbit);
@ -1027,8 +1149,7 @@ inline std::istream& operator>>(std::istream& is, picojson::value& x)
return is; return is;
} }
inline std::ostream& operator<<(std::ostream& os, const picojson::value& x) inline std::ostream &operator<<(std::ostream &os, const picojson::value &x) {
{
x.serialize(std::ostream_iterator<char>(os)); x.serialize(std::ostream_iterator<char>(os));
return os; return os;
} }

View File

@ -1,10 +1,10 @@
// //
// Tiny glTF loader. // Header-only tiny glTF 2.0 loader.
// //
// //
// The MIT License (MIT) // The MIT License (MIT)
// //
// Copyright (c) 2015 - 2016 Syoyo Fujita and many contributors. // Copyright (c) 2015 - 2017 Syoyo Fujita, Aurélien Chatelain and many contributors.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@ -25,13 +25,7 @@
// THE SOFTWARE. // THE SOFTWARE.
// Version: // Version:
// - v0.9.5 Support parsing `extras` parameter. // - v2.0.0 glTF 2.0!.
// - v0.9.4 Support parsing `shader`, `program` and `tecnique` thanks to
// @lukesanantonio
// - v0.9.3 Support binary glTF
// - v0.9.2 Support parsing `texture`
// - v0.9.1 Support loading glTF asset from memory
// - v0.9.0 Initial
// //
// Tiny glTF loader is using following third party libraries: // Tiny glTF loader is using following third party libraries:
// //
@ -298,21 +292,22 @@ struct AnimationChannel {
Value extras; Value extras;
AnimationChannel() AnimationChannel()
: sampler(-1)
, target_node(-1)
{ {
sampler = -1;
target_node = -1;
} }
}; };
struct AnimationSampler { struct AnimationSampler {
int input; // required int input; // required
std::string interpolation; // in ["LINEAR", "STEP", "CATMULLROMSPLINE", "CUBICSPLINE"], default "LINEAR"
int output; // required int output; // required
std::string interpolation; // in ["LINEAR", "STEP", "CATMULLROMSPLINE", "CUBICSPLINE"], default "LINEAR"
AnimationSampler() AnimationSampler()
: input(-1)
, output(-1)
, interpolation("LINEAR")
{ {
input = -1;
output = -1;
} }
}; };
@ -346,9 +341,9 @@ struct Sampler {
Value extras; Value extras;
Sampler() Sampler()
: wrapS(TINYGLTF_TEXTURE_WRAP_RPEAT)
, wrapT(TINYGLTF_TEXTURE_WRAP_RPEAT)
{ {
wrapS = TINYGLTF_TEXTURE_WRAP_RPEAT;
wrapT = TINYGLTF_TEXTURE_WRAP_RPEAT;
} }
}; };
@ -376,9 +371,9 @@ struct Texture {
Value extras; Value extras;
Texture() Texture()
: sampler(-1)
, source(-1)
{ {
sampler = -1;
source =-1;
} }
}; };
@ -482,9 +477,9 @@ typedef struct {
class Node { class Node {
public: public:
Node() Node()
: skin(-1)
, mesh(-1)
{ {
mesh = -1,
skin = -1;
} }
~Node() {} ~Node() {}
@ -1274,7 +1269,7 @@ static bool ParseStringIntProperty(std::map<std::string, int> *ret,
picojson::object::const_iterator dictItEnd(dict.end()); picojson::object::const_iterator dictItEnd(dict.end());
for (; dictIt != dictItEnd; ++dictIt) { for (; dictIt != dictItEnd; ++dictIt) {
if (!dictIt->second.is<int>()) { if (!dictIt->second.is<double>()) {
if (required) { if (required) {
if (err) { if (err) {
(*err) += "'" + property + "' value is not an int.\n"; (*err) += "'" + property + "' value is not an int.\n";
@ -1841,7 +1836,7 @@ static bool ParseNode(Node *node, std::string *err, const picojson::object &o) {
double mesh = -1.0; double mesh = -1.0;
ParseNumberProperty(&mesh, err, o, "mesh", false); ParseNumberProperty(&mesh, err, o, "mesh", false);
node->mesh = mesh; node->mesh = int(mesh);
node->children.clear(); node->children.clear();
picojson::object::const_iterator childrenObject = o.find("children"); picojson::object::const_iterator childrenObject = o.find("children");
@ -1850,7 +1845,7 @@ static bool ParseNode(Node *node, std::string *err, const picojson::object &o) {
const picojson::array &childrenArray = const picojson::array &childrenArray =
(childrenObject->second).get<picojson::array>(); (childrenObject->second).get<picojson::array>();
for (size_t i = 0; i < childrenArray.size(); i++) { for (size_t i = 0; i < childrenArray.size(); i++) {
if (!childrenArray[i].is<int>()) { if (!childrenArray[i].is<double>()) {
if (err) { if (err) {
(*err) += "Invalid `children` array.\n"; (*err) += "Invalid `children` array.\n";
} }
@ -1918,9 +1913,9 @@ static bool ParseMaterial(Material *material, std::string *err,
(it->second).get<picojson::object>(); (it->second).get<picojson::object>();
picojson::object::const_iterator itVal(values_object.begin()); picojson::object::const_iterator itVal(values_object.begin());
picojson::object::const_iterator itEnd(values_object.end()); picojson::object::const_iterator itValEnd(values_object.end());
for (; itVal != itEnd; itVal++) { for (; itVal != itValEnd; itVal++) {
Parameter param; Parameter param;
if (ParseParameterProperty(&param, err, values_object, itVal->first, if (ParseParameterProperty(&param, err, values_object, itVal->first,
false)) { false)) {
@ -1942,9 +1937,9 @@ static bool ParseMaterial(Material *material, std::string *err,
(extIt->second).get<picojson::object>(); (extIt->second).get<picojson::object>();
picojson::object::const_iterator itVal(values_object.begin()); picojson::object::const_iterator itVal(values_object.begin());
picojson::object::const_iterator itEnd(values_object.end()); picojson::object::const_iterator itValEnd(values_object.end());
for (; itVal != itEnd; itVal++) { for (; itVal != itValEnd; itVal++) {
Parameter param; Parameter param;
if (ParseParameterProperty(&param, err, values_object, itVal->first, if (ParseParameterProperty(&param, err, values_object, itVal->first,
false)) { false)) {
@ -2323,7 +2318,7 @@ if (v.contains("scenes") && v.get("scenes").is<picojson::array>()) {
// 7. Parse default scenes. // 7. Parse default scenes.
if (v.contains("scene") && v.get("scene").is<double>()) { if (v.contains("scene") && v.get("scene").is<double>()) {
const int defaultScene = v.get("scene").get<double>(); const int defaultScene = int(v.get("scene").get<double>());
model->defaultScene = static_cast<int>(defaultScene); model->defaultScene = static_cast<int>(defaultScene);
} }
@ -2362,7 +2357,7 @@ if (v.contains("scenes") && v.get("scenes").is<picojson::array>()) {
if (image.bufferView != -1) { if (image.bufferView != -1) {
// Load image from the buffer view. // Load image from the buffer view.
if ((size_t)image.bufferView >= model->bufferViews.size()) { if (size_t(image.bufferView) >= model->bufferViews.size()) {
if (err) { if (err) {
std::stringstream ss; std::stringstream ss;
ss << "bufferView \"" << image.bufferView ss << "bufferView \"" << image.bufferView
@ -2372,8 +2367,8 @@ if (v.contains("scenes") && v.get("scenes").is<picojson::array>()) {
return false; return false;
} }
const BufferView &bufferView = model->bufferViews[image.bufferView]; const BufferView &bufferView = model->bufferViews[size_t(image.bufferView)];
const Buffer &buffer = model->buffers[bufferView.buffer]; const Buffer &buffer = model->buffers[size_t(bufferView.buffer)];
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],