`texture` support.
diff --git a/examples/glview/README.md b/examples/glview/README.md
index b248bcf..cff927a 100644
--- a/examples/glview/README.md
+++ b/examples/glview/README.md
@@ -18,6 +18,7 @@
## TODO
-* [ ] Texture
+* [x] Texture
+ * [ ] Various texture format.
* [ ] Shader
* [ ] Animation
diff --git a/examples/glview/glview.cc b/examples/glview/glview.cc
index 1ab9817..fd3a466 100644
--- a/examples/glview/glview.cc
+++ b/examples/glview/glview.cc
@@ -20,6 +20,16 @@
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
+#define CheckGLErrors(desc) \
+ { \
+ GLenum e = glGetError(); \
+ if (e != GL_NO_ERROR) { \
+ printf("OpenGL error in \"%s\": %d (%d) %s:%d\n", desc, e, e, __FILE__, \
+ __LINE__); \
+ exit(20); \
+ } \
+ }
+
#define CAM_Z (3.0f)
int width = 768;
int height = 768;
@@ -32,19 +42,21 @@
float prev_quat[4];
float eye[3], lookat[3], up[3];
-GLFWwindow* window;
+GLFWwindow *window;
-typedef struct
-{
- GLuint vb;
-} GLBufferState;
+typedef struct { GLuint vb; } GLBufferState;
-typedef struct
-{
+typedef struct {
+ std::vector<GLuint> diffuseTex; // for each primitive in mesh
+} GLMeshState;
+
+typedef struct {
std::map<std::string, GLint> attribs;
+ std::map<std::string, GLint> uniforms;
} GLProgramState;
std::map<std::string, GLBufferState> gBufferState;
+std::map<std::string, GLMeshState> gMeshState;
GLProgramState gGLProgramState;
void CheckErrors(std::string desc) {
@@ -79,7 +91,7 @@
srcbuf[len] = 0;
fclose(fp);
- const GLchar* srcs[1];
+ const GLchar *srcs[1];
srcs[0] = &srcbuf.at(0);
shader = glCreateShader(shaderType);
@@ -93,7 +105,7 @@
printf("%s\n", log);
// assert(val == GL_TRUE && "failed to compile shader");
printf("ERR: Failed to load or compile shader [ %s ]\n",
- shaderSourceFilename);
+ shaderSourceFilename);
return false;
}
@@ -122,8 +134,7 @@
return true;
}
-void reshapeFunc(GLFWwindow* window, int w, int h)
-{
+void reshapeFunc(GLFWwindow *window, int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@@ -135,113 +146,187 @@
height = h;
}
-void keyboardFunc(GLFWwindow *window, int key, int scancode, int action, int mods) {
- if(action == GLFW_PRESS || action == GLFW_REPEAT){
+void keyboardFunc(GLFWwindow *window, int key, int scancode, int action,
+ int mods) {
+ if (action == GLFW_PRESS || action == GLFW_REPEAT) {
// Close window
- if(key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, GL_TRUE);
+ if (key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE)
+ glfwSetWindowShouldClose(window, GL_TRUE);
}
}
-void clickFunc(GLFWwindow* window, int button, int action, int mods){
- double x, y;
- glfwGetCursorPos(window,&x, &y);
+void clickFunc(GLFWwindow *window, int button, int action, int mods) {
+ double x, y;
+ glfwGetCursorPos(window, &x, &y);
- if(button == GLFW_MOUSE_BUTTON_LEFT){
- mouseLeftPressed = true;
- if(action == GLFW_PRESS){
- int id = -1;
- //int id = ui.Proc(x, y);
- if (id < 0) { // outside of UI
- trackball(prev_quat, 0.0, 0.0, 0.0, 0.0);
- }
- } else if(action == GLFW_RELEASE){
- mouseLeftPressed = false;
- }
+ if (button == GLFW_MOUSE_BUTTON_LEFT) {
+ mouseLeftPressed = true;
+ if (action == GLFW_PRESS) {
+ int id = -1;
+ // int id = ui.Proc(x, y);
+ if (id < 0) { // outside of UI
+ trackball(prev_quat, 0.0, 0.0, 0.0, 0.0);
+ }
+ } else if (action == GLFW_RELEASE) {
+ mouseLeftPressed = false;
+ }
}
- if(button == GLFW_MOUSE_BUTTON_RIGHT){
- if(action == GLFW_PRESS){
+ if (button == GLFW_MOUSE_BUTTON_RIGHT) {
+ if (action == GLFW_PRESS) {
mouseRightPressed = true;
- } else if(action == GLFW_RELEASE){
+ } else if (action == GLFW_RELEASE) {
mouseRightPressed = false;
}
}
- if(button == GLFW_MOUSE_BUTTON_MIDDLE){
- if(action == GLFW_PRESS){
+ if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
+ if (action == GLFW_PRESS) {
mouseMiddlePressed = true;
- } else if(action == GLFW_RELEASE){
+ } else if (action == GLFW_RELEASE) {
mouseMiddlePressed = false;
}
}
}
-void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y){
+void motionFunc(GLFWwindow *window, double mouse_x, double mouse_y) {
float rotScale = 1.0f;
float transScale = 2.0f;
- if(mouseLeftPressed){
- trackball(prev_quat,
- rotScale * (2.0f * prevMouseX - width) / (float)width,
- rotScale * (height - 2.0f * prevMouseY) / (float)height,
- rotScale * (2.0f * mouse_x - width) / (float)width,
- rotScale * (height - 2.0f * mouse_y) / (float)height);
+ if (mouseLeftPressed) {
+ trackball(prev_quat, rotScale * (2.0f * prevMouseX - width) / (float)width,
+ rotScale * (height - 2.0f * prevMouseY) / (float)height,
+ rotScale * (2.0f * mouse_x - width) / (float)width,
+ rotScale * (height - 2.0f * mouse_y) / (float)height);
- add_quats(prev_quat, curr_quat, curr_quat);
- } else if (mouseMiddlePressed) {
- eye[0] += -transScale * (mouse_x - prevMouseX) / (float)width;
- lookat[0] += -transScale * (mouse_x - prevMouseX) / (float)width;
- eye[1] += transScale * (mouse_y - prevMouseY) / (float)height;
- lookat[1] += transScale * (mouse_y - prevMouseY) / (float)height;
- } else if (mouseRightPressed) {
- eye[2] += transScale * (mouse_y - prevMouseY) / (float)height;
- lookat[2] += transScale * (mouse_y - prevMouseY) / (float)height;
- }
+ add_quats(prev_quat, curr_quat, curr_quat);
+ } else if (mouseMiddlePressed) {
+ eye[0] += -transScale * (mouse_x - prevMouseX) / (float)width;
+ lookat[0] += -transScale * (mouse_x - prevMouseX) / (float)width;
+ eye[1] += transScale * (mouse_y - prevMouseY) / (float)height;
+ lookat[1] += transScale * (mouse_y - prevMouseY) / (float)height;
+ } else if (mouseRightPressed) {
+ eye[2] += transScale * (mouse_y - prevMouseY) / (float)height;
+ lookat[2] += transScale * (mouse_y - prevMouseY) / (float)height;
+ }
// Update mouse point
prevMouseX = mouse_x;
prevMouseY = mouse_y;
}
-static void SetupGLState(Scene& scene, GLuint progId)
-{
- std::map<std::string, BufferView>::const_iterator it(scene.bufferViews.begin());
- std::map<std::string, BufferView>::const_iterator itEnd(scene.bufferViews.end());
+static void SetupGLState(Scene &scene, GLuint progId) {
+ // Buffer
+ {
+ std::map<std::string, BufferView>::const_iterator it(
+ scene.bufferViews.begin());
+ std::map<std::string, BufferView>::const_iterator itEnd(
+ scene.bufferViews.end());
- for (; it != itEnd; it++) {
- const BufferView& bufferView = it->second;
- if (bufferView.target == 0) {
- continue; // Unsupported bufferView.
+ for (; it != itEnd; it++) {
+ const BufferView &bufferView = it->second;
+ if (bufferView.target == 0) {
+ continue; // Unsupported bufferView.
+ }
+
+ const Buffer &buffer = scene.buffers[bufferView.buffer];
+ GLBufferState state;
+ glGenBuffers(1, &state.vb);
+ glBindBuffer(bufferView.target, state.vb);
+ glBufferData(bufferView.target, bufferView.byteLength,
+ &buffer.data.at(0) + bufferView.byteOffset, GL_STATIC_DRAW);
+ glBindBuffer(bufferView.target, 0);
+
+ gBufferState[it->first] = state;
}
+ }
- const Buffer& buffer = scene.buffers[bufferView.buffer];
- GLBufferState state;
- glGenBuffers(1, &state.vb);
- glBindBuffer(bufferView.target, state.vb);
- glBufferData(bufferView.target, bufferView.byteLength, &buffer.data.at(0) + bufferView.byteOffset, GL_STATIC_DRAW);
- glBindBuffer(bufferView.target, 0);
-
- gBufferState[it->first] = state;
+ // Texture
+ {
+ std::map<std::string, Mesh>::const_iterator it(scene.meshes.begin());
+ std::map<std::string, Mesh>::const_iterator itEnd(scene.meshes.end());
+
+ for (; it != itEnd; it++) {
+ const Mesh &mesh = it->second;
+
+ gMeshState[mesh.name].diffuseTex.resize(mesh.primitives.size());
+ for (size_t primId = 0; primId < mesh.primitives.size(); primId++) {
+ const Primitive &primitive = mesh.primitives[primId];
+
+ gMeshState[mesh.name].diffuseTex[primId] = 0;
+
+ if (primitive.material.empty()) {
+ continue;
+ }
+ Material &mat = scene.materials[primitive.material];
+ printf("material.name = %s\n", mat.name.c_str());
+ if (mat.values.find("diffuse") != mat.values.end()) {
+ std::string diffuseTexName = mat.values["diffuse"].stringValue;
+ if (scene.textures.find(diffuseTexName) != scene.textures.end()) {
+ Texture &tex = scene.textures[diffuseTexName];
+ if (scene.images.find(tex.source) != scene.images.end()) {
+ Image &image = scene.images[tex.source];
+ GLuint texId;
+ glGenTextures(1, &texId);
+ glBindTexture(tex.target, texId);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexParameterf(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // Ignore Texture.fomat.
+ GLenum format = GL_RGBA;
+ if (image.component == 3) {
+ format = GL_RGB;
+ }
+ glTexImage2D(tex.target, 0, tex.internalFormat, image.width,
+ image.height, 0, format, tex.type,
+ &image.image.at(0));
+
+ CheckErrors("texImage2D");
+ glBindTexture(tex.target, 0);
+
+ printf("TexId = %d\n", texId);
+ gMeshState[mesh.name].diffuseTex[primId] = texId;
+ }
+ }
+ }
+ }
+ }
}
glUseProgram(progId);
GLint vtloc = glGetAttribLocation(progId, "in_vertex");
GLint nrmloc = glGetAttribLocation(progId, "in_normal");
+ GLint uvloc = glGetAttribLocation(progId, "in_texcoord");
+
+ GLint diffuseTexLoc = glGetUniformLocation(progId, "diffuseTex");
+
gGLProgramState.attribs["POSITION"] = vtloc;
gGLProgramState.attribs["NORMAL"] = nrmloc;
-
+ gGLProgramState.attribs["TEXCOORD_0"] = uvloc;
+ gGLProgramState.uniforms["diffuseTex"] = diffuseTexLoc;
};
-void DrawMesh(Scene& scene, const Mesh& mesh)
-{
- for (size_t i = 0; i < mesh.primitives.size(); i++) {
- const Primitive& primitive = mesh.primitives[i];
+void DrawMesh(Scene &scene, const Mesh &mesh) {
- if (primitive.indices.empty()) return;
+ if (gGLProgramState.uniforms["diffuseTex"] >= 0) {
+ glUniform1i(gGLProgramState.uniforms["diffuseTex"], 0); // TEXTURE0
+ }
- std::map<std::string, std::string>::const_iterator it(primitive.attributes.begin());
- std::map<std::string, std::string>::const_iterator itEnd(primitive.attributes.end());
+ for (size_t i = 0; i < mesh.primitives.size(); i++) {
+ const Primitive &primitive = mesh.primitives[i];
+
+ if (primitive.indices.empty())
+ return;
+
+ std::map<std::string, std::string>::const_iterator it(
+ primitive.attributes.begin());
+ std::map<std::string, std::string>::const_iterator itEnd(
+ primitive.attributes.end());
+
+ // Assume TEXTURE_2D target for the texture object.
+ glBindTexture(GL_TEXTURE_2D, gMeshState[mesh.name].diffuseTex[i]);
for (; it != itEnd; it++) {
- const Accessor& accessor = scene.accessors[it->second];
+ const Accessor &accessor = scene.accessors[it->second];
glBindBuffer(GL_ARRAY_BUFFER, gBufferState[accessor.bufferView].vb);
CheckErrors("bind buffer");
int count = 1;
@@ -254,18 +339,22 @@
} else if (accessor.type == TINYGLTF_TYPE_VEC4) {
count = 4;
}
- // it->first would be "POSITION", "NORMAL", ...
- if ( (it->first.compare("POSITION") == 0) ||
- (it->first.compare("NORMAL") == 0)) {
- glVertexAttribPointer(gGLProgramState.attribs[it->first], count, accessor.componentType, GL_FALSE, accessor.byteStride, BUFFER_OFFSET(accessor.byteOffset));
+ // 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");
}
}
- const Accessor& indexAccessor = scene.accessors[primitive.indices];
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gBufferState[indexAccessor.bufferView].vb);
+ const Accessor &indexAccessor = scene.accessors[primitive.indices];
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
+ gBufferState[indexAccessor.bufferView].vb);
CheckErrors("bind buffer");
int mode = -1;
if (primitive.mode == TINYGLTF_MODE_TRIANGLES) {
@@ -281,26 +370,28 @@
} else if (primitive.mode == TINYGLTF_MODE_LINE_LOOP) {
mode = GL_LINE_LOOP;
};
- glDrawElements(mode, indexAccessor.count, indexAccessor.componentType, BUFFER_OFFSET(indexAccessor.byteOffset));
+ glDrawElements(mode, indexAccessor.count, indexAccessor.componentType,
+ BUFFER_OFFSET(indexAccessor.byteOffset));
CheckErrors("draw elements");
{
- std::map<std::string, std::string>::const_iterator it(primitive.attributes.begin());
- std::map<std::string, std::string>::const_iterator itEnd(primitive.attributes.end());
+ std::map<std::string, std::string>::const_iterator it(
+ primitive.attributes.begin());
+ std::map<std::string, std::string>::const_iterator itEnd(
+ primitive.attributes.end());
for (; it != itEnd; it++) {
- if ( (it->first.compare("POSITION") == 0) ||
- (it->first.compare("NORMAL") == 0)) {
+ if ((it->first.compare("POSITION") == 0) ||
+ (it->first.compare("NORMAL") == 0) ||
+ (it->first.compare("TEXCOORD_0") == 0)) {
glDisableVertexAttribArray(gGLProgramState.attribs[it->first]);
}
}
}
}
-
}
-void DrawScene(Scene& scene)
-{
+void DrawScene(Scene &scene) {
std::map<std::string, Mesh>::const_iterator it(scene.meshes.begin());
std::map<std::string, Mesh>::const_iterator itEnd(scene.meshes.end());
@@ -309,7 +400,6 @@
}
}
-
static void Init() {
trackball(curr_quat, 0, 0, 0, 0);
@@ -326,8 +416,7 @@
up[2] = 0.0f;
}
-int main(int argc, char **argv)
-{
+int main(int argc, char **argv) {
if (argc < 2) {
std::cout << "glview input.gltf <scale>\n" << std::endl;
return 0;
@@ -338,10 +427,10 @@
scale = atof(argv[2]);
}
- Scene scene;
+ Scene scene;
TinyGLTFLoader loader;
std::string err;
-
+
bool ret = loader.LoadFromFile(scene, err, argv[1]);
if (!err.empty()) {
printf("ERR: %s\n", err.c_str());
@@ -353,13 +442,14 @@
Init();
- if(!glfwInit()){
+ if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW." << std::endl;
return -1;
}
- window = glfwCreateWindow(width, height, "Simple glTF geometry viewer", NULL, NULL);
- if(window == NULL){
+ window = glfwCreateWindow(width, height, "Simple glTF geometry viewer", NULL,
+ NULL);
+ if (window == NULL) {
std::cerr << "Failed to open GLFW window. " << std::endl;
glfwTerminate();
return 1;
@@ -420,7 +510,7 @@
SetupGLState(scene, progId);
CheckErrors("SetupGLState");
- while(glfwWindowShouldClose(window) == GL_FALSE) {
+ while (glfwWindowShouldClose(window) == GL_FALSE) {
glfwPollEvents();
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -433,7 +523,8 @@
// camera(define it in projection matrix)
glMatrixMode(GL_PROJECTION);
glPushMatrix();
- gluLookAt(eye[0], eye[1], eye[2], lookat[0], lookat[1], lookat[2], up[0], up[1], up[2]);
+ gluLookAt(eye[0], eye[1], eye[2], lookat[0], lookat[1], lookat[2], up[0],
+ up[1], up[2]);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
diff --git a/examples/glview/shader.frag b/examples/glview/shader.frag
index bd2fc49..1f30d3e 100644
--- a/examples/glview/shader.frag
+++ b/examples/glview/shader.frag
@@ -1,6 +1,11 @@
+uniform sampler2D diffuseTex;
+
varying vec3 normal;
+varying vec2 texcoord;
void main(void)
{
- gl_FragColor = vec4(0.5 * normalize(normal) + 0.5, 1.0);
+ //gl_FragColor = vec4(0.5 * normalize(normal) + 0.5, 1.0);
+ //gl_FragColor = vec4(texcoord, 0.0, 1.0);
+ gl_FragColor = texture2D(diffuseTex, texcoord);
}
diff --git a/examples/glview/shader.vert b/examples/glview/shader.vert
index a21fa30..e21752d 100644
--- a/examples/glview/shader.vert
+++ b/examples/glview/shader.vert
@@ -1,7 +1,9 @@
attribute vec3 in_vertex;
attribute vec3 in_normal;
+attribute vec2 in_texcoord;
varying vec3 normal;
+varying vec2 texcoord;
void main(void)
{
@@ -9,4 +11,6 @@
gl_Position = p;
vec4 nn = gl_ModelViewMatrixInverseTranspose * vec4(normalize(in_normal), 0);
normal = nn.xyz;
+
+ texcoord = in_texcoord;
}
diff --git a/test.cc b/test.cc
index 8b3bfd1..7d6056d 100644
--- a/test.cc
+++ b/test.cc
@@ -6,8 +6,7 @@
#include <cstdio>
#include <iostream>
-std::string PrintMode(int mode)
-{
+std::string PrintMode(int mode) {
if (mode == TINYGLTF_MODE_POINTS) {
return "POINTS";
} else if (mode == TINYGLTF_MODE_LINE) {
@@ -24,9 +23,7 @@
return "**UNKNOWN**";
}
-
-std::string PrintType(int ty)
-{
+std::string PrintType(int ty) {
if (ty == TINYGLTF_TYPE_SCALAR) {
return "SCALAR";
} else if (ty == TINYGLTF_TYPE_VECTOR) {
@@ -49,8 +46,7 @@
return "**UNKNOWN**";
}
-std::string PrintComponentType(int ty)
-{
+std::string PrintComponentType(int ty) {
if (ty == TINYGLTF_COMPONENT_TYPE_BYTE) {
return "BYTE";
} else if (ty == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
@@ -72,8 +68,7 @@
return "**UNKNOWN**";
}
-std::string PrintFloatArray(const std::vector<double>& arr)
-{
+std::string PrintFloatArray(const std::vector<double> &arr) {
if (arr.size() == 0) {
return "";
}
@@ -88,8 +83,7 @@
return ss.str();
}
-std::string PrintStringArray(const std::vector<std::string>& arr)
-{
+std::string PrintStringArray(const std::vector<std::string> &arr) {
if (arr.size() == 0) {
return "";
}
@@ -104,9 +98,7 @@
return ss.str();
}
-
-std::string Indent(int indent)
-{
+std::string Indent(int indent) {
std::string s;
for (int i = 0; i < indent; i++) {
s += " ";
@@ -115,64 +107,82 @@
return s;
}
-void DumpNode(const Node& node, int indent)
-{
- std::cout << Indent(indent) << "name : " << node.name << std::endl;
- std::cout << Indent(indent) << "camera : " << node.camera << std::endl;
+void DumpNode(const Node &node, int indent) {
+ std::cout << Indent(indent) << "name : " << node.name << std::endl;
+ std::cout << Indent(indent) << "camera : " << node.camera << std::endl;
if (!node.rotation.empty()) {
- std::cout << Indent(indent) << "rotation : " << PrintFloatArray(node.rotation) << std::endl;
+ std::cout << Indent(indent)
+ << "rotation : " << PrintFloatArray(node.rotation)
+ << std::endl;
}
if (!node.scale.empty()) {
- std::cout << Indent(indent) << "scale : " << PrintFloatArray(node.scale) << std::endl;
+ std::cout << Indent(indent)
+ << "scale : " << PrintFloatArray(node.scale) << std::endl;
}
if (!node.translation.empty()) {
- std::cout << Indent(indent) << "translation : " << PrintFloatArray(node.translation) << std::endl;
+ std::cout << Indent(indent)
+ << "translation : " << PrintFloatArray(node.translation)
+ << std::endl;
}
if (!node.matrix.empty()) {
- std::cout << Indent(indent) << "matrix : " << PrintFloatArray(node.matrix) << std::endl;
+ std::cout << Indent(indent)
+ << "matrix : " << PrintFloatArray(node.matrix) << std::endl;
}
- std::cout << Indent(indent) << "meshes : " << PrintStringArray(node.meshes) << std::endl;
+ std::cout << Indent(indent)
+ << "meshes : " << PrintStringArray(node.meshes) << std::endl;
- std::cout << Indent(indent) << "children : " << PrintStringArray(node.children) << std::endl;
-
+ std::cout << Indent(indent)
+ << "children : " << PrintStringArray(node.children) << std::endl;
}
-void DumpPrimitive(const Primitive& primitive, int indent)
-{
- std::cout << Indent(indent) << "material : " << primitive.material << std::endl;
- std::cout << Indent(indent) << "mode : " << PrintMode(primitive.mode) << "(" << primitive.mode << ")" << std::endl;
- std::cout << Indent(indent) << "attributes(items=" << primitive.attributes.size() << ")" << std::endl;
- std::map<std::string, std::string>::const_iterator it(primitive.attributes.begin());
- std::map<std::string, std::string>::const_iterator itEnd(primitive.attributes.end());
+void DumpPrimitive(const Primitive &primitive, int indent) {
+ std::cout << Indent(indent) << "material : " << primitive.material
+ << std::endl;
+ std::cout << Indent(indent) << "mode : " << PrintMode(primitive.mode)
+ << "(" << primitive.mode << ")" << std::endl;
+ std::cout << Indent(indent)
+ << "attributes(items=" << primitive.attributes.size() << ")"
+ << std::endl;
+ std::map<std::string, std::string>::const_iterator it(
+ primitive.attributes.begin());
+ std::map<std::string, std::string>::const_iterator itEnd(
+ primitive.attributes.end());
for (; it != itEnd; it++) {
- std::cout << Indent(indent + 1) << it->first << ": " << it->second << std::endl;
+ std::cout << Indent(indent + 1) << it->first << ": " << it->second
+ << std::endl;
}
-
}
-void Dump(const Scene& scene)
-{
+void Dump(const Scene &scene) {
std::cout << "=== Dump glTF ===" << std::endl;
- std::cout << "asset.generator : " << scene.asset.generator << std::endl;
- std::cout << "asset.premultipliedAlpha : " << scene.asset.premultipliedAlpha << std::endl;
- std::cout << "asset.version : " << scene.asset.version << std::endl;
- std::cout << "asset.profile.api : " << scene.asset.profile_api << std::endl;
- std::cout << "asset.profile.version : " << scene.asset.profile_version << std::endl;
+ std::cout << "asset.generator : " << scene.asset.generator
+ << std::endl;
+ std::cout << "asset.premultipliedAlpha : " << scene.asset.premultipliedAlpha
+ << std::endl;
+ std::cout << "asset.version : " << scene.asset.version
+ << std::endl;
+ std::cout << "asset.profile.api : " << scene.asset.profile_api
+ << std::endl;
+ std::cout << "asset.profile.version : " << scene.asset.profile_version
+ << std::endl;
std::cout << std::endl;
std::cout << "=== Dump scene ===" << std::endl;
std::cout << "defaultScene: " << scene.defaultScene << std::endl;
{
- std::map<std::string, std::vector<std::string> >::const_iterator it(scene.scenes.begin());
- std::map<std::string, std::vector<std::string> >::const_iterator itEnd(scene.scenes.end());
+ std::map<std::string, std::vector<std::string> >::const_iterator it(
+ scene.scenes.begin());
+ std::map<std::string, std::vector<std::string> >::const_iterator itEnd(
+ 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()) ? ", " : "");
+ std::cout << it->second[i]
+ << ((i != (it->second.size() - 1)) ? ", " : "");
}
std::cout << " ] " << std::endl;
}
@@ -184,8 +194,10 @@
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) << "primitives(items=" << it->second.primitives.size() << "): " << std::endl;
-
+ std::cout << Indent(1)
+ << "primitives(items=" << it->second.primitives.size()
+ << "): " << std::endl;
+
for (size_t i = 0; i < it->second.primitives.size(); i++) {
DumpPrimitive(it->second.primitives[i], 2);
}
@@ -194,27 +206,38 @@
{
std::map<std::string, Accessor>::const_iterator it(scene.accessors.begin());
- std::map<std::string, Accessor>::const_iterator itEnd(scene.accessors.end());
- std::cout << "accessos(items=" << scene.accessors.size() << ")" << std::endl;
+ std::map<std::string, Accessor>::const_iterator itEnd(
+ scene.accessors.end());
+ std::cout << "accessos(items=" << scene.accessors.size() << ")"
+ << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
- std::cout << Indent(2) << "bufferView : " << it->second.bufferView << std::endl;
- std::cout << Indent(2) << "byteOffset : " << it->second.byteOffset << std::endl;
- std::cout << Indent(2) << "byteStride : " << it->second.byteStride << std::endl;
- std::cout << Indent(2) << "componentType: " << PrintComponentType(it->second.componentType) << "(" << it->second.componentType << ")" << std::endl;
- std::cout << Indent(2) << "count : " << it->second.count << std::endl;
- std::cout << Indent(2) << "type : " << PrintType(it->second.type) << std::endl;
+ std::cout << Indent(2) << "bufferView : " << it->second.bufferView
+ << std::endl;
+ std::cout << Indent(2) << "byteOffset : " << it->second.byteOffset
+ << std::endl;
+ std::cout << Indent(2) << "byteStride : " << it->second.byteStride
+ << std::endl;
+ std::cout << Indent(2) << "componentType: "
+ << PrintComponentType(it->second.componentType) << "("
+ << it->second.componentType << ")" << std::endl;
+ std::cout << Indent(2) << "count : " << it->second.count
+ << std::endl;
+ std::cout << Indent(2) << "type : " << PrintType(it->second.type)
+ << std::endl;
if (!it->second.minValues.empty()) {
std::cout << Indent(2) << "min : [";
for (size_t i = 0; i < it->second.minValues.size(); i++) {
- std::cout << it->second.minValues[i] << ((i != it->second.minValues.size()-1) ? ", " : "");
+ std::cout << it->second.minValues[i]
+ << ((i != it->second.minValues.size() - 1) ? ", " : "");
}
std::cout << "]" << std::endl;
}
if (!it->second.maxValues.empty()) {
std::cout << Indent(2) << "max : [";
for (size_t i = 0; i < it->second.maxValues.size(); i++) {
- std::cout << it->second.maxValues[i] << ((i != it->second.maxValues.size()-1) ? ", " : "");
+ std::cout << it->second.maxValues[i]
+ << ((i != it->second.maxValues.size() - 1) ? ", " : "");
}
std::cout << "]" << std::endl;
}
@@ -222,14 +245,20 @@
}
{
- std::map<std::string, BufferView>::const_iterator it(scene.bufferViews.begin());
- std::map<std::string, BufferView>::const_iterator itEnd(scene.bufferViews.end());
- std::cout << "bufferViews(items=" << scene.bufferViews.size() << ")" << std::endl;
+ std::map<std::string, BufferView>::const_iterator it(
+ scene.bufferViews.begin());
+ std::map<std::string, BufferView>::const_iterator itEnd(
+ scene.bufferViews.end());
+ std::cout << "bufferViews(items=" << scene.bufferViews.size() << ")"
+ << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
- std::cout << Indent(2) << "buffer : " << it->second.buffer << std::endl;
- std::cout << Indent(2) << "byteLength : " << it->second.byteLength << std::endl;
- std::cout << Indent(2) << "byteOffset : " << it->second.byteOffset << std::endl;
+ std::cout << Indent(2) << "buffer : " << it->second.buffer
+ << std::endl;
+ std::cout << Indent(2) << "byteLength : " << it->second.byteLength
+ << std::endl;
+ std::cout << Indent(2) << "byteOffset : " << it->second.byteOffset
+ << std::endl;
}
}
@@ -239,23 +268,35 @@
std::cout << "buffers(items=" << scene.buffers.size() << ")" << std::endl;
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::cout << Indent(2) << "byteLength : " << it->second.data.size()
+ << std::endl;
}
}
{
std::map<std::string, Material>::const_iterator it(scene.materials.begin());
- std::map<std::string, Material>::const_iterator itEnd(scene.materials.end());
- std::cout << "materials(items=" << scene.materials.size() << ")" << std::endl;
+ std::map<std::string, Material>::const_iterator itEnd(
+ scene.materials.end());
+ std::cout << "materials(items=" << scene.materials.size() << ")"
+ << std::endl;
for (; it != itEnd; it++) {
std::cout << Indent(1) << "name : " << it->first << std::endl;
- std::cout << Indent(1) << "technique : " << it->second.technique << std::endl;
- std::cout << Indent(1) << "values(items=" << it->second.values.size() << std::endl;
+ std::cout << Indent(1) << "technique : " << it->second.technique
+ << std::endl;
+ std::cout << Indent(1) << "values(items=" << it->second.values.size()
+ << std::endl;
- FloatParameterMap::const_iterator p(it->second.values.begin());
- FloatParameterMap::const_iterator pEnd(it->second.values.end());
+ ParameterMap::const_iterator p(it->second.values.begin());
+ ParameterMap::const_iterator pEnd(it->second.values.end());
for (; p != pEnd; p++) {
- std::cout << Indent(3) << p->first << PrintFloatArray(p->second) << std::endl;
+ if (!p->second.numberArray.empty()) {
+ std::cout << Indent(3) << p->first
+ << PrintFloatArray(p->second.numberArray) << std::endl;
+ }
+ if (!p->second.stringValue.empty()) {
+ std::cout << Indent(3) << p->first << " : " << p->second.stringValue
+ << std::endl;
+ }
}
}
}
@@ -270,7 +311,7 @@
DumpNode(it->second, 2);
}
}
-
+
{
std::map<std::string, Image>::const_iterator it(scene.images.begin());
std::map<std::string, Image>::const_iterator itEnd(scene.images.end());
@@ -279,24 +320,46 @@
std::cout << Indent(1) << "name : " << it->first << std::endl;
std::cout << Indent(2) << "width : " << it->second.width << std::endl;
- std::cout << Indent(2) << "height : " << it->second.height << std::endl;
- std::cout << Indent(2) << "component : " << it->second.component << std::endl;
+ std::cout << Indent(2) << "height : " << it->second.height
+ << std::endl;
+ std::cout << Indent(2) << "component : " << it->second.component
+ << std::endl;
std::cout << Indent(2) << "name : " << it->second.name << std::endl;
}
}
+
+ {
+ std::map<std::string, Texture>::const_iterator it(scene.textures.begin());
+ std::map<std::string, 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;
+ }
+ }
}
-int main(int argc, char** argv)
-{
+int main(int argc, char **argv) {
if (argc < 2) {
printf("Needs input.gltf\n");
exit(1);
}
- Scene scene;
+ Scene scene;
TinyGLTFLoader loader;
std::string err;
-
+
bool ret = loader.LoadFromFile(scene, err, argv[1]);
if (!err.empty()) {
diff --git a/tiny_gltf_loader.h b/tiny_gltf_loader.h
index 0481db6..361d634 100644
--- a/tiny_gltf_loader.h
+++ b/tiny_gltf_loader.h
@@ -31,7 +31,8 @@
//
//
// Version:
-// - v0.9.1 Support loading glTF asset from memory
+// - 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 libraries:
@@ -80,12 +81,20 @@
#define TINYGLTF_IMAGE_FORMAT_BMP (2)
#define TINYGLTF_IMAGE_FORMAT_GIF (3)
+#define TINYGLTF_TEXTURE_FORMAT_RGBA (6408)
+#define TINYGLTF_TEXTURE_TARGET_TEXTURE2D (3553)
+#define TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE (5121)
+
#define TINYGLTF_TARGET_ARRAY_BUFFER (34962)
#define TINYGLTF_TARGET_ELEMENT_ARRAY_BUFFER (34963)
-typedef std::map<std::string, std::vector<double> > FloatParameterMap;
+typedef struct {
+ std::string stringValue;
+ std::vector<double> numberArray;
+} Parameter;
-// LDR 8bit image
+typedef std::map<std::string, Parameter> ParameterMap;
+
typedef struct {
std::string name;
int width;
@@ -95,9 +104,19 @@
} Image;
typedef struct {
+ int format;
+ int internalFormat;
+ std::string sampler; // Required
+ std::string source; // Required
+ int target;
+ int type;
+ std::string name;
+} Texture;
+
+typedef struct {
std::string name;
std::string technique;
- FloatParameterMap values;
+ ParameterMap values;
} Material;
typedef struct {
@@ -191,6 +210,7 @@
std::map<std::string, Material> materials;
std::map<std::string, Mesh> meshes;
std::map<std::string, Node> nodes;
+ std::map<std::string, Texture> textures;
std::map<std::string, Image> images;
std::map<std::string, std::vector<std::string> > scenes; // list of nodes
@@ -212,9 +232,8 @@
/// Loads glTF asset from string(memory).
/// `length` = strlen(str);
/// Returns false and set error string to `err` if there's an error.
- bool LoadFromString(Scene &scene, std::string &err,
- const char* str, const unsigned int length, const std::string& baseDir);
-
+ bool LoadFromString(Scene &scene, std::string &err, const char *str,
+ const unsigned int length, const std::string &baseDir);
};
} // namespace tinygltf
@@ -557,7 +576,7 @@
if (data.empty()) {
return false;
- }
+ }
if (checkSize) {
if (data.size() != reqBytes) {
@@ -780,6 +799,39 @@
return true;
}
+bool ParseTexture(Texture &texture, std::string &err, const picojson::object &o,
+ const std::string &basedir) {
+
+ if (!ParseStringProperty(texture.sampler, err, o, "sampler", true)) {
+ return false;
+ }
+
+ if (!ParseStringProperty(texture.source, err, o, "source", true)) {
+ return false;
+ }
+
+ ParseStringProperty(texture.name, err, o, "name", false);
+
+ double format = TINYGLTF_TEXTURE_FORMAT_RGBA;
+ ParseNumberProperty(format, err, o, "format", false);
+
+ double internalFormat = TINYGLTF_TEXTURE_FORMAT_RGBA;
+ ParseNumberProperty(internalFormat, err, o, "internalFormat", false);
+
+ double target = TINYGLTF_TEXTURE_TARGET_TEXTURE2D;
+ ParseNumberProperty(target, err, o, "target", false);
+
+ double type = TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE;
+ ParseNumberProperty(type, err, o, "type", false);
+
+ texture.format = static_cast<int>(format);
+ texture.internalFormat = static_cast<int>(internalFormat);
+ texture.target = static_cast<int>(target);
+ texture.type = static_cast<int>(type);
+
+ return true;
+}
+
bool ParseBuffer(Buffer &buffer, std::string &err, const picojson::object &o,
const std::string &basedir) {
double byteLength;
@@ -1041,17 +1093,20 @@
for (; it != itEnd; it++) {
// Assume number values.
- std::vector<double> values;
- if (!ParseNumberArrayProperty(values, err, valuesObject, it->first,
- false)) {
+ Parameter param;
+ if (ParseStringProperty(param.stringValue, err, valuesObject, it->first,
+ false)) {
+ // Found string property.
+ } else if (!ParseNumberArrayProperty(param.numberArray, err, valuesObject,
+ it->first, false)) {
// Fallback to numer property.
double value;
if (ParseNumberProperty(value, err, valuesObject, it->first, false)) {
- values.push_back(value);
+ param.numberArray.push_back(value);
}
}
- material.values[it->first] = values;
+ material.values[it->first] = param;
}
}
@@ -1060,7 +1115,8 @@
}
bool TinyGLTFLoader::LoadFromString(Scene &scene, std::string &err,
- const char *str, unsigned int length, const std::string& baseDir) {
+ const char *str, unsigned int length,
+ const std::string &baseDir) {
picojson::value v;
std::string perr = picojson::parse(v, str, str + length);
@@ -1282,6 +1338,25 @@
}
}
+ // 9. Parse Texture
+ if (v.contains("textures") && v.get("textures").is<picojson::object>()) {
+
+ const picojson::object &root = v.get("textures").get<picojson::object>();
+
+ picojson::object::const_iterator it(root.begin());
+ picojson::object::const_iterator itEnd(root.end());
+ for (; it != itEnd; it++) {
+
+ Texture texture;
+ if (!ParseTexture(texture, err, (it->second).get<picojson::object>(),
+ baseDir)) {
+ return false;
+ }
+
+ scene.textures[it->first] = texture;
+ }
+ }
+
return true;
}