forked from blender/blender
Create parsing system that converts supported nodes and ignores unsupported #2
@ -16,8 +16,8 @@ static void export_nodegraph(MaterialX::DocumentPtr doc, Depsgraph *depsgraph, M
|
||||
material->nodetree->ensure_topology_cache();
|
||||
|
||||
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
|
||||
MaterialXMaterialOutputNode material_node(doc, depsgraph, material, output_node);
|
||||
material_node.convert();
|
||||
OutputMaterialNodeParser material_node(doc, depsgraph, material, output_node);
|
||||
material_node.compute();
|
||||
}
|
||||
|
||||
static void create_standard_surface(MaterialX::DocumentPtr doc, Material *material)
|
||||
|
@ -8,18 +8,10 @@
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
|
||||
MaterialXPrincipledBSDFNode::MaterialXPrincipledBSDFNode(MaterialX::DocumentPtr doc,
|
||||
const Depsgraph *depsgraph,
|
||||
const Material *material,
|
||||
const bNode *node)
|
||||
: NodeParser(doc, depsgraph, material, node)
|
||||
NodeItem BSDFPrincipledNodeParser::compute()
|
||||
{
|
||||
matx_node = doc->addNode(
|
||||
"standard_surface", MaterialX::createValidName(node->name), "surfaceshader");
|
||||
}
|
||||
NodeItem node = create_node("standard_surface", "surfaceshader");
|
||||
|
||||
MaterialX::NodePtr MaterialXPrincipledBSDFNode::convert()
|
||||
{
|
||||
MaterialX::Color3 default_white_color = MaterialX::Color3(1.0, 1.0, 1.0);
|
||||
#pragma region get inputs
|
||||
const bNodeSocket base_color_socket = node->input_by_identifier("Base Color");
|
||||
|
@ -8,13 +8,10 @@
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
|
||||
class MaterialXPrincipledBSDFNode : public NodeParser {
|
||||
class BSDFPrincipledNodeParser : public NodeParser {
|
||||
public:
|
||||
MaterialXPrincipledBSDFNode(MaterialX::DocumentPtr doc,
|
||||
const Depsgraph *depsgraph,
|
||||
const Material *material,
|
||||
const bNode *node);
|
||||
MaterialX::NodePtr convert() override;
|
||||
using NodeParser::NodeParser;
|
||||
NodeItem compute() override;
|
||||
};
|
||||
|
||||
} // namespace blender::nodes::materialx
|
||||
|
@ -11,33 +11,141 @@
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
|
||||
NodeParser::NodeParser(MaterialX::DocumentPtr doc,
|
||||
const Depsgraph *depsgraph,
|
||||
const Material *material,
|
||||
const bNode *node)
|
||||
: depsgraph(depsgraph), material(material), node(node), doc(doc)
|
||||
NodeItem::NodeItem(MaterialX::GraphElement *graph)
|
||||
: graph_(graph)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeParser::get_input_link_node(const bNodeSocket *sock,
|
||||
MaterialX::NodePtr matx_node_to,
|
||||
const char *input)
|
||||
void NodeItem::set_input(const std::string &name, const NodeItem &item)
|
||||
{
|
||||
const bNode *inode = sock->link->fromnode;
|
||||
if (inode->type == SH_NODE_BSDF_PRINCIPLED) {
|
||||
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();
|
||||
if (item.value) {
|
||||
set_input(name, item.value);
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -69,7 +177,6 @@ std::string NodeParser::get_mx_type(const bNodeSocket *sock)
|
||||
}
|
||||
}
|
||||
return mx_sock_type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::materialx
|
||||
|
@ -12,26 +12,55 @@
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
|
||||
class NodeParser {
|
||||
class NodeItem {
|
||||
public:
|
||||
const Depsgraph *depsgraph = nullptr;
|
||||
const Material *material = nullptr;
|
||||
const bNode *node = nullptr;
|
||||
MaterialX::NodePtr matx_node;
|
||||
MaterialX::DocumentPtr doc;
|
||||
MaterialX::ValuePtr value;
|
||||
MaterialX::NodePtr node;
|
||||
|
||||
private:
|
||||
MaterialX::GraphElement *graph_;
|
||||
|
||||
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 Material *material,
|
||||
const bNode *node);
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
|
||||
MaterialXMaterialOutputNode::MaterialXMaterialOutputNode(MaterialX::DocumentPtr doc,
|
||||
OutputMaterialNodeParser::OutputMaterialNodeParser(MaterialX::DocumentPtr doc,
|
||||
const Depsgraph *depsgraph,
|
||||
const Material *material,
|
||||
const bNode *node)
|
||||
@ -15,8 +15,9 @@ MaterialXMaterialOutputNode::MaterialXMaterialOutputNode(MaterialX::DocumentPtr
|
||||
matx_node = doc->addNode("surfacematerial", MaterialX::createValidName(node->name), "material");
|
||||
}
|
||||
|
||||
MaterialX::NodePtr MaterialXMaterialOutputNode::convert()
|
||||
{ const char *matx_socket = "surfaceshader";
|
||||
MaterialX::NodePtr OutputMaterialNodeParser::compute()
|
||||
{
|
||||
const char *matx_socket = "surfaceshader";
|
||||
const bNodeSocket sock = node->input_by_identifier("Surface");
|
||||
get_input_link_node(&sock, matx_node, matx_socket);
|
||||
return matx_node;
|
||||
|
@ -8,13 +8,13 @@
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
|
||||
class MaterialXMaterialOutputNode : public NodeParser {
|
||||
class OutputMaterialNodeParser : public NodeParser {
|
||||
public:
|
||||
MaterialXMaterialOutputNode(MaterialX::DocumentPtr doc,
|
||||
OutputMaterialNodeParser(MaterialX::DocumentPtr doc,
|
||||
const Depsgraph *depsgraph,
|
||||
const Material *material,
|
||||
const bNode *node);
|
||||
MaterialX::NodePtr convert() override;
|
||||
MaterialX::NodePtr compute() override;
|
||||
};
|
||||
|
||||
} // namespace blender::nodes::materialx
|
||||
|
@ -11,9 +11,9 @@
|
||||
|
||||
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 Material *material,
|
||||
const bNode *node)
|
||||
@ -22,7 +22,7 @@ MaterialXTexImageNode::MaterialXTexImageNode(MaterialX::DocumentPtr doc,
|
||||
matx_node = doc->addNode("image", MaterialX::createValidName(node->name), "color3");
|
||||
}
|
||||
|
||||
MaterialX::NodePtr MaterialXTexImageNode::convert()
|
||||
MaterialX::NodePtr TexImageNodeParser::compute()
|
||||
{
|
||||
Image *image = (Image *)node->id;
|
||||
NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
|
||||
|
@ -8,17 +8,17 @@
|
||||
|
||||
namespace blender::nodes::materialx {
|
||||
|
||||
class MaterialXTexImageNode : public NodeParser {
|
||||
class TexImageNodeParser : public NodeParser {
|
||||
protected:
|
||||
/* Following Cycles color for wrong Texture nodes. */
|
||||
static const MaterialX::Color3 texture_error_color_;
|
||||
|
||||
public:
|
||||
MaterialXTexImageNode(MaterialX::DocumentPtr doc,
|
||||
TexImageNodeParser(MaterialX::DocumentPtr doc,
|
||||
const Depsgraph *depsgraph,
|
||||
const Material *material,
|
||||
const bNode *node);
|
||||
MaterialX::NodePtr convert() override;
|
||||
MaterialX::NodePtr compute() override;
|
||||
};
|
||||
|
||||
} // namespace blender::nodes::materialx
|
||||
|
Loading…
Reference in New Issue
Block a user