Skip to content

Commit

Permalink
Merge pull request #199 from rdeioris/xformOpsTimeSamples
Browse files Browse the repository at this point in the history
Added support for timesamples in xformOps
  • Loading branch information
syoyo authored Oct 28, 2024
2 parents 69b6e5a + e201c66 commit 2a30dd7
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 38 deletions.
16 changes: 14 additions & 2 deletions src/prim-types.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2980,16 +2980,28 @@ struct XformOp {
return get_scalar();
}

// Type-safe way to get concrete 'default' value.
template <class T>
nonstd::optional<T> get_value() const {
nonstd::optional<T> get_value(double t = value::TimeCode::Default(),
value::TimeSampleInterpolationType interp =
value::TimeSampleInterpolationType::Linear) const {
if (is_timesamples()) {
T value;
if (get_interpolated_value(&value, t, interp)) {
return value;
}
return nonstd::nullopt;
}

return _var.get_value<T>();
}

template <class T>
bool get_interpolated_value(T *dst, double t = value::TimeCode::Default(),
value::TimeSampleInterpolationType interp =
value::TimeSampleInterpolationType::Linear) const {
return _var.get_interpolated_value<T>(t, interp, dst);
}

const primvar::PrimVar &get_var() const { return _var; }

primvar::PrimVar &var() { return _var; }
Expand Down
57 changes: 24 additions & 33 deletions src/xform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -631,17 +631,17 @@ bool Xformable::EvaluateXformOps(double t,
bool *resetXformStack,
std::string *err) const {
const auto RotateABC =
[](const XformOp &x) -> nonstd::expected<value::matrix4d, std::string> {
[t, tinterp](const XformOp &x) -> nonstd::expected<value::matrix4d, std::string> {
value::double3 v;
if (auto h = x.get_value<value::half3>()) {
if (auto h = x.get_value<value::half3>(t, tinterp)) {
v[0] = double(half_to_float(h.value()[0]));
v[1] = double(half_to_float(h.value()[1]));
v[2] = double(half_to_float(h.value()[2]));
} else if (auto f = x.get_value<value::float3>()) {
} else if (auto f = x.get_value<value::float3>(t, tinterp)) {
v[0] = double(f.value()[0]);
v[1] = double(f.value()[1]);
v[2] = double(f.value()[2]);
} else if (auto d = x.get_value<value::double3>()) {
} else if (auto d = x.get_value<value::double3>(t, tinterp)) {
v = d.value();
} else {
if (x.suffix.empty()) {
Expand Down Expand Up @@ -838,15 +838,6 @@ bool Xformable::EvaluateXformOps(double t,
value::matrix4d m; // local matrix
Identity(&m);

if (x.is_timesamples()) {
(void)t;
(void)tinterp;
if (err) {
(*err) += "TODO: xformOp property with timeSamples.\n";
}
return false;
}

switch (x.op_type) {
case XformOp::OpType::ResetXformStack: {
if (i != 0) {
Expand All @@ -865,14 +856,14 @@ bool Xformable::EvaluateXformOps(double t,
break;
}
case XformOp::OpType::Transform: {
if (auto sxf = x.get_value<value::matrix4f>()) {
if (auto sxf = x.get_value<value::matrix4f>(t, tinterp)) {
value::matrix4f mf = sxf.value();
for (size_t j = 0; j < 4; j++) {
for (size_t k = 0; k < 4; k++) {
m.m[j][k] = double(mf.m[j][k]);
}
}
} else if (auto sxd = x.get_value<value::matrix4d>()) {
} else if (auto sxd = x.get_value<value::matrix4d>(t, tinterp)) {
m = sxd.value();
} else {
if (err) {
Expand Down Expand Up @@ -911,15 +902,15 @@ bool Xformable::EvaluateXformOps(double t,
case XformOp::OpType::Scale: {
double sx, sy, sz;

if (auto sxh = x.get_value<value::half3>()) {
if (auto sxh = x.get_value<value::half3>(t, tinterp)) {
sx = double(half_to_float(sxh.value()[0]));
sy = double(half_to_float(sxh.value()[1]));
sz = double(half_to_float(sxh.value()[2]));
} else if (auto sxf = x.get_value<value::float3>()) {
} else if (auto sxf = x.get_value<value::float3>(t, tinterp)) {
sx = double(sxf.value()[0]);
sy = double(sxf.value()[1]);
sz = double(sxf.value()[2]);
} else if (auto sxd = x.get_value<value::double3>()) {
} else if (auto sxd = x.get_value<value::double3>(t, tinterp)) {
sx = sxd.value()[0];
sy = sxd.value()[1];
sz = sxd.value()[2];
Expand All @@ -945,15 +936,15 @@ bool Xformable::EvaluateXformOps(double t,
}
case XformOp::OpType::Translate: {
double tx, ty, tz;
if (auto txh = x.get_value<value::half3>()) {
if (auto txh = x.get_value<value::half3>(t, tinterp)) {
tx = double(half_to_float(txh.value()[0]));
ty = double(half_to_float(txh.value()[1]));
tz = double(half_to_float(txh.value()[2]));
} else if (auto txf = x.get_value<value::float3>()) {
} else if (auto txf = x.get_value<value::float3>(t, tinterp)) {
tx = double(txf.value()[0]);
ty = double(txf.value()[1]);
tz = double(txf.value()[2]);
} else if (auto txd = x.get_value<value::double3>()) {
} else if (auto txd = x.get_value<value::double3>(t, tinterp)) {
tx = txd.value()[0];
ty = txd.value()[1];
tz = txd.value()[2];
Expand All @@ -980,11 +971,11 @@ bool Xformable::EvaluateXformOps(double t,
// FIXME: Validate ROTATE_X, _Y, _Z implementation
case XformOp::OpType::RotateX: {
double angle; // in degrees
if (auto h = x.get_value<value::half>()) {
if (auto h = x.get_value<value::half>(t, tinterp)) {
angle = double(half_to_float(h.value()));
} else if (auto f = x.get_value<float>()) {
} else if (auto f = x.get_value<float>(t, tinterp)) {
angle = double(f.value());
} else if (auto d = x.get_value<double>()) {
} else if (auto d = x.get_value<double>(t, tinterp)) {
angle = d.value();
} else {
if (err) {
Expand Down Expand Up @@ -1020,11 +1011,11 @@ bool Xformable::EvaluateXformOps(double t,
}
case XformOp::OpType::RotateY: {
double angle; // in degrees
if (auto h = x.get_value<value::half>()) {
if (auto h = x.get_value<value::half>(t, tinterp)) {
angle = double(half_to_float(h.value()));
} else if (auto f = x.get_value<float>()) {
} else if (auto f = x.get_value<float>(t, tinterp)) {
angle = double(f.value());
} else if (auto d = x.get_value<double>()) {
} else if (auto d = x.get_value<double>(t, tinterp)) {
angle = d.value();
} else {
if (err) {
Expand Down Expand Up @@ -1060,11 +1051,11 @@ bool Xformable::EvaluateXformOps(double t,
}
case XformOp::OpType::RotateZ: {
double angle; // in degrees
if (auto h = x.get_value<value::half>()) {
if (auto h = x.get_value<value::half>(t, tinterp)) {
angle = double(half_to_float(h.value()));
} else if (auto f = x.get_value<float>()) {
} else if (auto f = x.get_value<float>(t, tinterp)) {
angle = double(f.value());
} else if (auto d = x.get_value<double>()) {
} else if (auto d = x.get_value<double>(t, tinterp)) {
angle = d.value();
} else {
if (err) {
Expand Down Expand Up @@ -1103,11 +1094,11 @@ bool Xformable::EvaluateXformOps(double t,
// linalg::quat also stores elements in (x, y, z, w)

value::matrix3d rm;
if (auto h = x.get_value<value::quath>()) {
if (auto h = x.get_value<value::quath>(t, tinterp)) {
rm = to_matrix3x3(h.value());
} else if (auto f = x.get_value<value::quatf>()) {
} else if (auto f = x.get_value<value::quatf>(t, tinterp)) {
rm = to_matrix3x3(f.value());
} else if (auto d = x.get_value<value::quatd>()) {
} else if (auto d = x.get_value<value::quatd>(t, tinterp)) {
rm = to_matrix3x3(d.value());
} else {
if (err) {
Expand Down
20 changes: 17 additions & 3 deletions src/xform.hh
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,17 @@ struct Xformable {
/// @param[out] resetTransformStack Is xformOpOrder contains !resetTransformStack!?
///
nonstd::expected<value::matrix4d, std::string> GetLocalMatrix(double t = value::TimeCode::Default(), value::TimeSampleInterpolationType tinterp = value::TimeSampleInterpolationType::Linear, bool *resetTransformStack = nullptr) const {
if (_dirty) {
if (_dirty || !value::TimeCode(t).is_default()) {
value::matrix4d m;
std::string err;
if (EvaluateXformOps(t, tinterp, &m, resetTransformStack, &err)) {
_matrix = m;
_dirty = false;
if (value::TimeCode(t).is_default()) {
_matrix = m;
_dirty = false;
}
else {
return m;
}
} else {
return nonstd::make_unexpected(err);
}
Expand All @@ -206,6 +211,15 @@ struct Xformable {

void set_dirty(bool onoff) { _dirty = onoff; }

bool has_timesamples() const {
for (size_t i = 0; i < xformOps.size(); i++) {
if (xformOps[i].has_timesamples()) {
return true;
}
}
return false;
}

// Return `token[]` representation of `xformOps`
std::vector<value::token> xformOpOrder() const;

Expand Down

0 comments on commit 2a30dd7

Please sign in to comment.