回答授权 Rhino 用户支持群中的一个问题,如何调用 RhinoCommon 给 Brep 中子面赋予不同的双面材质。
用户遇到的问题主要是,通过 brepObject.Attributes.RenderMaterial = rm0
修改物件的 RenderMaterial 会整体改变 Brep 的材质,而使用 Material 该用户无法将双面材质赋予给子面的同时保持其他面的材质。
这里提供一个范例,重要的地方在范例中注释出来了。
这个范例不会去新建 RenderMaterial,调用已经在 Rhino 中创建好的双面材质,双面材质已经放在下面的 3dm 文件中:
Brep子面材质.3dm (78.8 KB)
using System;
using Rhino;
using Rhino.Commands;
using Rhino.DocObjects;
using Rhino.Geometry;
using Rhino.Input;
using Rhino.Input.Custom;
using Rhino.Render;
Run();
void Run(){
var doc = RhinoDoc.ActiveDoc;
ObjRef objRef = null;
using (GetObject go = new GetObject())
{
go.SetCommandPrompt("Select brep object to set face materials to");
go.GeometryFilter = ObjectType.Brep;
var goRes = go.Get();
if (goRes != GetResult.Object)
{
return;
}
objRef = go.Object(0);
}
if (doc.Objects.FindId(objRef.ObjectId) is BrepObject brepObject)
{
RenderMaterial rm0 = Rhino.RhinoDoc.ActiveDoc.RenderMaterials[0];
RenderMaterial rm1 = Rhino.RhinoDoc.ActiveDoc.RenderMaterials[1];
Material m0 = rm0.ToMaterial(RenderTexture.TextureGeneration.Allow);
Material m1 = rm1.ToMaterial(RenderTexture.TextureGeneration.Allow);
// 非常重要!!!如果材质是从现有材质列表中选的,必须加上这个,才能关联双面材质等具有子材质的材质。
m0.RenderMaterialInstanceId = rm0.Id;
m1.RenderMaterialInstanceId = rm1.Id;
int m0MaterialIndex = doc.Materials.Add(m0);
// 非常重要,在材质 m1 上查找有没有和 m0 匹配的通道,如果没有,就创建一个
// 这样才能在给物件赋予 m1 材质的同时,通过通道在子曲面上使用 m0 材质
int m0ChannelIndex = m1.MaterialChannelIndexFromId(doc.Materials[m0MaterialIndex].Id,true);
int m1MaterialIndex = doc.Materials.Add(m1);
brepObject.Attributes.MaterialIndex = m1MaterialIndex;
brepObject.Attributes.MaterialSource = ObjectMaterialSource.MaterialFromObject;
Brep brep = brepObject.BrepGeometry;
for (int i = 0; i < brep.Faces.Count; i++)
{
if (i % 2 == 0)
brep.Faces[i].MaterialChannelIndex = m0ChannelIndex;
else
brep.Faces[i].ClearMaterialChannelIndex();
}
brepObject.CommitChanges();
}
}