Refactoring parsing TimeSample(W.I.P.)

This commit is contained in:
Syoyo Fujita
2022-07-21 04:49:42 +09:00
parent 7495c05d2a
commit 606ebb267b
5 changed files with 126 additions and 77 deletions

View File

@@ -57,15 +57,14 @@
#endif
#include "io-util.hh"
#include "math-util.inc"
//#include "math-util.inc"
#include "pprinter.hh"
#include "prim-types.hh"
#include "str-util.hh"
//#include "simple-type-reflection.hh"
#include "primvar.hh"
//#include "primvar.hh"
#include "stream-reader.hh"
#include "tinyusdz.hh"
#include "usdObj.hh"
#include "value-pprint.hh"
#include "value-type.hh"
@@ -2187,7 +2186,7 @@ bool AsciiParser::ReadBasicType(nonstd::optional<double> *value) {
// -- end basic
bool AsciiParser::ParseDictElement(std::string *out_key,
PrimVariable *out_var) {
MetaVariable *out_var) {
(void)out_key;
(void)out_var;
@@ -2267,7 +2266,7 @@ bool AsciiParser::ParseDictElement(std::string *out_key,
// Supports limited types for customData/Dictionary.
// TODO: array_qual
//
PrimVariable var;
MetaVariable var;
if (type_name == value::kBool) {
bool val;
if (!ReadBasicType(&val)) {
@@ -2306,7 +2305,7 @@ bool AsciiParser::ParseDictElement(std::string *out_key,
var.value = tok;
}
} else if (type_name == "dictionary") {
std::map<std::string, PrimVariable> dict;
std::map<std::string, MetaVariable> dict;
if (!ParseDict(&dict)) {
PUSH_ERROR_AND_RETURN("Failed to parse `dictionary`");
@@ -2343,7 +2342,7 @@ bool AsciiParser::MaybeCustom() {
return false;
}
bool AsciiParser::ParseDict(std::map<std::string, PrimVariable> *out_dict) {
bool AsciiParser::ParseDict(std::map<std::string, MetaVariable> *out_dict) {
// '{' (type name '=' value)+ '}'
if (!Expect('{')) {
return false;
@@ -2367,7 +2366,7 @@ bool AsciiParser::ParseDict(std::map<std::string, PrimVariable> *out_dict) {
}
std::string key;
PrimVariable var;
MetaVariable var;
if (!ParseDictElement(&key, &var)) {
PUSH_ERROR_AND_RETURN("Failed to parse dict element.");
}
@@ -2725,7 +2724,7 @@ bool AsciiParser::ParseStageMetaOpt() {
}
VariableDef &vardef = _supported_stage_metas.at(varname);
PrimVariable var;
MetaVariable var;
if (!ParseMetaValue(vardef.type, vardef.name, &var)) {
PushError("Failed to parse meta value.\n");
return false;
@@ -3234,8 +3233,31 @@ bool AsciiParser::Expect(char expect_c) {
//
// -- impl ParseTimeSampleData
//
template<>
bool AsciiParser::ParseTimeSampleData(
value::TimeSamples AsciiParser::ConvertToTimeSamples(
const TimeSampleData<float> &ts) {
value::TimeSamples dst;
for (const auto &item : ts) {
dst.times.push_back(std::get<0>(item));
if (item.second) {
dst.values.push_back(item.second.value());
} else {
// Blocked.
dst.values.push_back(value::Block());
}
}
return dst;
}
#if 0
template<>
bool AsciiParser::ParseTimeSamples(
nonstd::optional<value::float2> *out_value) {
nonstd::optional<std::array<float, 2>> value;
if (!ParseBasicTypeTuple(&value)) {
@@ -3444,6 +3466,7 @@ bool AsciiParser::ParseTimeSampleData(
return true;
}
#endif
// Parse magic
// #usda FLOAT
@@ -3656,8 +3679,8 @@ bool AsciiParser::ParseReference(Reference *out, bool *triple_deliminated) {
bool AsciiParser::ParseMetaValue(const std::string &vartype,
const std::string &varname,
PrimVariable *outvar) {
PrimVariable var;
MetaVariable *outvar) {
MetaVariable var;
// TODO: Refactor.
if (vartype == value::kBool) {
@@ -3995,7 +4018,7 @@ nonstd::optional<AsciiParser::VariableDef> AsciiParser::GetStageMetaDefinition(
return nonstd::nullopt;
}
bool AsciiParser::ParseStageMeta(std::tuple<ListEditQual, PrimVariable> *out) {
bool AsciiParser::ParseStageMeta(std::tuple<ListEditQual, MetaVariable> *out) {
if (!SkipCommentAndWhitespaceAndNewline()) {
return false;
}
@@ -4044,7 +4067,7 @@ bool AsciiParser::ParseStageMeta(std::tuple<ListEditQual, PrimVariable> *out) {
auto vardef = (*pvardef);
PrimVariable var;
MetaVariable var;
var.name = varname;
if (vardef.type == "path") {
@@ -4066,10 +4089,10 @@ bool AsciiParser::ParseStageMeta(std::tuple<ListEditQual, PrimVariable> *out) {
}
// std::vector<Path> paths;
// PrimVariable::Array arr;
// MetaVariable::Array arr;
// for (const auto &v : value) {
// std::cout << " " << v << "\n";
// PrimVariable _var;
// MetaVariable _var;
// _var.value = v;
// arr.values.push_back(_var);
// }
@@ -4126,7 +4149,7 @@ bool AsciiParser::ParseStageMeta(std::tuple<ListEditQual, PrimVariable> *out) {
return true;
}
nonstd::optional<std::tuple<ListEditQual, PrimVariable>>
nonstd::optional<std::tuple<ListEditQual, MetaVariable>>
AsciiParser::ParsePrimMeta() {
if (!SkipCommentAndWhitespaceAndNewline()) {
@@ -4164,7 +4187,7 @@ AsciiParser::ParsePrimMeta() {
SkipWhitespace();
VariableDef &vardef = _supported_prim_metas.at(varname);
PrimVariable var;
MetaVariable var;
if (!ParseMetaValue(vardef.type, vardef.name, &var)) {
PushError("Failed to parse Prim meta value.\n");
return nonstd::nullopt;
@@ -4174,7 +4197,7 @@ AsciiParser::ParsePrimMeta() {
}
bool AsciiParser::ParsePrimMetas(
std::map<std::string, std::tuple<ListEditQual, PrimVariable>> *args) {
std::map<std::string, std::tuple<ListEditQual, MetaVariable>> *args) {
// '(' args ')'
// args = list of argument, separated by newline.
@@ -4230,7 +4253,7 @@ bool AsciiParser::ParsePrimMetas(
DCOUT("Start PrimMeta parse.");
// ty = std::tuple<ListEditQual, PrimVariable>;
// ty = std::tuple<ListEditQual, MetaVariable>;
if (auto m = ParsePrimMeta()) {
DCOUT("arg: list-edit qual = " << tinyusdz::to_string(std::get<0>(m.value()))
<< ", name = " << std::get<1>(m.value()).name);
@@ -4331,7 +4354,7 @@ bool AsciiParser::ParseAttrMeta(AttrMeta *out_meta) {
out_meta->elementSize = value;
} else if (token == "customData") {
std::map<std::string, PrimVariable> dict;
std::map<std::string, MetaVariable> dict;
if (!ParseDict(&dict)) {
return false;
@@ -4452,7 +4475,7 @@ bool AsciiParser::ParseBasicPrimAttr(bool array_qual,
attr.meta = meta;
// if (meta.count("interpolation")) {
// const PrimVariable &var = meta.at("interpolation");
// const MetaVariable &var = meta.at("interpolation");
// auto p = var.value.get_value<value::token>();
// if (p) {
// attr.interpolation =
@@ -4465,7 +4488,7 @@ bool AsciiParser::ParseBasicPrimAttr(bool array_qual,
return true;
}
// bool ParsePrimAttr(std::map<std::string, PrimVariable> *props) {
// bool ParsePrimAttr(std::map<std::string, MetaVariable> *props) {
bool AsciiParser::ParsePrimAttr(std::map<std::string, Property> *props) {
// prim_attr : (custom?) uniform type (array_qual?) name '=' value
// | (custom?) type (array_qual?) name '=' value interpolation?
@@ -4596,25 +4619,28 @@ bool AsciiParser::ParsePrimAttr(std::map<std::string, Property> *props) {
// TODO(syoyo): Refactror and implement value parser dispatcher.
//
if (isTimeSample) {
#if 0 // TODO
if (type_name == "float") {
TimeSampledDataFloat values;
if (!ParseTimeSamples(&values)) {
return false;
if (auto pv = TryParseTimeSamples<float>()) {
value::TimeSamples ts = ConvertToTimeSamples<float>(pv.value());
PUSH_ERROR_AND_RETURN("TODO");
}
PrimVariable var;
var.timeSampledValue = values;
std::cout << "timeSample float:" << primattr_name << " = " << to_string(values) << "\n";
(*props)[primattr_name] = var;
// TODO: Implement
//Property prop;
//prop.attrib.timeSampledValue = values;
//std::cout << "timeSample float:" << primattr_name << " = " << to_string(values) << "\n";
//(*props)[primattr_name] = var;
#if 0 // TODO
} else if (type_name == "double") {
TimeSampledDataDouble values;
if (!ParseTimeSamples(&values)) {
return false;
}
PrimVariable var;
MetaVariable var;
var.timeSampledValue = values;
(*props)[primattr_name] = var;
@@ -4624,7 +4650,7 @@ bool AsciiParser::ParsePrimAttr(std::map<std::string, Property> *props) {
return false;
}
PrimVariable var;
MetaVariable var;
var.timeSampledValue = values;
(*props)[primattr_name] = var;
} else if (type_name == "double3") {
@@ -4633,7 +4659,7 @@ bool AsciiParser::ParsePrimAttr(std::map<std::string, Property> *props) {
return false;
}
PrimVariable var;
MetaVariable var;
var.timeSampledValue = values;
(*props)[primattr_name] = var;
} else if (type_name == "matrix4d") {
@@ -4642,7 +4668,7 @@ bool AsciiParser::ParsePrimAttr(std::map<std::string, Property> *props) {
return false;
}
PrimVariable var;
MetaVariable var;
var.timeSampledValue = values;
(*props)[primattr_name] = var;
@@ -4650,6 +4676,10 @@ bool AsciiParser::ParsePrimAttr(std::map<std::string, Property> *props) {
PushError(std::to_string(__LINE__) + " : TODO: timeSamples type " + type_name);
return false;
}
#else
} else {
PUSH_ERROR_AND_RETURN(" : TODO: timeSamples type " + type_name);
}
#endif
PUSH_ERROR_AND_RETURN("TODO: timeSamples type " + type_name);
@@ -4924,7 +4954,7 @@ bool AsciiParser::ParseClassBlock() {
return false;
}
std::map<std::string, std::tuple<ListEditQual, PrimVariable>> metas;
std::map<std::string, std::tuple<ListEditQual, MetaVariable>> metas;
if (!ParsePrimMetas(&metas)) {
return false;
}
@@ -5035,7 +5065,7 @@ bool AsciiParser::ParseOverBlock() {
return false;
}
std::map<std::string, std::tuple<ListEditQual, PrimVariable>> metas;
std::map<std::string, std::tuple<ListEditQual, MetaVariable>> metas;
if (!ParsePrimMetas(&metas)) {
return false;
}
@@ -5149,7 +5179,7 @@ bool AsciiParser::ParseDefBlock(uint32_t nestlevel) {
return false;
}
std::map<std::string, std::tuple<ListEditQual, PrimVariable>> metas;
std::map<std::string, std::tuple<ListEditQual, MetaVariable>> metas;
{
// look ahead
char c;

View File

@@ -247,8 +247,8 @@ class AsciiParser {
template <typename T, size_t N>
bool SepBy1TupleType(const char sep, std::vector<std::array<T, N>> *result);
bool ParseDictElement(std::string *out_key, PrimVariable *out_var);
bool ParseDict(std::map<std::string, PrimVariable> *out_dict);
bool ParseDictElement(std::string *out_key, MetaVariable *out_var);
bool ParseDict(std::map<std::string, MetaVariable> *out_dict);
bool MaybeListEditQual(tinyusdz::ListEditQual *qual);
@@ -324,10 +324,10 @@ class AsciiParser {
bool ParseAttrMeta(AttrMeta *out_meta);
bool ParsePrimMetas(
std::map<std::string, std::tuple<ListEditQual, PrimVariable>> *args);
std::map<std::string, std::tuple<ListEditQual, MetaVariable>> *args);
bool ParseMetaValue(const std::string &vartype, const std::string &varname,
PrimVariable *outvar);
MetaVariable *outvar);
bool ParseStageMetaOpt();
// Parsed Stage metadatum is stored in this instance.
@@ -387,26 +387,37 @@ class AsciiParser {
///
void Setup();
//template<typename T>
//bool ParseTimeSampleData(nonstd::optional<T> *out_value);
template<typename T>
bool ParseTimeSampleData(nonstd::optional<T> *out_value);
using TimeSampleData = std::vector<std::pair<double, nonstd::optional<T>>>;
///
/// Convert TimeSampleData<T> to TimeSamples(type-erased TimeSample Sdata struct)
///
template<typename T>
value::TimeSamples ConvertToTimeSamples(
const TimeSampleData<T> &in);
template <typename T>
bool ParseTimeSamples(
std::vector<std::pair<uint64_t, nonstd::optional<T>>> *out_samples) {
nonstd::optional<TimeSampleData<T>> TryParseTimeSamples() {
// timeSamples = '{' (int : T), + '}'
TimeSampleData<T> data;
if (!Expect('{')) {
return false;
return nonstd::nullopt;
}
if (!SkipWhitespaceAndNewline()) {
return false;
return nonstd::nullopt;
}
while (!Eof()) {
char c;
if (!Char1(&c)) {
return false;
return nonstd::nullopt;
}
if (c == '}') {
@@ -415,46 +426,47 @@ class AsciiParser {
Rewind(1);
uint64_t timeVal;
double timeVal;
// -inf, inf and nan are handled.
if (!ReadBasicType(&timeVal)) {
PushError("Parse time value failed.");
return false;
return nonstd::nullopt;
}
if (!SkipWhitespace()) {
return false;
return nonstd::nullopt;
}
if (!Expect(':')) {
return false;
return nonstd::nullopt;
}
if (!SkipWhitespace()) {
return false;
return nonstd::nullopt;
}
nonstd::optional<T> value;
if (!ParseTimeSampleData(&value)) {
return false;
if (!ReadBasicType(&value)) {
return nonstd::nullopt;
}
// It looks the last item also requires ','
if (!Expect(',')) {
return false;
return nonstd::nullopt;
}
if (!SkipWhitespaceAndNewline()) {
return false;
return nonstd::nullopt;
}
out_samples->push_back({timeVal, value});
data.push_back({timeVal, value});
}
return true;
return data;
}
nonstd::optional<std::tuple<ListEditQual, PrimVariable>> ParsePrimMeta();
nonstd::optional<std::tuple<ListEditQual, MetaVariable>> ParsePrimMeta();
bool ParsePrimAttr(std::map<std::string, Property> *props);
template <typename T>
@@ -463,7 +475,7 @@ class AsciiParser {
PrimAttrib *out_attr);
bool ParseStageMeta(std::tuple<ListEditQual, PrimVariable> *out);
bool ParseStageMeta(std::tuple<ListEditQual, MetaVariable> *out);
nonstd::optional<VariableDef> GetStageMetaDefinition(const std::string &name);
std::string GetCurrentPath();

View File

@@ -555,23 +555,23 @@ struct Rel {
std::string path;
};
// Variable class for GPrim Metadataum.
// TODO: Rename to MetaVariable
class PrimVariable {
// Variable class for GPrim and Attribute Metadataum.
// TODO: Rename to MetaVariable?
class MetaVariable {
public:
std::string type; // Explicit name of type
std::string name;
bool custom{false};
// using Array = std::vector<Variable>;
using Object = std::map<std::string, PrimVariable>;
using Object = std::map<std::string, MetaVariable>;
value::Value value;
// Array arr_value;
Object obj_value;
value::TimeSamples timeSamples;
PrimVariable &operator=(const PrimVariable &rhs) {
MetaVariable &operator=(const MetaVariable &rhs) {
type = rhs.type;
name = rhs.name;
custom = rhs.custom;
@@ -582,7 +582,7 @@ class PrimVariable {
return *this;
}
PrimVariable(const PrimVariable &rhs) {
MetaVariable(const MetaVariable &rhs) {
type = rhs.type;
name = rhs.name;
custom = rhs.custom;
@@ -590,7 +590,7 @@ class PrimVariable {
obj_value = rhs.obj_value;
}
static std::string type_name(const PrimVariable &v) {
static std::string type_name(const MetaVariable &v) {
if (!v.type.empty()) {
return v.type;
}
@@ -659,12 +659,12 @@ class PrimVariable {
bool valid() const { return !IsEmpty(); }
PrimVariable() = default;
MetaVariable() = default;
// Variable(std::string ty, std::string n) : type(ty), name(n) {}
// Variable(std::string ty) : type(ty) {}
// friend std::ostream &operator<<(std::ostream &os, const Object &obj);
// friend std::ostream &operator<<(std::ostream &os, const PrimVariable &var);
// friend std::ostream &operator<<(std::ostream &os, const MetaVariable &var);
// friend std::string str_object(const Object &obj, int indent = 0); // string
// representation of Object.
@@ -673,10 +673,10 @@ class PrimVariable {
// Meta for Stage and GPrim
struct GPrimMeta {
nonstd::optional<Interpolation> interpolation; // 'interpolation'
nonstd::optional<std::map<std::string, PrimVariable>>
nonstd::optional<std::map<std::string, MetaVariable>>
customData; // `customData`
std::map<std::string, PrimVariable> meta; // other meta values
std::map<std::string, MetaVariable> meta; // other meta values
};
struct AttrMeta {
@@ -684,10 +684,10 @@ struct AttrMeta {
// nullopt = not specified in USD scene
nonstd::optional<Interpolation> interpolation; // 'interpolation'
nonstd::optional<uint32_t> elementSize; // usdSkel 'elementSize'
nonstd::optional<std::map<std::string, PrimVariable>>
nonstd::optional<std::map<std::string, MetaVariable>>
customData; // `customData`
std::map<std::string, PrimVariable> meta; // other meta values
std::map<std::string, MetaVariable> meta; // other meta values
};
// PrimAttrib is a struct to hold attribute of a property(e.g. primvar)

View File

@@ -47,7 +47,7 @@ namespace tinyusdz {
namespace primvar {
struct PrimVar {
// For scalar value, times.size() == 0, and values.size() == 1
// For scalar(default) value, times.size() == 0, and values.size() == 1
value::TimeSamples var;
bool is_scalar() const {

View File

@@ -168,6 +168,7 @@ enum TypeId {
TYPE_ID_NULL,
TYPE_ID_VOID,
TYPE_ID_MONOSTATE,
TYPE_ID_BLOCK, // None as type
TYPE_ID_TOKEN,
TYPE_ID_STRING,
@@ -615,6 +616,10 @@ struct texcoord3d {
double s, t, r;
};
// Attribute Block(None)
struct Block {
};
using double2 = std::array<double, 2>;
using double3 = std::array<double, 3>;
using double4 = std::array<double, 4>;
@@ -658,6 +663,7 @@ struct TypeTrait;
DEFINE_TYPE_TRAIT(std::nullptr_t, "null", TYPE_ID_NULL, 1);
DEFINE_TYPE_TRAIT(void, "void", TYPE_ID_VOID, 1);
DEFINE_TYPE_TRAIT(Block, "none", TYPE_ID_BLOCK, 1);
DEFINE_TYPE_TRAIT(bool, kBool, TYPE_ID_BOOL, 1);
DEFINE_TYPE_TRAIT(uint8_t, kUChar, TYPE_ID_UCHAR, 1);
@@ -912,12 +918,13 @@ struct any_value {
return *(reinterpret_cast<const std::vector<T> *>(p->value()));
}
std::shared_ptr<base_value> p;
std::shared_ptr<base_value> p; // TODO: Use raw pointer?
};
// Handy, but not efficient for large time samples(e.g. 1000 or more)
struct TimeSamples {
std::vector<double> times;
std::vector<any_value> values; // Could contain 'None'
std::vector<any_value> values; // Could be an array of 'None' or Type T
bool Valid() {
if (times.size() > 0) {