forked from blender/blender
Implement export of Math node. Continue other arithmetic support for NodeItem #6
@ -103,13 +103,44 @@ NodeItem NodeItem::operator^(const NodeItem &other) const
|
||||
|
||||
bool NodeItem::operator==(const NodeItem &other) const
|
||||
{
|
||||
if (!*this) {
|
||||
return !other;
|
||||
}
|
||||
if (!other) {
|
||||
return !*this;
|
||||
}
|
||||
if (node && node == other.node) {
|
||||
return true;
|
||||
}
|
||||
if (value && other.value) {
|
||||
NodeItem cmp = if_else("==", other, val(1.0f), val(0.0f));
|
||||
return cmp.value->asA<float>() == 1.0f;
|
||||
if ((node && other.value) || (value && other.node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string t;
|
||||
auto val1 = value;
|
||||
auto val2 = other.value;
|
||||
if (!adjust_types(val1, val2, t)) {
|
||||
return false;
|
||||
}
|
||||
if (t == "float") {
|
||||
return val1->asA<float>() == val2->asA<float>();
|
||||
}
|
||||
if (t == "color3") {
|
||||
return val1->asA<MaterialX::Color3>() == val2->asA<MaterialX::Color3>();
|
||||
}
|
||||
if (t == "color4") {
|
||||
return val1->asA<MaterialX::Color4>() == val2->asA<MaterialX::Color4>();
|
||||
}
|
||||
if (t == "vector2") {
|
||||
return val1->asA<MaterialX::Vector2>() == val2->asA<MaterialX::Vector2>();
|
||||
}
|
||||
if (t == "vector3") {
|
||||
return val1->asA<MaterialX::Vector3>() == val2->asA<MaterialX::Vector3>();
|
||||
}
|
||||
if (t == "vector4") {
|
||||
return val1->asA<MaterialX::Vector4>() == val2->asA<MaterialX::Vector4>();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -182,17 +213,6 @@ NodeItem NodeItem::if_else(const std::string &condition,
|
||||
const NodeItem &if_val,
|
||||
const NodeItem &else_val) const
|
||||
{
|
||||
/* TODO: if_else() doesn't work correctly. Here is description
|
||||
* Node: <ifgreater>
|
||||
* Output the value of in1 if value1>value2, or the value of in2 if value1<=value2.
|
||||
<nodedef name="ND_ifgreater_color3" node="ifgreater" nodegroup="conditional">
|
||||
<input name="value1" type="float" value="1.0" />
|
||||
<input name="value2" type="float" value="0.0" />
|
||||
<input name="in1" type="color3" value="0.0, 0.0, 0.0" />
|
||||
<input name="in2" type="color3" value="0.0, 0.0, 0.0" />
|
||||
<output name="out" type="color3" defaultinput="in1" />
|
||||
</nodedef>
|
||||
*/
|
||||
if (condition == "<") {
|
||||
return other.if_else(">", *this, else_val, if_val);
|
||||
}
|
||||
@ -204,27 +224,46 @@ NodeItem NodeItem::if_else(const std::string &condition,
|
||||
}
|
||||
|
||||
NodeItem res = empty();
|
||||
if (type() != "float" || other.type() != "float") {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto val1 = if_val;
|
||||
auto val2 = else_val;
|
||||
std::string t;
|
||||
if (!adjust_types(val1, val2, t)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
std::function<bool(float, float)> func = nullptr;
|
||||
std::string mx_category;
|
||||
if (condition == ">") {
|
||||
res = arithmetic(other, "ifgreater", [](float a, float b) { return float(a > b); });
|
||||
mx_category = "ifgreater";
|
||||
func = [](float a, float b) { return a > b; };
|
||||
}
|
||||
else if (condition == ">=") {
|
||||
res = arithmetic(other, "ifgreatereq", [](float a, float b) { return float(a >= b); });
|
||||
mx_category = "ifgreatereq";
|
||||
func = [](float a, float b) { return a >= b; };
|
||||
}
|
||||
else if (condition == "==") {
|
||||
res = arithmetic(other, "ifequal", [](float a, float b) { return float(a == b); });
|
||||
mx_category = "ifequal";
|
||||
func = [](float a, float b) { return a == b; };
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
if (res.value) {
|
||||
/* Getting sum of elements via dot product with 1.0f and comparing to 0.0f */
|
||||
res = res.dot(val(1.0f)).value->asA<float>() == 0.0f ? else_val : if_val;
|
||||
if (value && other.value) {
|
||||
res = func(value->asA<float>(), other.value->asA<float>()) ? val1 : val2;
|
||||
}
|
||||
else if (res.node) {
|
||||
res.set_input("value1", if_val);
|
||||
res.set_input("value2", else_val);
|
||||
else {
|
||||
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t);
|
||||
res.set_input("value1", *this);
|
||||
res.set_input("value2", other);
|
||||
res.set_input("in1", val1);
|
||||
res.set_input("in2", val2);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -422,24 +461,12 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string t1 = type();
|
||||
std::string t2 = other.type();
|
||||
|
||||
std::string t;
|
||||
if (value && other.value) {
|
||||
std::string t = t1;
|
||||
auto val1 = value;
|
||||
auto val2 = other.value;
|
||||
if (t1 != t2) {
|
||||
if (t1 == "float") {
|
||||
val1 = float_to_type(val1->asA<float>(), t2);
|
||||
t = t2;
|
||||
}
|
||||
else if (t2 == "float") {
|
||||
val2 = float_to_type(val2->asA<float>(), t1);
|
||||
}
|
||||
else {
|
||||
return res;
|
||||
}
|
||||
if (!adjust_types(val1, val2, t)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (t == "float") {
|
||||
@ -482,20 +509,10 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string t = t1;
|
||||
auto val1 = *this;
|
||||
auto val2 = other;
|
||||
if (t1 != t2) {
|
||||
if (val1.value && t1 == "float") {
|
||||
val1.value = float_to_type(val1.value->asA<float>(), t2);
|
||||
t = t2;
|
||||
}
|
||||
else if (val2.value && t2 == "float") {
|
||||
val2.value = float_to_type(val2.value->asA<float>(), t1);
|
||||
}
|
||||
else {
|
||||
return res;
|
||||
}
|
||||
if (!adjust_types(val1, val2, t)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t);
|
||||
@ -505,7 +522,7 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
|
||||
return res;
|
||||
}
|
||||
|
||||
MaterialX::ValuePtr NodeItem::float_to_type(float v, std::string t) const
|
||||
MaterialX::ValuePtr NodeItem::float_to_type(float v, std::string t)
|
||||
{
|
||||
if (t == "float") {
|
||||
return MaterialX::Value::createValue<float>(v);
|
||||
@ -530,4 +547,50 @@ MaterialX::ValuePtr NodeItem::float_to_type(float v, std::string t) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool NodeItem::adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, std::string &t)
|
||||
{
|
||||
std::string t1 = val1->getTypeString();
|
||||
std::string t2 = val2->getTypeString();
|
||||
if (t1 != t2) {
|
||||
if (t1 == "float") {
|
||||
val1 = float_to_type(val1->asA<float>(), t2);
|
||||
t = t2;
|
||||
}
|
||||
else if (t2 == "float") {
|
||||
val2 = float_to_type(val2->asA<float>(), t1);
|
||||
t = t1;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
t = t1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NodeItem::adjust_types(NodeItem &val1, NodeItem &val2, std::string &t)
|
||||
{
|
||||
std::string t1 = val1.type();
|
||||
std::string t2 = val2.type();
|
||||
if (t1 != t2) {
|
||||
if (val1.value && t1 == "float") {
|
||||
val1.value = float_to_type(val1.value->asA<float>(), t2);
|
||||
t = t2;
|
||||
}
|
||||
else if (val2.value && t2 == "float") {
|
||||
val2.value = float_to_type(val2.value->asA<float>(), t1);
|
||||
t = t2;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
t = t1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::materialx
|
||||
|
@ -77,7 +77,9 @@ class NodeItem {
|
||||
NodeItem arithmetic(const NodeItem &other,
|
||||
const std::string &mx_category,
|
||||
std::function<float(float, float)> func) const;
|
||||
MaterialX::ValuePtr float_to_type(float v, std::string t) const;
|
||||
static MaterialX::ValuePtr float_to_type(float v, std::string t);
|
||||
static bool adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, std::string &t);
|
||||
static bool adjust_types(NodeItem &val1, NodeItem &val2, std::string &t);
|
||||
};
|
||||
|
||||
template<class T> NodeItem NodeItem::val(const T &data) const
|
||||
|
Loading…
Reference in New Issue
Block a user