在Autodesk Revit Forge Design Automation中创建带有纹理的材质。

问题描述 投票:0回答:1

我目前正在研究一些Revit API代码,这些代码运行于 欧特克Forge设计自动化云解决方案. 基本上,我是想 创建一个材质并附加一个纹理 通过以下代码。

 private void AddTexturePath(AssetProperty asset, string texturePath) {
  Asset connectedAsset = null;

  if (asset.NumberOfConnectedProperties == 0)
   asset.AddConnectedAsset("UnifiedBitmapSchema");

  connectedAsset = (Asset) asset.GetConnectedProperty(0);
  AssetPropertyString path = (AssetPropertyString) connectedAsset.FindByName(UnifiedBitmap.UnifiedbitmapBitmap);

  if (!path.IsValidValue(texturePath)) {
   File.Create("texture.png");
   texturePath = Path.GetFullPath("texture.png");
  }

  path.Value = texturePath;

 }

这其实是很好用的,因为纹理路径的值:

path.Value = texturePath;

必须是一个现有文件的引用。我在 Forge 的云端实例上没有这个文件,因为纹理名称的路径是由用户在发送 Workitem 请求时指定的。

问题在于,这将材质的纹理路径设置成了这样。

T:\Aces\Jobs\<workitem_id>\texture.png

基本上就是Workitem实例的工作文件夹。这个路径是没用的,因为像这样的纹理路径的材质需要在Revit中手动重新链接。

对我来说,最完美的结果是,如果我能以某种方式将材质纹理路径映射到一些用户友好的目录,如 "C:\Textures\texture.png",似乎Forge实例有一个 "C:\"驱动器(可能是某种Windows实例),但我的代码在低权限下运行,所以它不能在工作目录之外创建任何类型的目录文件。

有人知道如何解决这个问题吗?任何帮助将是非常感激的

c# autodesk-forge revit-api autodesk-designautomation
1个回答
1
投票

经过一整天的研究,我几乎得出了一个满意的解决方案。为了清楚起见--我将参考以下内容 Autodesk Forge Design Automation API for Revit,只是因为 "锻造".

基本上上面提供的代码是正确的。我没有找到任何可能的方法在 Forge 实例上创建一个文件,其目录与 Workitem 工作目录不同。

T:\Aces\Jobs\<workitem_id>\texture.png

有趣的是,在Forge实例上有一个C:\驱动器,其中包含Windows、Revit和.NET框架的安装(因为Forge实例基本上是某种安装了Revit的Windows实例)。可以列举很多这样的目录,但是我试过的所有目录都不允许创建目录或文件(我试过很多--大部分是最明显的、公开访问的Windows目录,如C:\Users\Public,C:\Program Files等)。这与Forge文档中的 "限制 "区域的内容是一致的。

你的应用程序是以低权限运行的,不能与Windows操作系统自由交互。

  • 写入访问通常被限制在作业的工作文件夹中。
  • 注册表的访问大多受到限制,应避免对注册表的写入。
  • 任何子进程也将以低权限执行。

因此,在尝试将 "虚拟 "纹理文件保存在Forge C:/\驱动器的某个地方后,我找到了另一个解决方案-----------------------------。纹理的纹理路径其实并不重要。这是因为Revit提供了一个替代方案来重新链接你的纹理。如果你启动Revit,你可以进入 "文件"-> "选项"-> "渲染",在 "附加渲染外观路径 "字段中,你可以指定你本地机器上的目录,Revit可以用来寻找丢失的纹理。有了这些,你就可以进行以下操作,以便完全控制在Forge上创建材质。

  1. 发送工作项目到Forge,创建材质。
  2. 在工作目录下创建一个虚拟纹理,文件名要正确。
  3. 将虚拟纹理文件附加到材质上。
  4. 输出生成的文件(.rvt或.rfa,取决于你在Forge上创建的内容)。
  5. 将所有纹理放入一个文件夹(或多个,这并不重要)。
  6. 将纹理的目录添加到附加渲染应用路径中。
  7. Revit会成功地将所有的纹理重新链接到新路径。

我希望有人会觉得这很有用

此外,根据Jeremy的要求,我发布了一个代码示例,用于在Revit中使用Revit API(在C#中)创建纹理材料和修改不同的外观属性。

private void SetAppearanceParameters(Document project, Material mat, MaterialData data) {
    using(Transaction setParameters = new Transaction(project, "Set material parameters")) {
        setParameters.Start();

        AppearanceAssetElement genericAsset = new FilteredElementCollector(project)
                .OfClass(typeof(AppearanceAssetElement))
                .ToElements()
                .Cast < AppearanceAssetElement > ().Where(i = >i.Name.Contains("Generic"))
                .FirstOrDefault();

        AppearanceAssetElement newAsset = genericAsset.Duplicate(data.Name);
        mat.AppearanceAssetId = newAsset.Id;

        using(AppearanceAssetEditScope editAsset = new AppearanceAssetEditScope(project)) {
            Asset editableAsset = editAsset.Start(newAsset.Id);
            AssetProperty assetProperty = editableAsset["generic_diffuse"];

            SetColor(editableAsset, data.MaterialAppearance.Color);
            SetGlossiness(editableAsset, data.MaterialAppearance.Gloss);
            SetReflectivity(editableAsset, data.MaterialAppearance.Reflectivity);
            SetTransparency(editableAsset, data.MaterialAppearance.Transparency);

            if (data.MaterialAppearance.Texture != null && data.MaterialAppearance.Texture.Length != 0) 
            AddTexturePath(assetProperty, $@"C:\{data.MaterialIdentity.Manufacturer}\textures\{data.MaterialAppearance.Texture}");

            editAsset.Commit(true);
        }
        setParameters.Commit();
    }
}

private void SetTransparency(Asset editableAsset, int transparency) {
    AssetPropertyDouble genericTransparency = editableAsset["generic_transparency"] as AssetPropertyDouble;
    genericTransparency.Value = Convert.ToDouble(transparency);
}

private void SetReflectivity(Asset editableAsset, int reflectivity) {
    AssetPropertyDouble genericReflectivityZero = (AssetPropertyDouble) editableAsset["generic_reflectivity_at_0deg"];
    genericReflectivityZero.Value = Convert.ToDouble(reflectivity) / 100;

    AssetPropertyDouble genericReflectivityAngle = (AssetPropertyDouble) editableAsset["generic_reflectivity_at_90deg"];
    genericReflectivityAngle.Value = Convert.ToDouble(reflectivity) / 100;
}

private void SetGlossiness(Asset editableAsset, int gloss) {
    AssetPropertyDouble glossProperty = (AssetPropertyDouble) editableAsset["generic_glossiness"];
    glossProperty.Value = Convert.ToDouble(gloss) / 100;
}

private void SetColor(Asset editableAsset, int[] color) {
    AssetPropertyDoubleArray4d genericDiffuseColor = (AssetPropertyDoubleArray4d) editableAsset["generic_diffuse"];
    Color newColor = new Color((byte) color[0], (byte) color[1], (byte) color[2]);
    genericDiffuseColor.SetValueAsColor(newColor);
}

private void AddTexturePath(AssetProperty asset, string texturePath) {
    Asset connectedAsset = null;
    if (asset.NumberOfConnectedProperties == 0) asset.AddConnectedAsset("UnifiedBitmapSchema");

    connectedAsset = (Asset) asset.GetConnectedProperty(0);
    AssetProperty prop = connectedAsset.FindByName(UnifiedBitmap.UnifiedbitmapBitmap);
    AssetPropertyString path = (AssetPropertyString) connectedAsset.FindByName(UnifiedBitmap.UnifiedbitmapBitmap);

    string fileName = Path.GetFileName(texturePath);
    File.Create(fileName);
    texturePath = Path.GetFullPath(fileName);

    path.Value = texturePath;
}
© www.soinside.com 2019 - 2024. All rights reserved.