Skip to content

Commit

Permalink
XYZ visualization
Browse files Browse the repository at this point in the history
  • Loading branch information
Nice3point committed May 24, 2024
1 parent 628ea21 commit 792f430
Show file tree
Hide file tree
Showing 17 changed files with 659 additions and 37 deletions.
1 change: 1 addition & 0 deletions source/RevitLookup/Core/ComponentModel/DescriptorMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public static Descriptor FindDescriptor(object obj, Type type)
ElementId value when type is null || type == typeof(ElementId) => new ElementIdDescriptor(value),
GuidEnum value when type is null || type == typeof(GuidEnum) => new GuidEnumDescriptor(value),
Definition value when type is null || type == typeof(Definition) => new DefinitionDescriptor(value),
XYZ value when type is null || type == typeof(XYZ) => new XyzDescriptor(value),

//Enumerator
DefinitionBindingMapIterator value => new DefinitionBindingMapIteratorDescriptor(value),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
using RevitLookup.Core.Contracts;
using RevitLookup.Core.Objects;
using RevitLookup.ViewModels.Contracts;
using RevitLookup.Views.Dialogs.Render;
using RevitLookup.Views.Dialogs.Visualization;

namespace RevitLookup.Core.ComponentModel.Descriptors;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
using RevitLookup.Core.Contracts;
using RevitLookup.Core.Objects;
using RevitLookup.ViewModels.Contracts;
using RevitLookup.Views.Dialogs.Render;
using RevitLookup.Views.Dialogs.Visualization;
using RevitLookup.Views.Extensions;

namespace RevitLookup.Core.ComponentModel.Descriptors;
Expand All @@ -48,7 +48,7 @@ public void RegisterMenu(ContextMenu contextMenu)
}
catch (Exception exception)
{
var logger = context.ServiceProvider.GetService<ILogger<FaceDescriptor>>();
var logger = context.ServiceProvider.GetService<ILogger<MeshDescriptor>>();
logger.LogError(exception, "VisualizationDialog error");
}
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2003-2024 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.

using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Extensions.Logging;
using RevitLookup.Core.Contracts;
using RevitLookup.Core.Objects;
using RevitLookup.ViewModels.Contracts;
using RevitLookup.Views.Dialogs.Visualization;
using RevitLookup.Views.Extensions;

namespace RevitLookup.Core.ComponentModel.Descriptors;

public class XyzDescriptor : Descriptor, IDescriptorConnector
{
private readonly XYZ _point;

public XyzDescriptor(XYZ point)
{
_point = point;
Name = point.ToString();
}

public void RegisterMenu(ContextMenu contextMenu)
{
contextMenu.AddMenuItem("VisualizeMenuItem")
.SetAvailability(!_point.IsUnitLength())
.SetCommand(_point, async point =>
{
if (Context.UiDocument is null) return;

var context = (ISnoopViewModel) contextMenu.DataContext;

try
{
var dialog = new XyzVisualizationDialog(context.ServiceProvider, point);
await dialog.ShowAsync();
}
catch (Exception exception)
{
var logger = context.ServiceProvider.GetService<ILogger<XyzDescriptor>>();
logger.LogError(exception, "VisualizationDialog error");
}
})
.SetShortcut(Key.F8);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
using Microsoft.Extensions.Logging;
using RevitLookup.Models.Render;

namespace RevitLookup.Core.Render;
namespace RevitLookup.Core.Visualization;

public sealed class FaceVisualizationServer(Face face, ILogger<FaceVisualizationServer> logger) : IDirectContext3DServer
{
private const double NormalLength = 1d;

private bool _hasGeometryUpdates = true;
private bool _hasEffectsUpdates = true;

Expand Down Expand Up @@ -133,7 +135,7 @@ private void MapGeometryBuffer()

Render3dUtils.MapSurfaceBuffer(_surfaceBuffer, mesh, _thickness);
Render3dUtils.MapMeshGridBuffer(_meshGridBuffer, mesh, _thickness);
Render3dUtils.MapNormalVectorBuffer(_normalBuffer, face.Evaluate(center), normal, _thickness);
Render3dUtils.MapNormalVectorBuffer(_normalBuffer, face.Evaluate(center), normal, _thickness + 0.2, NormalLength);
}

private void UpdateEffects()
Expand Down Expand Up @@ -203,7 +205,6 @@ public void UpdateTransparency(double value)
uiDocument.UpdateAllOpenViews();
}


public void UpdateSurfaceVisibility(bool visible)
{
var uiDocument = Context.UiDocument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
using Microsoft.Extensions.Logging;
using RevitLookup.Models.Render;

namespace RevitLookup.Core.Render;
namespace RevitLookup.Core.Visualization;

public sealed class MeshVisualizationServer(Mesh mesh, ILogger<MeshVisualizationServer> logger) : IDirectContext3DServer
{
private const double NormalLength = 1d;

private bool _hasGeometryUpdates = true;
private bool _hasEffectsUpdates = true;

Expand Down Expand Up @@ -65,9 +67,9 @@ public void RenderScene(View view, DisplayStyle displayStyle)
{
try
{
if (_hasGeometryUpdates || !_surfaceBuffer.IsValid() || !_meshGridBuffer.IsValid())
if (_hasGeometryUpdates || !_surfaceBuffer.IsValid() || !_meshGridBuffer.IsValid() || _normalBuffers.Any(storage => !storage.IsValid()))
{
UpdateGeometryBuffer();
MapGeometryBuffer();
_hasGeometryUpdates = false;
}

Expand Down Expand Up @@ -125,7 +127,7 @@ public void RenderScene(View view, DisplayStyle displayStyle)
}
}

private void UpdateGeometryBuffer()
private void MapGeometryBuffer()
{
Render3dUtils.MapSurfaceBuffer(_surfaceBuffer, mesh, _thickness);
Render3dUtils.MapMeshGridBuffer(_meshGridBuffer, mesh, _thickness);
Expand All @@ -150,7 +152,7 @@ private void MapNormalsBuffer()
}

var normal = Render3dUtils.GetNormal(mesh, i, mesh.DistributionOfNormals);
Render3dUtils.MapNormalVectorBuffer(buffer, vertex, normal, _thickness);
Render3dUtils.MapNormalVectorBuffer(buffer, vertex, normal, _thickness + 0.2, NormalLength);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
using Autodesk.Revit.DB.DirectContext3D;
using RevitLookup.Models.Render;

namespace RevitLookup.Core.Render;
namespace RevitLookup.Core.Visualization;

public static class Render3dUtils
{
Expand Down Expand Up @@ -178,16 +178,74 @@ public static void MapMeshGridBuffer(RenderingBufferStorage buffer, Mesh mesh, d
buffer.VertexFormat = new VertexFormat(buffer.FormatBits);
}

public static void MapNormalVectorBuffer(RenderingBufferStorage buffer, XYZ origin, XYZ normal, double thickness)
public static void MapSideBuffer(RenderingBufferStorage buffer, XYZ min, XYZ max)
{
const double arrowLength = 1d;
const double arrowHeadSize = 0.2;

var arrowStart = origin + 0.2 * normal + normal * thickness;
var arrowEnd = arrowStart + normal * arrowLength;
var arrowHeadBase = arrowEnd - normal.Multiply(arrowHeadSize);
var basisVector = Math.Abs(normal.Z).IsAlmostEqual(1) ? XYZ.BasisX : XYZ.BasisZ;
var perpendicular1 = normal.CrossProduct(basisVector).Normalize().Multiply(arrowHeadSize * 0.5);
var vertexCount = 4;

Check notice on line 183 in source/RevitLookup/Core/Visualization/Render3dUtils.cs

View workflow job for this annotation

GitHub Actions / qodana

Convert local variable or field into constant (private accessibility)

Convert into constant
var normal = (max - min).Normalize();
var length = (max - min).GetLength() / 2;

XYZ point1;
XYZ point2;
XYZ point3;
XYZ point4;
if (normal.IsAlmostEqualTo(XYZ.BasisX))
{
point1 = new XYZ(min.X, min.Y - length, min.Z);
point2 = new XYZ(min.X, min.Y + length, min.Z);
point3 = new XYZ(max.X, max.Y - length, max.Z);
point4 = new XYZ(max.X, max.Y + length, max.Z);
}
else if (normal.IsAlmostEqualTo(XYZ.BasisY))
{
point1 = new XYZ(min.X, min.Y, min.Z - length);
point2 = new XYZ(min.X, min.Y, min.Z + length);
point3 = new XYZ(max.X, max.Y, max.Z - length);
point4 = new XYZ(max.X, max.Y, max.Z + length);
}
else
{
point1 = new XYZ(min.X - length, min.Y, min.Z);
point2 = new XYZ(min.X + length, min.Y, min.Z);
point3 = new XYZ(max.X - length, max.Y, max.Z);
point4 = new XYZ(max.X + length, max.Y, max.Z);
}

buffer.VertexBufferCount = vertexCount;
buffer.PrimitiveCount = 2;

var vertexBufferSizeInFloats = VertexPosition.GetSizeInFloats() * buffer.VertexBufferCount;
buffer.FormatBits = VertexFormatBits.Position;
buffer.VertexBuffer = new VertexBuffer(vertexBufferSizeInFloats);
buffer.VertexBuffer.Map(vertexBufferSizeInFloats);

var vertexStream = buffer.VertexBuffer.GetVertexStreamPosition();
vertexStream.AddVertex(new VertexPosition(point1));
vertexStream.AddVertex(new VertexPosition(point2));
vertexStream.AddVertex(new VertexPosition(point3));
vertexStream.AddVertex(new VertexPosition(point4));

buffer.VertexBuffer.Unmap();
buffer.IndexBufferCount = 2 * IndexTriangle.GetSizeInShortInts();
buffer.IndexBuffer = new IndexBuffer(buffer.IndexBufferCount);
buffer.IndexBuffer.Map(buffer.IndexBufferCount);

var indexStream = buffer.IndexBuffer.GetIndexStreamTriangle();
indexStream.AddTriangle(new IndexTriangle(0, 1, 2));
indexStream.AddTriangle(new IndexTriangle(1, 2, 3));

buffer.IndexBuffer.Unmap();
buffer.VertexFormat = new VertexFormat(buffer.FormatBits);
}

public static void MapNormalVectorBuffer(RenderingBufferStorage buffer, XYZ origin, XYZ vector, double offset, double length)
{
const double headSize = 0.2;

var arrowStart = origin + vector * offset;
var arrowEnd = arrowStart + vector * length;
var arrowHeadBase = arrowEnd - vector * headSize;
var basisVector = Math.Abs(vector.Z).IsAlmostEqual(1) ? XYZ.BasisX : XYZ.BasisZ;
var perpendicular1 = vector.CrossProduct(basisVector).Normalize().Multiply(headSize * 0.5);

buffer.VertexBufferCount = 4;
buffer.PrimitiveCount = 3;
Expand Down
Loading

0 comments on commit 792f430

Please sign in to comment.