MaterialX: add support for Vector nodes #27

Merged
Bogdan Nagirniak merged 13 commits from Vasyl-Pidhirskyi/blender:BLEN-525 into matx-export-material 2023-09-22 10:03:45 +02:00
10 changed files with 121 additions and 144 deletions
Showing only changes of commit f9f73e7459 - Show all commits

View File

@ -617,6 +617,23 @@ NodeItem NodeItem::empty() const
return NodeItem(graph_);
}
NodeItem NodeItem::rotate3d(NodeItem rotation, bool invert)
{
NodeItem res = *this;
if (res.type() == Type::Vector3 && rotation.type() == Type::Vector3) {
for (int i = 0; i <= 2; i++) {
int j = invert ? 2 - i : i;
MaterialX::Vector3 axis_vector = MaterialX::Vector3();
axis_vector[j] = 1.0f;
res = create_node(
"rotate3d",
NodeItem::Type::Vector3,
{{"in", res}, {"amount", rotation.extract(j)}, {"axis", val(axis_vector)}});
}
}
return res;
}
NodeItem::Type NodeItem::type() const
{
if (value) {

View File

@ -107,6 +107,7 @@ class NodeItem {
/* Useful functions */
NodeItem empty() const;
NodeItem rotate3d(NodeItem rotation, bool invert = false);
template<class T> NodeItem val(const T &data) const;
Type type() const;

View File

@ -74,23 +74,27 @@ static int gpu_shader_bump(GPUMaterial *mat,
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
NodeItem distance = get_input_value("Distance", NodeItem::Type::Float);
NodeItem height = get_input_link("Height", NodeItem::Type::Float);
NodeItem normal = get_input_link("Normal", NodeItem::Type::Vector3);
if (node_->custom1) {
distance = distance * val(-1.0f);
if (!height) {
if (!normal) {
return create_node(
"normal", NodeItem::Type::Vector3, {{"space", val(std::string("world"))}});
}
return normal;
}
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
NodeItem distance = get_input_value("Distance", NodeItem::Type::Float);
NodeItem height_normal = create_node(
"heighttonormal", NodeItem::Type::Vector3, {{"in", height}, {"scale", strength}});
NodeItem res = create_node("normalmap",
return create_node("normalmap",
NodeItem::Type::Vector3,
{{"in", height_normal}, {"scale", distance}, {"normal", normal}});
return res;
{{"in", height_normal},
{"scale", node_->custom1 ? distance * val(-1.0f) : distance},
{"normal", normal}});
}
#endif
NODE_SHADER_MATERIALX_END

View File

@ -45,11 +45,9 @@ NODE_SHADER_MATERIALX_BEGIN
NodeItem height = get_input_value("Height", NodeItem::Type::Float) - midlevel;
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
NodeItem res = create_node("displacement",
return create_node("displacement",
NodeItem::Type::Displacementshader,
{{"displacement", height}, {"scale", scale}});
return res;
}
#endif
NODE_SHADER_MATERIALX_END

View File

@ -78,61 +78,35 @@ NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeItem res = empty();
NodeItem location = get_input_value("Location", NodeItem::Type::Vector3);
NodeItem scale = get_input_value("Scale", NodeItem::Type::Vector3);
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
NodeItem angle = (get_input_value("Rotation", NodeItem::Type::Vector3) / val(float(M_PI))) *
val(180.0f);
MaterialX::Vector3 axis_vector;
const int mode = node_->custom1;
switch (mode) {
if (!vector) {
return res;
}
NodeItem scale = get_input_value("Scale", NodeItem::Type::Vector3);
NodeItem location = get_input_value("Location", NodeItem::Type::Vector3);
NodeItem rotation = (get_input_value("Rotation", NodeItem::Type::Vector3) *
val(float(180.0f / M_PI)));
switch (node_->custom1) {
case NODE_MAPPING_TYPE_POINT:
res = vector * scale;
res = (vector * scale).rotate3d(rotation) + location;
break;
case NODE_MAPPING_TYPE_TEXTURE:
res = vector - location;
res = (vector - location).rotate3d(rotation, true) / scale;
break;
case NODE_MAPPING_TYPE_VECTOR:
res = vector * scale;
res = (vector * scale).rotate3d(rotation * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f)));
break;
case NODE_MAPPING_TYPE_NORMAL:
res = vector / scale;
res = create_node(
"normalize", NodeItem::Type::Vector3, {{"in", (vector / scale).rotate3d(rotation)}});
break;
default:
BLI_assert_unreachable();
return vector;
}
bool tex = mode == NODE_MAPPING_TYPE_TEXTURE;
float inv = tex ? -1.0 : 1.0;
for (int i = tex ? 2 : 0; tex ? i >= 0 : i <= 2; tex ? i-- : i++) {
axis_vector = MaterialX::Vector3(0.0f, 0.0f, 0.0f);
axis_vector[i] = inv;
if (i == 2) { // invert Z axis to get the same result as Cycles
inv *= -1.0f;
}
axis_vector[i] = inv;
res = create_node("rotate3d",
NodeItem::Type::Vector3,
{{"in", res}, {"amount", angle.extract(i)}, {"axis", val(axis_vector)}});
}
switch (mode) {
case NODE_MAPPING_TYPE_POINT:
res = res + location;
break;
case NODE_MAPPING_TYPE_TEXTURE:
res = res / scale;
break;
case NODE_MAPPING_TYPE_NORMAL:
res = create_node("normalize", NodeItem::Type::Vector3, {{"in", res}});
break;
}
return res;
}
#endif

View File

@ -38,14 +38,13 @@ static int gpu_shader_normal(GPUMaterial *mat,
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
std::string name = socket_out_->name;
NodeItem in1 = get_output_default("Normal", NodeItem::Type::Vector3);
NodeItem in2 = get_input_value("Normal", NodeItem::Type::Vector3);
if (name == "Dot") {
NodeItem res = create_node("dotproduct", NodeItem::Type::Float, {{"in1", in1}, {"in2", in2}});
return res;
NodeItem res = get_output_default("Normal", NodeItem::Type::Vector3);
if (STREQ(socket_out_->name, "Dot")) {
res = res.dotproduct(get_input_value("Normal", NodeItem::Type::Vector3));
}
return in1;
return res;
}
#endif
NODE_SHADER_MATERIALX_END

View File

@ -126,7 +126,7 @@ NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
NodeShaderNormalMap *normal_map_node = static_cast<NodeShaderNormalMap *>(node_->storage);
NodeItem color = get_input_value("Color", NodeItem::Type::Color3);
NodeItem color = get_input_value("Color", NodeItem::Type::Vector3);
NodeItem strength = get_input_value("Strength", NodeItem::Type::Float);
std::string space;

View File

@ -49,11 +49,9 @@ NODE_SHADER_MATERIALX_BEGIN
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
NodeItem res = create_node("displacement",
return create_node("displacement",
NodeItem::Type::Displacementshader,
{{"displacement", vector}, {"scale", scale}});
return res;
}
#endif
NODE_SHADER_MATERIALX_END

View File

@ -215,75 +215,62 @@ static void node_shader_update_vector_rotate(bNodeTree *ntree, bNode *node)
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
/* NOTE: This node doesn't have an implementation in MaterialX.*/
NodeItem res = create_node("rotate3d", NodeItem::Type::Vector3);
MaterialX::Vector3 axis_vector;
NodeItem angle = empty();
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3);
if (!vector) {
return empty();
}
NodeItem angle = empty();
NodeItem axis = empty();
NodeItem center = get_input_value("Center", NodeItem::Type::Vector3) *
val(MaterialX::Vector3(1.0f, 1.0f, -1.0f));
NodeItem vector = get_input_link("Vector", NodeItem::Type::Vector3) - center;
const int mode = node_->custom1;
const int invert = node_->custom2 ? -1.0f : 1.0f;
NodeItem res = vector - center;
int mode = node_->custom1;
bool invert = node_->custom1;
switch (mode) {
case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ:
if (mode == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
angle = get_input_value("Rotation", NodeItem::Type::Vector3);
if (angle == 0.0) {
return vector;
angle = angle * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f));
}
angle = (angle / val(float(M_PI))) * val(180.0f);
for (int i = node_->custom2 ? 2 : 0; node_->custom2 ? i >= 0 : i <= 2;
node_->custom2 ? i-- : i++) {
axis_vector = MaterialX::Vector3(0.0f, 0.0f, 0.0f);
int inv = invert;
if (i == 2) {
inv *= -1.0f;
}
axis_vector[i] = inv;
NodeItem res_rot = create_node(
"rotate3d",
NodeItem::Type::Vector3,
{{"in", vector}, {"amount", angle.extract(i)}, {"axis", val(axis_vector)}});
vector = res_rot;
}
res = vector;
break;
default: {
else {
angle = get_input_value("Angle", NodeItem::Type::Float);
if (angle == 0.0) {
return vector;
}
angle = (angle / val(float(M_PI))) * val(180.0f);
NodeItem axis = empty();
if (node_->custom2) {
angle = angle * val(-1.0f);
}
angle = angle * val(float(180.0f / M_PI));
angle = invert ? angle * val(-1.0f) : angle;
switch (mode) {
case NODE_VECTOR_ROTATE_TYPE_AXIS:
axis = get_input_value("Axis", NodeItem::Type::Vector3);
axis = axis * val(MaterialX::Vector3(1.0f, 1.0f, -1.0f));
case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: {
return res.rotate3d(angle, invert) + center;
}
case NODE_VECTOR_ROTATE_TYPE_AXIS: {
axis = get_input_value("Axis", NodeItem::Type::Vector3) *
val(MaterialX::Vector3(1.0f, 1.0f, -1.0f));
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_X:
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_X: {
axis = val(MaterialX::Vector3(1.0f, 0.0f, 0.0f));
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: {
axis = val(MaterialX::Vector3(0.0f, 1.0f, 0.0f));
break;
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
}
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: {
axis = val(MaterialX::Vector3(0.0f, 0.0f, -1.0f));
break;
default:
}
default: {
BLI_assert_unreachable();
return vector;
}
res.set_input("in", vector);
res.set_input("amount", angle);
res.set_input("axis", axis);
}
}
return res + center;
return create_node("rotate3d",
NodeItem::Type::Vector3,
{{"in", res}, {"amount", angle}, {"axis", axis}}) +
center;
}
#endif
NODE_SHADER_MATERIALX_END

View File

@ -140,13 +140,13 @@ static int gpu_shader_vect_transform(GPUMaterial *mat,
NODE_SHADER_MATERIALX_BEGIN
#ifdef WITH_MATERIALX
{
/* NOTE: SHD_VECT_TRANSFORM_SPACE_CAMERA don't have an implementation in MaterialX.*/
NodeItem res = empty();
std::string name = socket_out_->name;
NodeShaderVectTransform *nodeprop = (NodeShaderVectTransform *)node_->storage;
std::string fromspace = "world";
std::string tospace = "world";
std::string fromspace;
std::string tospace;
std::string category;
NodeItem vector = get_input_value("Vector", NodeItem::Type::Vector3);
switch (nodeprop->convert_from) {
Vasyl-Pidhirskyi marked this conversation as resolved
Review

Here and other places:

default:
	BLI_assert_unreachable();
Here and other places: ``` default: BLI_assert_unreachable(); ```
case SHD_VECT_TRANSFORM_SPACE_WORLD:
fromspace = "world";
@ -154,12 +154,12 @@ NODE_SHADER_MATERIALX_BEGIN
case SHD_VECT_TRANSFORM_SPACE_OBJECT:
fromspace = "object";
break;
case SHD_VECT_TRANSFORM_SPACE_CAMERA:
return vector;
default:
/* NOTE: SHD_VECT_TRANSFORM_SPACE_CAMERA don't have an implementation in MaterialX.*/
BLI_assert_unreachable();
return vector;
}
switch (nodeprop->convert_to) {
case SHD_VECT_TRANSFORM_SPACE_WORLD:
tospace = "world";
@ -167,35 +167,34 @@ NODE_SHADER_MATERIALX_BEGIN
case SHD_VECT_TRANSFORM_SPACE_OBJECT:
tospace = "object";
break;
case SHD_VECT_TRANSFORM_SPACE_CAMERA:
return vector;
default:
/* NOTE: SHD_VECT_TRANSFORM_SPACE_CAMERA don't have an implementation in MaterialX.*/
BLI_assert_unreachable();
return vector;
}
if (fromspace == tospace) {
return vector;
}
switch (nodeprop->type) {
case SHD_VECT_TRANSFORM_TYPE_POINT:
res = create_node("transformpoint", NodeItem::Type::Vector3);
category = "transformpoint";
break;
case SHD_VECT_TRANSFORM_TYPE_NORMAL:
res = create_node("transformnormal", NodeItem::Type::Vector3);
category = "transformnormal";
break;
case SHD_VECT_TRANSFORM_TYPE_VECTOR:
res = create_node("transformvector", NodeItem::Type::Vector3);
category = "transformvector";
break;
default:
BLI_assert_unreachable();
return vector;
}
res.set_input("in", vector);
res.set_input("fromspace", val(fromspace));
res.set_input("tospace", val(tospace));
return res;
return create_node(category,
NodeItem::Type::Vector3,
{{"in", vector}, {"fromspace", val(fromspace)}, {"tospace", val(tospace)}});
}
#endif
NODE_SHADER_MATERIALX_END