mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-08-14 08:35:56 +08:00
Merge branch 'master' of github.com:syoyo/tinygltfloader
This commit is contained in:
commit
a5c15e9e76
@ -15,10 +15,15 @@ Simple OpenGL viewer for glTF geometry.
|
||||
> premake4 gmake
|
||||
$ make
|
||||
|
||||
### Windows(not tested)
|
||||
### Windows(not tested well)
|
||||
|
||||
Edit glew and glfw path in `premake4.lua`, then
|
||||
|
||||
> premake5.exe vs2013
|
||||
Open .sln in Visual Studio 2013
|
||||
|
||||
Open .sln in Visual Studio 2013
|
||||
|
||||
When running .exe, glew and glfw dll must exist in the working directory.
|
||||
|
||||
## TODO
|
||||
|
||||
|
@ -142,7 +142,9 @@ bool LinkShader(GLuint &prog, GLuint &vertShader, GLuint &fragShader) {
|
||||
|
||||
void reshapeFunc(GLFWwindow *window, int w, int h) {
|
||||
(void)window;
|
||||
glViewport(0, 0, w, h);
|
||||
int fb_w, fb_h;
|
||||
glfwGetFramebufferSize(window, &fb_w, &fb_h);
|
||||
glViewport(0, 0, fb_w, fb_h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0, (float)w / (float)h, 0.1f, 1000.0f);
|
||||
@ -235,6 +237,7 @@ static void SetupGLState(tinygltf::Scene &scene, GLuint progId) {
|
||||
for (; it != itEnd; it++) {
|
||||
const tinygltf::BufferView &bufferView = it->second;
|
||||
if (bufferView.target == 0) {
|
||||
std::cout << "WARN: bufferView.target is zero" << std::endl;
|
||||
continue; // Unsupported bufferView.
|
||||
}
|
||||
|
||||
@ -242,6 +245,7 @@ static void SetupGLState(tinygltf::Scene &scene, GLuint progId) {
|
||||
GLBufferState state;
|
||||
glGenBuffers(1, &state.vb);
|
||||
glBindBuffer(bufferView.target, state.vb);
|
||||
std::cout << "buffer.size= " << buffer.data.size() << ", byteOffset = " << bufferView.byteOffset << std::endl;
|
||||
glBufferData(bufferView.target, bufferView.byteLength,
|
||||
&buffer.data.at(0) + bufferView.byteOffset, GL_STATIC_DRAW);
|
||||
glBindBuffer(bufferView.target, 0);
|
||||
@ -349,17 +353,22 @@ void DrawMesh(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
|
||||
count = 3;
|
||||
} else if (accessor.type == TINYGLTF_TYPE_VEC4) {
|
||||
count = 4;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
// it->first would be "POSITION", "NORMAL", "TEXCOORD_0", ...
|
||||
if ((it->first.compare("POSITION") == 0) ||
|
||||
(it->first.compare("NORMAL") == 0) ||
|
||||
(it->first.compare("TEXCOORD_0") == 0)) {
|
||||
glVertexAttribPointer(
|
||||
gGLProgramState.attribs[it->first], count, accessor.componentType,
|
||||
GL_FALSE, accessor.byteStride, BUFFER_OFFSET(accessor.byteOffset));
|
||||
CheckErrors("vertex attrib pointer");
|
||||
glEnableVertexAttribArray(gGLProgramState.attribs[it->first]);
|
||||
CheckErrors("enable vertex attrib array");
|
||||
|
||||
if (gGLProgramState.attribs[it->first] >= 0) {
|
||||
glVertexAttribPointer(
|
||||
gGLProgramState.attribs[it->first], count, accessor.componentType,
|
||||
GL_FALSE, accessor.byteStride, BUFFER_OFFSET(accessor.byteOffset));
|
||||
CheckErrors("vertex attrib pointer");
|
||||
glEnableVertexAttribArray(gGLProgramState.attribs[it->first]);
|
||||
CheckErrors("enable vertex attrib array");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,7 +389,9 @@ void DrawMesh(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
|
||||
mode = GL_LINES;
|
||||
} else if (primitive.mode == TINYGLTF_MODE_LINE_LOOP) {
|
||||
mode = GL_LINE_LOOP;
|
||||
};
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
glDrawElements(mode, indexAccessor.count, indexAccessor.componentType,
|
||||
BUFFER_OFFSET(indexAccessor.byteOffset));
|
||||
CheckErrors("draw elements");
|
||||
@ -395,7 +406,9 @@ void DrawMesh(tinygltf::Scene &scene, const tinygltf::Mesh &mesh) {
|
||||
if ((it->first.compare("POSITION") == 0) ||
|
||||
(it->first.compare("NORMAL") == 0) ||
|
||||
(it->first.compare("TEXCOORD_0") == 0)) {
|
||||
glDisableVertexAttribArray(gGLProgramState.attribs[it->first]);
|
||||
if (gGLProgramState.attribs[it->first] >= 0) {
|
||||
glDisableVertexAttribArray(gGLProgramState.attribs[it->first]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -489,7 +502,7 @@ int main(int argc, char **argv) {
|
||||
glfwSetMouseButtonCallback(window, clickFunc);
|
||||
glfwSetCursorPosCallback(window, motionFunc);
|
||||
|
||||
glewExperimental = true;
|
||||
glewExperimental = true; // This may be only true for linux environment.
|
||||
if (glewInit() != GLEW_OK) {
|
||||
std::cerr << "Failed to initialize GLEW." << std::endl;
|
||||
return -1;
|
||||
@ -515,17 +528,12 @@ int main(int argc, char **argv) {
|
||||
CheckErrors("link");
|
||||
|
||||
{
|
||||
// At least `in_vertex` should be used in the shader.
|
||||
GLint vtxLoc = glGetAttribLocation(progId, "in_vertex");
|
||||
if (vtxLoc < 0) {
|
||||
printf("vertex loc not found.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
GLint tnLoc = glGetAttribLocation(progId, "in_normal");
|
||||
if (tnLoc < 0) {
|
||||
printf("normal loc not found.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
glUseProgram(progId);
|
||||
@ -534,6 +542,8 @@ int main(int argc, char **argv) {
|
||||
SetupGLState(scene, progId);
|
||||
CheckErrors("SetupGLState");
|
||||
|
||||
std::cout << "# of meshes = " << scene.meshes.size() << std::endl;
|
||||
|
||||
while (glfwWindowShouldClose(window) == GL_FALSE) {
|
||||
glfwPollEvents();
|
||||
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
|
||||
|
@ -1,36 +1,41 @@
|
||||
solution "glview"
|
||||
-- location ( "build" )
|
||||
configurations { "Debug", "Release" }
|
||||
platforms {"native", "x64", "x32"}
|
||||
|
||||
project "glview"
|
||||
-- location ( "build" )
|
||||
configurations { "Debug", "Release" }
|
||||
platforms {"native", "x64", "x32"}
|
||||
|
||||
project "glview"
|
||||
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
files { "glview.cc", "trackball.cc" }
|
||||
includedirs { "./" }
|
||||
includedirs { "../../" }
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
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 { "linux" }
|
||||
linkoptions { "`pkg-config --libs glfw3`" }
|
||||
links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" }
|
||||
|
||||
configuration { "windows" }
|
||||
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
|
||||
defines { "_CRT_SECURE_NO_WARNINGS" }
|
||||
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" }
|
||||
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" }
|
||||
links { "glfw3", "GLEW" }
|
||||
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }
|
||||
|
||||
configuration "Debug"
|
||||
defines { "DEBUG" }
|
||||
flags { "Symbols", "ExtraWarnings"}
|
||||
configuration "Debug"
|
||||
defines { "DEBUG" }
|
||||
flags { "Symbols", "ExtraWarnings"}
|
||||
|
||||
configuration "Release"
|
||||
defines { "NDEBUG" }
|
||||
flags { "Optimize", "ExtraWarnings"}
|
||||
configuration "Release"
|
||||
defines { "NDEBUG" }
|
||||
flags { "Optimize", "ExtraWarnings"}
|
||||
|
||||
|
2
examples/writer/Makefile
Normal file
2
examples/writer/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
all:
|
||||
$(CXX) -o gltf_writer -I../../ writer.cc
|
11
examples/writer/README.md
Normal file
11
examples/writer/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Simple glTF writer in C++.
|
||||
|
||||
Read glTF with tinygltfloader, and write it to glTF JSON.
|
||||
|
||||
## TODO
|
||||
|
||||
* [ ] Asset export option(embed, external file)
|
||||
* [ ] Textures
|
||||
* [ ] Materials
|
||||
* [ ] etc.
|
||||
|
431
examples/writer/writer.cc
Normal file
431
examples/writer/writer.cc
Normal file
@ -0,0 +1,431 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#define TINYGLTF_LOADER_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "../../tiny_gltf_loader.h"
|
||||
|
||||
static std::string GetFilePathExtension(const std::string& filename) {
|
||||
if (filename.find_last_of(".") != std::string::npos)
|
||||
return filename.substr(filename.find_last_of(".") + 1);
|
||||
return "";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// writer module
|
||||
// @todo { move writer code to tiny_gltf_writer.h }
|
||||
|
||||
static std::string EncodeType(int ty) {
|
||||
if (ty == TINYGLTF_TYPE_SCALAR) {
|
||||
return "SCALAR";
|
||||
} else if (ty == TINYGLTF_TYPE_VECTOR) {
|
||||
return "VECTOR";
|
||||
} else if (ty == TINYGLTF_TYPE_VEC2) {
|
||||
return "VEC2";
|
||||
} else if (ty == TINYGLTF_TYPE_VEC3) {
|
||||
return "VEC3";
|
||||
} else if (ty == TINYGLTF_TYPE_VEC4) {
|
||||
return "VEC4";
|
||||
} else if (ty == TINYGLTF_TYPE_MATRIX) {
|
||||
return "MATRIX";
|
||||
} else if (ty == TINYGLTF_TYPE_MAT2) {
|
||||
return "MAT2";
|
||||
} else if (ty == TINYGLTF_TYPE_MAT3) {
|
||||
return "MAT3";
|
||||
} else if (ty == TINYGLTF_TYPE_MAT4) {
|
||||
return "MAT4";
|
||||
}
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
|
||||
// http://www.adp-gmbh.ch/cpp/common/base64.html
|
||||
static const std::string base64_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
std::string base64_encode(unsigned char const* bytes_to_encode,
|
||||
unsigned int in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] =
|
||||
((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] =
|
||||
((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (i = 0; (i < 4); i++) ret += base64_chars[char_array_4[i]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j < 3; j++) char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] =
|
||||
((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] =
|
||||
((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++) ret += base64_chars[char_array_4[j]];
|
||||
|
||||
while ((i++ < 3)) ret += '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EncodeBuffers(picojson::object* o,
|
||||
const std::map<std::string, tinygltf::Buffer>& buffers) {
|
||||
std::map<std::string, tinygltf::Buffer>::const_iterator it(buffers.begin());
|
||||
std::map<std::string, tinygltf::Buffer>::const_iterator itEnd(buffers.end());
|
||||
for (; it != itEnd; it++) {
|
||||
// @todo { Support external file resource. }
|
||||
picojson::object buf;
|
||||
std::string b64_data =
|
||||
base64_encode(it->second.data.data(), it->second.data.size());
|
||||
buf["type"] = picojson::value("arraybuffer");
|
||||
buf["uri"] = picojson::value(
|
||||
std::string("data:application/octet-stream;base64,") + b64_data);
|
||||
buf["byteLength"] =
|
||||
picojson::value(static_cast<double>(it->second.data.size()));
|
||||
|
||||
(*o)[it->first] = picojson::value(buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeBufferViews(
|
||||
picojson::object* o,
|
||||
const std::map<std::string, tinygltf::BufferView>& bufferViews) {
|
||||
std::map<std::string, tinygltf::BufferView>::const_iterator it(
|
||||
bufferViews.begin());
|
||||
std::map<std::string, tinygltf::BufferView>::const_iterator itEnd(
|
||||
bufferViews.end());
|
||||
|
||||
for (; it != itEnd; it++) {
|
||||
picojson::object buf;
|
||||
buf["buffer"] = picojson::value(it->second.buffer);
|
||||
buf["byteLength"] =
|
||||
picojson::value(static_cast<double>(it->second.byteLength));
|
||||
buf["byteOffset"] =
|
||||
picojson::value(static_cast<double>(it->second.byteOffset));
|
||||
buf["target"] = picojson::value(static_cast<double>(it->second.target));
|
||||
|
||||
(*o)[it->first] = picojson::value(buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeFloatArray(picojson::array* arr, const std::vector<double>& values) {
|
||||
for (size_t i = 0; i < values.size(); i++) {
|
||||
arr->push_back(picojson::value(values[i]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeStringArray(picojson::array* arr,
|
||||
const std::vector<std::string>& values) {
|
||||
for (size_t i = 0; i < values.size(); i++) {
|
||||
arr->push_back(picojson::value(values[i]));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeNode(picojson::object* o, const tinygltf::Node& node) {
|
||||
(*o)["name"] = picojson::value(node.name);
|
||||
(*o)["camera"] = picojson::value(node.camera);
|
||||
|
||||
if (!node.rotation.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeFloatArray(&arr, node.rotation);
|
||||
(*o)["rotation"] = picojson::value(arr);
|
||||
}
|
||||
if (!node.scale.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeFloatArray(&arr, node.scale);
|
||||
(*o)["scale"] = picojson::value(arr);
|
||||
}
|
||||
if (!node.translation.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeFloatArray(&arr, node.translation);
|
||||
(*o)["translation"] = picojson::value(arr);
|
||||
}
|
||||
|
||||
if (!node.matrix.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeFloatArray(&arr, node.matrix);
|
||||
(*o)["matrix"] = picojson::value(arr);
|
||||
}
|
||||
|
||||
if (!node.meshes.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeStringArray(&arr, node.meshes);
|
||||
(*o)["meshes"] = picojson::value(arr);
|
||||
}
|
||||
|
||||
if (!node.children.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeStringArray(&arr, node.children);
|
||||
(*o)["children"] = picojson::value(arr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeNodes(picojson::object* o,
|
||||
const std::map<std::string, tinygltf::Node>& nodes) {
|
||||
std::map<std::string, tinygltf::Node>::const_iterator it(nodes.begin());
|
||||
std::map<std::string, tinygltf::Node>::const_iterator itEnd(nodes.end());
|
||||
|
||||
for (; it != itEnd; it++) {
|
||||
picojson::object node;
|
||||
EncodeNode(&node, it->second);
|
||||
|
||||
(*o)[it->first] = picojson::value(node);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeScenes(
|
||||
picojson::object* o,
|
||||
const std::map<std::string, std::vector<std::string> >& scenes) {
|
||||
std::map<std::string, std::vector<std::string> >::const_iterator it(
|
||||
scenes.begin());
|
||||
std::map<std::string, std::vector<std::string> >::const_iterator itEnd(
|
||||
scenes.end());
|
||||
|
||||
for (; it != itEnd; it++) {
|
||||
picojson::object buf;
|
||||
picojson::array arr;
|
||||
for (size_t i = 0; i < it->second.size(); i++) {
|
||||
arr.push_back(picojson::value(it->second[i]));
|
||||
}
|
||||
|
||||
buf["nodes"] = picojson::value(arr);
|
||||
|
||||
(*o)[it->first] = picojson::value(buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeAccessors(
|
||||
picojson::object* o,
|
||||
const std::map<std::string, tinygltf::Accessor>& accessors) {
|
||||
std::map<std::string, tinygltf::Accessor>::const_iterator it(
|
||||
accessors.begin());
|
||||
std::map<std::string, tinygltf::Accessor>::const_iterator itEnd(
|
||||
accessors.end());
|
||||
for (; it != itEnd; it++) {
|
||||
picojson::object buf;
|
||||
buf["bufferView"] = picojson::value(it->second.bufferView);
|
||||
buf["byteOffset"] =
|
||||
picojson::value(static_cast<double>(it->second.byteOffset));
|
||||
buf["byteStride"] =
|
||||
picojson::value(static_cast<double>(it->second.byteStride));
|
||||
buf["componentType"] =
|
||||
picojson::value(static_cast<double>(it->second.componentType));
|
||||
buf["count"] = picojson::value(static_cast<double>(it->second.count));
|
||||
buf["type"] = picojson::value(EncodeType(it->second.type));
|
||||
|
||||
if (!it->second.minValues.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeFloatArray(&arr, it->second.minValues);
|
||||
buf["min"] = picojson::value(arr);
|
||||
}
|
||||
if (!it->second.maxValues.empty()) {
|
||||
picojson::array arr;
|
||||
EncodeFloatArray(&arr, it->second.maxValues);
|
||||
buf["max"] = picojson::value(arr);
|
||||
}
|
||||
|
||||
(*o)[it->first] = picojson::value(buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodePrimitive(picojson::object* o,
|
||||
const tinygltf::Primitive& primitive) {
|
||||
(*o)["material"] = picojson::value(primitive.material);
|
||||
(*o)["indices"] = picojson::value(primitive.indices);
|
||||
(*o)["mode"] = picojson::value(static_cast<double>(primitive.mode));
|
||||
|
||||
std::map<std::string, std::string>::const_iterator it(
|
||||
primitive.attributes.begin());
|
||||
std::map<std::string, std::string>::const_iterator itEnd(
|
||||
primitive.attributes.end());
|
||||
|
||||
picojson::object attributes;
|
||||
for (; it != itEnd; it++) {
|
||||
picojson::object buf;
|
||||
attributes[it->first] = picojson::value(it->second);
|
||||
}
|
||||
|
||||
(*o)["attributes"] = picojson::value(attributes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EncodeMeshes(picojson::object* o,
|
||||
const std::map<std::string, tinygltf::Mesh>& meshes) {
|
||||
std::map<std::string, tinygltf::Mesh>::const_iterator it(meshes.begin());
|
||||
std::map<std::string, tinygltf::Mesh>::const_iterator itEnd(meshes.end());
|
||||
for (; it != itEnd; it++) {
|
||||
picojson::object buf;
|
||||
|
||||
buf["name"] = picojson::value(it->second.name);
|
||||
|
||||
picojson::array arr;
|
||||
for (size_t i = 0; i < it->second.primitives.size(); i++) {
|
||||
picojson::object primitive;
|
||||
EncodePrimitive(&primitive, it->second.primitives[i]);
|
||||
arr.push_back(picojson::value(primitive));
|
||||
}
|
||||
buf["primitives"] = picojson::value(arr);
|
||||
|
||||
(*o)[it->first] = picojson::value(buf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveGLTF(const std::string& output_filename,
|
||||
const tinygltf::Scene& scene) {
|
||||
picojson::object root;
|
||||
|
||||
{
|
||||
picojson::object asset;
|
||||
asset["generator"] = picojson::value("tinygltf_writer");
|
||||
asset["premultipliedAlpha"] = picojson::value(true);
|
||||
asset["version"] = picojson::value(static_cast<double>(1));
|
||||
picojson::object profile;
|
||||
profile["api"] = picojson::value("WebGL");
|
||||
profile["version"] = picojson::value("1.0.2");
|
||||
asset["profile"] = picojson::value(profile);
|
||||
root["assets"] = picojson::value(asset);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object buffers;
|
||||
bool ret = EncodeBuffers(&buffers, scene.buffers);
|
||||
assert(ret);
|
||||
root["buffers"] = picojson::value(buffers);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object bufferViews;
|
||||
bool ret = EncodeBufferViews(&bufferViews, scene.bufferViews);
|
||||
assert(ret);
|
||||
root["bufferViews"] = picojson::value(bufferViews);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object accessors;
|
||||
bool ret = EncodeAccessors(&accessors, scene.accessors);
|
||||
assert(ret);
|
||||
root["accessors"] = picojson::value(accessors);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object meshes;
|
||||
bool ret = EncodeMeshes(&meshes, scene.meshes);
|
||||
assert(ret);
|
||||
root["meshes"] = picojson::value(meshes);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object nodes;
|
||||
bool ret = EncodeNodes(&nodes, scene.nodes);
|
||||
assert(ret);
|
||||
root["nodes"] = picojson::value(nodes);
|
||||
}
|
||||
|
||||
root["scene"] = picojson::value(scene.defaultScene);
|
||||
{
|
||||
picojson::object scenes;
|
||||
bool ret = EncodeScenes(&scenes, scene.scenes);
|
||||
assert(ret);
|
||||
root["scenes"] = picojson::value(scenes);
|
||||
}
|
||||
|
||||
// @todo {}
|
||||
picojson::object shaders;
|
||||
picojson::object programs;
|
||||
picojson::object techniques;
|
||||
picojson::object materials;
|
||||
picojson::object skins;
|
||||
root["shaders"] = picojson::value(shaders);
|
||||
root["programs"] = picojson::value(programs);
|
||||
root["techniques"] = picojson::value(techniques);
|
||||
root["materials"] = picojson::value(materials);
|
||||
root["skins"] = picojson::value(skins);
|
||||
|
||||
picojson::value v = picojson::value(root);
|
||||
|
||||
std::ofstream ifs(output_filename);
|
||||
if (ifs.bad()) {
|
||||
std::cerr << "Failed to open " << output_filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string s = v.serialize();
|
||||
ifs.write(s.data(), s.size());
|
||||
ifs.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 3) {
|
||||
printf("Needs input.gltf output.gltf\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tinygltf::Scene scene;
|
||||
tinygltf::TinyGLTFLoader loader;
|
||||
std::string err;
|
||||
std::string input_filename(argv[1]);
|
||||
std::string ext = GetFilePathExtension(input_filename);
|
||||
|
||||
bool ret = false;
|
||||
if (ext.compare("glb") == 0) {
|
||||
// assume binary glTF.
|
||||
ret = loader.LoadBinaryFromFile(&scene, &err, input_filename.c_str());
|
||||
} else {
|
||||
// assume ascii glTF.
|
||||
ret = loader.LoadASCIIFromFile(&scene, &err, input_filename.c_str());
|
||||
}
|
||||
|
||||
if (!err.empty()) {
|
||||
printf("Err: %s\n", err.c_str());
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printf("Failed to parse glTF\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = SaveGLTF(argv[2], scene);
|
||||
|
||||
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
@ -29,6 +29,16 @@ static std::string PrintMode(int mode) {
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
|
||||
static std::string PrintTarget(int target) {
|
||||
if (target == 34962) {
|
||||
return "GL_ARRAY_BUFFER";
|
||||
} else if (target == 34963) {
|
||||
return "GL_ELEMENT_ARRAY_BUFFER";
|
||||
} else {
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string PrintType(int ty) {
|
||||
if (ty == TINYGLTF_TYPE_SCALAR) {
|
||||
return "SCALAR";
|
||||
@ -146,6 +156,8 @@ static void DumpNode(const tinygltf::Node &node, int indent) {
|
||||
static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) {
|
||||
std::cout << Indent(indent) << "material : " << primitive.material
|
||||
<< std::endl;
|
||||
std::cout << Indent(indent) << "indices : " << primitive.indices
|
||||
<< std::endl;
|
||||
std::cout << Indent(indent) << "mode : " << PrintMode(primitive.mode)
|
||||
<< "(" << primitive.mode << ")" << std::endl;
|
||||
std::cout << Indent(indent)
|
||||
@ -265,6 +277,8 @@ static void Dump(const tinygltf::Scene &scene) {
|
||||
<< std::endl;
|
||||
std::cout << Indent(2) << "byteOffset : " << it->second.byteOffset
|
||||
<< std::endl;
|
||||
std::cout << Indent(2) << "target : " << PrintTarget(it->second.target)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Tiny glTF loader.
|
||||
//
|
||||
// Copyright (c) 2015, Syoyo Fujita.
|
||||
// Copyright (c) 2015-2016, Syoyo Fujita.
|
||||
// All rights reserved.
|
||||
// (Licensed under 2-clause BSD liecense)
|
||||
//
|
||||
@ -1124,8 +1124,8 @@ static bool ParseBuffer(Buffer *buffer, std::string *err,
|
||||
if (err) {
|
||||
std::stringstream ss;
|
||||
ss << "Invalid `byteLength'. Must be equal or less than binary size: "
|
||||
"`byteLength' = " << byteLength
|
||||
<< ", binary size = " << bin_size << std::endl;
|
||||
"`byteLength' = "
|
||||
<< byteLength << ", binary size = " << bin_size << std::endl;
|
||||
(*err) += ss.str();
|
||||
}
|
||||
return false;
|
||||
@ -1589,6 +1589,12 @@ bool TinyGLTFLoader::LoadFromString(Scene *scene, std::string *err,
|
||||
picojson::object::const_iterator it(root.begin());
|
||||
picojson::object::const_iterator itEnd(root.end());
|
||||
for (; it != itEnd; it++) {
|
||||
if (!((it->second).is<picojson::object>())) {
|
||||
if (err) {
|
||||
(*err) += "`scenes' does not contain an object.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const picojson::object &o = (it->second).get<picojson::object>();
|
||||
std::vector<std::string> nodes;
|
||||
if (!ParseStringArrayProperty(&nodes, err, o, "nodes", false)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user