Skip to content

Commit

Permalink
Implement selective geometry preview using shaders (#7587) (#7614)
Browse files Browse the repository at this point in the history
* Implement selective geometry preview using shaders

* Move "Isolate Selected Geometries" into Settings menu
  • Loading branch information
ellensi committed Feb 16, 2017
1 parent da9f8ad commit baa0279
Show file tree
Hide file tree
Showing 15 changed files with 159 additions and 17 deletions.
9 changes: 9 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.en-US.resx
Expand Up @@ -1783,6 +1783,9 @@ Do you want to install the latest Dynamo update?</value>
<data name="DynamoViewEditMenuPresetsMenu" xml:space="preserve">
<value>Presets</value>
</data>
<data name="DynamoViewSettingsMenuIsolationMode" xml:space="preserve">
<value>Isolate Selected Geometries</value>
</data>
<data name="DynamoViewSettingsMenuShowEdges" xml:space="preserve">
<value>Show Edges</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions src/DynamoCoreWpf/Properties/Resources.resx
Expand Up @@ -1783,6 +1783,9 @@ Do you want to install the latest Dynamo update?</value>
<data name="DynamoViewEditMenuPresetsMenu" xml:space="preserve">
<value>Presets</value>
</data>
<data name="DynamoViewSettingsMenuIsolationMode" xml:space="preserve">
<value>Isolate Selected Geometries</value>
</data>
<data name="DynamoViewSettingsMenuShowEdges" xml:space="preserve">
<value>Show Edges</value>
</data>
Expand Down
34 changes: 34 additions & 0 deletions src/DynamoCoreWpf/ViewModels/Watch3D/AttachedProperties.cs
Expand Up @@ -127,6 +127,40 @@ private static void IsFrozenPropertyChanged(DependencyObject obj, DependencyProp
}
}

/// <summary>
/// A flag indicating whether the geometry is currently under Isolate Selected Geometries mode.
/// </summary>
public static readonly DependencyProperty IsolationModeProperty = DependencyProperty.RegisterAttached(
"IsolationMode",
typeof(bool),
typeof(GeometryModel3D),
new PropertyMetadata(false, IsolationModePropertyChanged));

public static void SetIsolationMode(UIElement element, bool value)
{
element.SetValue(IsolationModeProperty, value);
}

public static bool GetIsolationMode(UIElement element)
{
return (bool)element.GetValue(IsolationModeProperty);
}

private static void IsolationModePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (obj is GeometryModel3D && obj.GetType() != typeof(BillboardTextModel3D))
{
var geom = (GeometryModel3D)obj;

if (geom.IsAttached)
{
var host = geom.RenderHost;
geom.Detach();
geom.Attach(host);
}
}
}

/// <summary>
/// A flag indicating whether the geometry is special render package, such as used to draw manipulators.
/// </summary>
Expand Down
25 changes: 25 additions & 0 deletions src/DynamoCoreWpf/ViewModels/Watch3D/DefaultWatch3DViewModel.cs
Expand Up @@ -150,6 +150,23 @@ public bool CanNavigateBackground
}
}

/// <summary>
/// A flag which indicates whether Isolate Selected Geometries mode is activated.
/// </summary>
private bool isolationMode;
public bool IsolationMode
{
get
{
return isolationMode;
}
set
{
isolationMode = value;
RaisePropertyChanged("IsolationMode");
}
}

/// <summary>
/// A flag which indicates whether the user is holding the
/// navigation override key (ESC).
Expand Down Expand Up @@ -298,9 +315,17 @@ private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyC
handler(CanNavigateBackground);
}
break;
case "IsolationMode":
OnIsolationModeRequestUpdate();
break;
}
}

protected virtual void OnIsolationModeRequestUpdate()
{
// Override in inherited classes.
}

private void UnregisterEventHandlers()
{
DynamoSelection.Instance.Selection.CollectionChanged -= SelectionChangedHandler;
Expand Down
Expand Up @@ -289,6 +289,10 @@ private DynamoMeshVertex[] CreateVertexArray()
var vertexCount = geometry.Positions.Count;
var result = new DynamoMeshVertex[vertexCount];

var isSelected = (bool)GetValue(AttachedProperties.ShowSelectedProperty);
var isIsolationMode = (bool)GetValue(AttachedProperties.IsolationModeProperty);
var isSpecialPackage = (bool)GetValue(AttachedProperties.IsSpecialRenderPackageProperty);

for (var i = 0; i < vertexCount; i++)
{
result[i] = new DynamoMeshVertex
Expand All @@ -299,7 +303,9 @@ private DynamoMeshVertex[] CreateVertexArray()
Normal = normals != null ? normals[i] : Vector3.Zero,
Tangent = tangents != null ? tangents[i] : Vector3.Zero,
BiTangent = bitangents != null ? bitangents[i] : Vector3.Zero,
Parameters = new Vector4((bool)GetValue(AttachedProperties.ShowSelectedProperty) ? 1 : 0, RequiresPerVertexColoration ? 1 : 0,0,0)
Parameters = new Vector4(isSelected ? 1 : 0,
(isIsolationMode && !isSpecialPackage) ? 1 : 0,
RequiresPerVertexColoration ? 1 : 0, 0)
};
}

Expand Down
Expand Up @@ -102,11 +102,16 @@ private DynamoLineVertex[] CreateVertexArray()
finalColor = color;
}

var isSelected = (bool)GetValue(AttachedProperties.ShowSelectedProperty);
var isIsolationMode = (bool)GetValue(AttachedProperties.IsolationModeProperty);
var isSpecialPackage = (bool)GetValue(AttachedProperties.IsSpecialRenderPackageProperty);

result[i] = new DynamoLineVertex
{
Position = new Vector4(positions[i], 1f),
Color = finalColor,
Parameters = new Vector4((bool)GetValue(AttachedProperties.ShowSelectedProperty) ? 1 : 0, 0, 0, 0)
Parameters = new Vector4(isSelected ? 1 : 0,
(isIsolationMode && !isSpecialPackage) ? 1 : 0, 0, 0)
};
}

Expand Down
Expand Up @@ -96,11 +96,16 @@ private DynamoPointVertex[] CreateVertexArray()
finalColor = color;
}

var isSelected = (bool)GetValue(AttachedProperties.ShowSelectedProperty);
var isIsolationMode = (bool)GetValue(AttachedProperties.IsolationModeProperty);
var isSpecialPackage = (bool)GetValue(AttachedProperties.IsSpecialRenderPackageProperty);

result[i] = new DynamoPointVertex
{
Position = new Vector4(positions[i], 1f),
Color = finalColor,
Parameters = new Vector4((bool)GetValue(AttachedProperties.ShowSelectedProperty) ? 1 : 0, 0, 0, 0)
Parameters = new Vector4(isSelected ? 1 : 0,
(isIsolationMode && !isSpecialPackage) ? 1 : 0, 0, 0)
};
}

Expand Down
41 changes: 34 additions & 7 deletions src/DynamoCoreWpf/ViewModels/Watch3D/HelixWatch3DViewModel.cs
Expand Up @@ -612,11 +612,11 @@ protected override void SelectionChangedHandler(object sender, NotifyCollectionC
Model3DDictionary.Values.
Where(v => v is GeometryModel3D).
Cast<GeometryModel3D>().ToList().ForEach(g => g.SetValue(AttachedProperties.ShowSelectedProperty, false));
return;
break;

case NotifyCollectionChangedAction.Remove:
SetSelection(e.OldItems, false);
return;
break;

case NotifyCollectionChangedAction.Add:

Expand All @@ -631,11 +631,16 @@ protected override void SelectionChangedHandler(object sender, NotifyCollectionC
&& recentlyAddedNodes.TrueForAll(n => e.NewItems.Contains((object)n)))
{
recentlyAddedNodes.Clear();
return;
break;
}

SetSelection(e.NewItems, true);
return;
break;
}

if (IsolationMode)
{
OnIsolationModeRequestUpdate();
}
}

Expand Down Expand Up @@ -806,6 +811,17 @@ protected override void OnModelPropertyChanged(object sender, PropertyChangedEve
}
}

/// <summary>
/// Update the attached properties and recalculate transparency sorting
/// after any update under Isolate Selected Geometries mode.
/// </summary>
protected override void OnIsolationModeRequestUpdate()
{
Model3DDictionary.Values.OfType<GeometryModel3D>().ToList().
ForEach(g => AttachedProperties.SetIsolationMode(g, IsolationMode));
OnSceneItemsChanged();
}

protected override void ZoomToFit(object parameter)
{
var idents = FindIdentifiersForContext();
Expand Down Expand Up @@ -1085,6 +1101,7 @@ private void InitializeHelix()

if (!Model3DDictionary.ContainsKey(DefaultLightName))
{
AttachedProperties.SetIsSpecialRenderPackage(directionalLight, true);
Model3DDictionary.Add(DefaultLightName, directionalLight);
}

Expand All @@ -1102,6 +1119,7 @@ private void InitializeHelix()

if (!model3DDictionary.ContainsKey(DefaultGridName))
{
AttachedProperties.SetIsSpecialRenderPackage(gridModel3D, true);
Model3DDictionary.Add(DefaultGridName, gridModel3D);
}

Expand All @@ -1117,6 +1135,7 @@ private void InitializeHelix()

if (!Model3DDictionary.ContainsKey(DefaultAxesName))
{
AttachedProperties.SetIsSpecialRenderPackage(axesModel3D, true);
Model3DDictionary.Add(DefaultAxesName, axesModel3D);
}

Expand Down Expand Up @@ -2086,11 +2105,19 @@ public int Compare(Model3D x, Model3D y)
return result;
}

var transA = (bool) a.GetValue(AttachedProperties.HasTransparencyProperty);
var transB = (bool) b.GetValue(AttachedProperties.HasTransparencyProperty);
result = transA.CompareTo(transB);
// under Isolate Selected Geometries mode, selected geometries will have higher precedence
// and rendered as closer to the camera compared to unselected geometries
var selectedA = AttachedProperties.GetIsolationMode(a) &&
!AttachedProperties.GetShowSelected(a) && !AttachedProperties.IsSpecialRenderPackage(a);
var selectedB = AttachedProperties.GetIsolationMode(b) &&
!AttachedProperties.GetShowSelected(b) && !AttachedProperties.IsSpecialRenderPackage(b);
result = selectedA.CompareTo(selectedB);
if (result != 0) return result;

// if only one of transA and transB has transparency, sort by having this property
var transA = AttachedProperties.GetHasTransparencyProperty(a);
var transB = AttachedProperties.GetHasTransparencyProperty(b);
result = transA.CompareTo(transB);
if (result != 0) return result;

// if both items has transparency, sort by distance
Expand Down
Binary file modified src/DynamoCoreWpf/ViewModels/Watch3D/Resources/_dynamo.bfx
Binary file not shown.
14 changes: 11 additions & 3 deletions src/DynamoCoreWpf/ViewModels/Watch3D/Shaders/Custom.fx
Expand Up @@ -59,7 +59,8 @@ float4 PShaderCustom(PSInputCustom input) : SV_Target
}

bool isSelected = input.customParams.x;
bool requiresPerVertexColoration = input.customParams.y;
bool isIsolationMode = input.customParams.y;
bool requiresPerVertexColoration = input.customParams.z;

if (bHasDiffuseMap)
{
Expand Down Expand Up @@ -102,7 +103,14 @@ float4 PShaderCustom(PSInputCustom input) : SV_Target
}

/// set diffuse alpha
I.a = vMaterialDiffuse.a;
if (!isIsolationMode || isSelected)
{
I.a = vMaterialDiffuse.a;
}
else
{
I.a = vTransparentMaterial.a;
}

/// get reflection-color
if (bHasCubeMap)
Expand All @@ -115,7 +123,7 @@ float4 PShaderCustom(PSInputCustom input) : SV_Target
I = I * input.c;
}

if (isSelected)
if (isSelected && !isIsolationMode)
{
I = lerp(vSelectionColor,I,0.3);
}
Expand Down
10 changes: 8 additions & 2 deletions src/DynamoCoreWpf/ViewModels/Watch3D/Shaders/Lines.fx
Expand Up @@ -126,15 +126,21 @@ GSInputLS VShaderLines(VSInputLS input)
}

bool isSelected = input.parameters.x;
bool isIsolationMode = input.parameters.y;
float4 finalColor;

if (isSelected) {
if (isSelected && !isIsolationMode) {
finalColor = lerp(vSelectionColor, input.c, 0.3);
}
else {
finalColor = input.c;
}

// unselected geometry is transparent under Isolate Selected Geometries mode
if (isIsolationMode && !isSelected) {
finalColor.a = vTransparentLinePoint.a;
}

//set position into clip space
output.p = mul(output.p, mWorld);
output.p = mul(output.p, mView);
Expand Down Expand Up @@ -236,7 +242,7 @@ float4 PShaderLinesFade(PSInputLS input) : SV_Target
// Alpha is computed from the function exp2(-2(x)^2).
float sigma = 2.0f / (vLineParams.y + 1e-6);
dist *= dist;
float alpha = exp2(-2 * dist / sigma);
float alpha = input.c.a * exp2(-2 * dist / sigma);

//if(alpha<0.1) discard;

Expand Down
3 changes: 2 additions & 1 deletion src/DynamoCoreWpf/ViewModels/Watch3D/Shaders/Material.fx
Expand Up @@ -27,7 +27,8 @@ float2 vShadowMapSize = float2(1024, 1024);
float4 vShadowMapInfo = float4(0.005, 1.0, 0.5, 0.0);

float4 vSelectionColor = float4(0.0, 0.62, 1.0, 1.0);

float4 vTransparentMaterial = 0.1f;
float4 vTransparentLinePoint = 0.2f;

//--------------------------------------------------------------------------------------
// GLOBAL Variables (Varing)
Expand Down
8 changes: 7 additions & 1 deletion src/DynamoCoreWpf/ViewModels/Watch3D/Shaders/Points.fx
Expand Up @@ -55,19 +55,25 @@ GSInputPS VShaderPoints(GSInputPS input)
output.parameters = input.parameters;

bool isSelected = input.parameters.x;
bool isIsolationMode = input.parameters.y;

//set position into clip space
output.p = mul(output.p, mWorld);
output.p = mul(output.p, mView);
output.p = mul(output.p, mProjection);

if (isSelected) {
if (isSelected && !isIsolationMode) {
output.c = lerp(vSelectionColor, input.c, 0.3);
}
else {
output.c = input.c;
}

// unselected geometry is transparent under Isolate Selected Geometries mode
if (isIsolationMode && !isSelected) {
output.c.a = vTransparentLinePoint.a;
}

return output;
}

Expand Down
4 changes: 4 additions & 0 deletions src/DynamoCoreWpf/Views/Core/DynamoView.xaml
Expand Up @@ -707,6 +707,10 @@
IsEnabled="{Binding ChangeScaleFactorEnabled}"
Command="{Binding ChangeScaleFactorCommand}" />
<Separator />
<MenuItem Focusable="False"
IsCheckable="True"
IsChecked="{Binding Path=BackgroundPreviewViewModel.IsolationMode, Mode=TwoWay}"
Header="{x:Static p:Resources.DynamoViewSettingsMenuIsolationMode}"></MenuItem>
<MenuItem Focusable="False"
IsCheckable="True"
IsChecked="{Binding Path=RenderPackageFactoryViewModel.ShowEdges, Mode=TwoWay}"
Expand Down

0 comments on commit baa0279

Please sign in to comment.