mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Reactor Animatable<T>.
Fix syntax of prim-meta-add-variantSets-000.usda
This commit is contained in:
@@ -212,11 +212,15 @@ std::string print_animatable(const Animatable<T> &v, const uint32_t indent = 0)
|
||||
std::stringstream ss;
|
||||
|
||||
if (v.is_timesamples()) {
|
||||
ss << print_typed_timesamples(v.ts, indent);
|
||||
ss << print_typed_timesamples(v.get_timesamples(), indent);
|
||||
} else if (v.is_blocked()) {
|
||||
ss << "None";
|
||||
} else if (v.is_scalar()) {
|
||||
ss << v.value;
|
||||
T a;
|
||||
if (!v.get(&a)) {
|
||||
return "[Animatable: InternalError]";
|
||||
}
|
||||
ss << a;
|
||||
} else {
|
||||
return "[FIXME: Invalid Animatable]";
|
||||
}
|
||||
@@ -229,11 +233,15 @@ std::string print_animatable_token(const Animatable<T> &v, const uint32_t indent
|
||||
std::stringstream ss;
|
||||
|
||||
if (v.is_timesamples()) {
|
||||
ss << print_typed_token_timesamples(v.ts, indent);
|
||||
ss << print_typed_token_timesamples(v.get_timesamples(), indent);
|
||||
} else if (v.is_blocked()) {
|
||||
ss << "None";
|
||||
} else if (v.is_scalar()) {
|
||||
ss << quote(to_string(v.value));
|
||||
T a;
|
||||
if (!v.get(&a)) {
|
||||
return "[Animatable: InternalError]";
|
||||
}
|
||||
ss << quote(to_string(a));
|
||||
} else {
|
||||
return "[FIXME: Invalid Animatable]";
|
||||
}
|
||||
@@ -516,9 +524,14 @@ std::string print_typed_attr(const TypedAttribute<Animatable<T>> &attr, const st
|
||||
|
||||
if (pv) {
|
||||
if (pv.value().is_timesamples()) {
|
||||
ss << ".timeSamples = " << print_typed_timesamples(pv.value().ts, indent+1);
|
||||
ss << ".timeSamples = " << print_typed_timesamples(pv.value().get_timesamples(), indent+1);
|
||||
} else {
|
||||
ss << " = " << pv.value().value;
|
||||
T a;
|
||||
if (pv.value().get(&a)) {
|
||||
ss << " = " << a;
|
||||
} else {
|
||||
ss << " = [InternalError]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,8 +86,7 @@ static nonstd::optional<Animatable<T>> ConvertToAnimatable(const primvar::PrimVa
|
||||
if (var.is_scalar()) {
|
||||
|
||||
if (auto pv = var.get_value<T>()) {
|
||||
dst.value = pv.value();
|
||||
dst.blocked = false;
|
||||
dst.set(pv.value());
|
||||
|
||||
return std::move(dst);
|
||||
}
|
||||
@@ -97,9 +96,9 @@ static nonstd::optional<Animatable<T>> ConvertToAnimatable(const primvar::PrimVa
|
||||
|
||||
// Attribute Block?
|
||||
if (auto pvb = var.get_ts_value<value::ValueBlock>(i)) {
|
||||
dst.ts.add_blocked_sample(t);
|
||||
dst.add_blocked_sample(t);
|
||||
} else if (auto pv = var.get_ts_value<T>(i)) {
|
||||
dst.ts.add_sample(t, pv.value());
|
||||
dst.add_sample(t, pv.value());
|
||||
} else {
|
||||
// Type mismatch
|
||||
DCOUT(i << "/" << var.var().times.size() << " type mismatch.");
|
||||
@@ -133,8 +132,7 @@ nonstd::optional<Animatable<Extent>> ConvertToAnimatable(const primvar::PrimVar
|
||||
ext.lower = pv.value()[0];
|
||||
ext.upper = pv.value()[1];
|
||||
|
||||
dst.value = ext;
|
||||
dst.blocked = false;
|
||||
dst.set(ext);
|
||||
|
||||
} else {
|
||||
return nonstd::nullopt;
|
||||
@@ -148,13 +146,13 @@ nonstd::optional<Animatable<Extent>> ConvertToAnimatable(const primvar::PrimVar
|
||||
|
||||
// Attribute Block?
|
||||
if (auto pvb = var.get_ts_value<value::ValueBlock>(i)) {
|
||||
dst.ts.add_blocked_sample(t);
|
||||
dst.add_blocked_sample(t);
|
||||
} else if (auto pv = var.get_ts_value<std::vector<value::float3>>(i)) {
|
||||
if (pv.value().size() == 2) {
|
||||
Extent ext;
|
||||
ext.lower = pv.value()[0];
|
||||
ext.upper = pv.value()[1];
|
||||
dst.ts.add_sample(t, ext);
|
||||
dst.add_sample(t, ext);
|
||||
} else {
|
||||
DCOUT(i << "/" << var.var().times.size() << " array size mismatch.");
|
||||
return nonstd::nullopt;
|
||||
|
||||
@@ -767,7 +767,7 @@ struct TypedTimeSamples {
|
||||
|
||||
bool empty() const { return _samples.empty(); }
|
||||
|
||||
void Update() {
|
||||
void update() const {
|
||||
std::sort(_samples.begin(), _samples.end(),
|
||||
[](const Sample &a, const Sample &b) { return a.t < b.t; });
|
||||
|
||||
@@ -782,7 +782,7 @@ struct TypedTimeSamples {
|
||||
bool get(
|
||||
T *dst,
|
||||
double t = value::TimeCode::Default(),
|
||||
TimeSampleInterpolationType interp = TimeSampleInterpolationType::Held) {
|
||||
TimeSampleInterpolationType interp = TimeSampleInterpolationType::Held) const {
|
||||
|
||||
if (!dst) {
|
||||
return false;
|
||||
@@ -793,7 +793,7 @@ struct TypedTimeSamples {
|
||||
}
|
||||
|
||||
if (_dirty) {
|
||||
Update();
|
||||
update();
|
||||
}
|
||||
|
||||
if (value::TimeCode(t).is_default()) {
|
||||
@@ -806,7 +806,6 @@ struct TypedTimeSamples {
|
||||
_samples.begin(), _samples.end(), t,
|
||||
[](const Sample &a, double tval) { return a.t < tval; });
|
||||
|
||||
// TODO: Support other interpolation method for example cubic?
|
||||
if (interp == TimeSampleInterpolationType::Linear) {
|
||||
size_t idx0 = size_t(std::max(
|
||||
int64_t(0),
|
||||
@@ -856,7 +855,7 @@ struct TypedTimeSamples {
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
void add_sample(const double t, T &v) {
|
||||
void add_sample(const double t, const T &v) {
|
||||
Sample s;
|
||||
s.t = t;
|
||||
s.value = v;
|
||||
@@ -872,55 +871,124 @@ struct TypedTimeSamples {
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
const std::vector<Sample> &get_samples() const { return _samples; }
|
||||
std::vector<Sample> &samples() { return _samples; }
|
||||
const std::vector<Sample> &get_samples() const {
|
||||
if (_dirty) {
|
||||
update();
|
||||
}
|
||||
|
||||
return _samples; }
|
||||
|
||||
std::vector<Sample> &samples() {
|
||||
if (_dirty) {
|
||||
update();
|
||||
}
|
||||
|
||||
return _samples;
|
||||
}
|
||||
|
||||
private:
|
||||
// Need to be sorted when look up the value.
|
||||
std::vector<Sample> _samples;
|
||||
bool _dirty{false};
|
||||
// Need to be sorted when looking up the value.
|
||||
mutable std::vector<Sample> _samples;
|
||||
mutable bool _dirty{false};
|
||||
};
|
||||
|
||||
//
|
||||
// Scalar or TimeSamples.
|
||||
//
|
||||
template <typename T>
|
||||
struct Animatable {
|
||||
// scalar
|
||||
T value;
|
||||
bool blocked{false};
|
||||
public:
|
||||
|
||||
// timesamples
|
||||
TypedTimeSamples<T> ts;
|
||||
bool is_blocked() const { return _blocked; }
|
||||
|
||||
bool is_timesamples() const { return !ts.empty(); }
|
||||
|
||||
bool is_scalar() const { return ts.empty(); }
|
||||
|
||||
bool is_blocked() const { return blocked; }
|
||||
|
||||
#if 0 // TODO
|
||||
T Get() const { return value; }
|
||||
|
||||
T Get(double t) {
|
||||
if (IsTimeSampled()) {
|
||||
// TODO: lookup value by t
|
||||
return timeSamples.Get(t);
|
||||
bool is_timesamples() const {
|
||||
if (is_blocked()) {
|
||||
return false;
|
||||
}
|
||||
return value;
|
||||
return !_ts.empty();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_scalar() const {
|
||||
if (is_blocked()) {
|
||||
return false;
|
||||
}
|
||||
return _ts.empty();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get value at specific time.
|
||||
///
|
||||
bool get(double t, T *v, const TimeSampleInterpolationType tinerp = TimeSampleInterpolationType::Held) const {
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_blocked()) {
|
||||
return false;
|
||||
} else if (is_scalar()) {
|
||||
(*v) = _value;
|
||||
return true;
|
||||
} else { // timesamples
|
||||
return _ts.get(v, t, tinerp);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Get scalar value. For timesamples value, fetch the value at Default time.
|
||||
///
|
||||
bool get(T *v) const {
|
||||
if (!v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_blocked()) {
|
||||
return false;
|
||||
} else if (is_scalar()) {
|
||||
(*v) = _value;
|
||||
return true;
|
||||
} else { // timesamples
|
||||
return get(value::TimeCode::Default(), v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TimeSamples
|
||||
void set(double t, const T &v);
|
||||
//void set(double t, const T &v);
|
||||
|
||||
void add_sample(const double t, const T &v) {
|
||||
_ts.add_sample(t, v);
|
||||
}
|
||||
|
||||
// Add None(ValueBlock) sample to timesamples
|
||||
void add_blocked_sample(const double t) {
|
||||
_ts.add_blocked_sample(t);
|
||||
}
|
||||
|
||||
// Scalar
|
||||
void set(const T &v) {
|
||||
value = v;
|
||||
_value = v;
|
||||
_blocked = false;
|
||||
}
|
||||
|
||||
const TypedTimeSamples<T> &get_timesamples() const {
|
||||
return _ts;
|
||||
}
|
||||
|
||||
Animatable() {}
|
||||
|
||||
Animatable(const T &v) : value(v) {}
|
||||
Animatable(const T &v) : _value(v) {}
|
||||
|
||||
// TODO: Init with timesamples
|
||||
|
||||
private:
|
||||
|
||||
// scalar
|
||||
T _value;
|
||||
bool _blocked{false};
|
||||
|
||||
// timesamples
|
||||
TypedTimeSamples<T> _ts;
|
||||
};
|
||||
|
||||
///
|
||||
|
||||
@@ -413,14 +413,17 @@ void ToProperty(const TypedAttribute<Animatable<T>> &input, Property &output) {
|
||||
nonstd::optional<Animatable<T>> aval = input.get_value();
|
||||
if (aval) {
|
||||
if (aval.value().is_scalar()) {
|
||||
value::Value val(aval.value().value);
|
||||
primvar::PrimVar pvar;
|
||||
pvar.set_scalar(val);
|
||||
Attribute attr;
|
||||
attr.set_var(std::move(pvar));
|
||||
attr.variability() = Variability::Uniform;
|
||||
output = Property(attr, /* custom */ false);
|
||||
return;
|
||||
T a;
|
||||
if (aval.value().get(&a)) {
|
||||
value::Value val(a);
|
||||
primvar::PrimVar pvar;
|
||||
pvar.set_scalar(val);
|
||||
Attribute attr;
|
||||
attr.set_var(std::move(pvar));
|
||||
attr.variability() = Variability::Uniform;
|
||||
output = Property(attr, /* custom */ false);
|
||||
return;
|
||||
}
|
||||
} else if (aval.value().is_blocked()) {
|
||||
Attribute attr;
|
||||
attr.set_type_name(value::TypeTraits<T>::type_name());
|
||||
@@ -484,11 +487,16 @@ void ToProperty(
|
||||
primvar::PrimVar pvar;
|
||||
|
||||
if (v.is_timesamples()) {
|
||||
value::TimeSamples ts = ToTypelessTimeSamples(v.ts);
|
||||
value::TimeSamples ts = ToTypelessTimeSamples(v.get_timesamples());
|
||||
pvar.set_timesamples(ts);
|
||||
} else if (v.is_scalar()) {
|
||||
value::Value val(v.value);
|
||||
pvar.set_scalar(val);
|
||||
T a;
|
||||
if (v.get(&a)) {
|
||||
value::Value val(a);
|
||||
pvar.set_scalar(val);
|
||||
} else {
|
||||
DCOUT("??? Invalid Animatable value.");
|
||||
}
|
||||
} else {
|
||||
DCOUT("??? Invalid Animatable value.");
|
||||
}
|
||||
|
||||
@@ -25,9 +25,11 @@ bool EvaluateUsdPreviewSurfaceAttribute(
|
||||
if (shader.diffuseColor.authored()) {
|
||||
|
||||
} else {
|
||||
value::color3f col = shader.diffuseColor.get_value().value;
|
||||
out_val = col;
|
||||
return true;
|
||||
value::color3f col;
|
||||
if (shader.diffuseColor.get_value().get(&col)) {
|
||||
out_val = col;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,13 +37,9 @@ const std::vector<value::point3f> GeomMesh::GetPoints(
|
||||
}
|
||||
|
||||
if (auto pv = points.get_value()) {
|
||||
if (pv.value().is_timesamples()) {
|
||||
std::vector<value::point3f> v;
|
||||
if (pv.value().ts.get(&v, time, interp)) {
|
||||
dst = v;
|
||||
}
|
||||
} else if (pv.value().is_scalar()) {
|
||||
dst = pv.value().value;
|
||||
std::vector<value::point3f> val;
|
||||
if (pv.value().get(time, &val, interp)) {
|
||||
dst = std::move(val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,14 +77,11 @@ const std::vector<value::normal3f> GeomMesh::GetNormals(
|
||||
}
|
||||
|
||||
if (normals.get_value()) {
|
||||
if (normals.get_value().value().is_timesamples()) {
|
||||
// TODO
|
||||
(void)time;
|
||||
(void)interp;
|
||||
return dst;
|
||||
}
|
||||
|
||||
dst = normals.get_value().value().value;
|
||||
std::vector<value::normal3f> val;
|
||||
if (normals.get_value().value().get(time, &val, interp)) {
|
||||
dst = std::move(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +116,11 @@ const std::vector<int32_t> GeomMesh::GetFaceVertexCounts() const {
|
||||
}
|
||||
|
||||
if (auto pv = faceVertexCounts.get_value()) {
|
||||
dst = pv.value().value;
|
||||
std::vector<int32_t> val;
|
||||
// TOOD: timesamples
|
||||
if (pv.value().get(&val)) {
|
||||
dst = std::move(val);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
@@ -141,7 +138,11 @@ const std::vector<int32_t> GeomMesh::GetFaceVertexIndices() const {
|
||||
}
|
||||
|
||||
if (auto pv = faceVertexIndices.get_value()) {
|
||||
dst = pv.value().value;
|
||||
std::vector<int32_t> val;
|
||||
// TOOD: timesamples
|
||||
if (pv.value().get(&val)) {
|
||||
dst = std::move(val);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
@@ -252,8 +253,17 @@ nonstd::expected<bool, std::string> GeomMesh::ValidateGeomSubset() {
|
||||
|
||||
if (faceVertexCounts.get_value()) {
|
||||
const auto fvp = faceVertexCounts.get_value();
|
||||
const auto &fv = fvp.value().value;
|
||||
size_t n = fv.size();
|
||||
std::vector<int32_t> fvc;
|
||||
|
||||
if (fvp.value().is_timesamples()) {
|
||||
return nonstd::make_unexpected("TODO: faceVertexCounts.timeSamples\n");
|
||||
}
|
||||
|
||||
if (!fvp.value().get(&fvc)) {
|
||||
return nonstd::make_unexpected("Failed to get faceVertexCounts data.");
|
||||
}
|
||||
|
||||
size_t n = fvc.size();
|
||||
|
||||
// Currently we only check if face ids are valid.
|
||||
for (size_t i = 0; i < geom_subset_children.size(); i++) {
|
||||
|
||||
@@ -26,8 +26,8 @@ bool SkelAnimation::get_blendShapeWeights(
|
||||
const TimeSampleInterpolationType tinterp) {
|
||||
Animatable<std::vector<float>> v;
|
||||
if (blendShapeWeights.get_value(&v)) {
|
||||
// Evaluate at time `tc` with `tinterp` interpolation
|
||||
return v.ts.get(vals, t, tinterp);
|
||||
// Evaluate at time `t` with `tinterp` interpolation
|
||||
return v.get(t, vals, tinterp);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -38,8 +38,8 @@ bool SkelAnimation::get_rotations(std::vector<value::quatf> *vals,
|
||||
const TimeSampleInterpolationType tinterp) {
|
||||
Animatable<std::vector<value::quatf>> v;
|
||||
if (rotations.get_value(&v)) {
|
||||
// Evaluate at time `tc` with `tinterp` interpolation
|
||||
return v.ts.get(vals, t, tinterp);
|
||||
// Evaluate at time `t` with `tinterp` interpolation
|
||||
return v.get(t, vals, tinterp);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -49,8 +49,8 @@ bool SkelAnimation::get_scales(std::vector<value::half3> *vals, const double t,
|
||||
const TimeSampleInterpolationType tinterp) {
|
||||
Animatable<std::vector<value::half3>> v;
|
||||
if (scales.get_value(&v)) {
|
||||
// Evaluate at time `tc` with `tinterp` interpolation
|
||||
return v.ts.get(vals, t, tinterp);
|
||||
// Evaluate at time `t` with `tinterp` interpolation
|
||||
return v.get(t, vals, tinterp);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -61,8 +61,8 @@ bool SkelAnimation::get_translations(
|
||||
const TimeSampleInterpolationType tinterp) {
|
||||
Animatable<std::vector<value::float3>> v;
|
||||
if (translations.get_value(&v)) {
|
||||
// Evaluate at time `tc` with `tinterp` interpolation
|
||||
return v.ts.get(vals, t, tinterp);
|
||||
// Evaluate at time `t` with `tinterp` interpolation
|
||||
return v.get(t, vals, tinterp);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -279,9 +279,63 @@ inline value::float4 operator*(const value::float4 &a, const float b) {
|
||||
return {a[0] * b, a[1] * b, a[2] * b, a[3] * b};
|
||||
}
|
||||
|
||||
// normal
|
||||
inline value::normal3f operator+(const value::normal3f &a, const value::normal3f &b) {
|
||||
return {a[0] + b[0], a[1] + b[1], a[2] + b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator+(const float a, const value::normal3f &b) {
|
||||
return {a + b[0], a + b[1], a + b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator+(const value::normal3f &a, const float b) {
|
||||
return {a[0] + b, a[1] + b, a[2] + b};
|
||||
}
|
||||
|
||||
inline value::normal3f operator-(const value::normal3f &a, const value::normal3f &b) {
|
||||
return {a[0] - b[0], a[1] - b[1], a[2] - b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator-(const float a, const value::normal3f &b) {
|
||||
return {a - b[0], a - b[1], a - b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator-(const value::normal3f &a, const float b) {
|
||||
return {a[0] - b, a[1] - b, a[2] - b};
|
||||
}
|
||||
|
||||
inline value::normal3f operator*(const value::normal3f &a, const value::normal3f &b) {
|
||||
return {a[0] * b[0], a[1] * b[1], a[2] * b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator*(const float a, const value::normal3f &b) {
|
||||
return {a * b[0], a * b[1], a * b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator*(const value::normal3f &a, const float b) {
|
||||
return {a[0] * b, a[1] * b, a[2] * b};
|
||||
}
|
||||
|
||||
inline value::normal3f operator/(const value::normal3f &a, const value::normal3f &b) {
|
||||
return {a[0] / b[0], a[1] / b[1], a[2] / b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator/(const float a, const value::normal3f &b) {
|
||||
return {a / b[0], a / b[1], a / b[2]};
|
||||
}
|
||||
|
||||
inline value::normal3f operator/(const value::normal3f &a, const float b) {
|
||||
return {a[0] / b, a[1] / b, a[2] / b};
|
||||
}
|
||||
|
||||
// -- lerp
|
||||
|
||||
// no lerp by default
|
||||
template <typename T>
|
||||
inline T lerp(const T &a, const T &b, const double t) {
|
||||
return (1.0 - t) * a + t * b;
|
||||
(void)b;
|
||||
(void)t;
|
||||
return a;
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -319,6 +373,11 @@ inline value::float3 lerp(const value::float3 &a, const value::float3 &b, const
|
||||
return float(1.0 - t) * a + float(t) * b;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline value::normal3f lerp(const value::normal3f &a, const value::normal3f &b, const double t) {
|
||||
return float(1.0 - t) * a + float(t) * b;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline value::float4 lerp(const value::float4 &a, const value::float4 &b, const double t) {
|
||||
return float(1.0 - t) * a + float(t) * b;
|
||||
|
||||
@@ -673,42 +673,49 @@ struct quatd {
|
||||
struct vector3h {
|
||||
half x, y, z;
|
||||
|
||||
half operator[](size_t idx) const { return *(&x + idx); }
|
||||
half operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
struct vector3f {
|
||||
float x, y, z;
|
||||
|
||||
float operator[](size_t idx) const { return *(&x + idx); }
|
||||
float operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
struct vector3d {
|
||||
double x, y, z;
|
||||
|
||||
double operator[](size_t idx) const { return *(&x + idx); }
|
||||
double operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
struct normal3h {
|
||||
half x, y, z;
|
||||
|
||||
half operator[](size_t idx) const { return *(&x + idx); }
|
||||
half operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
struct normal3f {
|
||||
float x, y, z;
|
||||
|
||||
float operator[](size_t idx) const { return *(&x + idx); }
|
||||
float operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
struct normal3d {
|
||||
double x, y, z;
|
||||
|
||||
double operator[](size_t idx) const { return *(&x + idx); }
|
||||
double operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
struct point3h {
|
||||
half x, y, z;
|
||||
|
||||
half operator[](size_t idx) const { return *(&x + idx); }
|
||||
half operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
@@ -796,6 +803,7 @@ inline point3h operator/(const point3h &a, const point3h &b) {
|
||||
struct point3f {
|
||||
float x, y, z;
|
||||
|
||||
float operator[](size_t idx) const { return *(&x + idx); }
|
||||
float operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
@@ -883,6 +891,7 @@ inline point3f operator/(const point3f &a, const point3f &b) {
|
||||
struct point3d {
|
||||
double x, y, z;
|
||||
|
||||
double operator[](size_t idx) const { return *(&x + idx); }
|
||||
double operator[](size_t idx) { return *(&x + idx); }
|
||||
};
|
||||
|
||||
@@ -891,6 +900,7 @@ struct color3h {
|
||||
|
||||
// C++11 or later, struct is tightly packed, so use the pointer offset is
|
||||
// valid.
|
||||
half operator[](size_t idx) const { return *(&r + idx); }
|
||||
half operator[](size_t idx) { return *(&r + idx); }
|
||||
};
|
||||
|
||||
@@ -899,6 +909,7 @@ struct color3f {
|
||||
|
||||
// C++11 or later, struct is tightly packed, so use the pointer offset is
|
||||
// valid.
|
||||
float operator[](size_t idx) const{ return *(&r + idx); }
|
||||
float operator[](size_t idx) { return *(&r + idx); }
|
||||
};
|
||||
|
||||
@@ -907,6 +918,7 @@ struct color4h {
|
||||
|
||||
// C++11 or later, struct is tightly packed, so use the pointer offset is
|
||||
// valid.
|
||||
half operator[](size_t idx) const { return *(&r + idx); }
|
||||
half operator[](size_t idx) { return *(&r + idx); }
|
||||
};
|
||||
|
||||
@@ -915,6 +927,7 @@ struct color4f {
|
||||
|
||||
// C++11 or later, struct is tightly packed, so use the pointer offset is
|
||||
// valid.
|
||||
float operator[](size_t idx) const { return *(&r + idx); }
|
||||
float operator[](size_t idx) { return *(&r + idx); }
|
||||
};
|
||||
|
||||
@@ -923,6 +936,7 @@ struct color3d {
|
||||
|
||||
// C++11 or later, struct is tightly packed, so use the pointer offset is
|
||||
// valid.
|
||||
double operator[](size_t idx) const { return *(&r + idx); }
|
||||
double operator[](size_t idx) { return *(&r + idx); }
|
||||
};
|
||||
|
||||
@@ -931,6 +945,7 @@ struct color4d {
|
||||
|
||||
// C++11 or later, struct is tightly packed, so use the pointer offset is
|
||||
// valid.
|
||||
double operator[](size_t idx) const { return *(&r + idx); }
|
||||
double operator[](size_t idx) { return *(&r + idx); }
|
||||
};
|
||||
|
||||
|
||||
@@ -10,4 +10,5 @@ def Xform "Bottle" (
|
||||
string modelingVariant = "Tall"
|
||||
}
|
||||
add variantSets = "modelingVariant"
|
||||
)
|
||||
) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user