gpt4 book ai didi

c++ - Material 变化回调 (C++)

转载 作者:太空宇宙 更新时间:2023-11-04 12:38:54 24 4
gpt4 key购买 nike

我目前正在 Maya 2018 和 2019 中处理自定义视口(viewport)。目前,我正在实现我的 Material 解析器以将 Maya Material 解析为我自己框架的 Material 。

但是,我在创建回调方面非常吃力。我已经设法让初始回调开始工作,这可以在下面的代码片段中看到。这只是在将网格和 Material 添加到场景时加载它们的回调。

MCallbackId material_added_id = MDGMessage::addNodeAddedCallback(
MaterialAddedCallback,
"mesh",
m_material_parser.get(),
&status
);

在这个回调函数中,我获取了连接到这个网格的所有着色器,并尝试将回调附加到对着色器对象所做的任何更改(参见下面的代码片段)。

void wmr::MaterialParser::Parse(const MFnMesh& mesh)
{
// ...
MObjectArray shaders; // References to the shaders used on the meshes
MIntArray material_indices; // Indices to the materials in the object array

// Get all attached shaders for this instance
mesh.getConnectedShaders(instance_index, shaders, material_indices);

switch (shaders.length())
{
// No shaders applied to this mesh instance
case 0:
{
}
break;
// All faces use the same material
case 1:
{
MPlug surface_shader = GetSurfaceShader(shaders[0]);

// Invalid surface shader
if (!surface_shader.has_value())
return;

// Find all plugs that are connected to this shader
MPlugArray connected_plugs;
surface_shader.value().connectedTo(connected_plugs, true, false);

// Could not find a valid connected plug
if (connected_plugs.length() != 1)
return;

auto shader_type = GetShaderType(connected_plugs[0].node());

// Shader type not supported by this plug-in
if (shader_type == detail::SurfaceShaderType::UNSUPPORTED)
return;

// Found a Lambert shader
if (shader_type == detail::SurfaceShaderType::LAMBERT)
{
MGlobal::displayInfo("Found a Lambert shader!");

MPlug color_plug = GetPlugByName(connected_plugs[0].node(), "color");

// Retrieve the texture associated with this plug
auto texture_path = GetPlugTexture(color_plug);

// Print the texture location
MGlobal::displayInfo(texture_path.asChar());

// Add callback that filters on material changes
MStatus status;
MCallbackId attributeId = MNodeMessage::addAttributeChangedCallback(
shaders[0],
MaterialCallback,
this,
&status
);
CallbackManager::GetInstance().RegisterCallback(attributeId);
}
}
break;
// Two or more materials are used
default:
{
// ...
break;
}
}
}

void MaterialCallback(MNodeMessage::AttributeMessage msg, MPlug &plug, MPlug &otherPlug, void *clientData)
{
MGlobal::displayInfo("Hey! Im a material callback!");
}

注意开关盒。特别是 case 1:,当找到一个着色器时。 “Found Lambert” 在找到 lambert 着色器时打印在输出中。之后,我将回调 addAttributeChangedCallback 附加到着色器对象。但是,这永远不会被触发。

输出如下所示(有时更改透明度和颜色值后)。如您所见,“嘿!我是 Material 回调!” 没有打印在任何地方,但是当我更改 Material 的属性时应该调用它。

// Found a Lambert shader!

//
select -r pCylinder1 ;
setAttr "lambert1.transparency" -type double3 0.0779221 0.0779221 0.0779221 ;
setAttr "lambert1.transparency" -type double3 0.194805 0.194805 0.194805 ;
setAttr "lambert1.color" -type double3 0.0779221 0.0779221 0.0779221 ;

所以,我不确定我在这里做错了什么,因为据我所知,关于这个问题的样本不多(或任何)。

一些帮助将不胜感激。提前致谢!

最佳答案

我自己解决了我的问题。为了让提问者没有给出答案而感到沮丧,我会告诉你问题是什么:)

因此,实现存在两个问题。首先,我将回调绑定(bind)到不正确的对象。我将回调绑定(bind)到 shader[0]。这个连接的着色器是一个带有表面着色器、位移着色器等的着色器组。当我更改 Lambert 着色器的属性时,此 shader[0] 的属性不会改变。因此,我必须将回调绑定(bind)到 connected_plug[0](这是一个连接到 shader[0] 的插头)。 connected_plug[0] 是已接收到的着色器组中的表面着色器节点。

其次,我使用了不正确的回调函数。 addAttributeChangedCallback 结果是错误的工厂函数。相反,我不得不使用 addNodeDirtyCallback,因为我将回调绑定(bind)到的对象是一个节点/插件。

MObjectArray shaders;
mesh.getConnectedShaders(instance_index, shaders, material_indices);

// ...

MPlugArray connected_plugs;
surface_shader.value().connectedTo(connected_plugs, true, false);

// ...

MObject connected_plug = connected_plugs[0].node();

// ...

// Add callback that filters on material changes
MStatus status;
MCallbackId attributeId = MNodeMessage::addNodeDirtyCallback(
connected_plug,
DirtyNodeCallback,
this,
&status
);

关于c++ - Material 变化回调 (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55221304/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com