Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9902da8b5e |
@@ -1,12 +1,12 @@
|
||||
using Autodesk.Revit.DB;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Speckle.Connectors.Common.Instances;
|
||||
using Speckle.Connectors.Common.Operations.Receive;
|
||||
using Speckle.Converters.Common;
|
||||
using Speckle.Converters.RevitShared.Settings;
|
||||
using Speckle.Objects.Other;
|
||||
using Speckle.Sdk;
|
||||
using Speckle.Sdk.Common;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.Extensions;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
|
||||
@@ -57,7 +57,8 @@ public class RevitMaterialBaker
|
||||
|
||||
if (targetRenderMaterialProxy is null)
|
||||
{
|
||||
var layerParents = context.GetAscendants().Where(parent => parent is Layer);
|
||||
//var layerParents = context.GetAscendants().Where(parent => parent is Layer);
|
||||
var layerParents = context.GetAscendants();
|
||||
|
||||
var layer = layerParents.FirstOrDefault(layer =>
|
||||
unpackedRoot.RenderMaterialProxies.Any(rmp => rmp.objects.Contains(layer.applicationId!))
|
||||
@@ -102,6 +103,48 @@ public class RevitMaterialBaker
|
||||
}
|
||||
}
|
||||
|
||||
public void MapInstanceRenderMaterials(
|
||||
RootObjectUnpackerResult unpackedRoot,
|
||||
IReadOnlyCollection<LocalToGlobalMap> localToGlobalMaps
|
||||
)
|
||||
{
|
||||
if (unpackedRoot.RenderMaterialProxies is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var context in unpackedRoot.ObjectsToConvert)
|
||||
{
|
||||
if (context.Current.applicationId is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var targetRenderMaterialProxy = unpackedRoot.RenderMaterialProxies.FirstOrDefault(rmp =>
|
||||
rmp.objects.Contains(context.Current.applicationId)
|
||||
);
|
||||
|
||||
if (targetRenderMaterialProxy is null)
|
||||
{
|
||||
var maps = localToGlobalMaps.Where(m => m.AtomicObject.applicationId == context.Current.applicationId).ToList();
|
||||
var map = localToGlobalMaps.FirstOrDefault(m => m.AtomicObject.applicationId == context.Current.applicationId);
|
||||
var instance = map?.InstanceChain.FirstOrDefault(i =>
|
||||
unpackedRoot.RenderMaterialProxies.Any(rmp => rmp.objects.Contains(i))
|
||||
);
|
||||
|
||||
if (instance is not null)
|
||||
{
|
||||
var instanceRenderMaterialProxy = unpackedRoot.RenderMaterialProxies.First(rmp =>
|
||||
rmp.objects.Contains(instance)
|
||||
);
|
||||
|
||||
targetRenderMaterialProxy = instanceRenderMaterialProxy;
|
||||
targetRenderMaterialProxy.objects.Add(context.Current.applicationId!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will bake render materials in the revit document.
|
||||
/// </summary>
|
||||
|
||||
+33
-6
@@ -44,7 +44,7 @@ public sealed class RevitHostObjectBuilder(
|
||||
IReceiveConversionHandler conversionHandler
|
||||
) : IHostObjectBuilder, IDisposable
|
||||
{
|
||||
public Task<HostObjectBuilderResult> Build(
|
||||
/*public Task<HostObjectBuilderResult> Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
@@ -53,7 +53,33 @@ public sealed class RevitHostObjectBuilder(
|
||||
) =>
|
||||
threadContext.RunOnMainAsync(
|
||||
() => Task.FromResult(BuildSync(rootObject, projectName, modelName, onOperationProgressed, cancellationToken))
|
||||
);*/
|
||||
|
||||
public Task<HostObjectBuilderResult> Build(
|
||||
Base rootObject,
|
||||
string projectName,
|
||||
string modelName,
|
||||
IProgress<CardProgress> onOperationProgressed,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
bool x = false;
|
||||
#if REVIT2026
|
||||
x = converterSettings.Current.Document.IsInEditMode();
|
||||
#endif
|
||||
|
||||
/*bool mod = converterSettings.Current.Document.IsModified;
|
||||
bool ro = converterSettings.Current.Document.IsReadOnly;
|
||||
bool mof = converterSettings.Current.Document.IsModifiable;*/
|
||||
if (x)
|
||||
{
|
||||
throw new ConversionException($"We are in modify mode!!!!!");
|
||||
}
|
||||
|
||||
return threadContext.RunOnMainAsync(
|
||||
() => Task.FromResult(BuildSync(rootObject, projectName, modelName, onOperationProgressed, cancellationToken))
|
||||
);
|
||||
}
|
||||
|
||||
private HostObjectBuilderResult BuildSync(
|
||||
Base rootObject,
|
||||
@@ -122,7 +148,7 @@ public sealed class RevitHostObjectBuilder(
|
||||
)
|
||||
{
|
||||
var id = localToGlobalMap.AtomicObject.id;
|
||||
var originalAppId = localToGlobalMap.AtomicObject.applicationId ?? id;
|
||||
//var originalAppId = localToGlobalMap.AtomicObject.applicationId ?? id;
|
||||
|
||||
// Apply transformations...
|
||||
ITransformable? newTransformable = null;
|
||||
@@ -136,13 +162,13 @@ public sealed class RevitHostObjectBuilder(
|
||||
localToGlobalMap.AtomicObject.id = id;
|
||||
|
||||
// create modified ID and store mapping <- fixes CNX-1707 but causes us material mapping headache!!!
|
||||
string modifiedAppId = $"{originalAppId}_{Guid.NewGuid().ToString("N")[..8]}";
|
||||
/*string modifiedAppId = $"{originalAppId}_{Guid.NewGuid().ToString("N")[..8]}";
|
||||
if (originalAppId != null)
|
||||
{
|
||||
originalToModifiedIds[originalAppId] = modifiedAppId;
|
||||
}
|
||||
|
||||
localToGlobalMap.AtomicObject.applicationId = modifiedAppId;
|
||||
localToGlobalMap.AtomicObject.applicationId = modifiedAppId;*/
|
||||
localToGlobalMap.Matrix = new HashSet<Matrix4x4>();
|
||||
}
|
||||
}
|
||||
@@ -167,6 +193,7 @@ public sealed class RevitHostObjectBuilder(
|
||||
if (unpackedRoot.RenderMaterialProxies != null)
|
||||
{
|
||||
transactionManager.StartTransaction(true, "Baking materials");
|
||||
materialBaker.MapInstanceRenderMaterials(unpackedRoot, localToGlobalMaps);
|
||||
materialBaker.MapLayersRenderMaterials(unpackedRoot);
|
||||
var map = materialBaker.BakeMaterials(unpackedRoot.RenderMaterialProxies, baseGroupName);
|
||||
foreach (var kvp in map)
|
||||
@@ -203,12 +230,12 @@ public sealed class RevitHostObjectBuilder(
|
||||
}
|
||||
|
||||
// 4 - Paint solids
|
||||
{
|
||||
/*{
|
||||
using var _ = activityFactory.Start("Painting solids");
|
||||
transactionManager.StartTransaction(true, "Painting solids");
|
||||
PostBakePaint(conversionResults.postBakePaintTargets);
|
||||
transactionManager.CommitTransaction();
|
||||
}
|
||||
}*/
|
||||
|
||||
// 5 - Create group
|
||||
{
|
||||
|
||||
+119
@@ -16,6 +16,7 @@ using Speckle.Sdk.Common.Exceptions;
|
||||
using Speckle.Sdk.Logging;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.Collections;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
using Speckle.Sdk.Models.Instances;
|
||||
|
||||
namespace Speckle.Connectors.Rhino.Operations.Receive;
|
||||
@@ -118,6 +119,21 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
|
||||
_colorBaker.ParseColors(unpackedRoot.ColorProxies);
|
||||
}
|
||||
|
||||
foreach (var a in atomicObjectsWithoutInstanceComponentsWithPath)
|
||||
{
|
||||
var id = a.current.applicationId;
|
||||
if (id == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_materialBaker.ObjectIdAndMaterialIndexMap.TryGetValue(id, out int mIndex))
|
||||
{
|
||||
var mati = FindMissingMaterialIndex(id, instanceComponentsWithPath);
|
||||
_materialBaker.ObjectIdAndMaterialIndexMap[id] = mati;
|
||||
}
|
||||
}
|
||||
|
||||
// 4 - Bake layers
|
||||
// See [CNX-325: Rhino: Change receive operation order to increase performance](https://linear.app/speckle/issue/CNX-325/rhino-change-receive-operation-order-to-increase-performance)
|
||||
onOperationProgressed.Report(new("Baking layers (redraw disabled)", null));
|
||||
@@ -332,6 +348,63 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
|
||||
return _converterSettings.Current.Document.Objects.Add(obj, atts);
|
||||
}
|
||||
|
||||
private int FindMissingMaterialIndex(
|
||||
string? objectId,
|
||||
ICollection<(Collection[] path, IInstanceComponent instance)> instances
|
||||
)
|
||||
{
|
||||
var ids = GetInstanceAscendants(objectId, instances);
|
||||
foreach (var id in ids)
|
||||
{
|
||||
if (_materialBaker.ObjectIdAndMaterialIndexMap.TryGetValue(id, out int mIndex))
|
||||
{
|
||||
return mIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private List<string> GetInstanceAscendants(
|
||||
string? objectId,
|
||||
ICollection<(Collection[] path, IInstanceComponent instance)> instances
|
||||
)
|
||||
{
|
||||
var ascendants = new List<string>();
|
||||
|
||||
while (objectId != null)
|
||||
{
|
||||
ascendants.Add(objectId);
|
||||
objectId = GetFirstParent(objectId, instances);
|
||||
}
|
||||
|
||||
return ascendants;
|
||||
}
|
||||
|
||||
private string? GetFirstParent(
|
||||
string objectId,
|
||||
ICollection<(Collection[] path, IInstanceComponent instance)> instances
|
||||
)
|
||||
{
|
||||
// Step 1: Find the definition ID for the given objectId
|
||||
string? defId = instances
|
||||
?.Select(i => i.instance)
|
||||
.OfType<InstanceDefinitionProxy>()
|
||||
.FirstOrDefault(d => d.objects.Contains(objectId))
|
||||
?.applicationId;
|
||||
|
||||
if (defId == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Step 2: Find the first InstanceProxy with matching definitionId
|
||||
return instances
|
||||
?.Select(i => i.instance)
|
||||
.OfType<InstanceProxy>()
|
||||
.FirstOrDefault(p => p.definitionId == defId)
|
||||
?.applicationId;
|
||||
}
|
||||
|
||||
private List<Guid> BakeObjectsAsFallbackGroup(
|
||||
IEnumerable<(GeometryBase, Base)> fallbackConversionResult,
|
||||
Base originatingObject,
|
||||
@@ -364,4 +437,50 @@ public class RhinoHostObjectBuilder : IHostObjectBuilder
|
||||
|
||||
return objectIds;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
public void MapLayersRenderMaterials(RootObjectUnpackerResult unpackedRoot)
|
||||
{
|
||||
if (unpackedRoot.RenderMaterialProxies is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var context in unpackedRoot.ObjectsToConvert)
|
||||
{
|
||||
if (context.Current.applicationId is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var targetRenderMaterialProxy = unpackedRoot.RenderMaterialProxies.FirstOrDefault(rmp =>
|
||||
rmp.objects.Contains(context.Current.applicationId)
|
||||
);
|
||||
|
||||
if (targetRenderMaterialProxy is null)
|
||||
{
|
||||
var layerParents = context.GetAscendants();
|
||||
|
||||
var layer = layerParents.FirstOrDefault(layer =>
|
||||
unpackedRoot.RenderMaterialProxies.Any(rmp => rmp.objects.Contains(layer.applicationId!))
|
||||
);
|
||||
|
||||
if (layer is not null)
|
||||
{
|
||||
var layerRenderMaterialProxy = unpackedRoot.RenderMaterialProxies.First(rmp =>
|
||||
rmp.objects.Contains(layer.applicationId!)
|
||||
);
|
||||
|
||||
targetRenderMaterialProxy = layerRenderMaterialProxy;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetRenderMaterialProxy is null)
|
||||
{
|
||||
continue; // exit fast, no proxy, we can't do much more.
|
||||
}
|
||||
// We mutate the existing proxy list that comes from source application. Because we do not keep track of parent-child relationship of objects in terms of render materials.
|
||||
targetRenderMaterialProxy.objects.Add(context.Current.applicationId!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.Sdk.Models;
|
||||
using Speckle.Sdk.Models.GraphTraversal;
|
||||
|
||||
@@ -19,4 +19,5 @@ public class LocalToGlobalMap
|
||||
public TraversalContext TraversalContext { get; set; }
|
||||
public Base AtomicObject { get; set; }
|
||||
public IReadOnlyCollection<Matrix4x4> Matrix { get; set; }
|
||||
public List<string> InstanceChain { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.DoubleNumerics;
|
||||
using Speckle.InterfaceGenerator;
|
||||
using Speckle.Sdk.Dependencies;
|
||||
using Speckle.Sdk.Models;
|
||||
@@ -80,6 +80,7 @@ public class LocalToGlobalUnpacker : ILocalToGlobalUnpacker
|
||||
objectAtRelative,
|
||||
objectAtRelative,
|
||||
new HashSet<Matrix4x4>(),
|
||||
new List<string>(),
|
||||
localToGlobalMaps
|
||||
);
|
||||
}
|
||||
@@ -93,6 +94,7 @@ public class LocalToGlobalUnpacker : ILocalToGlobalUnpacker
|
||||
(TraversalContext tc, Base obj) objectAtRelative,
|
||||
(TraversalContext tc, Base obj) searchForDefinition,
|
||||
HashSet<Matrix4x4> matrices,
|
||||
List<string> instanceChain,
|
||||
HashSet<LocalToGlobalMap> localToGlobalMaps
|
||||
)
|
||||
{
|
||||
@@ -105,25 +107,29 @@ public class LocalToGlobalUnpacker : ILocalToGlobalUnpacker
|
||||
);
|
||||
if (definitionProxy is null)
|
||||
{
|
||||
localToGlobalMaps.Add(
|
||||
new LocalToGlobalMap(
|
||||
new TraversalContext(objectAtRelative.obj, objectAtRelative.tc.PropName, objectAtRelative.tc.Parent),
|
||||
objectAtRelative.obj,
|
||||
matrices
|
||||
)
|
||||
);
|
||||
var map = new LocalToGlobalMap(
|
||||
new TraversalContext(objectAtRelative.obj, objectAtRelative.tc.PropName, objectAtRelative.tc.Parent),
|
||||
objectAtRelative.obj,
|
||||
matrices
|
||||
)
|
||||
{
|
||||
InstanceChain = instanceChain
|
||||
};
|
||||
localToGlobalMaps.Add(map);
|
||||
return;
|
||||
}
|
||||
var instances = instanceProxies.Where(ic => ic.instanceProxy.definitionId == definitionProxy.applicationId);
|
||||
foreach (var instance in instances)
|
||||
{
|
||||
HashSet<Matrix4x4> newMatrices = [.. matrices, instance.instanceProxy.transform]; // Do not mutate the list!
|
||||
List<string> newInstanceChain = [.. instanceChain, instance.instanceProxy.applicationId];
|
||||
UnpackMatrix(
|
||||
instanceDefinitionProxies,
|
||||
instanceProxies,
|
||||
objectAtRelative,
|
||||
instance,
|
||||
newMatrices,
|
||||
newInstanceChain,
|
||||
localToGlobalMaps
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Speckle.Sdk.Transports;
|
||||
using Speckle.Sdk.Transports;
|
||||
|
||||
namespace Speckle.Connectors.Common.Operations;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user