mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-08-10 05:38:58 +08:00
Initial support of converting Alembic curve to .gltf.
This commit is contained in:
parent
c39d93879a
commit
1db9a358a7
@ -22,10 +22,40 @@ Edit include and lib paths for Alembic OpenEXR(ilmbase) in `Makefile`, then simp
|
||||
|
||||
I am testing with Alembic data using Blender's Alembic exporter(feature available from Blender 2.78)
|
||||
|
||||
## Extensions
|
||||
|
||||
### Curves
|
||||
|
||||
Curves are reprenseted as point primitive(mode = 0) in glTF level for the backward compatibility of existing glTF specification.
|
||||
The number of vertices per curve information is aded to `NVERRTS` attribute.
|
||||
"ext_mode" extra property is added and set it to "curves" string to specify the object as curves primitive.
|
||||
|
||||
Here is an example JSON description of curves primitive.
|
||||
|
||||
|
||||
"meshes": {
|
||||
"curves_1": {
|
||||
"primitives": [
|
||||
{
|
||||
"attributes": {
|
||||
"POSITION": "accessor_vertices",
|
||||
"NVERTS": "accessor_nverts",
|
||||
},
|
||||
"material": "material_1",
|
||||
"mode": 0,
|
||||
"extra" {
|
||||
"ext_mode" : "curves"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
## TODO
|
||||
|
||||
* [ ] Support normals and texcoords
|
||||
* [ ] Support mutiple meshes
|
||||
* [ ] Support animation(time samples)
|
||||
* [ ] Support scene graph(node hierarchy)
|
||||
* [ ] Support Point, Curve and SubD?
|
||||
* [ ] Support Point and SubD?
|
||||
|
@ -40,13 +40,38 @@
|
||||
|
||||
#include "../../tiny_gltf_loader.h" // To import some TINYGLTF_*** macros.
|
||||
|
||||
// @todo { texcoords, normals }
|
||||
typedef struct
|
||||
{
|
||||
std::vector<float> vertices;
|
||||
|
||||
// Either `normals` or `facevarying_normals` is filled.
|
||||
std::vector<float> normals;
|
||||
std::vector<float> facevarying_normals;
|
||||
|
||||
// Either `texcoords` or `facevarying_texcoords` is filled.
|
||||
std::vector<float> texcoords;
|
||||
std::vector<float> facevarying_texcoords;
|
||||
|
||||
std::vector<unsigned int> faces;
|
||||
} Mesh;
|
||||
|
||||
// Curves are represented as an array of curve.
|
||||
// i'th curve has nverts[i] points.
|
||||
// TODO(syoyo) knots, order to support NURBS curve.
|
||||
typedef struct
|
||||
{
|
||||
std::vector<float> points;
|
||||
std::vector<int> nverts; // # of vertices per strand(curve).
|
||||
} Curves;
|
||||
|
||||
// Points represent particle data.
|
||||
// TODO(syoyo)
|
||||
typedef struct
|
||||
{
|
||||
std::vector<float> points;
|
||||
std::vector<float> radiuss;
|
||||
} Points;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// writer module
|
||||
// @todo { move writer code to tiny_gltf_writer.h }
|
||||
@ -264,13 +289,114 @@ BuildFaceSet(
|
||||
|
||||
}
|
||||
|
||||
static void readPolyNormals(
|
||||
std::vector<float> *normals,
|
||||
std::vector<float> *facevarying_normals,
|
||||
Alembic::AbcGeom::IN3fGeomParam normals_param)
|
||||
{
|
||||
normals->clear();
|
||||
facevarying_normals->clear();
|
||||
|
||||
if (!normals_param) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((normals_param.getScope() != Alembic::AbcGeom::kVertexScope) &&
|
||||
(normals_param.getScope() != Alembic::AbcGeom::kVaryingScope) &&
|
||||
(normals_param.getScope() != Alembic::AbcGeom::kFacevaryingScope))
|
||||
{
|
||||
std::cout << "Normal vector has an unsupported scope" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (normals_param.getScope() == Alembic::AbcGeom::kVertexScope) {
|
||||
std::cout << "Normal: VertexScope" << std::endl;
|
||||
} else if (normals_param.getScope() == Alembic::AbcGeom::kVaryingScope) {
|
||||
std::cout << "Normal: VaryingScope" << std::endl;
|
||||
} else if (normals_param.getScope() == Alembic::AbcGeom::kFacevaryingScope) {
|
||||
std::cout << "Normal: FacevaryingScope" << std::endl;
|
||||
}
|
||||
|
||||
// @todo { lerp normal among time sample.}
|
||||
Alembic::AbcGeom::IN3fGeomParam::Sample samp;
|
||||
Alembic::AbcGeom::ISampleSelector samplesel(
|
||||
0.0, Alembic::AbcGeom::ISampleSelector::kNearIndex);
|
||||
normals_param.getExpanded(samp, samplesel);
|
||||
|
||||
Alembic::Abc::N3fArraySamplePtr P = samp.getVals();
|
||||
size_t sample_size = P->size();
|
||||
|
||||
if (normals_param.getScope() == Alembic::AbcGeom::kFacevaryingScope) {
|
||||
for (size_t i = 0; i < sample_size; i++) {
|
||||
facevarying_normals->push_back((*P)[i].x);
|
||||
facevarying_normals->push_back((*P)[i].y);
|
||||
facevarying_normals->push_back((*P)[i].z);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < sample_size; i++) {
|
||||
normals->push_back((*P)[i].x);
|
||||
normals->push_back((*P)[i].y);
|
||||
normals->push_back((*P)[i].z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @todo { Support multiple UVset. }
|
||||
static void readPolyUVs(
|
||||
std::vector<float> *uvs,
|
||||
std::vector<float> *facevarying_uvs,
|
||||
Alembic::AbcGeom::IV2fGeomParam uvs_param)
|
||||
{
|
||||
uvs->clear();
|
||||
facevarying_uvs->clear();
|
||||
|
||||
if (!uvs_param) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uvs_param.getNumSamples() > 0) {
|
||||
std::string uv_set_name = Alembic::Abc::GetSourceName(uvs_param.getMetaData());
|
||||
std::cout << "UVset : " << uv_set_name << std::endl;
|
||||
}
|
||||
|
||||
if (uvs_param.isConstant()) {
|
||||
std::cout << "UV is constant" << std::endl;
|
||||
}
|
||||
|
||||
if (uvs_param.getScope() == Alembic::AbcGeom::kVertexScope) {
|
||||
std::cout << "UV: VertexScope" << std::endl;
|
||||
} else if (uvs_param.getScope() == Alembic::AbcGeom::kVaryingScope) {
|
||||
std::cout << "UV: VaryingScope" << std::endl;
|
||||
} else if (uvs_param.getScope() == Alembic::AbcGeom::kFacevaryingScope) {
|
||||
std::cout << "UV: FacevaryingScope" << std::endl;
|
||||
}
|
||||
|
||||
// @todo { lerp normal among time sample.}
|
||||
Alembic::AbcGeom::IV2fGeomParam::Sample samp;
|
||||
Alembic::AbcGeom::ISampleSelector samplesel(
|
||||
0.0, Alembic::AbcGeom::ISampleSelector::kNearIndex);
|
||||
uvs_param.getIndexed(samp, samplesel);
|
||||
|
||||
Alembic::Abc::V2fArraySamplePtr P = samp.getVals();
|
||||
size_t sample_size = P->size();
|
||||
|
||||
if (uvs_param.getScope() == Alembic::AbcGeom::kFacevaryingScope) {
|
||||
for (size_t i = 0; i < sample_size; i++) {
|
||||
facevarying_uvs->push_back((*P)[i].x);
|
||||
facevarying_uvs->push_back((*P)[i].y);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < sample_size; i++) {
|
||||
uvs->push_back((*P)[i].x);
|
||||
uvs->push_back((*P)[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Traverse Alembic object tree and extract mesh object.
|
||||
// Currently we only extract first found polygon mesh.
|
||||
static void VisitObjectAndExtractMesh(Mesh* mesh, std::stringstream& ss, bool& foundMesh, const Alembic::AbcGeom::IObject& obj, const std::string& indent) {
|
||||
if (foundMesh) {
|
||||
return;
|
||||
}
|
||||
// Currently we only extract first found geometry object.
|
||||
static void VisitObjectAndExtractObject(Mesh* mesh, Curves* curves, std::stringstream& ss, bool& foundMesh, bool &foundCurves, const Alembic::AbcGeom::IObject& obj, const std::string& indent) {
|
||||
|
||||
std::string path = obj.getFullName();
|
||||
|
||||
@ -283,8 +409,12 @@ static void VisitObjectAndExtractMesh(Mesh* mesh, std::stringstream& ss, bool& f
|
||||
|
||||
for (size_t i = 0; i < obj.getNumChildren(); i++) {
|
||||
const Alembic::AbcGeom::ObjectHeader& header = obj.getChildHeader(i);
|
||||
ss << " Child: header = " << header.getName() << std::endl;
|
||||
|
||||
if (Alembic::AbcGeom::IPolyMesh::matches(header)) {
|
||||
Alembic::AbcGeom::ICompoundProperty cprops = obj.getChild(i).getProperties();
|
||||
VisitProperties(ss, props, indent);
|
||||
|
||||
if ((!foundMesh) && (Alembic::AbcGeom::IPolyMesh::matches(header))) {
|
||||
// Polygon
|
||||
Alembic::AbcGeom::IPolyMesh pmesh(obj, header.getName());
|
||||
|
||||
@ -303,10 +433,31 @@ static void VisitObjectAndExtractMesh(Mesh* mesh, std::stringstream& ss, bool& f
|
||||
<< std::endl;
|
||||
|
||||
|
||||
// normals
|
||||
Alembic::AbcGeom::IN3fGeomParam normals_param = ps.getNormalsParam();
|
||||
std::vector<float> normals;
|
||||
std::vector<float> facevarying_normals;
|
||||
readPolyNormals(&normals, &facevarying_normals, normals_param);
|
||||
std::cout << " # of normals = " << (normals.size() / 3) << std::endl;
|
||||
std::cout << " # of facevarying normals = " << (facevarying_normals.size() / 3) << std::endl;
|
||||
mesh->normals = normals;
|
||||
|
||||
|
||||
// UV
|
||||
Alembic::AbcGeom::IV2fGeomParam uvs_param = ps.getUVsParam();
|
||||
std::vector<float> uvs;
|
||||
std::vector<float> facevarying_uvs;
|
||||
readPolyUVs(&uvs, &facevarying_uvs, uvs_param);
|
||||
std::cout << " # of uvs = " << (uvs.size() / 2) << std::endl;
|
||||
std::cout << " # of facevarying_uvs = " << (facevarying_uvs.size() / 2) << std::endl;
|
||||
mesh->texcoords = uvs;
|
||||
mesh->facevarying_texcoords = facevarying_uvs;
|
||||
|
||||
std::vector<unsigned int> faces; // temp
|
||||
bool ret = BuildFaceSet(faces, P, psample.getFaceIndices(), psample.getFaceCounts());
|
||||
assert(ret);
|
||||
(void)(ret);
|
||||
if (!ret) {
|
||||
std::cout << " No faces in polymesh" << std::endl;
|
||||
}
|
||||
|
||||
mesh->vertices.resize(3 * P->size());
|
||||
memcpy(mesh->vertices.data(), P->get(), sizeof(float) * 3 * P->size());
|
||||
@ -318,13 +469,75 @@ static void VisitObjectAndExtractMesh(Mesh* mesh, std::stringstream& ss, bool& f
|
||||
} else {
|
||||
std::cout << "Warning: # of samples = 0" << std::endl;
|
||||
}
|
||||
} else if ((!foundCurves) && Alembic::AbcGeom::ICurves::matches(header)) {
|
||||
// Curves
|
||||
Alembic::AbcGeom::ICurves curve(obj, header.getName());
|
||||
|
||||
Alembic::AbcGeom::ISampleSelector samplesel(
|
||||
0.0, Alembic::AbcGeom::ISampleSelector::kNearIndex);
|
||||
Alembic::AbcGeom::ICurvesSchema::Sample psample;
|
||||
Alembic::AbcGeom::ICurvesSchema& ps = curve.getSchema();
|
||||
|
||||
std::cout << " # of samples = " << ps.getNumSamples() << std::endl;
|
||||
|
||||
if (ps.getNumSamples() > 0) {
|
||||
ps.get(psample, samplesel);
|
||||
|
||||
const size_t num_curves = psample.getNumCurves();
|
||||
std::cout << " # of curves = " << num_curves << std::endl;
|
||||
|
||||
Alembic::Abc::P3fArraySamplePtr P = psample.getPositions();
|
||||
Alembic::Abc::FloatArraySamplePtr knots = psample.getKnots();
|
||||
Alembic::Abc::UcharArraySamplePtr orders = psample.getOrders();
|
||||
|
||||
Alembic::Abc::Int32ArraySamplePtr num_vertices = psample.getCurvesNumVertices();
|
||||
|
||||
if (knots) std::cout << " # of knots= " << knots->size() << std::endl;
|
||||
if (orders) std::cout << " # of orders= " << orders->size() << std::endl;
|
||||
std::cout << " # of nvs= " << num_vertices->size() << std::endl;
|
||||
|
||||
curves->points.resize(3 * P->size());
|
||||
memcpy(curves->points.data(), P->get(), sizeof(float) * 3 * P->size());
|
||||
|
||||
//for (size_t k = 0; k < P->size(); k++) {
|
||||
// std::cout << "P[" << k << "] " << (*P)[k].x << ", " << (*P)[k].y << ", " << (*P)[k].z << std::endl;
|
||||
//}
|
||||
|
||||
//if (knots) {
|
||||
//for (size_t k = 0; k < knots->size(); k++) {
|
||||
// std::cout << "knots[" << k << "] " << (*knots)[k] << std::endl;
|
||||
//}
|
||||
//}
|
||||
|
||||
//if (orders) {
|
||||
//for (size_t k = 0; k < orders->size(); k++) {
|
||||
// std::cout << "orders[" << k << "] " << (*orders)[k] << std::endl;
|
||||
//}
|
||||
//}
|
||||
|
||||
//for (size_t k = 0; k < num_vertices->size(); k++) {
|
||||
// std::cout << "nv[" << k << "] " << (*num_vertices)[k] << std::endl;
|
||||
//}
|
||||
|
||||
if (num_vertices) {
|
||||
curves->nverts.resize(num_vertices->size());
|
||||
memcpy(curves->nverts.data(), num_vertices->get(), sizeof(int) * num_vertices->size());
|
||||
}
|
||||
|
||||
foundCurves = true;
|
||||
return;
|
||||
|
||||
} else {
|
||||
std::cout << "Warning: # of samples = 0" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VisitObjectAndExtractMesh(mesh, ss, foundMesh, Alembic::AbcGeom::IObject(obj, obj.getChildHeader(i).getName()), indent);
|
||||
VisitObjectAndExtractObject(mesh, curves, ss, foundMesh, foundCurves, Alembic::AbcGeom::IObject(obj, obj.getChildHeader(i).getName()), indent);
|
||||
}
|
||||
}
|
||||
|
||||
static bool SaveGLTF(const std::string& output_filename,
|
||||
static bool SaveMeshToGLTF(const std::string& output_filename,
|
||||
const Mesh& mesh) {
|
||||
picojson::object root;
|
||||
|
||||
@ -398,6 +611,7 @@ static bool SaveGLTF(const std::string& output_filename,
|
||||
picojson::object attributes;
|
||||
|
||||
attributes["POSITION"] = picojson::value(std::string("accessor_vertices"));
|
||||
|
||||
|
||||
picojson::object primitive;
|
||||
primitive["attributes"] = picojson::value(attributes);
|
||||
@ -506,6 +720,209 @@ static bool SaveGLTF(const std::string& output_filename,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SaveCurvesToGLTF(const std::string& output_filename,
|
||||
const Curves& curves) {
|
||||
picojson::object root;
|
||||
|
||||
{
|
||||
picojson::object asset;
|
||||
asset["generator"] = picojson::value("abc2gltf");
|
||||
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;
|
||||
{
|
||||
{
|
||||
std::string b64data = base64_encode(reinterpret_cast<unsigned char const*>(curves.points.data()), curves.points.size() * sizeof(float));
|
||||
picojson::object buf;
|
||||
|
||||
buf["type"] = picojson::value("arraybuffer");
|
||||
buf["uri"] = picojson::value(
|
||||
std::string("data:application/octet-stream;base64,") + b64data);
|
||||
buf["byteLength"] =
|
||||
picojson::value(static_cast<double>(curves.points.size() * sizeof(float)));
|
||||
|
||||
buffers["points"] = picojson::value(buf);
|
||||
}
|
||||
|
||||
// Out extension
|
||||
{
|
||||
std::string b64data = base64_encode(reinterpret_cast<unsigned char const*>(curves.nverts.data()), curves.nverts.size() * sizeof(int));
|
||||
picojson::object buf;
|
||||
|
||||
buf["type"] = picojson::value("arraybuffer");
|
||||
buf["uri"] = picojson::value(
|
||||
std::string("data:application/octet-stream;base64,") + b64data);
|
||||
buf["byteLength"] =
|
||||
picojson::value(static_cast<double>(curves.nverts.size() * sizeof(int)));
|
||||
|
||||
buffers["nverts"] = picojson::value(buf);
|
||||
}
|
||||
|
||||
}
|
||||
root["buffers"] = picojson::value(buffers);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object buffer_views;
|
||||
{
|
||||
{
|
||||
picojson::object buffer_view_points;
|
||||
buffer_view_points["buffer"] = picojson::value(std::string("points"));
|
||||
buffer_view_points["byteLength"] = picojson::value(static_cast<double>(curves.points.size() * sizeof(float)));
|
||||
buffer_view_points["byteOffset"] = picojson::value(static_cast<double>(0));
|
||||
buffer_view_points["target"] = picojson::value(static_cast<int64_t>(TINYGLTF_TARGET_ARRAY_BUFFER));
|
||||
buffer_views["bufferView_points"] = picojson::value(buffer_view_points);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object buffer_view_nverts;
|
||||
buffer_view_nverts["buffer"] = picojson::value(std::string("nverts"));
|
||||
buffer_view_nverts["byteLength"] = picojson::value(static_cast<double>(curves.nverts.size() * sizeof(int)));
|
||||
buffer_view_nverts["byteOffset"] = picojson::value(static_cast<double>(0));
|
||||
buffer_view_nverts["target"] = picojson::value(static_cast<int64_t>(TINYGLTF_TARGET_ARRAY_BUFFER));
|
||||
buffer_views["bufferView_nverts"] = picojson::value(buffer_view_nverts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
root["bufferViews"] = picojson::value(buffer_views);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object attributes;
|
||||
|
||||
attributes["POSITION"] = picojson::value(std::string("accessor_points"));
|
||||
attributes["NVERTS"] = picojson::value(std::string("accessor_nverts"));
|
||||
|
||||
// Extra information for curves primtive.
|
||||
picojson::object extra;
|
||||
extra["ext_mode"] = picojson::value("curves");
|
||||
|
||||
picojson::object primitive;
|
||||
primitive["attributes"] = picojson::value(attributes);
|
||||
//primitive["indices"] = picojson::value("accessor_indices");
|
||||
primitive["material"] = picojson::value("material_1");
|
||||
primitive["mode"] = picojson::value(static_cast<int64_t>(TINYGLTF_MODE_POINTS)); // Use GL_POINTS for backward compatibility
|
||||
primitive["extra"] = picojson::value(extra);
|
||||
|
||||
|
||||
picojson::array primitive_array;
|
||||
primitive_array.push_back(picojson::value(primitive));
|
||||
|
||||
picojson::object m;
|
||||
m["primitives"] = picojson::value(primitive_array);
|
||||
|
||||
picojson::object meshes;
|
||||
meshes["mesh_1"] = picojson::value(m);
|
||||
|
||||
|
||||
root["meshes"] = picojson::value(meshes);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object accessors;
|
||||
|
||||
{
|
||||
picojson::object accessor_points;
|
||||
accessor_points["bufferView"] = picojson::value(std::string("bufferView_points"));
|
||||
accessor_points["byteOffset"] = picojson::value(static_cast<int64_t>(0));
|
||||
accessor_points["byteStride"] = picojson::value(static_cast<double>(3 * sizeof(float)));
|
||||
accessor_points["componentType"] = picojson::value(static_cast<int64_t>(TINYGLTF_COMPONENT_TYPE_FLOAT));
|
||||
accessor_points["count"] = picojson::value(static_cast<int64_t>(curves.points.size()));
|
||||
accessor_points["type"] = picojson::value(std::string("VEC3"));
|
||||
accessors["accessor_points"] = picojson::value(accessor_points);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object accessor_nverts;
|
||||
accessor_nverts["bufferView"] = picojson::value(std::string("bufferView_nverts"));
|
||||
accessor_nverts["byteOffset"] = picojson::value(static_cast<int64_t>(0));
|
||||
accessor_nverts["byteStride"] = picojson::value(static_cast<double>(sizeof(int)));
|
||||
accessor_nverts["componentType"] = picojson::value(static_cast<int64_t>(TINYGLTF_COMPONENT_TYPE_INT));
|
||||
accessor_nverts["count"] = picojson::value(static_cast<int64_t>(curves.nverts.size()));
|
||||
accessor_nverts["type"] = picojson::value(std::string("SCALAR"));
|
||||
accessors["accessor_nverts"] = picojson::value(accessor_nverts);
|
||||
}
|
||||
|
||||
picojson::object accessor_indices;
|
||||
|
||||
root["accessors"] = picojson::value(accessors);
|
||||
}
|
||||
|
||||
{
|
||||
// Use Default Material(Do not supply `material.technique`)
|
||||
picojson::object default_material;
|
||||
picojson::object materials;
|
||||
|
||||
materials["material_1"] = picojson::value(default_material);
|
||||
|
||||
root["materials"] = picojson::value(materials);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object nodes;
|
||||
picojson::object node;
|
||||
picojson::array meshes;
|
||||
|
||||
meshes.push_back(picojson::value(std::string("mesh_1")));
|
||||
|
||||
node["meshes"] = picojson::value(meshes);
|
||||
|
||||
nodes["node_1"] = picojson::value(node);
|
||||
root["nodes"] = picojson::value(nodes);
|
||||
}
|
||||
|
||||
{
|
||||
picojson::object defaultScene;
|
||||
picojson::array nodes;
|
||||
|
||||
nodes.push_back(picojson::value(std::string("node_1")));
|
||||
|
||||
defaultScene["nodes"] = picojson::value(nodes);
|
||||
|
||||
root["scene"] = picojson::value("defaultScene");
|
||||
picojson::object scenes;
|
||||
scenes["defaultScene"] = picojson::value(defaultScene);
|
||||
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);
|
||||
|
||||
std::ofstream ifs(output_filename.c_str());
|
||||
if (ifs.bad()) {
|
||||
std::cerr << "Failed to open " << output_filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
picojson::value v = picojson::value(root);
|
||||
|
||||
std::string s = v.serialize(/* pretty */true);
|
||||
ifs.write(s.data(), static_cast<ssize_t>(s.size()));
|
||||
ifs.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string abc_filename;
|
||||
@ -528,13 +945,15 @@ int main(int argc, char** argv) {
|
||||
|
||||
std::stringstream ss;
|
||||
Mesh mesh;
|
||||
Curves curves;
|
||||
bool foundMesh = false;
|
||||
VisitObjectAndExtractMesh(&mesh, ss, foundMesh, root, /* indent */" ");
|
||||
bool foundCurves = false;
|
||||
VisitObjectAndExtractObject(&mesh, &curves, ss, foundMesh, foundCurves, root, /* indent */" ");
|
||||
|
||||
std::cout << ss.str() << std::endl;
|
||||
|
||||
if (foundMesh) {
|
||||
bool ret = SaveGLTF(gltf_filename, mesh);
|
||||
bool ret = SaveMeshToGLTF(gltf_filename, mesh);
|
||||
if (ret) {
|
||||
std::cout << "Wrote " << gltf_filename << std::endl;
|
||||
} else {
|
||||
@ -544,5 +963,14 @@ int main(int argc, char** argv) {
|
||||
std::cout << "No polygon mesh found in Alembic file" << std::endl;
|
||||
}
|
||||
|
||||
if (foundCurves) {
|
||||
bool ret = SaveCurvesToGLTF(gltf_filename, curves);
|
||||
if (ret) {
|
||||
std::cout << "Wrote " << gltf_filename << std::endl;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user