mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-04-22 14:09:55 +08:00
texture
support.
This commit is contained in:
parent
b495603c67
commit
bde7021b94
@ -18,6 +18,7 @@ Simple OpenGL viewer for glTF geometry.
|
||||
|
||||
## TODO
|
||||
|
||||
* [ ] Texture
|
||||
* [x] Texture
|
||||
* [ ] Various texture format.
|
||||
* [ ] Shader
|
||||
* [ ] Animation
|
||||
|
@ -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;
|
||||
@ -34,17 +44,19 @@ float eye[3], lookat[3], up[3];
|
||||
|
||||
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) {
|
||||
@ -122,8 +134,7 @@ bool LinkShader(GLuint &prog, GLuint &vertShader, GLuint &fragShader) {
|
||||
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,10 +146,12 @@ void reshapeFunc(GLFWwindow* window, int w, int h)
|
||||
height = h;
|
||||
}
|
||||
|
||||
void keyboardFunc(GLFWwindow *window, int key, int scancode, int action, int mods) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,8 +192,7 @@ void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y){
|
||||
float transScale = 2.0f;
|
||||
|
||||
if (mouseLeftPressed) {
|
||||
trackball(prev_quat,
|
||||
rotScale * (2.0f * prevMouseX - width) / (float)width,
|
||||
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);
|
||||
@ -201,10 +213,13 @@ void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y){
|
||||
prevMouseY = mouse_y;
|
||||
}
|
||||
|
||||
static void SetupGLState(Scene& scene, GLuint progId)
|
||||
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());
|
||||
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;
|
||||
@ -216,29 +231,99 @@ static void SetupGLState(Scene& scene, GLuint progId)
|
||||
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);
|
||||
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)
|
||||
{
|
||||
void DrawMesh(Scene &scene, const Mesh &mesh) {
|
||||
|
||||
if (gGLProgramState.uniforms["diffuseTex"] >= 0) {
|
||||
glUniform1i(gGLProgramState.uniforms["diffuseTex"], 0); // TEXTURE0
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mesh.primitives.size(); i++) {
|
||||
const Primitive &primitive = mesh.primitives[i];
|
||||
|
||||
if (primitive.indices.empty()) return;
|
||||
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());
|
||||
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];
|
||||
@ -254,10 +339,13 @@ void DrawMesh(Scene& scene, const Mesh& mesh)
|
||||
} else if (accessor.type == TINYGLTF_TYPE_VEC4) {
|
||||
count = 4;
|
||||
}
|
||||
// it->first would be "POSITION", "NORMAL", ...
|
||||
// it->first would be "POSITION", "NORMAL", "TEXCOORD_0", ...
|
||||
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.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");
|
||||
@ -265,7 +353,8 @@ void DrawMesh(Scene& scene, const Mesh& mesh)
|
||||
}
|
||||
|
||||
const Accessor &indexAccessor = scene.accessors[primitive.indices];
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gBufferState[indexAccessor.bufferView].vb);
|
||||
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 @@ void DrawMesh(Scene& scene, const Mesh& mesh)
|
||||
} 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)) {
|
||||
(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 @@ void DrawScene(Scene& scene)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Init() {
|
||||
trackball(curr_quat, 0, 0, 0, 0);
|
||||
|
||||
@ -326,8 +416,7 @@ static void Init() {
|
||||
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;
|
||||
@ -358,7 +447,8 @@ int main(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
window = glfwCreateWindow(width, height, "Simple glTF geometry viewer", NULL, NULL);
|
||||
window = glfwCreateWindow(width, height, "Simple glTF geometry viewer", NULL,
|
||||
NULL);
|
||||
if (window == NULL) {
|
||||
std::cerr << "Failed to open GLFW window. " << std::endl;
|
||||
glfwTerminate();
|
||||
@ -433,7 +523,8 @@ int main(int argc, char **argv)
|
||||
// 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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 @@ void main(void)
|
||||
gl_Position = p;
|
||||
vec4 nn = gl_ModelViewMatrixInverseTranspose * vec4(normalize(in_normal), 0);
|
||||
normal = nn.xyz;
|
||||
|
||||
texcoord = in_texcoord;
|
||||
}
|
||||
|
207
test.cc
207
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 @@ std::string PrintMode(int mode)
|
||||
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 @@ std::string PrintType(int ty)
|
||||
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 @@ std::string PrintComponentType(int ty)
|
||||
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 @@ std::string PrintFloatArray(const std::vector<double>& arr)
|
||||
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 @@ std::string PrintStringArray(const std::vector<std::string>& arr)
|
||||
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 @@ std::string Indent(int indent)
|
||||
return s;
|
||||
}
|
||||
|
||||
void DumpNode(const Node& node, int indent)
|
||||
{
|
||||
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) << "children : " << PrintStringArray(node.children) << std::endl;
|
||||
std::cout << Indent(indent)
|
||||
<< "meshes : " << PrintStringArray(node.meshes) << 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,7 +194,9 @@ void Dump(const Scene& scene)
|
||||
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 @@ void Dump(const Scene& scene)
|
||||
|
||||
{
|
||||
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 @@ void Dump(const Scene& scene)
|
||||
}
|
||||
|
||||
{
|
||||
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 @@ void Dump(const Scene& scene)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,15 +320,37 @@ void Dump(const Scene& scene)
|
||||
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);
|
||||
|
@ -31,6 +31,7 @@
|
||||
//
|
||||
//
|
||||
// Version:
|
||||
// - v0.9.2 Support parsing `texture`
|
||||
// - v0.9.1 Support loading glTF asset from memory
|
||||
// - v0.9.0 Initial
|
||||
//
|
||||
@ -80,12 +81,20 @@ namespace tinygltf {
|
||||
#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;
|
||||
|
||||
typedef std::map<std::string, Parameter> ParameterMap;
|
||||
|
||||
// LDR 8bit image
|
||||
typedef struct {
|
||||
std::string name;
|
||||
int width;
|
||||
@ -94,10 +103,20 @@ typedef struct {
|
||||
std::vector<unsigned char> image;
|
||||
} 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 @@ public:
|
||||
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 @@ public:
|
||||
/// 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
|
||||
@ -780,6 +799,39 @@ bool ParseImage(Image &image, std::string &err, const picojson::object &o,
|
||||
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 @@ bool ParseMaterial(Material &material, std::string &err,
|
||||
|
||||
for (; it != itEnd; it++) {
|
||||
// Assume number values.
|
||||
std::vector<double> values;
|
||||
if (!ParseNumberArrayProperty(values, err, valuesObject, it->first,
|
||||
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 ParseMaterial(Material &material, std::string &err,
|
||||
}
|
||||
|
||||
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 @@ bool TinyGLTFLoader::LoadFromString(Scene &scene, std::string &err,
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user