Revit2020材质自定义导出如何设置UV坐标
使用IExportContext接口实现自定义导出的时候,发现通过(PolymeshTopology)node.GetUVs()得到的UV坐标和纹理图不匹配,这导致的结果是导出的纹理被缩放,如下图
[图片]revit中的屋顶纹理

[图片]导出的b3dm屋顶纹理

经过一番排查,发现revit在设置材质贴图的时候会设置贴图的实际长宽尺寸,对应材质属性中的texture_RealWorldScaleX和texture_RealWorldScaleY
[图片]纹理编辑器页面

我们可以利用这两个参数重新计算UV值
1、首先需要获得这两个属性的值
[代码]获取texture_RealWorldScaleX和texture_RealWorldScaleY
Autodesk.Revit.DB.Visual.Asset currentAsset = null;
public void OnMaterial(MaterialNode node)
{
//获取Asset
if (node.HasOverriddenAppearance)
{
currentAsset = node.GetAppearanceOverride();
}
else
{
currentAsset = node.GetAppearance();
}
//关键代码
try
{
Asset textureAsset = FindTextureAsset(asset as AssetProperty);
//获取实际缩放尺寸X
{
string name = "texture_RealWorldScaleX";
AssetProperty property = textureAsset.FindByName(name);
var propertyTyped = property as AssetPropertyDistance;
//转换为公制单位
TextureRealWorldScaleX =
UnitUtils.Convert(propertyTyped.Value,
propertyTyped.DisplayUnitType, DisplayUnitType.DUT_METERS);
}
//获取实际缩放尺寸Y
{
string name = "texture_RealWorldScaleY";
AssetProperty property = textureAsset.FindByName(name);
var propertyTyped = property as AssetPropertyDistance;
//转换为公制单位
TextureRealWorldScaleY =
UnitUtils.Convert(propertyTyped.Value,
propertyTyped.DisplayUnitType, DisplayUnitType.DUT_METERS);
}
}
catch (Exception e)
{
}
}
[代码]FindTextureAsset自定义方法,用递归找到包含贴图信息的Asset
private Autodesk.Revit.DB.Visual.Asset FindTextureAsset(AssetProperty ap)
{
//Log("--FindTextureAsset--");
Autodesk.Revit.DB.Visual.Asset result = null;
if (ap.Type == AssetPropertyType.Asset)
{
if (!IsTextureAsset(ap as Autodesk.Revit.DB.Visual.Asset))
{
for (int i = 0; i < (ap as Autodesk.Revit.DB.Visual.Asset).Size; i++)
{
if (null != FindTextureAsset((ap as Autodesk.Revit.DB.Visual.Asset)[i]))
{
result = FindTextureAsset((ap as Autodesk.Revit.DB.Visual.Asset)[i]);
break;
}
}
}
else
{
result = ap as Autodesk.Revit.DB.Visual.Asset;
}
//Log("--FindTextureAsset-end-");
return result;
}
else
{
for (int j = 0; j < ap.NumberOfConnectedProperties; j++)
{
if (null != FindTextureAsset(ap.GetConnectedProperty(j)))
{
result = FindTextureAsset(ap.GetConnectedProperty(j));
}
}
//Log("--FindTextureAsset-end-");
return result;
}
}
[代码]IsTextureAsset自定义方法,判断Asset是否包含贴图信息
private bool IsTextureAsset(Autodesk.Revit.DB.Visual.Asset asset)
{
AssetProperty assetProprty = GetAssetProprty(asset, "assettype");
if (assetProprty != null && (assetProprty as AssetPropertyString).Value == "texture")
{
return true;
}
return GetAssetProprty(asset, "unifiedbitmap_Bitmap") != null;
}
2、接下来计算UV值
[代码]计算UV值
//取得UV坐标
IList<UV> uvs = node.GetUVs();
//重新计算UV值
foreach (UV uv in uvs)
{
double u = UnitUtils.ConvertFromInternalUnits(uv.U, DisplayUnitType.DUT_METERS);
double v = UnitUtils.ConvertFromInternalUnits(uv.V, DisplayUnitType.DUT_METERS);
baseTexCoords.Add(u / currentMaterial.TextureRealWorldScaleX);
baseTexCoords.Add(v / currentMaterial.TextureRealWorldScaleY);
}
这样就能得到和revit中相同的纹理显示效果
参考文章
Revit API: IExportContext converting UV to the range (0,1) - Revit API Forum
参考思路


浙公网安备 33010602011771号