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
5 changed files with 249 additions and 16 deletions
Showing only changes of commit b2cb85ad48 - Show all commits

View File

@ -8,8 +8,163 @@ namespace blender::nodes::materialx {
NodeItem MathNodeParser::compute()
{
/* TODO: implement */
return empty();
auto op = node->custom1;
printf("%d\n", int(op));
NodeItem res = empty();
/* Single operand operations */
NodeItem x = get_input_value(0);
switch (op) {
case NODE_MATH_SINE:
res = x.sin();
break;
case NODE_MATH_COSINE:
res = x.cos();
break;
case NODE_MATH_TANGENT:
res = x.tan();
break;
case NODE_MATH_ARCSINE:
res = x.asin();
break;
case NODE_MATH_ARCCOSINE:
res = x.acos();
break;
case NODE_MATH_ARCTANGENT:
res = x.atan();
break;
case NODE_MATH_ROUND:
res = (x + value(0.5f)).floor();
break;
case NODE_MATH_ABSOLUTE:
res = x.abs();
break;
case NODE_MATH_FLOOR:
res = x.floor();
break;
case NODE_MATH_CEIL:
res = x.ceil();
break;
case NODE_MATH_FRACTION:
res = x % value(1.0f);
break;
case NODE_MATH_SQRT:
res = x.sqrt();
break;
case NODE_MATH_INV_SQRT:
res = value(1.0f) / x.sqrt();
break;
case NODE_MATH_SIGN:
res = x.sign();
break;
case NODE_MATH_EXPONENT:
res = x.exp();
break;
case NODE_MATH_RADIANS:
res = x * value(float(M_PI) / 180.0f);
break;
case NODE_MATH_DEGREES:
res = x * value(180.0f * float(M_1_PI));
break;
case NODE_MATH_SINH:
res = x.sinh();
break;
case NODE_MATH_COSH:
res = x.cosh();
break;
case NODE_MATH_TANH:
res = x.tanh();
break;
default: {
/* 2-operand operations */
NodeItem y = get_input_value(1);
switch (op) {
case NODE_MATH_ADD:
res = x + y;
break;
case NODE_MATH_SUBTRACT:
res = x - y;
break;
case NODE_MATH_MULTIPLY:
res = x * y;
break;
case NODE_MATH_DIVIDE:
res = x / y;
break;
case NODE_MATH_POWER:
res = x ^ y;
break;
case NODE_MATH_LOGARITHM:
res = x.ln() / y.ln();
break;
case NODE_MATH_MINIMUM:
res = x.min(y);
break;
case NODE_MATH_MAXIMUM:
res = x.max(y);
break;
case NODE_MATH_LESS_THAN:
res = x.if_else("<", y, value(1.0f), value(0.0f));
break;
case NODE_MATH_GREATER_THAN:
res = x.if_else(">", y, value(1.0f), value(0.0f));
break;
case NODE_MATH_MODULO:
res = x % y;
break;
case NODE_MATH_ARCTAN2:
res = x.atan2(y);
break;
case NODE_MATH_TRUNC:
//res = x.atan2(y);
break;
case NODE_MATH_SNAP:
//res = x.atan2(y);
break;
case NODE_MATH_PINGPONG:
//res = x.atan2(y);
break;
case NODE_MATH_FLOORED_MODULO:
//res = x.atan2(y);
break;
default: {
/* 3-operand operations */
NodeItem z = get_input_value(2);
switch (op) {
case NODE_MATH_WRAP:
//res = x * y + z;
break;
case NODE_MATH_COMPARE:
//res = x * y + z;
break;
case NODE_MATH_MULTIPLY_ADD:
res = x * y + z;
break;
case NODE_MATH_SMOOTH_MIN:
//res = x * y + z;
break;
case NODE_MATH_SMOOTH_MAX:
//res = x * y + z;
break;
default:
/* TODO: log unsupported operation*/
}
}
}
}
}
bool clamp_output = node->custom2 != 0;
if (clamp_output && res) {
res = res.clamp();
}
return res;
}
} // namespace blender::nodes::materialx

View File

@ -257,11 +257,46 @@ NodeItem NodeItem::atan() const
return arithmetic("atan", [](float a) { return std::atanf(a); });
}
NodeItem NodeItem::log() const
NodeItem NodeItem::atan2(const NodeItem &other) const
{
return arithmetic(other, "atan2", [](float a, float b) { return std::atan2f(a, b); });
}
NodeItem NodeItem::sinh() const
{
return exp() - (val(0.0f) - *this).exp()) / val(2.0f);
}
NodeItem NodeItem::cosh() const
{
return exp() - (val(0.0f) - *this).exp()) / val(2.0f);
}
NodeItem NodeItem::tanh() const
{
return sinh() / cosh();
}
NodeItem NodeItem::ln() const
{
return arithmetic("ln", [](float a) { return std::logf(a); });
}
NodeItem NodeItem::sqrt() const
{
return arithmetic("sqrt", [](float a) { return std::sqrtf(a); });
}
NodeItem NodeItem::sign() const
{
return arithmetic("sign", [](float a) { return a < 0.0f ? -1.0f : (a == 0.0f ? 0.0f : 1.0f); });
}
NodeItem NodeItem::exp() const
{
return arithmetic("exp", [](float a) { return std::expf(a); });
}
NodeItem NodeItem::to_color3() const
{
std::string t = type();

View File

@ -58,7 +58,14 @@ class NodeItem {
NodeItem asin() const;
NodeItem acos() const;
NodeItem atan() const;
NodeItem log() const;
NodeItem atan2(const NodeItem &other) const;
NodeItem sinh() const;
NodeItem cosh() const;
NodeItem tanh() const;
NodeItem ln() const;
NodeItem sqrt() const;
NodeItem sign() const;
NodeItem exp() const;
NodeItem to_color3() const;
bool is_numeric() const;

View File

@ -30,9 +30,42 @@ NodeItem NodeParser::create_node(const std::string &mx_category,
NodeItem NodeParser::get_input_default(const std::string &name)
{
NodeItem res = empty();
return get_input_default(node->input_by_identifier(name));
}
const bNodeSocket &socket = node->input_by_identifier(name);
NodeItem NodeParser::get_input_default(int index)
{
return get_input_default(node->input_socket(index));
}
NodeItem NodeParser::get_input_link(const std::string &name)
{
return get_input_link(node->input_by_identifier(name));
}
NodeItem NodeParser::get_input_link(int index)
{
return get_input_link(node->input_socket(index));
}
NodeItem NodeParser::get_input_value(const std::string &name)
{
return get_input_value(node->input_by_identifier(name));
}
NodeItem NodeParser::get_input_value(int index)
{
return get_input_value(node->input_socket(index));
}
NodeItem NodeParser::empty() const
{
return NodeItem(graph);
}
NodeItem NodeParser::get_input_default(const bNodeSocket &socket)
{
NodeItem res = empty();
switch (socket.type) {
case SOCK_FLOAT: {
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
@ -55,11 +88,11 @@ NodeItem NodeParser::get_input_default(const std::string &name)
return res;
}
NodeItem NodeParser::get_input_link(const std::string &name)
NodeItem NodeParser::get_input_link(const bNodeSocket &socket)
{
NodeItem res = empty();
const bNodeLink *link = node->input_by_identifier(name).link;
const bNodeLink *link = socket.link;
if (!(link && link->is_used())) {
return res;
}
@ -102,18 +135,13 @@ NodeItem NodeParser::get_input_link(const std::string &name)
return res;
}
NodeItem NodeParser::get_input_value(const std::string &name)
NodeItem NodeParser::get_input_value(const bNodeSocket &socket)
{
NodeItem res = get_input_link(name);
NodeItem res = get_input_link(socket);
if (!res) {
res = get_input_default(name);
res = get_input_default(socket);
}
return res;
}
NodeItem NodeParser::empty() const
{
return NodeItem(graph);
}
} // namespace blender::nodes::materialx

View File

@ -33,10 +33,18 @@ class NodeParser {
const std::string &mx_type,
bool accessory = false);
NodeItem get_input_default(const std::string &name);
NodeItem get_input_default(int index);
NodeItem get_input_link(const std::string &name);
NodeItem get_input_link(int index);
NodeItem get_input_value(const std::string &name);
NodeItem get_input_value(int index);
NodeItem empty() const;
template<class T> NodeItem value(const T &data) const;
private:
NodeItem get_input_default(const bNodeSocket &socket);
NodeItem get_input_link(const bNodeSocket &socket);
NodeItem get_input_value(const bNodeSocket &socket);
};
template<class T> NodeItem NodeParser::value(const T &data) const