Implement export of Math node. Continue other arithmetic support for NodeItem #6

Merged
Bogdan Nagirniak merged 9 commits from BogdanNagirniak/blender:matx-arithmetic into matx-export-material 2023-08-31 12:35:55 +02:00
2 changed files with 117 additions and 52 deletions
Showing only changes of commit 0517ab20a3 - Show all commits

View File

@ -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

View File

@ -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