Create parsing system that converts supported nodes and ignores unsupported #2

Merged
Bogdan Nagirniak merged 14 commits from Vasyl-Pidhirskyi/blender:BLEN-500 into matx-export-material 2023-08-28 12:29:46 +02:00
9 changed files with 203 additions and 77 deletions
Showing only changes of commit b9323f2298 - Show all commits

View File

@ -16,8 +16,8 @@ static void export_nodegraph(MaterialX::DocumentPtr doc, Depsgraph *depsgraph, M
material->nodetree->ensure_topology_cache(); material->nodetree->ensure_topology_cache();
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
MaterialXMaterialOutputNode material_node(doc, depsgraph, material, output_node); OutputMaterialNodeParser material_node(doc, depsgraph, material, output_node);
material_node.convert(); material_node.compute();
} }
static void create_standard_surface(MaterialX::DocumentPtr doc, Material *material) static void create_standard_surface(MaterialX::DocumentPtr doc, Material *material)

View File

@ -8,18 +8,10 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
MaterialXPrincipledBSDFNode::MaterialXPrincipledBSDFNode(MaterialX::DocumentPtr doc, NodeItem BSDFPrincipledNodeParser::compute()
const Depsgraph *depsgraph,
const Material *material,
const bNode *node)
: NodeParser(doc, depsgraph, material, node)
{ {
matx_node = doc->addNode( NodeItem node = create_node("standard_surface", "surfaceshader");
"standard_surface", MaterialX::createValidName(node->name), "surfaceshader");
}
MaterialX::NodePtr MaterialXPrincipledBSDFNode::convert()
{
MaterialX::Color3 default_white_color = MaterialX::Color3(1.0, 1.0, 1.0); MaterialX::Color3 default_white_color = MaterialX::Color3(1.0, 1.0, 1.0);
#pragma region get inputs #pragma region get inputs
const bNodeSocket base_color_socket = node->input_by_identifier("Base Color"); const bNodeSocket base_color_socket = node->input_by_identifier("Base Color");

View File

@ -8,13 +8,10 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
class MaterialXPrincipledBSDFNode : public NodeParser { class BSDFPrincipledNodeParser : public NodeParser {
public: public:
MaterialXPrincipledBSDFNode(MaterialX::DocumentPtr doc, using NodeParser::NodeParser;
const Depsgraph *depsgraph, NodeItem compute() override;
const Material *material,
const bNode *node);
MaterialX::NodePtr convert() override;
}; };
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -11,33 +11,141 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
NodeParser::NodeParser(MaterialX::DocumentPtr doc, NodeItem::NodeItem(MaterialX::GraphElement *graph)
const Depsgraph *depsgraph, : graph_(graph)
const Material *material,
const bNode *node)
: depsgraph(depsgraph), material(material), node(node), doc(doc)
{ {
} }
void NodeParser::get_input_link_node(const bNodeSocket *sock, void NodeItem::set_input(const std::string &name, const NodeItem &item)
MaterialX::NodePtr matx_node_to,
const char *input)
{ {
const bNode *inode = sock->link->fromnode; if (item.value) {
if (inode->type == SH_NODE_BSDF_PRINCIPLED) { set_input(name, item.value);
MaterialXPrincipledBSDFNode maxt_node(doc, depsgraph, material, inode);
maxt_node.convert();
}
else if (inode->type == SH_NODE_TEX_IMAGE) {
MaterialXTexImageNode maxt_node(doc, depsgraph, material, inode);
maxt_node.convert();
} }
else { else {
return; set_input(name, item.node);
}
}
void NodeItem::set_input(const std::string &name, const MaterialX::ValuePtr value)
{
if (value->isA<float>()) {
set_input(name, value->asA<float>(), "float");
}
else if (value->isA<MaterialX::Vector3>()) {
set_input(name, value->asA<MaterialX::Vector3>(), "vector3");
}
else if (value->isA<MaterialX::Vector4>()) {
set_input(name, value->asA<MaterialX::Vector4>(), "vector4");
}
else if (value->isA<MaterialX::Color3>()) {
set_input(name, value->asA<MaterialX::Color3>(), "color3");
}
else if (value->isA<MaterialX::Color4>()) {
set_input(name, value->asA<MaterialX::Color4>(), "color4");
}
else {
BLI_assert_unreachable();
}
}
void NodeItem::set_input(const std::string &name, const MaterialX::NodePtr node)
{
node->setConnectedNode(name, node);
}
NodeItem::operator bool() const
{
return !value && !node;
}
NodeParser::NodeParser(MaterialX::GraphElement *graph,
const Depsgraph *depsgraph,
const Material *material,
const bNode *node)
: graph(graph), depsgraph(depsgraph), material(material), node(node)
{
}
NodeItem NodeParser::create_node(const std::string &mx_category, const std::string &mx_type)
{
NodeItem item(graph);
item.node = graph->addNode(mx_category, MaterialX::createValidName(node->name), mx_type);
return item;
}
NodeItem NodeParser::get_input_default(const std::string &name)
{
const bNodeSocket &socket = node->input_by_identifier(name);
NodeItem item(graph);
switch (socket.type) {
case SOCK_FLOAT: {
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
item.value = MaterialX::Value::createValue<float>(v);
} break;
case SOCK_VECTOR: {
const float *v = socket.default_value_typed<bNodeSocketValueVector>()->value;
item.value = MaterialX::Value::createValue<MaterialX::Vector3>(
MaterialX::Vector3(v[0], v[1], v[2]));
} break;
case SOCK_RGBA: {
const float *v = socket.default_value_typed<bNodeSocketValueRGBA>()->value;
item.value = MaterialX::Value::createValue<MaterialX::Color4>(
MaterialX::Color4(v[0], v[1], v[2], v[3]));
} break;
default: {
// TODO log warn
}
}
return item;
}
NodeItem NodeParser::get_input_link(const std::string &name)
{
NodeItem item(graph);
const bNodeLink *link = node->input_by_identifier(name).link;
if (!link->is_used()) {
return item;
}
const bNode *in_node = link->fromnode;
/* Passing NODE_REROUTE nodes */
while (in_node->type == NODE_REROUTE) {
link = in_node->input_socket(0).link;
if (!link->is_used()) {
return item;
}
in_node = link->fromnode;
}
/* Getting required NodeParser object */
std::unique_ptr<NodeParser> parser;
switch (in_node->type) {
case SH_NODE_BSDF_PRINCIPLED:
parser = std::make_unique<BSDFPrincipledNodeParser>(graph, depsgraph, material, in_node);
break;
case SH_NODE_TEX_IMAGE:
parser = std::make_unique<TexImageNodeParser>(graph, depsgraph, material, in_node);
break;
default:
// TODO: warning log
return item;
}
item = parser->compute();
return item;
}
NodeItem NodeParser::get_input_value(const std::string &name)
{
NodeItem item = get_input_link(name);
if (!item) {
item = get_input_value(name);
}
return item;
} }
const bNodeSocket *sock_from = sock->link->fromsock;
matx_node_to->addInput(input, get_mx_type(sock))->setNodeName(MaterialX::createValidName(inode->name));
};
std::string NodeParser::get_mx_type(const bNodeSocket *sock) std::string NodeParser::get_mx_type(const bNodeSocket *sock)
{ {
@ -69,7 +177,6 @@ std::string NodeParser::get_mx_type(const bNodeSocket *sock)
} }
} }
return mx_sock_type; return mx_sock_type;
}; }
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -12,26 +12,55 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
class NodeParser { class NodeItem {
public: public:
const Depsgraph *depsgraph = nullptr; MaterialX::ValuePtr value;
const Material *material = nullptr; MaterialX::NodePtr node;
const bNode *node = nullptr;
MaterialX::NodePtr matx_node; private:
MaterialX::DocumentPtr doc; MaterialX::GraphElement *graph_;
public: public:
NodeParser(MaterialX::DocumentPtr doc, NodeItem(MaterialX::GraphElement *graph);
~NodeItem() = default;
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;
};
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 {
public:
MaterialX::GraphElement *graph;
const Depsgraph *depsgraph;
const Material *material;
const bNode *node;
public:
NodeParser(MaterialX::GraphElement *graph,
const Depsgraph *depsgraph, const Depsgraph *depsgraph,
const Material *material, const Material *material,
const bNode *node); const bNode *node);
virtual ~NodeParser() = default; virtual ~NodeParser() = default;
virtual MaterialX::NodePtr convert() = 0; virtual NodeItem compute() = 0;
protected:
NodeItem create_node(const std::string &mx_category, const std::string &mx_type);
NodeItem get_input_default(const std::string &name);
NodeItem get_input_link(const std::string &name);
NodeItem get_input_value(const std::string &name);
void get_input_link_node(const bNodeSocket *sock,
MaterialX::NodePtr matx_node_from,
const char *input);
std::string get_mx_type(const bNodeSocket *sock); std::string get_mx_type(const bNodeSocket *sock);
}; };

View File

@ -6,7 +6,7 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
MaterialXMaterialOutputNode::MaterialXMaterialOutputNode(MaterialX::DocumentPtr doc, OutputMaterialNodeParser::OutputMaterialNodeParser(MaterialX::DocumentPtr doc,
const Depsgraph *depsgraph, const Depsgraph *depsgraph,
const Material *material, const Material *material,
const bNode *node) const bNode *node)
@ -15,8 +15,9 @@ MaterialXMaterialOutputNode::MaterialXMaterialOutputNode(MaterialX::DocumentPtr
matx_node = doc->addNode("surfacematerial", MaterialX::createValidName(node->name), "material"); matx_node = doc->addNode("surfacematerial", MaterialX::createValidName(node->name), "material");
} }
MaterialX::NodePtr MaterialXMaterialOutputNode::convert() MaterialX::NodePtr OutputMaterialNodeParser::compute()
{ const char *matx_socket = "surfaceshader"; {
const char *matx_socket = "surfaceshader";
const bNodeSocket sock = node->input_by_identifier("Surface"); const bNodeSocket sock = node->input_by_identifier("Surface");
get_input_link_node(&sock, matx_node, matx_socket); get_input_link_node(&sock, matx_node, matx_socket);
return matx_node; return matx_node;

View File

@ -8,13 +8,13 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
class MaterialXMaterialOutputNode : public NodeParser { class OutputMaterialNodeParser : public NodeParser {
public: public:
MaterialXMaterialOutputNode(MaterialX::DocumentPtr doc, OutputMaterialNodeParser(MaterialX::DocumentPtr doc,
const Depsgraph *depsgraph, const Depsgraph *depsgraph,
const Material *material, const Material *material,
const bNode *node); const bNode *node);
MaterialX::NodePtr convert() override; MaterialX::NodePtr compute() override;
}; };
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx

View File

@ -11,9 +11,9 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
const MaterialX::Color3 MaterialXTexImageNode::texture_error_color_{1.0, 0.0, 1.0}; const MaterialX::Color3 TexImageNodeParser::texture_error_color_{1.0, 0.0, 1.0};
MaterialXTexImageNode::MaterialXTexImageNode(MaterialX::DocumentPtr doc, TexImageNodeParser::TexImageNodeParser(MaterialX::DocumentPtr doc,
const Depsgraph *depsgraph, const Depsgraph *depsgraph,
const Material *material, const Material *material,
const bNode *node) const bNode *node)
@ -22,7 +22,7 @@ MaterialXTexImageNode::MaterialXTexImageNode(MaterialX::DocumentPtr doc,
matx_node = doc->addNode("image", MaterialX::createValidName(node->name), "color3"); matx_node = doc->addNode("image", MaterialX::createValidName(node->name), "color3");
} }
MaterialX::NodePtr MaterialXTexImageNode::convert() MaterialX::NodePtr TexImageNodeParser::compute()
{ {
Image *image = (Image *)node->id; Image *image = (Image *)node->id;
NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage); NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);

View File

@ -8,17 +8,17 @@
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
class MaterialXTexImageNode : public NodeParser { class TexImageNodeParser : public NodeParser {
protected: protected:
/* Following Cycles color for wrong Texture nodes. */ /* Following Cycles color for wrong Texture nodes. */
static const MaterialX::Color3 texture_error_color_; static const MaterialX::Color3 texture_error_color_;
public: public:
MaterialXTexImageNode(MaterialX::DocumentPtr doc, TexImageNodeParser(MaterialX::DocumentPtr doc,
const Depsgraph *depsgraph, const Depsgraph *depsgraph,
const Material *material, const Material *material,
const bNode *node); const bNode *node);
MaterialX::NodePtr convert() override; MaterialX::NodePtr compute() override;
}; };
} // namespace blender::nodes::materialx } // namespace blender::nodes::materialx