mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Move test USD files.
Refactor source code. Rename Group to Scope.
This commit is contained in:
@@ -1621,7 +1621,6 @@ struct LuxSphereLight
|
||||
struct LuxDomeLight
|
||||
{
|
||||
std::string name;
|
||||
|
||||
int64_t parent_id{-1}; // Index to xform node
|
||||
|
||||
//
|
||||
@@ -1656,6 +1655,9 @@ struct BlendShape {
|
||||
};
|
||||
|
||||
struct SkelRoot {
|
||||
std::string name;
|
||||
int64_t parent_id{-1};
|
||||
|
||||
AnimatableExtent extent;
|
||||
Purpose purpose{Purpose::Default};
|
||||
AnimatableVisibility visibility{Visibility::Inherited};
|
||||
@@ -1663,10 +1665,15 @@ struct SkelRoot {
|
||||
// TODO
|
||||
// std::vector<std::string> xformOpOrder;
|
||||
// ref proxyPrim
|
||||
|
||||
int64_t skeleton_id{-1}; // index to scene.skeletons
|
||||
};
|
||||
|
||||
// Skelton
|
||||
struct Skelton {
|
||||
// Skeleton
|
||||
struct Skeleton {
|
||||
|
||||
std::string name;
|
||||
|
||||
std::vector<Matrix4d>
|
||||
bindTransforms; // bind-pose transform of each joint in world coordinate.
|
||||
AnimatableExtent extent;
|
||||
@@ -1707,7 +1714,7 @@ struct SkelBindingAPI {
|
||||
-1}; // index to Scene.animations. ref skel:animationSource
|
||||
int64_t blendShapeTargets{
|
||||
-1}; // index to Scene.blendshapes. ref skel:bindShapeTargets
|
||||
int64_t skeleton{-1}; // index to Scene.skeltons. // ref skel:skelton
|
||||
int64_t skeleton{-1}; // index to Scene.skeletons. // ref skel:skeleton
|
||||
};
|
||||
|
||||
// Generic Prim
|
||||
@@ -2121,11 +2128,10 @@ struct Volume {
|
||||
|
||||
|
||||
|
||||
// Corresponds to USD's Scope.
|
||||
// `Scope` is uncommon in graphics community, so we use `Group`.
|
||||
// `Scope` is uncommon in graphics community, its something like `Group`.
|
||||
// From USD doc: Scope is the simplest grouping primitive, and does not carry
|
||||
// the baggage of transformability.
|
||||
struct Group {
|
||||
struct Scope {
|
||||
std::string name;
|
||||
|
||||
int64_t parent_id{-1};
|
||||
|
||||
283
src/tinyusdz.cc
283
src/tinyusdz.cc
@@ -45,7 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// local debug flag(now defined in tinyusdz.hh)
|
||||
#define TINYUSDZ_LOCAL_DEBUG_PRINT (1)
|
||||
#define TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
|
||||
#include "integerCoding.h"
|
||||
#include "lz4-compression.hh"
|
||||
@@ -113,6 +113,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
_warn += ss.str() + "\n"; \
|
||||
} while (0)
|
||||
|
||||
#if defined(TINYUSDZ_LOCAL_DEBUG_PRINT)
|
||||
#define DCOUT(x) do { std::cout << __FILE__ << ":" << __func__ << ":" << std::to_string(__LINE__) << "\n"; } while (false)
|
||||
#else
|
||||
#define DCOUT(x)
|
||||
#endif
|
||||
|
||||
namespace tinyusdz {
|
||||
|
||||
namespace {
|
||||
@@ -1448,6 +1454,16 @@ class Parser {
|
||||
&path_index_to_spec_index_map,
|
||||
PrimvarReader_float2 *preader);
|
||||
|
||||
bool ReconstructSkelRoot(const Node &node, const FieldValuePairVector &fields,
|
||||
const std::unordered_map<uint32_t, uint32_t>
|
||||
&path_index_to_spec_index_map,
|
||||
SkelRoot *skelRoot);
|
||||
|
||||
bool ReconstructSkeleton(const Node &node, const FieldValuePairVector &fields,
|
||||
const std::unordered_map<uint32_t, uint32_t>
|
||||
&path_index_to_spec_index_map,
|
||||
Skeleton *skeleton);
|
||||
|
||||
bool ReconstructSceneRecursively(int parent_id, int level,
|
||||
const std::unordered_map<uint32_t, uint32_t>
|
||||
&path_index_to_spec_index_map,
|
||||
@@ -2484,21 +2500,13 @@ bool Parser::ReadDictionary(Value::Dictionary *d) {
|
||||
|
||||
bool Parser::UnpackValueRep(const ValueRep &rep, Value *value) {
|
||||
ValueType ty = GetValueType(rep.GetType());
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << GetValueTypeRepr(rep.GetType()) << "\n";
|
||||
#endif
|
||||
DCOUT(GetValueTypeRepr(rep.GetType()));
|
||||
if (rep.IsInlined()) {
|
||||
uint32_t d = (rep.GetPayload() & ((1ull << (sizeof(uint32_t) * 8)) - 1));
|
||||
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << "d = " << d << "\n";
|
||||
std::cout << "ty.id = " << ty.id << "\n";
|
||||
#endif
|
||||
DCOUT("d = " << d << ", ty.id = " << ty.id);
|
||||
if (ty.id == VALUE_TYPE_BOOL) {
|
||||
assert((!rep.IsCompressed()) && (!rep.IsArray()));
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << "Bool: " << d << "\n";
|
||||
#endif
|
||||
|
||||
value->SetBool(d ? true : false);
|
||||
|
||||
@@ -2820,10 +2828,6 @@ bool Parser::UnpackValueRep(const ValueRep &rep, Value *value) {
|
||||
return true;
|
||||
} else {
|
||||
// TODO(syoyo)
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cerr << "TODO: Inlined Value: " << GetValueTypeRepr(rep.GetType())
|
||||
<< "\n";
|
||||
#endif
|
||||
PUSH_ERROR("TODO: Inlined Value: " + GetValueTypeRepr(rep.GetType()));
|
||||
|
||||
return false;
|
||||
@@ -4928,11 +4932,9 @@ bool Parser::ReconstructGeomMesh(
|
||||
const Spec &spec = _specs[spec_index];
|
||||
|
||||
Path path = GetPath(spec.path_index);
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << "Path prim part: " << path.GetPrimPart()
|
||||
DCOUT("Path prim part: " << path.GetPrimPart()
|
||||
<< ", prop part: " << path.GetPropPart()
|
||||
<< ", spec_index = " << spec_index << "\n";
|
||||
#endif
|
||||
<< ", spec_index = " << spec_index);
|
||||
|
||||
if (!_live_fieldsets.count(spec.fieldset_index)) {
|
||||
_err += "FieldSet id: " + std::to_string(spec.fieldset_index.value) +
|
||||
@@ -4948,17 +4950,11 @@ bool Parser::ReconstructGeomMesh(
|
||||
|
||||
PrimAttrib attr;
|
||||
bool ret = ParseAttribute(child_fields, &attr, prop_name);
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << "prop: " << prop_name << ", ret = " << ret << "\n";
|
||||
#endif
|
||||
std::cout << "prop: " << prop_name << ", ret = " << ret << "\n";
|
||||
DCOUT("prop: " << prop_name << ", ret = " << ret);
|
||||
|
||||
if (ret) {
|
||||
// TODO(syoyo): Support more prop names
|
||||
if (prop_name == "points") {
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << "got point\n";
|
||||
#endif
|
||||
auto p = attr.var.get_value<std::vector<primvar::point3f>>();
|
||||
if (p) {
|
||||
mesh->points = (*p);
|
||||
@@ -4991,9 +4987,6 @@ bool Parser::ReconstructGeomMesh(
|
||||
|
||||
// Currently we only support vec2f for uv coords.
|
||||
//if (auto p = primvar::as_vector<Vec2f>(&attr.var)) {
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
// std::cout << "got explicit UVCoords!\n";
|
||||
#endif
|
||||
// mesh->st.buffer = (*p);
|
||||
// mesh->st.variability = attr.variability;
|
||||
//}
|
||||
@@ -5002,11 +4995,6 @@ bool Parser::ReconstructGeomMesh(
|
||||
if (p) {
|
||||
mesh->faceVertexCounts = (*p);
|
||||
}
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
// // aaa: typeName: int[]
|
||||
std::cout << "got faceVertexCounts. \n";
|
||||
std::cout << " num = " << mesh->faceVertexCounts.size() << "\n";
|
||||
#endif
|
||||
//}
|
||||
} else if (prop_name == "faceVertexIndices") {
|
||||
auto p = attr.var.get_value<std::vector<int>>();
|
||||
@@ -5014,19 +5002,9 @@ bool Parser::ReconstructGeomMesh(
|
||||
mesh->faceVertexIndices = (*p);
|
||||
}
|
||||
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
// aaa: typeName: int[]
|
||||
std::cout << "got faceVertexIndices\n";
|
||||
std::cout << " num = " << mesh->faceVertexIndices.size() << "\n";
|
||||
#endif
|
||||
//}
|
||||
|
||||
} else if (prop_name == "holeIndices") {
|
||||
//if (auto p = primvar::as_vector<int>(&attr.var)) {
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
// aaa: typeName: int[]
|
||||
// std::cout << "got holeIdicies\n";
|
||||
#endif
|
||||
// mesh->holeIndices = (*p);
|
||||
//}
|
||||
} else if (prop_name == "cornerIndices") {
|
||||
@@ -5050,9 +5028,7 @@ bool Parser::ReconstructGeomMesh(
|
||||
// mesh->creaseSharpnesses = (*p);
|
||||
//}
|
||||
} else if (prop_name == "subdivisionScheme") {
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
//std::cout << "subdivisionScheme:" << attr.stringVal << "\n";
|
||||
#endif
|
||||
auto p = attr.var.get_value<primvar::token>();
|
||||
//if (auto p = primvar::as_basic<std::string>(&attr.var)) {
|
||||
// if (p->compare("none") == 0) {
|
||||
// mesh->subdivisionScheme = SubdivisionScheme::None;
|
||||
@@ -5442,11 +5418,9 @@ bool Parser::ReconstructPreviewSurface(
|
||||
if (p) {
|
||||
shader->diffuseColor.color = (*p);
|
||||
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << "diffuseColor: " << shader->diffuseColor.color[0]
|
||||
DCOUT("diffuseColor: " << shader->diffuseColor.color[0]
|
||||
<< ", " << shader->diffuseColor.color[1] << ", "
|
||||
<< shader->diffuseColor.color[2] << "\n";
|
||||
#endif
|
||||
<< shader->diffuseColor.color[2]);
|
||||
}
|
||||
} else if (prop_name.compare("inputs:diffuseColor.connect") == 0) {
|
||||
// Currently we assume texture is assigned to this attribute.
|
||||
@@ -5458,11 +5432,6 @@ bool Parser::ReconstructPreviewSurface(
|
||||
// if (auto p = primvar::as_basic<Vec3f>(&attr.var)) {
|
||||
// shader->emissiveColor.color = (*p);
|
||||
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
// std::cout << "emissiveColor: " << shader->emissiveColor.color[0]
|
||||
// << ", " << shader->emissiveColor.color[1] << ", "
|
||||
// << shader->emissiveColor.color[2] << "\n";
|
||||
#endif
|
||||
//}
|
||||
} else if (prop_name.compare("inputs:emissiveColor.connect") == 0) {
|
||||
// Currently we assume texture is assigned to this attribute.
|
||||
@@ -5477,6 +5446,178 @@ bool Parser::ReconstructPreviewSurface(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ReconstructSkelRoot(
|
||||
const Node &node, const FieldValuePairVector &fields,
|
||||
const std::unordered_map<uint32_t, uint32_t> &path_index_to_spec_index_map,
|
||||
SkelRoot *skelRoot) {
|
||||
DCOUT("Parse skelRoot");
|
||||
(void)skelRoot;
|
||||
|
||||
for (const auto &fv : fields) {
|
||||
if (fv.first == "properties") {
|
||||
if (fv.second.GetTypeName() != "TokenArray") {
|
||||
_err += "`properties` attribute must be TokenArray type\n";
|
||||
return false;
|
||||
}
|
||||
assert(fv.second.IsArray());
|
||||
|
||||
for (size_t i = 0; i < fv.second.GetStringArray().size(); i++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < node.GetChildren().size(); i++) {
|
||||
int child_index = int(node.GetChildren()[i]);
|
||||
if ((child_index < 0) || (child_index >= int(_nodes.size()))) {
|
||||
_err += "Invalid child node id: " + std::to_string(child_index) +
|
||||
". Must be in range [0, " + std::to_string(_nodes.size()) + ")\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// const Node &child_node = _nodes[size_t(child_index)];
|
||||
|
||||
if (!path_index_to_spec_index_map.count(uint32_t(child_index))) {
|
||||
// No specifier assigned to this child node.
|
||||
_err += "No specifier found for node id: " + std::to_string(child_index) +
|
||||
"\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t spec_index =
|
||||
path_index_to_spec_index_map.at(uint32_t(child_index));
|
||||
if (spec_index >= _specs.size()) {
|
||||
_err += "Invalid specifier id: " + std::to_string(spec_index) +
|
||||
". Must be in range [0, " + std::to_string(_specs.size()) + ")\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const Spec &spec = _specs[spec_index];
|
||||
|
||||
Path path = GetPath(spec.path_index);
|
||||
DCOUT("Path prim part: " << path.GetPrimPart()
|
||||
<< ", prop part: " << path.GetPropPart()
|
||||
<< ", spec_index = " << spec_index);
|
||||
|
||||
if (!_live_fieldsets.count(spec.fieldset_index)) {
|
||||
_err += "FieldSet id: " + std::to_string(spec.fieldset_index.value) +
|
||||
" must exist in live fieldsets.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const FieldValuePairVector &child_fields =
|
||||
_live_fieldsets.at(spec.fieldset_index);
|
||||
|
||||
{
|
||||
std::string prop_name = path.GetPropPart();
|
||||
|
||||
PrimAttrib attr;
|
||||
|
||||
bool ret = ParseAttribute(child_fields, &attr, prop_name);
|
||||
DCOUT("prop:" << prop_name << ", ret = " << ret);
|
||||
|
||||
if (ret) {
|
||||
// Currently we only support predefined PBR attributes.
|
||||
|
||||
if (prop_name.compare("info:id") == 0) {
|
||||
auto p = attr.var.get_value<std::string>(); // `token` type, but treat it as string
|
||||
if (p) {
|
||||
//shader_type = (*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ReconstructSkeleton(
|
||||
const Node &node, const FieldValuePairVector &fields,
|
||||
const std::unordered_map<uint32_t, uint32_t> &path_index_to_spec_index_map,
|
||||
Skeleton *skeleton) {
|
||||
DCOUT("Parse skeleton");
|
||||
(void)skeleton;
|
||||
|
||||
for (const auto &fv : fields) {
|
||||
if (fv.first == "properties") {
|
||||
if (fv.second.GetTypeName() != "TokenArray") {
|
||||
PUSH_ERROR("`properties` attribute must be TokenArray type");
|
||||
return false;
|
||||
}
|
||||
assert(fv.second.IsArray());
|
||||
|
||||
for (size_t i = 0; i < fv.second.GetStringArray().size(); i++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < node.GetChildren().size(); i++) {
|
||||
int child_index = int(node.GetChildren()[i]);
|
||||
if ((child_index < 0) || (child_index >= int(_nodes.size()))) {
|
||||
_err += "Invalid child node id: " + std::to_string(child_index) +
|
||||
". Must be in range [0, " + std::to_string(_nodes.size()) + ")\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// const Node &child_node = _nodes[size_t(child_index)];
|
||||
|
||||
if (!path_index_to_spec_index_map.count(uint32_t(child_index))) {
|
||||
// No specifier assigned to this child node.
|
||||
_err += "No specifier found for node id: " + std::to_string(child_index) +
|
||||
"\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t spec_index =
|
||||
path_index_to_spec_index_map.at(uint32_t(child_index));
|
||||
if (spec_index >= _specs.size()) {
|
||||
_err += "Invalid specifier id: " + std::to_string(spec_index) +
|
||||
". Must be in range [0, " + std::to_string(_specs.size()) + ")\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const Spec &spec = _specs[spec_index];
|
||||
|
||||
Path path = GetPath(spec.path_index);
|
||||
DCOUT("Path prim part: " << path.GetPrimPart()
|
||||
<< ", prop part: " << path.GetPropPart()
|
||||
<< ", spec_index = " << spec_index);
|
||||
|
||||
if (!_live_fieldsets.count(spec.fieldset_index)) {
|
||||
_err += "FieldSet id: " + std::to_string(spec.fieldset_index.value) +
|
||||
" must exist in live fieldsets.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const FieldValuePairVector &child_fields =
|
||||
_live_fieldsets.at(spec.fieldset_index);
|
||||
|
||||
{
|
||||
std::string prop_name = path.GetPropPart();
|
||||
|
||||
PrimAttrib attr;
|
||||
|
||||
bool ret = ParseAttribute(child_fields, &attr, prop_name);
|
||||
DCOUT("prop:" << prop_name << ", ret = " << ret);
|
||||
|
||||
if (ret) {
|
||||
// Currently we only support predefined PBR attributes.
|
||||
|
||||
if (prop_name.compare("info:id") == 0) {
|
||||
auto p = attr.var.get_value<std::string>(); // `token` type, but treat it as string
|
||||
if (p) {
|
||||
//shader_type = (*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ReconstructSceneRecursively(
|
||||
int parent, int level,
|
||||
const std::unordered_map<uint32_t, uint32_t> &path_index_to_spec_index_map,
|
||||
@@ -5594,6 +5735,12 @@ bool Parser::ReconstructSceneRecursively(
|
||||
}
|
||||
|
||||
scene->primChildren = fv.second.GetTokenArray();
|
||||
} else if (fv.first == "documentation") { // 'doc'
|
||||
if (fv.second.GetTypeId() != VALUE_TYPE_STRING) {
|
||||
PUSH_ERROR("Type must be String for `documentation`, but got " + fv.second.GetTypeName() + "\n");
|
||||
return false;
|
||||
}
|
||||
scene->doc = fv.second.GetString();
|
||||
} else {
|
||||
PUSH_ERROR("TODO: " + fv.first + "\n");
|
||||
//_err += "TODO: " + fv.first + "\n";
|
||||
@@ -5758,11 +5905,35 @@ bool Parser::ReconstructSceneRecursively(
|
||||
|
||||
PUSH_WARN("TODO: Reconstruct dictionary value of `assetInfo`");
|
||||
//_nodes[size_t(parent)].SetAssetInfo(assetInfo);
|
||||
} else if (node_type == "Skeleton") {
|
||||
Skeleton skeleton;
|
||||
if (!ReconstructSkeleton(node, fields, path_index_to_spec_index_map,
|
||||
&skeleton)) {
|
||||
_err += "Failed to reconstruct Skeleton.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
skeleton.name = node.GetLocalPath(); // FIXME
|
||||
|
||||
scene->skeletons.push_back(skeleton);
|
||||
|
||||
} else if (node_type == "SkelRoot") {
|
||||
SkelRoot skelRoot;
|
||||
if (!ReconstructSkelRoot(node, fields, path_index_to_spec_index_map,
|
||||
&skelRoot)) {
|
||||
_err += "Failed to reconstruct SkelRoot.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
skelRoot.name = node.GetLocalPath(); // FIXME
|
||||
|
||||
scene->skel_roots.push_back(skelRoot);
|
||||
} else {
|
||||
#ifdef TINYUSDZ_LOCAL_DEBUG_PRINT
|
||||
std::cout << "TODO or we can ignore this node: node_type: " << node_type
|
||||
<< "\n";
|
||||
#endif
|
||||
PUSH_WARN("TODO: Reconstruct node_type " + node_type);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node.GetChildren().size(); i++) {
|
||||
|
||||
@@ -500,7 +500,7 @@ struct StringAndIdMap {
|
||||
enum NodeType {
|
||||
NODE_TYPE_NULL = 0,
|
||||
NODE_TYPE_XFORM,
|
||||
NODE_TYPE_GROUP,
|
||||
NODE_TYPE_SCOPE,
|
||||
NODE_TYPE_SPHERE,
|
||||
NODE_TYPE_GEOM_MESH,
|
||||
NODE_TYPE_GEOM_BASISCURVES,
|
||||
@@ -541,6 +541,7 @@ struct Scene {
|
||||
std::string defaultPrim; // prim node name
|
||||
double metersPerUnit = 1.0; // default [m]
|
||||
double timeCodesPerSecond = 24.0; // default 24 fps
|
||||
std::string doc; // `documentation`
|
||||
std::vector<std::string> primChildren; // TODO: Move to nodes[0].primChildren?
|
||||
|
||||
// Currently `string` type value only.
|
||||
@@ -559,8 +560,10 @@ struct Scene {
|
||||
std::vector<GeomPoints> geom_points;
|
||||
std::vector<Material> materials;
|
||||
std::vector<Shader> shaders; // TODO(syoyo): Support othre shaders
|
||||
std::vector<Group> groups;
|
||||
std::vector<Scope> scopes; // TODO(syoyo): We may not need this?
|
||||
std::vector<Volume> volumes;
|
||||
std::vector<SkelRoot> skel_roots;
|
||||
std::vector<Skeleton> skeletons;
|
||||
|
||||
StringAndIdMap geom_meshes_map; // Path <-> array index map
|
||||
StringAndIdMap materials_map; // Path <-> array index map
|
||||
|
||||
Reference in New Issue
Block a user