mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-08-14 06:45:52 +08:00
Rename.
Add some missing files.
This commit is contained in:
parent
cb0a8794c3
commit
cf30d42cbc
@ -2,4 +2,4 @@
|
|||||||
EXTRA_CXXFLAGS :=
|
EXTRA_CXXFLAGS :=
|
||||||
|
|
||||||
all:
|
all:
|
||||||
clang++ -std=c++11 -g -O1 -I../../ -I../common $(EXTRA_CXXFLAGS) -o mesh-modify mesh-modify.cc mesh-util.cc tinygltf_impl.cc
|
clang++ -std=c++11 -g -O1 -I../../ -I../common $(EXTRA_CXXFLAGS) -o mesh-conv mesh-conv.cc mesh-util.cc tinygltf_impl.cc
|
5
examples/mesh-conv/Makefile.meson
Normal file
5
examples/mesh-conv/Makefile.meson
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
all:
|
||||||
|
ninja
|
||||||
|
|
||||||
|
clean:
|
||||||
|
ninja -t clean
|
43
examples/mesh-conv/README.md
Normal file
43
examples/mesh-conv/README.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Mesh modify experiment
|
||||||
|
|
||||||
|
Sometimes we want to tweak mesh attributes(e.g. vertex position, uv coord, etc).
|
||||||
|
glTF itself does not allow ASCII representation of such data.
|
||||||
|
|
||||||
|
This example show how to
|
||||||
|
|
||||||
|
- Export mesh data from .bin to .obj
|
||||||
|
- Import mesh data to .bin(update corresponding buffer data) from .obj
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Wavefront .obj to glTF
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mesh-modify obj2gltf input.obj
|
||||||
|
```
|
||||||
|
|
||||||
|
All shapes in .obj are concatenated and create single glTF mesh.
|
||||||
|
(tinyobjloader's skin weight extension `vw` supported)
|
||||||
|
|
||||||
|
#### Limitation
|
||||||
|
|
||||||
|
Buffer is stored as external file(`.bin`)
|
||||||
|
|
||||||
|
### glTF to Wavefront .obj
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mesh-modify gltf2obj input.gltf
|
||||||
|
```
|
||||||
|
|
||||||
|
.obj will be created for each glTF Mesh.
|
||||||
|
(Skin weight data is exported to .obj using tinyobjloader's skin weight extension `vw`)
|
||||||
|
|
||||||
|
#### Limitation
|
||||||
|
|
||||||
|
Buffer is stored as external file(`.bin`)
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
* [ ] obj2gltf: Assign glTF material from .mtl
|
||||||
|
* [ ] modify/patch mesh geometry in glTF
|
||||||
|
* By using JSON Patch or JSON Merge feature
|
3
examples/mesh-conv/bootstrap-meson.sh
Executable file
3
examples/mesh-conv/bootstrap-meson.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
rm -rf build
|
||||||
|
CXX=clang++ CC=clang meson build -Db_sanitize=address -Db_lundef=false --buildtype=debug
|
||||||
|
cp Makefile.meson build/Makefile
|
@ -148,13 +148,11 @@ struct MeshPrim {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
|
||||||
static std::string GetFilePathExtension(const std::string &FileName) {
|
static std::string GetFilePathExtension(const std::string &FileName) {
|
||||||
if (FileName.find_last_of(".") != std::string::npos)
|
if (FileName.find_last_of(".") != std::string::npos)
|
||||||
return FileName.substr(FileName.find_last_of(".") + 1);
|
return FileName.substr(FileName.find_last_of(".") + 1);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static size_t ComponentTypeByteSize(int type) {
|
static size_t ComponentTypeByteSize(int type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -296,13 +294,11 @@ static std::string FindFile(const std::vector<std::string> &paths,
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static std::string GetBaseDir(const std::string &filepath) {
|
static std::string GetBaseDir(const std::string &filepath) {
|
||||||
if (filepath.find_last_of("/\\") != std::string::npos)
|
if (filepath.find_last_of("/\\") != std::string::npos)
|
||||||
return filepath.substr(0, filepath.find_last_of("/\\"));
|
return filepath.substr(0, filepath.find_last_of("/\\"));
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int GetSlotId(const std::string &name) {
|
static int GetSlotId(const std::string &name) {
|
||||||
if (name.rfind("TEXCOORD_", 0) == 0) {
|
if (name.rfind("TEXCOORD_", 0) == 0) {
|
||||||
@ -575,7 +571,6 @@ static bool DumpMesh(const tinygltf::Model &model, const tinygltf::Mesh &mesh,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static bool ExtractMesh(const std::string &asset_path, tinygltf::Model &model,
|
static bool ExtractMesh(const std::string &asset_path, tinygltf::Model &model,
|
||||||
std::vector<example::MeshPrim> *outs) {
|
std::vector<example::MeshPrim> *outs) {
|
||||||
// Get .bin data
|
// Get .bin data
|
||||||
@ -623,117 +618,127 @@ static bool ExtractMesh(const std::string &asset_path, tinygltf::Model &model,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc < 2) {
|
if (argc < 3) {
|
||||||
std::cout << "mesh-dump input.gltf" << std::endl;
|
std::cout << "mesh-modify <op> <args>" << std::endl;
|
||||||
|
std::cout << " op\n\n";
|
||||||
|
std::cout << " gltf2obj input.gltf <flip_texcoord_y>\n";
|
||||||
|
std::cout << " obj2gltf input.obj <verbose>\n";
|
||||||
|
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
std::string op = argv[1];
|
||||||
|
|
||||||
tinygltf::Model model;
|
if (op == "gltf2obj") {
|
||||||
tinygltf::TinyGLTF loader;
|
|
||||||
std::string err;
|
|
||||||
std::string warn;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
bool flip_texcoord_y = true;
|
||||||
std::string input_filename(argv[1] ? argv[1]
|
if (argc > 3) {
|
||||||
: "../../../models/Cube/Cube.gltf");
|
flip_texcoord_y = (std::atoi(argv[3]) > 0) ? true : false;
|
||||||
#else
|
|
||||||
std::string input_filename(argv[1] ? argv[1] : "../../models/Cube/Cube.gltf");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string ext = GetFilePathExtension(input_filename);
|
|
||||||
|
|
||||||
{
|
|
||||||
bool ret = false;
|
|
||||||
if (ext.compare("glb") == 0) {
|
|
||||||
// assume binary glTF.
|
|
||||||
ret = loader.LoadBinaryFromFile(&model, &err, &warn,
|
|
||||||
input_filename.c_str());
|
|
||||||
} else {
|
|
||||||
// assume ascii glTF.
|
|
||||||
ret =
|
|
||||||
loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!warn.empty()) {
|
tinygltf::Model model;
|
||||||
printf("Warn: %s\n", warn.c_str());
|
tinygltf::TinyGLTF loader;
|
||||||
|
std::string err;
|
||||||
|
std::string warn;
|
||||||
|
|
||||||
|
std::string input_filename(argv[2]);
|
||||||
|
|
||||||
|
std::string ext = GetFilePathExtension(input_filename);
|
||||||
|
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
if (ext.compare("glb") == 0) {
|
||||||
|
// assume binary glTF.
|
||||||
|
ret = loader.LoadBinaryFromFile(&model, &err, &warn,
|
||||||
|
input_filename.c_str());
|
||||||
|
} else {
|
||||||
|
// assume ascii glTF.
|
||||||
|
ret =
|
||||||
|
loader.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!warn.empty()) {
|
||||||
|
printf("Warn: %s\n", warn.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
printf("ERR: %s\n", err.c_str());
|
||||||
|
}
|
||||||
|
if (!ret) {
|
||||||
|
printf("Failed to load .glTF : %s\n", argv[1]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err.empty()) {
|
json j;
|
||||||
printf("ERR: %s\n", err.c_str());
|
{
|
||||||
|
std::ifstream i(input_filename);
|
||||||
|
i >> j;
|
||||||
}
|
}
|
||||||
if (!ret) {
|
std::cout << "j = " << j << "\n";
|
||||||
printf("Failed to load .glTF : %s\n", argv[1]);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
json j;
|
json j_patch = R"([
|
||||||
{
|
{ "op": "add", "path": "/buffers/-", "value": {
|
||||||
std::ifstream i(input_filename);
|
"name": "plane/data",
|
||||||
i >> j;
|
"byteLength": 480,
|
||||||
}
|
"uri": "plane1.bin"
|
||||||
std::cout << "j = " << j << "\n";
|
} }
|
||||||
|
])"_json;
|
||||||
|
|
||||||
json j_patch = R"([
|
// a JSON value
|
||||||
{ "op": "add", "path": "/buffers/-", "value": {
|
json j_original = R"({
|
||||||
"name": "plane/data",
|
"baz": ["one", "two", "three"],
|
||||||
"byteLength": 480,
|
"foo": "bar"
|
||||||
"uri": "plane1.bin"
|
})"_json;
|
||||||
} }
|
|
||||||
])"_json;
|
|
||||||
|
|
||||||
// a JSON value
|
//json j_patch = R"([
|
||||||
json j_original = R"({
|
// { "op": "remove", "path": "/buffers" }
|
||||||
"baz": ["one", "two", "three"],
|
//])"_json;
|
||||||
"foo": "bar"
|
|
||||||
})"_json;
|
|
||||||
|
|
||||||
//json j_patch = R"([
|
std::cout << "patch = " << j_patch.dump(2) << "\n";
|
||||||
// { "op": "remove", "path": "/buffers" }
|
|
||||||
//])"_json;
|
|
||||||
|
|
||||||
std::cout << "patch = " << j_patch.dump(2) << "\n";
|
json j_ret = j.patch(j_patch);
|
||||||
|
std::cout << "patched = " << j_ret.dump(2) << "\n";
|
||||||
|
|
||||||
json j_ret = j.patch(j_patch);
|
std::string basedir = GetBaseDir(input_filename);
|
||||||
std::cout << "patched = " << j_ret.dump(2) << "\n";
|
std::vector<example::MeshPrim> meshes;
|
||||||
|
bool ret = ExtractMesh(basedir, model, &meshes);
|
||||||
|
|
||||||
std::string basedir = GetBaseDir(input_filename);
|
size_t n = 0;
|
||||||
std::vector<example::MeshPrim> meshes;
|
for (const auto &mesh : meshes) {
|
||||||
bool ret = ExtractMesh(basedir, model, &meshes);
|
// Assume no duplicated name in .glTF data
|
||||||
|
std::string filename;
|
||||||
|
if (mesh.name.empty()) {
|
||||||
|
filename = "untitled-" + std::to_string(n) + ".obj";
|
||||||
|
} else {
|
||||||
|
filename = mesh.name + ".obj";
|
||||||
|
}
|
||||||
|
|
||||||
size_t n = 0;
|
bool ok = example::SaveAsObjMesh(filename, mesh, flip_texcoord_y);
|
||||||
for (const auto &mesh : meshes) {
|
if (!ok) {
|
||||||
// Assume no duplicated name in .glTF data
|
return EXIT_FAILURE;
|
||||||
std::string filename;
|
}
|
||||||
if (mesh.name.empty()) {
|
n++;
|
||||||
filename = "untitled-" + std::to_string(n) + ".obj";
|
|
||||||
} else {
|
|
||||||
filename = mesh.name + ".obj";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool flip_y = true; // flip texcoord Y?
|
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
bool ok = example::SaveAsObjMesh(filename, mesh,);
|
} else if (op == "obj2gltf") {
|
||||||
if (!ok) {
|
std::string input_filename(argv[2]);
|
||||||
return EXIT_FAILURE;
|
|
||||||
|
bool verbose = false;
|
||||||
|
if (argc > 3) {
|
||||||
|
verbose = (std::atoi(argv[3]) > 0) ? true : false;
|
||||||
}
|
}
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
||||||
#else
|
|
||||||
|
|
||||||
{
|
|
||||||
std::string input_filename(argv[1]);
|
|
||||||
|
|
||||||
// Require facevarying layout?
|
// Require facevarying layout?
|
||||||
// false = try to keep GL-like mesh data as much as possible.
|
// facevarying representation is required if a vertex can have multiple normal/uv value.
|
||||||
// true = reorder vertex data and re-assign vertex indices.
|
// drawback of facevarying is mesh data increases.
|
||||||
|
// false = try to keep shared vertex representation as much as possible.
|
||||||
|
// true = reorder vertex data and re-assign vertex indices for facevarying data layout.
|
||||||
bool facevarying = false;
|
bool facevarying = false;
|
||||||
|
|
||||||
example::MeshPrim mesh;
|
example::MeshPrim mesh;
|
||||||
@ -742,7 +747,9 @@ int main(int argc, char **argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintMeshPrim(mesh);
|
if (verbose) {
|
||||||
|
PrintMeshPrim(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
std::string output_filename("output.gltf");
|
std::string output_filename("output.gltf");
|
||||||
|
|
||||||
@ -752,9 +759,11 @@ int main(int argc, char **argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
std::cout << "Write glTF: " << output_filename << "\n";
|
std::cout << "Write glTF: " << output_filename << "\n";
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::cerr << "Unknown operation: " << op << "\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
@ -54,7 +54,7 @@ struct MeshPrim {
|
|||||||
///
|
///
|
||||||
/// Save MeshPrim as wavefront .obj
|
/// Save MeshPrim as wavefront .obj
|
||||||
///
|
///
|
||||||
bool SaveAsObjMesh(const std::string &filename, const MeshPrim &mesh);
|
bool SaveAsObjMesh(const std::string &filename, const MeshPrim &mesh, bool flip_texcoord_y = true);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Save MeshPrim as glTF mesh
|
/// Save MeshPrim as glTF mesh
|
7
examples/mesh-conv/meson.build
Normal file
7
examples/mesh-conv/meson.build
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
project('mesh-conv', 'cpp', default_options : ['cpp_std=c++11'])
|
||||||
|
|
||||||
|
thread_dep = dependency('threads')
|
||||||
|
|
||||||
|
incdir = include_directories(['../../', '../common'])
|
||||||
|
|
||||||
|
executable('mesh-conv', ['mesh-conv.cc', 'mesh-util.cc', 'tinygltf_impl.cc'], include_directories : incdir, dependencies : thread_dep)
|
9
examples/mesh-conv/tinygltf_impl.cc
Normal file
9
examples/mesh-conv/tinygltf_impl.cc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#define TINYGLTF_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "../../tiny_gltf.h"
|
||||||
|
#else
|
||||||
|
#include "tiny_gltf.h"
|
||||||
|
#endif
|
@ -1,13 +0,0 @@
|
|||||||
# Mesh modify experiment
|
|
||||||
|
|
||||||
Sometimes we want to tweak mesh attributes(e.g. vertex position, uv coord, etc).
|
|
||||||
glTF itself does not allow ASCII representation of such data.
|
|
||||||
|
|
||||||
This example show how to
|
|
||||||
|
|
||||||
- Export mesh data from .bin to .obj
|
|
||||||
- Import mesh data to .bin(update corresponding buffer data) from .obj
|
|
||||||
|
|
||||||
## Requirement
|
|
||||||
|
|
||||||
Assume Buffer is stored as external file(`.bin`)
|
|
@ -1,7 +0,0 @@
|
|||||||
project('mesh-modify', 'cpp', default_options : ['cpp_std=c++11'])
|
|
||||||
|
|
||||||
thread_dep = dependency('threads')
|
|
||||||
|
|
||||||
incdir = include_directories(['../../', '../common'])
|
|
||||||
|
|
||||||
executable('mesh-modify', ['mesh-modify.cc', 'mesh-util.cc', 'tinygltf_impl.cc'], include_directories : incdir, dependencies : thread_dep)
|
|
Loading…
x
Reference in New Issue
Block a user