forked from blender/blender
Arithmetic support for NodeItem and node implementation with arithmetic #4
@ -25,20 +25,27 @@ void NodeItem::set_input(const std::string &name, const NodeItem &item)
|
||||
|
||||
void NodeItem::set_input(const std::string &name, const MaterialX::ValuePtr value)
|
||||
{
|
||||
std::string mx_type = value->getTypeString();
|
||||
if (value->isA<float>()) {
|
||||
set_input(name, value->asA<float>(), "float");
|
||||
set_input(name, value->asA<float>(), mx_type);
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector2>()) {
|
||||
set_input(name, value->asA<MaterialX::Vector2>(), mx_type);
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector3>()) {
|
||||
set_input(name, value->asA<MaterialX::Vector3>(), "vector3");
|
||||
set_input(name, value->asA<MaterialX::Vector3>(), mx_type);
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector4>()) {
|
||||
set_input(name, value->asA<MaterialX::Vector4>(), "vector4");
|
||||
set_input(name, value->asA<MaterialX::Vector4>(), mx_type);
|
||||
}
|
||||
else if (value->isA<MaterialX::Color3>()) {
|
||||
set_input(name, value->asA<MaterialX::Color3>(), "color3");
|
||||
set_input(name, value->asA<MaterialX::Color3>(), mx_type);
|
||||
}
|
||||
else if (value->isA<MaterialX::Color4>()) {
|
||||
set_input(name, value->asA<MaterialX::Color4>(), "color4");
|
||||
set_input(name, value->asA<MaterialX::Color4>(), mx_type);
|
||||
}
|
||||
else if (value->isA<std::string>()) {
|
||||
set_input(name, value->asA<std::string>(), mx_type);
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
@ -55,25 +62,164 @@ NodeItem::operator bool() const
|
||||
return value || node;
|
||||
}
|
||||
|
||||
NodeItem NodeItem::to_color3()
|
||||
NodeItem NodeItem::operator+(const NodeItem &other)
|
||||
{
|
||||
return arithmetic(other, "add", [](float a, float b) { return a + b; });
|
||||
}
|
||||
|
||||
NodeItem NodeItem::operator-(const NodeItem &other)
|
||||
{
|
||||
return arithmetic(other, "subtract", [](float a, float b) { return a - b; });
|
||||
}
|
||||
|
||||
NodeItem NodeItem::operator*(const NodeItem &other)
|
||||
{
|
||||
return arithmetic(other, "multiply", [](float a, float b) { return a * b; });
|
||||
}
|
||||
|
||||
NodeItem NodeItem::operator/(const NodeItem &other)
|
||||
{
|
||||
return arithmetic(other, "divide", [](float a, float b) { return b == 0.0f ? 0.0f : a / b; });
|
||||
}
|
||||
|
||||
NodeItem NodeItem::to_color3() const
|
||||
{
|
||||
NodeItem res(graph_);
|
||||
if (value) {
|
||||
MaterialX::Color3 c;
|
||||
if (value->isA<float>()) {
|
||||
float v = value->asA<float>();
|
||||
c = {v, v ,v};
|
||||
}
|
||||
else if (value->isA<MaterialX::Color3>()) {
|
||||
auto v = value->asA<MaterialX::Color3>();
|
||||
c = {v[0], v[1], v[2]};
|
||||
}
|
||||
else if (value->isA<MaterialX::Color4>()) {
|
||||
auto v = value->asA<MaterialX::Color4>();
|
||||
c = {v[0], v[1], v[2]};
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector3>()) {
|
||||
auto v = value->asA<MaterialX::Vector3>();
|
||||
c = {v[0], v[1], v[2]};
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector4>()) {
|
||||
auto v = value->asA<MaterialX::Vector4>();
|
||||
c = {v[0], v[1], v[2]};
|
||||
}
|
||||
else {
|
||||
/* Default color */
|
||||
c = {0.0f, 0.0f, 0.0f};
|
||||
}
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Color3>(c);
|
||||
}
|
||||
else if (node) {
|
||||
res.node = node;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NodeItem NodeItem::arithmetic(const std::string &mx_category, std::function<float(float)> func)
|
||||
{
|
||||
std::string t = value ? value->getTypeString() : node->getType();
|
||||
NodeItem res(graph_);
|
||||
if (value) {
|
||||
if (value->isA<float>()) {
|
||||
float v = value->asA<float>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Color3>(MaterialX::Color3(v, v, v));
|
||||
res.value = MaterialX::Value::createValue<float>(func(v));
|
||||
}
|
||||
else if (value->isA<MaterialX::Color3>()) {
|
||||
res.value = value;
|
||||
auto v = value->asA<MaterialX::Color3>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Color3>(
|
||||
{func(v[0]), func(v[1]), func(v[2])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Color4>()) {
|
||||
auto c = value->asA<MaterialX::Color4>();
|
||||
auto v = value->asA<MaterialX::Color4>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Color4>(
|
||||
{func(v[0]), func(v[1]), func(v[2]), func(v[3])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector2>()) {
|
||||
auto v = value->asA<MaterialX::Vector2>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Vector2>({func(v[0]), func(v[1])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector3>()) {
|
||||
auto v = value->asA<MaterialX::Vector3>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
|
||||
{func(v[0]), func(v[1]), func(v[2])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector4>()) {
|
||||
auto v = value->asA<MaterialX::Vector4>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Vector4>(
|
||||
{func(v[0]), func(v[1]), func(v[2]), func(v[3])});
|
||||
}
|
||||
else {
|
||||
/* Nothing change */
|
||||
res.value = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t);
|
||||
res.set_input("in", *this);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NodeItem NodeItem::arithmetic(const NodeItem &other,
|
||||
const std::string &mx_category,
|
||||
std::function<float(float, float)> func)
|
||||
{
|
||||
std::string t1 = value ? value->getTypeString() : node->getType();
|
||||
std::string t2 = other.value ? other.value->getTypeString() : other.node->getType();
|
||||
if (t1 != t2) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
NodeItem res(graph_);
|
||||
if (value && other.value) {
|
||||
if (value->isA<float>()) {
|
||||
float v1 = value->asA<float>();
|
||||
float v2 = other.value->asA<float>();
|
||||
res.value = MaterialX::Value::createValue<float>(func(v1, v2));
|
||||
}
|
||||
else if (value->isA<MaterialX::Color3>()) {
|
||||
auto v1 = value->asA<MaterialX::Color3>();
|
||||
auto v2 = other.value->asA<MaterialX::Color3>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Color3>(
|
||||
MaterialX::Color3(c[0], c[1], c[2]));
|
||||
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Color4>()) {
|
||||
auto v1 = value->asA<MaterialX::Color4>();
|
||||
auto v2 = other.value->asA<MaterialX::Color4>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Color4>(
|
||||
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector2>()) {
|
||||
auto v1 = value->asA<MaterialX::Vector2>();
|
||||
auto v2 = other.value->asA<MaterialX::Vector2>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Vector2>(
|
||||
{func(v1[0], v2[0]), func(v1[1], v2[1])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector3>()) {
|
||||
auto v1 = value->asA<MaterialX::Vector3>();
|
||||
auto v2 = other.value->asA<MaterialX::Vector3>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
|
||||
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])});
|
||||
}
|
||||
else if (value->isA<MaterialX::Vector4>()) {
|
||||
auto v1 = value->asA<MaterialX::Vector4>();
|
||||
auto v2 = other.value->asA<MaterialX::Vector4>();
|
||||
res.value = MaterialX::Value::createValue<MaterialX::Vector4>(
|
||||
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])});
|
||||
}
|
||||
else {
|
||||
/* default color */
|
||||
res.value = value;
|
||||
}
|
||||
}
|
||||
else if (node) {
|
||||
res.node = node;
|
||||
else {
|
||||
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t1);
|
||||
res.set_input("in1", *this);
|
||||
res.set_input("in2", other);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -31,8 +31,19 @@ class NodeItem {
|
||||
void set_input(const std::string &name, const MaterialX::NodePtr node);
|
||||
|
||||
operator bool() const;
|
||||
template<class T> NodeItem &operator=(const T &value);
|
||||
NodeItem operator+(const NodeItem &other);
|
||||
NodeItem operator-(const NodeItem &other);
|
||||
NodeItem operator*(const NodeItem &other);
|
||||
NodeItem operator/(const NodeItem &other);
|
||||
|
||||
NodeItem to_color3();
|
||||
NodeItem to_color3() const;
|
||||
|
||||
private:
|
||||
NodeItem arithmetic(const std::string &mx_category, std::function<float(float)> func);
|
||||
NodeItem arithmetic(const NodeItem &other,
|
||||
const std::string &mx_category,
|
||||
std::function<float(float, float)> func);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@ -41,6 +52,13 @@ void NodeItem::set_input(const std::string &name, const T &value, const std::str
|
||||
node->setInputValue(name, value, mx_type);
|
||||
}
|
||||
|
||||
template<class T> NodeItem &NodeItem::operator=(const T &value)
|
||||
{
|
||||
this->value = MaterialX::Value::createValue<T>(value);
|
||||
node = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
class NodeParser {
|
||||
public:
|
||||
MaterialX::GraphElement *graph;
|
||||
|
Loading…
Reference in New Issue
Block a user