forked from blender/blender
Implement export of Math node. Continue other arithmetic support for NodeItem #6
@ -152,11 +152,13 @@ if(WITH_MATERIALX)
|
|||||||
materialx/nodes/invert.cc
|
materialx/nodes/invert.cc
|
||||||
materialx/nodes/math.cc
|
materialx/nodes/math.cc
|
||||||
materialx/nodes/mix_rgb.cc
|
materialx/nodes/mix_rgb.cc
|
||||||
|
materialx/nodes/node_item.cc
|
||||||
materialx/nodes/node_parser.cc
|
materialx/nodes/node_parser.cc
|
||||||
materialx/nodes/output_material.cc
|
materialx/nodes/output_material.cc
|
||||||
materialx/nodes/tex_image.cc
|
materialx/nodes/tex_image.cc
|
||||||
|
|
||||||
materialx/material.h
|
materialx/material.h
|
||||||
|
materialx/nodes/node_item.h
|
||||||
materialx/nodes/node_parser.h
|
materialx/nodes/node_parser.h
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@ -8,31 +8,16 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem BSDFPrincipledNodeParser::compute()
|
NodeItem BSDFPrincipledNodeParser::compute()
|
||||||
{
|
{
|
||||||
auto enabled = [](NodeItem &val) -> bool {
|
NodeItem zero = value(0.0f);
|
||||||
if (val.node) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!val.value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (val.value->isA<float>()) {
|
|
||||||
return val.value->asA<float>() != 0.0f;
|
|
||||||
}
|
|
||||||
if (val.value->isA<MaterialX::Color4>()) {
|
|
||||||
auto c = val.value->asA<MaterialX::Color4>();
|
|
||||||
return c[0] != 0.0f || c[1] != 0.0f || c[2] != 0.0f;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Getting required inputs
|
/* Getting required inputs
|
||||||
* Note: if some inputs are not needed they won't be taken */
|
* Note: if some inputs are not needed they won't be taken */
|
||||||
NodeItem base_color = get_input_value("Base Color");
|
NodeItem base_color = get_input_value("Base Color");
|
||||||
|
|
||||||
NodeItem subsurface = get_input_value("Subsurface");
|
NodeItem subsurface = get_input_value("Subsurface");
|
||||||
NodeItem subsurface_radius = empty_value();
|
NodeItem subsurface_radius = empty();
|
||||||
NodeItem subsurface_color = empty_value();
|
NodeItem subsurface_color = empty();
|
||||||
if (enabled(subsurface)) {
|
if (subsurface != zero) {
|
||||||
subsurface_radius = get_input_value("Subsurface Radius");
|
subsurface_radius = get_input_value("Subsurface Radius");
|
||||||
subsurface_color = get_input_value("Subsurface Color");
|
subsurface_color = get_input_value("Subsurface Color");
|
||||||
}
|
}
|
||||||
@ -42,33 +27,33 @@ NodeItem BSDFPrincipledNodeParser::compute()
|
|||||||
// NodeItem specular_tint = get_input_value("Specular Tint");
|
// NodeItem specular_tint = get_input_value("Specular Tint");
|
||||||
NodeItem roughness = get_input_value("Roughness");
|
NodeItem roughness = get_input_value("Roughness");
|
||||||
|
|
||||||
NodeItem anisotropic = empty_value();
|
NodeItem anisotropic = empty();
|
||||||
NodeItem anisotropic_rotation = empty_value();
|
NodeItem anisotropic_rotation = empty();
|
||||||
if (enabled(metallic)) {
|
if (metallic != zero) {
|
||||||
/* TODO: use Specular Tint input */
|
/* TODO: use Specular Tint input */
|
||||||
anisotropic = get_input_value("Anisotropic");
|
anisotropic = get_input_value("Anisotropic");
|
||||||
if (enabled(anisotropic)) {
|
if (anisotropic != zero) {
|
||||||
anisotropic_rotation = get_input_value("Anisotropic Rotation");
|
anisotropic_rotation = get_input_value("Anisotropic Rotation");
|
||||||
// anisotropic_rotation = 0.5 - (anisotropic_rotation % 1.0)
|
// anisotropic_rotation = 0.5 - (anisotropic_rotation % 1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem sheen = get_input_value("Sheen");
|
NodeItem sheen = get_input_value("Sheen");
|
||||||
// sheen_tint = empty_value();
|
// sheen_tint = empty();
|
||||||
// if enabled(sheen):
|
// if enabled(sheen):
|
||||||
// sheen_tint = get_input_value("Sheen Tint");
|
// sheen_tint = get_input_value("Sheen Tint");
|
||||||
|
|
||||||
NodeItem clearcoat = get_input_value("Clearcoat");
|
NodeItem clearcoat = get_input_value("Clearcoat");
|
||||||
NodeItem clearcoat_roughness = empty_value();
|
NodeItem clearcoat_roughness = empty();
|
||||||
if (enabled(clearcoat)) {
|
if (clearcoat != zero) {
|
||||||
clearcoat_roughness = get_input_value("Clearcoat Roughness");
|
clearcoat_roughness = get_input_value("Clearcoat Roughness");
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem ior = get_input_value("IOR");
|
NodeItem ior = get_input_value("IOR");
|
||||||
|
|
||||||
NodeItem transmission = get_input_value("Transmission");
|
NodeItem transmission = get_input_value("Transmission");
|
||||||
NodeItem transmission_roughness = empty_value();
|
NodeItem transmission_roughness = empty();
|
||||||
if (enabled(transmission)) {
|
if (transmission != zero) {
|
||||||
transmission_roughness = get_input_value("Transmission Roughness");
|
transmission_roughness = get_input_value("Transmission Roughness");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,11 +75,11 @@ NodeItem BSDFPrincipledNodeParser::compute()
|
|||||||
res.set_input("normal", normal);
|
res.set_input("normal", normal);
|
||||||
res.set_input("tangent", tangent);
|
res.set_input("tangent", tangent);
|
||||||
|
|
||||||
if (enabled(metallic)) {
|
if (metallic != zero) {
|
||||||
res.set_input("metalness", metallic);
|
res.set_input("metalness", metallic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled(specular)) {
|
if (specular != zero) {
|
||||||
res.set_input("specular", specular);
|
res.set_input("specular", specular);
|
||||||
res.set_input("specular_color", base_color.to_color3());
|
res.set_input("specular_color", base_color.to_color3());
|
||||||
res.set_input("specular_roughness", roughness);
|
res.set_input("specular_roughness", roughness);
|
||||||
@ -103,26 +88,26 @@ NodeItem BSDFPrincipledNodeParser::compute()
|
|||||||
res.set_input("specular_rotation", anisotropic_rotation);
|
res.set_input("specular_rotation", anisotropic_rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled(transmission)) {
|
if (transmission != zero) {
|
||||||
res.set_input("transmission", transmission);
|
res.set_input("transmission", transmission);
|
||||||
res.set_input("transmission_color", base_color.to_color3());
|
res.set_input("transmission_color", base_color.to_color3());
|
||||||
res.set_input("transmission_extra_roughness", transmission_roughness);
|
res.set_input("transmission_extra_roughness", transmission_roughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled(subsurface)) {
|
if (subsurface != zero) {
|
||||||
res.set_input("subsurface", subsurface);
|
res.set_input("subsurface", subsurface);
|
||||||
res.set_input("subsurface_color", subsurface_color);
|
res.set_input("subsurface_color", subsurface_color);
|
||||||
res.set_input("subsurface_radius", subsurface_radius);
|
res.set_input("subsurface_radius", subsurface_radius);
|
||||||
res.set_input("subsurface_anisotropy", anisotropic);
|
res.set_input("subsurface_anisotropy", anisotropic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled(sheen)) {
|
if (sheen != zero) {
|
||||||
res.set_input("sheen", sheen);
|
res.set_input("sheen", sheen);
|
||||||
res.set_input("sheen_color", base_color.to_color3());
|
res.set_input("sheen_color", base_color.to_color3());
|
||||||
res.set_input("sheen_roughness", roughness);
|
res.set_input("sheen_roughness", roughness);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled(clearcoat)) {
|
if (clearcoat != zero) {
|
||||||
res.set_input("coat", clearcoat);
|
res.set_input("coat", clearcoat);
|
||||||
res.set_input("coat_color", base_color.to_color3());
|
res.set_input("coat_color", base_color.to_color3());
|
||||||
res.set_input("coat_roughness", clearcoat_roughness);
|
res.set_input("coat_roughness", clearcoat_roughness);
|
||||||
@ -132,7 +117,7 @@ NodeItem BSDFPrincipledNodeParser::compute()
|
|||||||
res.set_input("coat_normal", clearcoat_normal);
|
res.set_input("coat_normal", clearcoat_normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabled(emission)) {
|
if (emission != zero) {
|
||||||
res.set_input("emission", emission_strength);
|
res.set_input("emission", emission_strength);
|
||||||
res.set_input("emission_color", emission);
|
res.set_input("emission_color", emission);
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,164 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem MathNodeParser::compute()
|
NodeItem MathNodeParser::compute()
|
||||||
{
|
{
|
||||||
/* TODO: implement */
|
/* TODO: finish some math operations */
|
||||||
return empty_value();
|
|
||||||
|
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;
|
||||||
|
case NODE_MATH_TRUNC:
|
||||||
|
res = x.sign() * x.abs().floor();
|
||||||
|
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_SNAP:
|
||||||
|
// res = ;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_PINGPONG:
|
||||||
|
// res = ;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_FLOORED_MODULO:
|
||||||
|
// res = ;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
/* 3-operand operations */
|
||||||
|
NodeItem z = get_input_value(2);
|
||||||
|
switch (op) {
|
||||||
|
case NODE_MATH_WRAP:
|
||||||
|
// res = ;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_COMPARE:
|
||||||
|
res = z.if_else("<", (x - y).abs(), value(1.0f), value(0.0f));
|
||||||
|
break;
|
||||||
|
case NODE_MATH_MULTIPLY_ADD:
|
||||||
|
res = x * y + z;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SMOOTH_MIN:
|
||||||
|
// res = ;
|
||||||
|
break;
|
||||||
|
case NODE_MATH_SMOOTH_MAX:
|
||||||
|
// res = ;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool clamp_output = node->custom2 != 0;
|
||||||
|
if (clamp_output && res) {
|
||||||
|
res = res.clamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -9,7 +9,7 @@ namespace blender::nodes::materialx {
|
|||||||
NodeItem MixRGBNodeParser::compute()
|
NodeItem MixRGBNodeParser::compute()
|
||||||
{
|
{
|
||||||
/* TODO: implement */
|
/* TODO: implement */
|
||||||
return empty_value();
|
return empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
599
source/blender/nodes/shader/materialx/nodes/node_item.cc
Normal file
599
source/blender/nodes/shader/materialx/nodes/node_item.cc
Normal file
@ -0,0 +1,599 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include "node_item.h"
|
||||||
|
|
||||||
|
#include "BLI_assert.h"
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
NodeItem::NodeItem(MaterialX::GraphElement *graph) : graph_(graph) {}
|
||||||
|
|
||||||
|
NodeItem NodeItem::empty() const
|
||||||
|
{
|
||||||
|
return NodeItem(graph_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeItem::set_input(const std::string &name, const NodeItem &item)
|
||||||
|
{
|
||||||
|
if (item.value) {
|
||||||
|
set_input(name, item.value);
|
||||||
|
}
|
||||||
|
else if (item.node) {
|
||||||
|
set_input(name, item.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeItem::set_input(const std::string &name, const MaterialX::ValuePtr value)
|
||||||
|
{
|
||||||
|
std::string mx_type = value->getTypeString();
|
||||||
|
if (mx_type == "float") {
|
||||||
|
set_input(name, value->asA<float>(), mx_type);
|
||||||
|
}
|
||||||
|
else if (mx_type == "integer") {
|
||||||
|
set_input(name, value->asA<int>(), mx_type);
|
||||||
|
}
|
||||||
|
else if (mx_type == "vector2") {
|
||||||
|
set_input(name, value->asA<MaterialX::Vector2>(), mx_type);
|
||||||
|
}
|
||||||
|
else if (mx_type == "vector3") {
|
||||||
|
set_input(name, value->asA<MaterialX::Vector3>(), mx_type);
|
||||||
|
}
|
||||||
|
else if (mx_type == "vector4") {
|
||||||
|
set_input(name, value->asA<MaterialX::Vector4>(), mx_type);
|
||||||
|
}
|
||||||
|
else if (mx_type == "color3") {
|
||||||
|
set_input(name, value->asA<MaterialX::Color3>(), mx_type);
|
||||||
|
}
|
||||||
|
else if (mx_type == "color4") {
|
||||||
|
set_input(name, value->asA<MaterialX::Color4>(), mx_type);
|
||||||
|
}
|
||||||
|
else if (mx_type == "string") {
|
||||||
|
set_input(name, value->asA<std::string>(), mx_type);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeItem::set_input(const std::string &name, const MaterialX::NodePtr node)
|
||||||
|
{
|
||||||
|
this->node->setConnectedNode(name, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem::operator bool() const
|
||||||
|
{
|
||||||
|
return value || node;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::operator+(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(other, "add", [](float a, float b) { return a + b; });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::operator-(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(other, "subtract", [](float a, float b) { return a - b; });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::operator-() const
|
||||||
|
{
|
||||||
|
return val(0.0f) - *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::operator*(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(other, "multiply", [](float a, float b) { return a * b; });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::operator/(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(other, "divide", [](float a, float b) { return b == 0.0f ? 0.0f : a / b; });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::operator%(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(
|
||||||
|
other, "modulo", [](float a, float b) { return b == 0.0f ? 0.0f : std::fmodf(a, b); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::operator^(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(other, "power", [](float a, float b) { return std::powf(a, b); });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeItem::operator==(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
if (!*this) {
|
||||||
|
return !other;
|
||||||
|
}
|
||||||
|
if (!other) {
|
||||||
|
return !*this;
|
||||||
|
}
|
||||||
|
if (node && node == other.node) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((node && other.value) || (value && other.node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string mx_type;
|
||||||
|
auto val1 = value;
|
||||||
|
auto val2 = other.value;
|
||||||
|
if (!adjust_types(val1, val2, mx_type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mx_type == "float") {
|
||||||
|
return val1->asA<float>() == val2->asA<float>();
|
||||||
|
}
|
||||||
|
if (mx_type == "color3") {
|
||||||
|
return val1->asA<MaterialX::Color3>() == val2->asA<MaterialX::Color3>();
|
||||||
|
}
|
||||||
|
if (mx_type == "color4") {
|
||||||
|
return val1->asA<MaterialX::Color4>() == val2->asA<MaterialX::Color4>();
|
||||||
|
}
|
||||||
|
if (mx_type == "vector2") {
|
||||||
|
return val1->asA<MaterialX::Vector2>() == val2->asA<MaterialX::Vector2>();
|
||||||
|
}
|
||||||
|
if (mx_type == "vector3") {
|
||||||
|
return val1->asA<MaterialX::Vector3>() == val2->asA<MaterialX::Vector3>();
|
||||||
|
}
|
||||||
|
if (mx_type == "vector4") {
|
||||||
|
return val1->asA<MaterialX::Vector4>() == val2->asA<MaterialX::Vector4>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeItem::operator!=(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::abs() const
|
||||||
|
{
|
||||||
|
return arithmetic("absval", [](float a) { return std::fabsf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::floor() const
|
||||||
|
{
|
||||||
|
return arithmetic("floor", [](float a) { return std::floorf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::ceil() const
|
||||||
|
{
|
||||||
|
return arithmetic("ceil", [](float a) { return std::ceilf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::min(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(other, "min", [](float a, float b) { return std::min(a, b); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::max(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
return arithmetic(other, "max", [](float a, float b) { return std::max(a, b); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::dotproduct(const NodeItem &other) const
|
||||||
|
{
|
||||||
|
NodeItem d = arithmetic(other, "dotproduct", [](float a, float b) { return a * b; });
|
||||||
|
if (d.value) {
|
||||||
|
std::string mx_type = d.type();
|
||||||
|
float f = 0.0f;
|
||||||
|
if (mx_type == "float") {
|
||||||
|
f = value->asA<float>();
|
||||||
|
}
|
||||||
|
else if (mx_type == "color3") {
|
||||||
|
auto v = value->asA<MaterialX::Color3>();
|
||||||
|
f = v[0] + v[1] + v[2];
|
||||||
|
}
|
||||||
|
else if (mx_type == "color4") {
|
||||||
|
auto v = value->asA<MaterialX::Color4>();
|
||||||
|
f = v[0] + v[1] + v[2] + v[3];
|
||||||
|
}
|
||||||
|
else if (mx_type == "vector2") {
|
||||||
|
auto v = value->asA<MaterialX::Vector2>();
|
||||||
|
f = v[0] + v[1];
|
||||||
|
}
|
||||||
|
else if (mx_type == "vector3") {
|
||||||
|
auto v = value->asA<MaterialX::Vector3>();
|
||||||
|
f = v[0] + v[1] + v[2];
|
||||||
|
}
|
||||||
|
else if (mx_type == "vector4") {
|
||||||
|
auto v = value->asA<MaterialX::Vector4>();
|
||||||
|
f = v[0] + v[1] + v[2] + v[3];
|
||||||
|
}
|
||||||
|
d.value = MaterialX::Value::createValue(f);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::if_else(const std::string &condition,
|
||||||
|
const NodeItem &other,
|
||||||
|
const NodeItem &if_val,
|
||||||
|
const NodeItem &else_val) const
|
||||||
|
{
|
||||||
|
if (condition == "<") {
|
||||||
|
return other.if_else(">", *this, else_val, if_val);
|
||||||
|
}
|
||||||
|
if (condition == "<=") {
|
||||||
|
return other.if_else(">=", *this, else_val, if_val);
|
||||||
|
}
|
||||||
|
if (condition == "!=") {
|
||||||
|
return if_else("==", other, else_val, if_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem res = empty();
|
||||||
|
if (type() != "float" || other.type() != "float") {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto val1 = if_val;
|
||||||
|
auto val2 = else_val;
|
||||||
|
std::string mx_type;
|
||||||
|
if (!adjust_types(val1, val2, mx_type)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<bool(float, float)> func = nullptr;
|
||||||
|
std::string mx_category;
|
||||||
|
if (condition == ">") {
|
||||||
|
mx_category = "ifgreater";
|
||||||
|
func = [](float a, float b) { return a > b; };
|
||||||
|
}
|
||||||
|
else if (condition == ">=") {
|
||||||
|
mx_category = "ifgreatereq";
|
||||||
|
func = [](float a, float b) { return a >= b; };
|
||||||
|
}
|
||||||
|
else if (condition == "==") {
|
||||||
|
mx_category = "ifequal";
|
||||||
|
func = [](float a, float b) { return a == b; };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value && other.value) {
|
||||||
|
res = func(value->asA<float>(), other.value->asA<float>()) ? val1 : val2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, mx_type);
|
||||||
|
res.set_input("value1", *this);
|
||||||
|
res.set_input("value2", other);
|
||||||
|
res.set_input("in1", val1);
|
||||||
|
res.set_input("in2", val2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) const
|
||||||
|
{
|
||||||
|
return (val(1.0f) - *this) * a + *this * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::clamp(const NodeItem &min_val, const NodeItem &max_val) const
|
||||||
|
{
|
||||||
|
return min(max_val).max(min_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::clamp(float min_val, float max_val) const
|
||||||
|
{
|
||||||
|
return clamp(val(min_val), val(max_val));
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::sin() const
|
||||||
|
{
|
||||||
|
return arithmetic("sin", [](float a) { return std::sinf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::cos() const
|
||||||
|
{
|
||||||
|
return arithmetic("cos", [](float a) { return std::cosf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::tan() const
|
||||||
|
{
|
||||||
|
return arithmetic("tan", [](float a) { return std::tanf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::asin() const
|
||||||
|
{
|
||||||
|
return arithmetic("asin", [](float a) { return std::asinf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::acos() const
|
||||||
|
{
|
||||||
|
return arithmetic("acos", [](float a) { return std::acosf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::atan() const
|
||||||
|
{
|
||||||
|
return arithmetic("atan", [](float a) { return std::atanf(a); });
|
||||||
|
}
|
||||||
|
|
||||||
|
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() - (-*this).exp()) / val(2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::cosh() const
|
||||||
|
{
|
||||||
|
return (exp() - (-*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();
|
||||||
|
NodeItem res = empty();
|
||||||
|
if (value) {
|
||||||
|
MaterialX::Color3 c;
|
||||||
|
if (t == "float") {
|
||||||
|
float v = value->asA<float>();
|
||||||
|
c = {v, v, v};
|
||||||
|
}
|
||||||
|
else if (t == "color3") {
|
||||||
|
auto v = value->asA<MaterialX::Color3>();
|
||||||
|
c = {v[0], v[1], v[2]};
|
||||||
|
}
|
||||||
|
else if (t == "color4") {
|
||||||
|
auto v = value->asA<MaterialX::Color4>();
|
||||||
|
c = {v[0], v[1], v[2]};
|
||||||
|
}
|
||||||
|
else if (t == "vector3") {
|
||||||
|
auto v = value->asA<MaterialX::Vector3>();
|
||||||
|
c = {v[0], v[1], v[2]};
|
||||||
|
}
|
||||||
|
else if (t == "vector4") {
|
||||||
|
auto v = value->asA<MaterialX::Vector4>();
|
||||||
|
c = {v[0], v[1], v[2]};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
res.value = MaterialX::Value::createValue<MaterialX::Color3>(c);
|
||||||
|
}
|
||||||
|
else if (node) {
|
||||||
|
if (t != "color3") {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
res.node = node;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeItem::is_numeric() const
|
||||||
|
{
|
||||||
|
std::string t = type();
|
||||||
|
return ELEM(t, "float", "color3", "color4", "vector2", "vector3", "vector4");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NodeItem::type() const
|
||||||
|
{
|
||||||
|
return value ? value->getTypeString() : node->getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::arithmetic(const std::string &mx_category,
|
||||||
|
std::function<float(float)> func) const
|
||||||
|
{
|
||||||
|
if (!is_numeric()) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string t = value ? value->getTypeString() : node->getType();
|
||||||
|
NodeItem res(graph_);
|
||||||
|
if (value) {
|
||||||
|
if (t == "float") {
|
||||||
|
float v = value->asA<float>();
|
||||||
|
res.value = MaterialX::Value::createValue<float>(func(v));
|
||||||
|
}
|
||||||
|
else if (t == "color3") {
|
||||||
|
auto v = value->asA<MaterialX::Color3>();
|
||||||
|
res.value = MaterialX::Value::createValue<MaterialX::Color3>(
|
||||||
|
{func(v[0]), func(v[1]), func(v[2])});
|
||||||
|
}
|
||||||
|
else if (t == "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 (t == "vector2") {
|
||||||
|
auto v = value->asA<MaterialX::Vector2>();
|
||||||
|
res.value = MaterialX::Value::createValue<MaterialX::Vector2>({func(v[0]), func(v[1])});
|
||||||
|
}
|
||||||
|
else if (t == "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 (t == "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 {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) const
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
if (!is_numeric() || !other.is_numeric()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string mx_type;
|
||||||
|
if (value && other.value) {
|
||||||
|
auto val1 = value;
|
||||||
|
auto val2 = other.value;
|
||||||
|
if (!adjust_types(val1, val2, mx_type)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mx_type == "float") {
|
||||||
|
float v1 = val1->asA<float>();
|
||||||
|
float v2 = val2->asA<float>();
|
||||||
|
res.value = MaterialX::Value::createValue<float>(func(v1, v2));
|
||||||
|
}
|
||||||
|
else if (mx_type == "color3") {
|
||||||
|
auto v1 = val1->asA<MaterialX::Color3>();
|
||||||
|
auto v2 = val2->asA<MaterialX::Color3>();
|
||||||
|
res.value = MaterialX::Value::createValue<MaterialX::Color3>(
|
||||||
|
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])});
|
||||||
|
}
|
||||||
|
else if (mx_type == "color4") {
|
||||||
|
auto v1 = val1->asA<MaterialX::Color4>();
|
||||||
|
auto v2 = val2->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 (mx_type == "vector2") {
|
||||||
|
auto v1 = val1->asA<MaterialX::Vector2>();
|
||||||
|
auto v2 = val2->asA<MaterialX::Vector2>();
|
||||||
|
res.value = MaterialX::Value::createValue<MaterialX::Vector2>(
|
||||||
|
{func(v1[0], v2[0]), func(v1[1], v2[1])});
|
||||||
|
}
|
||||||
|
else if (mx_type == "vector3") {
|
||||||
|
auto v1 = val1->asA<MaterialX::Vector3>();
|
||||||
|
auto v2 = val2->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 (mx_type == "vector4") {
|
||||||
|
auto v1 = val1->asA<MaterialX::Vector4>();
|
||||||
|
auto v2 = val2->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 {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto val1 = *this;
|
||||||
|
auto val2 = other;
|
||||||
|
if (!adjust_types(val1, val2, mx_type)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, mx_type);
|
||||||
|
res.set_input("in1", val1);
|
||||||
|
res.set_input("in2", val2);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialX::ValuePtr NodeItem::float_to_type(float v, std::string mx_type)
|
||||||
|
{
|
||||||
|
if (mx_type == "float") {
|
||||||
|
return MaterialX::Value::createValue<float>(v);
|
||||||
|
}
|
||||||
|
if (mx_type == "color3") {
|
||||||
|
return MaterialX::Value::createValue<MaterialX::Color3>({v, v, v});
|
||||||
|
}
|
||||||
|
if (mx_type == "color4") {
|
||||||
|
return MaterialX::Value::createValue<MaterialX::Color4>({v, v, v, 1.0f});
|
||||||
|
}
|
||||||
|
if (mx_type == "vector2") {
|
||||||
|
return MaterialX::Value::createValue<MaterialX::Vector2>({v, v});
|
||||||
|
}
|
||||||
|
if (mx_type == "vector3") {
|
||||||
|
return MaterialX::Value::createValue<MaterialX::Vector3>({v, v, v});
|
||||||
|
}
|
||||||
|
if (mx_type == "vector4") {
|
||||||
|
return MaterialX::Value::createValue<MaterialX::Vector4>({v, v, v, 1.0f});
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeItem::adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, std::string &mx_type)
|
||||||
|
{
|
||||||
|
std::string t1 = val1->getTypeString();
|
||||||
|
std::string t2 = val2->getTypeString();
|
||||||
|
if (t1 != t2) {
|
||||||
|
if (t1 == "float") {
|
||||||
|
val1 = float_to_type(val1->asA<float>(), t2);
|
||||||
|
mx_type = t2;
|
||||||
|
}
|
||||||
|
else if (t2 == "float") {
|
||||||
|
val2 = float_to_type(val2->asA<float>(), t1);
|
||||||
|
mx_type = t1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mx_type = t1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeItem::adjust_types(NodeItem &val1, NodeItem &val2, std::string &mx_type)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
mx_type = t2;
|
||||||
|
}
|
||||||
|
else if (val2.value && t2 == "float") {
|
||||||
|
val2.value = float_to_type(val2.value->asA<float>(), t1);
|
||||||
|
mx_type = t1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mx_type = t1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
99
source/blender/nodes/shader/materialx/nodes/node_item.h
Normal file
99
source/blender/nodes/shader/materialx/nodes/node_item.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <MaterialXCore/Node.h>
|
||||||
|
|
||||||
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
class NodeItem {
|
||||||
|
public:
|
||||||
|
MaterialX::ValuePtr value;
|
||||||
|
MaterialX::NodePtr node;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MaterialX::GraphElement *graph_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NodeItem(MaterialX::GraphElement *graph);
|
||||||
|
~NodeItem() = default;
|
||||||
|
|
||||||
|
NodeItem empty() const;
|
||||||
|
template<class T> NodeItem val(const T &data) const;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void set_input(const std::string &name, const T &value, const std::string &mx_type);
|
||||||
|
void set_input(const std::string &name, const NodeItem &item);
|
||||||
|
void set_input(const std::string &name, const MaterialX::ValuePtr value);
|
||||||
|
void set_input(const std::string &name, const MaterialX::NodePtr node);
|
||||||
|
|
||||||
|
operator bool() const;
|
||||||
|
NodeItem operator+(const NodeItem &other) const;
|
||||||
|
NodeItem operator-(const NodeItem &other) const;
|
||||||
|
NodeItem operator-() const;
|
||||||
|
NodeItem operator*(const NodeItem &other) const;
|
||||||
|
NodeItem operator/(const NodeItem &other) const;
|
||||||
|
NodeItem operator%(const NodeItem &other) const;
|
||||||
|
NodeItem operator^(const NodeItem &other) const;
|
||||||
|
bool operator==(const NodeItem &other) const;
|
||||||
|
bool operator!=(const NodeItem &other) const;
|
||||||
|
|
||||||
|
NodeItem abs() const;
|
||||||
|
NodeItem floor() const;
|
||||||
|
NodeItem ceil() const;
|
||||||
|
NodeItem min(const NodeItem &other) const;
|
||||||
|
NodeItem max(const NodeItem &other) const;
|
||||||
|
NodeItem dotproduct(const NodeItem &other) const;
|
||||||
|
NodeItem if_else(const std::string &condition,
|
||||||
|
const NodeItem &other,
|
||||||
|
const NodeItem &if_val,
|
||||||
|
const NodeItem &else_val) const;
|
||||||
|
NodeItem blend(const NodeItem &a, const NodeItem &b) const;
|
||||||
|
NodeItem clamp(const NodeItem &min_val, const NodeItem &max_val) const;
|
||||||
|
NodeItem clamp(float min_val = 0.0f, float max_val = 1.0f) const;
|
||||||
|
NodeItem sin() const;
|
||||||
|
NodeItem cos() const;
|
||||||
|
NodeItem tan() const;
|
||||||
|
NodeItem asin() const;
|
||||||
|
NodeItem acos() const;
|
||||||
|
NodeItem atan() 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;
|
||||||
|
std::string type() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodeItem arithmetic(const std::string &mx_category, std::function<float(float)> func) const;
|
||||||
|
NodeItem arithmetic(const NodeItem &other,
|
||||||
|
const std::string &mx_category,
|
||||||
|
std::function<float(float, float)> func) const;
|
||||||
|
static MaterialX::ValuePtr float_to_type(float v, std::string mx_type);
|
||||||
|
/* Functions for adjusting values to make equal types */
|
||||||
|
static bool adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, std::string &mx_type);
|
||||||
|
static bool adjust_types(NodeItem &val1, NodeItem &val2, std::string &mx_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> NodeItem NodeItem::val(const T &data) const
|
||||||
|
{
|
||||||
|
NodeItem res(graph_);
|
||||||
|
res.value = MaterialX::Value::createValue<T>(data);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void NodeItem::set_input(const std::string &name, const T &value, const std::string &mx_type)
|
||||||
|
{
|
||||||
|
node->setInputValue(name, value, mx_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
@ -8,323 +8,6 @@
|
|||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
NodeItem::NodeItem(MaterialX::GraphElement *graph) : graph_(graph) {}
|
|
||||||
|
|
||||||
NodeItem NodeItem::empty() const
|
|
||||||
{
|
|
||||||
return NodeItem(graph_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeItem::set_input(const std::string &name, const NodeItem &item)
|
|
||||||
{
|
|
||||||
if (item.value) {
|
|
||||||
set_input(name, item.value);
|
|
||||||
}
|
|
||||||
else if (item.node) {
|
|
||||||
set_input(name, item.node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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>(), 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>(), mx_type);
|
|
||||||
}
|
|
||||||
else if (value->isA<MaterialX::Vector4>()) {
|
|
||||||
set_input(name, value->asA<MaterialX::Vector4>(), mx_type);
|
|
||||||
}
|
|
||||||
else if (value->isA<MaterialX::Color3>()) {
|
|
||||||
set_input(name, value->asA<MaterialX::Color3>(), mx_type);
|
|
||||||
}
|
|
||||||
else if (value->isA<MaterialX::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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeItem::set_input(const std::string &name, const MaterialX::NodePtr node)
|
|
||||||
{
|
|
||||||
this->node->setConnectedNode(name, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem::operator bool() const
|
|
||||||
{
|
|
||||||
return value || node;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::operator+(const NodeItem &other) const
|
|
||||||
{
|
|
||||||
return arithmetic(other, "add", [](float a, float b) { return a + b; });
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::operator-(const NodeItem &other) const
|
|
||||||
{
|
|
||||||
return arithmetic(other, "subtract", [](float a, float b) { return a - b; });
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::operator*(const NodeItem &other) const
|
|
||||||
{
|
|
||||||
return arithmetic(other, "multiply", [](float a, float b) { return a * b; });
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::operator/(const NodeItem &other) const
|
|
||||||
{
|
|
||||||
return arithmetic(other, "divide", [](float a, float b) { return b == 0.0f ? 0.0f : a / b; });
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NodeItem::operator==(const NodeItem &other) const
|
|
||||||
{
|
|
||||||
if (node && node == other.node) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/* TODO: implement */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::min(const NodeItem &other) const
|
|
||||||
{
|
|
||||||
return arithmetic(other, "min", [](float a, float b) { return std::min(a, b); });
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::max(const NodeItem &other) const
|
|
||||||
{
|
|
||||||
return arithmetic(other, "max", [](float a, float b) { return std::max(a, b); });
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) const
|
|
||||||
{
|
|
||||||
return (val(1.0f) - *this) * a + *this * b;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::to_color3() const
|
|
||||||
{
|
|
||||||
std::string t = type();
|
|
||||||
NodeItem res = empty();
|
|
||||||
if (value) {
|
|
||||||
MaterialX::Color3 c;
|
|
||||||
if (t == "float") {
|
|
||||||
float v = value->asA<float>();
|
|
||||||
c = {v, v, v};
|
|
||||||
}
|
|
||||||
else if (t == "color3") {
|
|
||||||
auto v = value->asA<MaterialX::Color3>();
|
|
||||||
c = {v[0], v[1], v[2]};
|
|
||||||
}
|
|
||||||
else if (t == "color4") {
|
|
||||||
auto v = value->asA<MaterialX::Color4>();
|
|
||||||
c = {v[0], v[1], v[2]};
|
|
||||||
}
|
|
||||||
else if (t == "vector3") {
|
|
||||||
auto v = value->asA<MaterialX::Vector3>();
|
|
||||||
c = {v[0], v[1], v[2]};
|
|
||||||
}
|
|
||||||
else if (t == "vector4") {
|
|
||||||
auto v = value->asA<MaterialX::Vector4>();
|
|
||||||
c = {v[0], v[1], v[2]};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
res.value = MaterialX::Value::createValue<MaterialX::Color3>(c);
|
|
||||||
}
|
|
||||||
else if (node) {
|
|
||||||
if (t != "color3") {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
res.node = node;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NodeItem::is_numeric() const
|
|
||||||
{
|
|
||||||
std::string t = type();
|
|
||||||
return ELEM(t, "float", "color3", "color4", "vector2", "vector3", "vector4");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NodeItem::type() const
|
|
||||||
{
|
|
||||||
return value ? value->getTypeString() : node->getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::arithmetic(const std::string &mx_category,
|
|
||||||
std::function<float(float)> func) const
|
|
||||||
{
|
|
||||||
if (!is_numeric()) {
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string t = value ? value->getTypeString() : node->getType();
|
|
||||||
NodeItem res(graph_);
|
|
||||||
if (value) {
|
|
||||||
if (t == "float") {
|
|
||||||
float v = value->asA<float>();
|
|
||||||
res.value = MaterialX::Value::createValue<float>(func(v));
|
|
||||||
}
|
|
||||||
else if (t == "color3") {
|
|
||||||
auto v = value->asA<MaterialX::Color3>();
|
|
||||||
res.value = MaterialX::Value::createValue<MaterialX::Color3>(
|
|
||||||
{func(v[0]), func(v[1]), func(v[2])});
|
|
||||||
}
|
|
||||||
else if (t == "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 (t == "vector2") {
|
|
||||||
auto v = value->asA<MaterialX::Vector2>();
|
|
||||||
res.value = MaterialX::Value::createValue<MaterialX::Vector2>({func(v[0]), func(v[1])});
|
|
||||||
}
|
|
||||||
else if (t == "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 (t == "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 {
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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) const
|
|
||||||
{
|
|
||||||
NodeItem res = empty();
|
|
||||||
if (!is_numeric() || !other.is_numeric()) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string t1 = type();
|
|
||||||
std::string t2 = other.type();
|
|
||||||
|
|
||||||
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 (t == "float") {
|
|
||||||
float v1 = val1->asA<float>();
|
|
||||||
float v2 = val2->asA<float>();
|
|
||||||
res.value = MaterialX::Value::createValue<float>(func(v1, v2));
|
|
||||||
}
|
|
||||||
else if (t == "color3") {
|
|
||||||
auto v1 = val1->asA<MaterialX::Color3>();
|
|
||||||
auto v2 = val2->asA<MaterialX::Color3>();
|
|
||||||
res.value = MaterialX::Value::createValue<MaterialX::Color3>(
|
|
||||||
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])});
|
|
||||||
}
|
|
||||||
else if (t == "color4") {
|
|
||||||
auto v1 = val1->asA<MaterialX::Color4>();
|
|
||||||
auto v2 = val2->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 (t == "vector2") {
|
|
||||||
auto v1 = val1->asA<MaterialX::Vector2>();
|
|
||||||
auto v2 = val2->asA<MaterialX::Vector2>();
|
|
||||||
res.value = MaterialX::Value::createValue<MaterialX::Vector2>(
|
|
||||||
{func(v1[0], v2[0]), func(v1[1], v2[1])});
|
|
||||||
}
|
|
||||||
else if (t == "vector3") {
|
|
||||||
auto v1 = val1->asA<MaterialX::Vector3>();
|
|
||||||
auto v2 = val2->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 (t == "vector4") {
|
|
||||||
auto v1 = val1->asA<MaterialX::Vector4>();
|
|
||||||
auto v2 = val2->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 {
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, t);
|
|
||||||
res.set_input("in1", val1);
|
|
||||||
res.set_input("in2", val2);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialX::ValuePtr NodeItem::float_to_type(float v, std::string t) const
|
|
||||||
{
|
|
||||||
if (t == "float") {
|
|
||||||
return MaterialX::Value::createValue<float>(v);
|
|
||||||
}
|
|
||||||
if (t == "color3") {
|
|
||||||
return MaterialX::Value::createValue<MaterialX::Color3>({v, v, v});
|
|
||||||
}
|
|
||||||
if (t == "color4") {
|
|
||||||
return MaterialX::Value::createValue<MaterialX::Color4>({v, v, v, 1.0f});
|
|
||||||
}
|
|
||||||
if (t == "vector2") {
|
|
||||||
return MaterialX::Value::createValue<MaterialX::Vector2>({v, v});
|
|
||||||
}
|
|
||||||
if (t == "vector3") {
|
|
||||||
return MaterialX::Value::createValue<MaterialX::Vector3>({v, v, v});
|
|
||||||
}
|
|
||||||
if (t == "vector4") {
|
|
||||||
return MaterialX::Value::createValue<MaterialX::Vector4>({v, v, v, 1.0f});
|
|
||||||
}
|
|
||||||
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
NodeParser::NodeParser(MaterialX::GraphElement *graph,
|
||||||
const Depsgraph *depsgraph,
|
const Depsgraph *depsgraph,
|
||||||
const Material *material,
|
const Material *material,
|
||||||
@ -337,7 +20,7 @@ NodeItem NodeParser::create_node(const std::string &mx_category,
|
|||||||
const std::string &mx_type,
|
const std::string &mx_type,
|
||||||
bool accessory)
|
bool accessory)
|
||||||
{
|
{
|
||||||
NodeItem res = empty_value();
|
NodeItem res = empty();
|
||||||
res.node = graph->addNode(mx_category,
|
res.node = graph->addNode(mx_category,
|
||||||
accessory ? MaterialX::EMPTY_STRING :
|
accessory ? MaterialX::EMPTY_STRING :
|
||||||
MaterialX::createValidName(node->name),
|
MaterialX::createValidName(node->name),
|
||||||
@ -347,9 +30,42 @@ NodeItem NodeParser::create_node(const std::string &mx_category,
|
|||||||
|
|
||||||
NodeItem NodeParser::get_input_default(const std::string &name)
|
NodeItem NodeParser::get_input_default(const std::string &name)
|
||||||
{
|
{
|
||||||
NodeItem res = empty_value();
|
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) {
|
switch (socket.type) {
|
||||||
case SOCK_FLOAT: {
|
case SOCK_FLOAT: {
|
||||||
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
|
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
|
||||||
@ -372,11 +88,11 @@ NodeItem NodeParser::get_input_default(const std::string &name)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::get_input_link(const std::string &name)
|
NodeItem NodeParser::get_input_link(const bNodeSocket &socket)
|
||||||
{
|
{
|
||||||
NodeItem res = empty_value();
|
NodeItem res = empty();
|
||||||
|
|
||||||
const bNodeLink *link = node->input_by_identifier(name).link;
|
const bNodeLink *link = socket.link;
|
||||||
if (!(link && link->is_used())) {
|
if (!(link && link->is_used())) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -419,18 +135,13 @@ NodeItem NodeParser::get_input_link(const std::string &name)
|
|||||||
return res;
|
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) {
|
if (!res) {
|
||||||
res = get_input_default(name);
|
res = get_input_default(socket);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeParser::empty_value()
|
|
||||||
{
|
|
||||||
return NodeItem(graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <MaterialXCore/Document.h>
|
#include "node_item.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
@ -12,63 +12,6 @@
|
|||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
class NodeItem {
|
|
||||||
public:
|
|
||||||
MaterialX::ValuePtr value;
|
|
||||||
MaterialX::NodePtr node;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MaterialX::GraphElement *graph_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
NodeItem(MaterialX::GraphElement *graph);
|
|
||||||
~NodeItem() = default;
|
|
||||||
|
|
||||||
NodeItem empty() const;
|
|
||||||
template<class T> NodeItem val(const T &data) const;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void set_input(const std::string &name, const T &value, const std::string &mx_type);
|
|
||||||
void set_input(const std::string &name, const NodeItem &item);
|
|
||||||
void set_input(const std::string &name, const MaterialX::ValuePtr value);
|
|
||||||
void set_input(const std::string &name, const MaterialX::NodePtr node);
|
|
||||||
|
|
||||||
operator bool() const;
|
|
||||||
NodeItem operator+(const NodeItem &other) const;
|
|
||||||
NodeItem operator-(const NodeItem &other) const;
|
|
||||||
NodeItem operator*(const NodeItem &other) const;
|
|
||||||
NodeItem operator/(const NodeItem &other) const;
|
|
||||||
bool operator==(const NodeItem &other) const;
|
|
||||||
|
|
||||||
NodeItem min(const NodeItem &other) const;
|
|
||||||
NodeItem max(const NodeItem &other) const;
|
|
||||||
NodeItem blend(const NodeItem &a, const NodeItem &b) const;
|
|
||||||
|
|
||||||
NodeItem to_color3() const;
|
|
||||||
bool is_numeric() const;
|
|
||||||
std::string type() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
NodeItem arithmetic(const std::string &mx_category, std::function<float(float)> func) const;
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T> NodeItem NodeItem::val(const T &data) const
|
|
||||||
{
|
|
||||||
NodeItem res(graph_);
|
|
||||||
res.value = MaterialX::Value::createValue<T>(data);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void NodeItem::set_input(const std::string &name, const T &value, const std::string &mx_type)
|
|
||||||
{
|
|
||||||
node->setInputValue(name, value, mx_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
class NodeParser {
|
class NodeParser {
|
||||||
public:
|
public:
|
||||||
MaterialX::GraphElement *graph;
|
MaterialX::GraphElement *graph;
|
||||||
@ -90,11 +33,25 @@ class NodeParser {
|
|||||||
const std::string &mx_type,
|
const std::string &mx_type,
|
||||||
bool accessory = false);
|
bool accessory = false);
|
||||||
NodeItem get_input_default(const std::string &name);
|
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(const std::string &name);
|
||||||
|
NodeItem get_input_link(int index);
|
||||||
NodeItem get_input_value(const std::string &name);
|
NodeItem get_input_value(const std::string &name);
|
||||||
NodeItem empty_value();
|
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
|
||||||
|
{
|
||||||
|
return empty().val(data);
|
||||||
|
}
|
||||||
|
|
||||||
#define DECLARE_PARSER(T) \
|
#define DECLARE_PARSER(T) \
|
||||||
class T : public NodeParser { \
|
class T : public NodeParser { \
|
||||||
public: \
|
public: \
|
||||||
|
@ -8,7 +8,7 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem OutputMaterialNodeParser::compute()
|
NodeItem OutputMaterialNodeParser::compute()
|
||||||
{
|
{
|
||||||
NodeItem node = empty_value();
|
NodeItem node = empty();
|
||||||
NodeItem surface = get_input_link("Surface");
|
NodeItem surface = get_input_link("Surface");
|
||||||
if (surface) {
|
if (surface) {
|
||||||
node = create_node("surfacematerial", "material");
|
node = create_node("surfacematerial", "material");
|
||||||
|
Loading…
Reference in New Issue
Block a user