From ddf69ce4ab28558d5b8af2b7ab20bdee310ef947 Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Fri, 13 Nov 2020 22:24:29 +0900 Subject: [PATCH] Add type-erased helper class PrimValue. --- CMakeLists.txt | 1 + README.md | 1 + doc/TODO.md | 24 +++++++ doc/usdc_format.md | 14 ++++ src/tinyusdz.hh | 162 +++++++++++++++++++++++++++++++++++++++------ src/usda-writer.cc | 39 +++++++++++ src/usda-writer.hh | 12 ++++ 7 files changed, 233 insertions(+), 20 deletions(-) create mode 100644 doc/TODO.md create mode 100644 src/usda-writer.cc create mode 100644 src/usda-writer.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index d8863b93..e5c9bade 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ endif() set(TINYUSDZ_SOURCES ${PROJECT_SOURCE_DIR}/src/tinyusdz.cc + ${PROJECT_SOURCE_DIR}/src/usda-writer.cc ) set(TINYUSDZ_DEP_SOURCES diff --git a/README.md b/README.md index 7d8669f8..56092495 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ See [prim_format.md](doc/prim_format.md) and [preview_surface.md](doc/preview_su ## TODO +* [ ] Support Crate(binary) version 0.8.0(USD v20.11 default) * [ ] Write parser based on the schema definition. * [ ] Subdivision surface using OpenSubdiv. * [ ] Replace OpenSubdiv with our own subdiv library or embree3's one. diff --git a/doc/TODO.md b/doc/TODO.md new file mode 100644 index 00000000..baa493ef --- /dev/null +++ b/doc/TODO.md @@ -0,0 +1,24 @@ +# USDC parser + +Base implementation in TinyUSDZ: v0.7.0 + +* [ ] v0.8.0 support + * [ ] PayloadListOp/Payload + layer offsets + * [ ] LayerOffset +* [ ] v0.9.0 support + * [ ] TimeCode, TimeCode[] + +# USDA parser + +* [ ] USDA parser + +# USDC writer + +* [ ] USDC writer + +# USDA writer + +* [ ] USDA writer + + +EoL. diff --git a/doc/usdc_format.md b/doc/usdc_format.md index 669d3db1..646e65b7 100644 --- a/doc/usdc_format.md +++ b/doc/usdc_format.md @@ -7,6 +7,20 @@ => total 88 bytes +## Version + +From pxr/usd/usd/crateFile.cpp + +``` +// Version history: +// 0.9.0: Added support for the timecode and timecode[] value types. +// 0.8.0: Added support for SdfPayloadListOp values and SdfPayload values with +// layer offsets. +// 0.7.0: Array sizes written as 64 bit ints. +``` + +* 0.8.0(USD v20.11) + ## Compression version 0.4.0 or later uses LZ4 for compression and interger compression(pxr original? compression. its backend still uses LZ4) for index arrays. diff --git a/src/tinyusdz.hh b/src/tinyusdz.hh index 8dc10bec..a694731d 100644 --- a/src/tinyusdz.hh +++ b/src/tinyusdz.hh @@ -44,6 +44,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace tinyusdz { +constexpr int version_major = 0; +constexpr int version_minor = 7; +constexpr int version_micro = 0; + // Simple image class. // No colorspace conversion will be applied when decoding image data(e.g. from // .jpg, .png). @@ -433,6 +437,30 @@ class Path { bool valid{false}; }; +class TimeCode { + TimeCode(double tm = 0.0) : _time(tm) {} + + size_t hash() const { return std::hash{}(_time); } + + double value() const { return _time; } + + private: + double _time; +}; + +class LayerOffset { + private: + double _offset; + double _scale; +}; + +class Payload { + private: + std::string _asset_path; + Path _prim_path; + LayerOffset _layer_offset; +}; + enum ValueTypeId { VALUE_TYPE_INVALID = 0, @@ -585,6 +613,99 @@ struct TimeSamples { std::vector values; }; +/// +/// Simple type-erased primitive value class for frequently used data types(e.g. `float[]`) +/// +template +struct TypeTrait; + +// TODO(syoyo): Support `Token` type +template <> +struct TypeTrait { + static constexpr auto type_name = "string"; + static constexpr ValueTypeId type_id = VALUE_TYPE_STRING; +}; + +template <> +struct TypeTrait { + static constexpr auto type_name = "int"; + static constexpr ValueTypeId type_id = VALUE_TYPE_INT; +}; + +template <> +struct TypeTrait { + static constexpr auto type_name = "half"; + static constexpr ValueTypeId type_id = VALUE_TYPE_HALF; +}; + +template <> +struct TypeTrait { + static constexpr auto type_name = "vec2f"; + static constexpr ValueTypeId type_id = VALUE_TYPE_VEC2F; +}; + +template <> +struct TypeTrait { + static constexpr auto type_name = "vec3f"; + static constexpr ValueTypeId type_id = VALUE_TYPE_VEC3F; +}; + +template <> +struct TypeTrait { + static constexpr auto type_name = "vec4f"; + static constexpr ValueTypeId type_id = VALUE_TYPE_VEC3F; +}; + +template <> +struct TypeTrait { + static constexpr auto type_name = "matrix4d"; + static constexpr ValueTypeId type_id = VALUE_TYPE_MATRIX4D; +}; + +template +class PrimValue { + private: + T m_value; + + public: + T value() const { return m_value; } + + template ::value>::type + * = nullptr> + PrimValue &operator=(const U &u) { + m_value = u; + + return (*this); + } + + std::string type_name() { return std::string(TypeTrait::type_name); } + bool is_array() const { return false; } +}; + +/// +/// array of PrimmValue +/// multi-dimensional type is not supported(e.g. float[][]) +/// +template +class PrimValue> { + private: + std::vector m_value; + + template ::value>::type + * = nullptr> + PrimValue &operator=(const std::vector &u) { + m_value = u; + + return (*this); + } + + std::string type_name() { + return std::string(TypeTrait::type_name) + "[]"; + } + + bool is_array() const { return true; } +}; + /// /// Represent value. /// multi-dimensional type is not supported(e.g. float[][]) @@ -1519,8 +1640,7 @@ struct BlendShape { // values in `offsets` and `normalOffsets`. }; -struct SkelRoot -{ +struct SkelRoot { Extent extent; Purpose purpose{PurposeDefault}; Visibility visibility{VisibilityInherited}; @@ -1531,15 +1651,16 @@ struct SkelRoot }; // Skelton -struct Skelton -{ - std::vector bindTransforms; // bind-pose transform of each joint in world coordinate. +struct Skelton { + std::vector + bindTransforms; // bind-pose transform of each joint in world coordinate. Extent extent; std::vector jointNames; std::vector joints; - std::vector restTransforms; // rest-pose transforms of each joint in local coordinate. + std::vector restTransforms; // rest-pose transforms of each joint + // in local coordinate. Purpose purpose{PurposeDefault}; Visibility visibility{VisibilityInherited}; @@ -1549,28 +1670,29 @@ struct Skelton // ref proxyPrim }; -struct SkelAnimation -{ +struct SkelAnimation { std::vector blendShapes; std::vector blendShapeWeights; std::vector joints; - std::vector rotations; // Joint-local unit quaternion rotations - std::vector scales; // Joint-local scaling. pxr USD schema uses half3, but we use float3 for convenience. - std::vector translations; // Joint-local translation. - + std::vector rotations; // Joint-local unit quaternion rotations + std::vector scales; // Joint-local scaling. pxr USD schema uses half3, + // but we use float3 for convenience. + std::vector translations; // Joint-local translation. }; // W.I.P. struct SkelBindingAPI { - Matrix4d geomBindTransform; // primvars:skel:geomBindTransform - std::vector jointIndices; // primvars:skel:jointIndices - std::vector jointWeights; // primvars:skel:jointWeights - std::vector blendShapes; // optional? - std::vector joints; // optional + Matrix4d geomBindTransform; // primvars:skel:geomBindTransform + std::vector jointIndices; // primvars:skel:jointIndices + std::vector jointWeights; // primvars:skel:jointWeights + std::vector blendShapes; // optional? + std::vector joints; // optional - int64_t animationSource{-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 animationSource{ + -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 }; // Polygon mesh geometry diff --git a/src/usda-writer.cc b/src/usda-writer.cc new file mode 100644 index 00000000..0549b5fc --- /dev/null +++ b/src/usda-writer.cc @@ -0,0 +1,39 @@ +#include "usda-writer.hh" + +#include + +namespace tinyusdz { + +namespace { + +// TODO + +bool WriteNode(std::ostream &ofs, const Node &node, int indent) { + return false; +} + + +} + +bool SaveAsUSDA(const std::string &filename, const Scene &scene, std::string *warn, std::string *err) { + std::stringstream ss; + + ss << "#usda 1.0\n"; + ss << "(\n"; + ss << " doc = \"TinyUSDZ v" << tinyusdz::version_major << "." << tinyusdz::version_minor << "." << tinyusdz::version_micro << "\"\n"; + ss << " metersPerUnit = 1\n"; + ss << " upAxis = \"Z\"\n"; + ss << ")\n"; + + // TODO + + for (const auto &node : scene.nodes) { + if (!WriteNode(ss, node, 0)) { + return false; + } + } + + return false; +} + +} // namespace tinyusdz diff --git a/src/usda-writer.hh b/src/usda-writer.hh new file mode 100644 index 00000000..67450997 --- /dev/null +++ b/src/usda-writer.hh @@ -0,0 +1,12 @@ +#pragma once + +#include "tinyusdz.hh" + +namespace tinyusdz { + +/// +/// Save scene as USDA(ASCII) +/// +bool SaveAsUSDA(const std::string &filename, const Scene &scene, std::string *warn, std::string *err); + +} // namespace tinyusdz