forked from blender/blender
Implement export of Math node. Continue other arithmetic support for NodeItem #6
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user