Merge branch 'Vertex-Snapping' of https://github.com/cNori/FlaxEngineFork into cNori-Vertex-Snapping

This commit is contained in:
Wojtek Figat
2024-03-04 20:20:58 +01:00
4 changed files with 32 additions and 52 deletions

View File

@@ -263,6 +263,8 @@ namespace FlaxEditor.Gizmo
// Note: because selection may contain objects and their children we have to split them and get only parents. // Note: because selection may contain objects and their children we have to split them and get only parents.
// Later during transformation we apply translation/scale/rotation only on them (children inherit transformations) // Later during transformation we apply translation/scale/rotation only on them (children inherit transformations)
SceneGraphTools.BuildNodesParents(_selection, _selectionParents); SceneGraphTools.BuildNodesParents(_selection, _selectionParents);
base.OnSelectionChanged(newSelection);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -85,6 +85,7 @@ namespace FlaxEditor.Gizmo
{ {
InitDrawing(); InitDrawing();
ModeChanged += ResetTranslationScale; ModeChanged += ResetTranslationScale;
} }
/// <summary> /// <summary>
@@ -437,8 +438,6 @@ namespace FlaxEditor.Gizmo
{ {
case Mode.Translate: case Mode.Translate:
UpdateTranslateScale(); UpdateTranslateScale();
if (Owner.SnapToVertex)
UpdateVertexSnapping();
break; break;
case Mode.Scale: case Mode.Scale:
UpdateTranslateScale(); UpdateTranslateScale();
@@ -447,6 +446,8 @@ namespace FlaxEditor.Gizmo
UpdateRotate(dt); UpdateRotate(dt);
break; break;
} }
if (Owner.SnapToVertex)
UpdateVertexSnapping();
} }
else else
{ {
@@ -553,43 +554,23 @@ namespace FlaxEditor.Gizmo
for (int i = 0; i < SelectionCount; i++) for (int i = 0; i < SelectionCount; i++)
{ {
var obj = GetSelectedObject(i); var obj = GetSelectedObject(i);
if (obj.CanVertexSnap && obj.RayCastSelf(ref ray, out var distance, out _) && distance < closestDistance) if (obj.RayCastSelf(ref ray, out var distance, out _) && distance < closestDistance)
{ {
closestDistance = distance; closestDistance = distance;
closestObject = obj; closestObject = obj;
} }
} }
if (closestObject == null) if (closestObject == null)
{ return; // ignore it if there is nothing under the mouse closestObject is only null if ray caster missed everything or Selection Count == 0
// Find the closest object in selection (in case ray didn't hit anything)
for (int i = 0; i < SelectionCount; i++)
{
var obj = GetSelectedObject(i);
if (obj.CanVertexSnap)
{
GetSelectedObjectsBounds(out var bounds, out _);
CollisionsHelper.ClosestPointBoxPoint(ref bounds, ref ray.Ray.Position, out var point);
var distance = Vector3.Distance(ref point, ref ray.Ray.Position);
if (distance < closestDistance)
{
closestDistance = distance;
closestObject = obj;
}
}
}
}
_vertexSnapObject = closestObject; _vertexSnapObject = closestObject;
if (closestObject == null)
return;
// Find the closest vertex to bounding box point (collision detection approximation) if (!closestObject.OnVertexSnap(ref ray.Ray, closestDistance, out _vertexSnapPoint))
var closestPoint = ray.Ray.GetPoint(closestDistance);
if (!closestObject.OnVertexSnap(ref closestPoint, out _vertexSnapPoint))
{ {
// Failed to get the closest point //The OnVertexSnap is unimplemented or failed to get point return because there is nothing to do
_vertexSnapPoint = closestPoint; _vertexSnapPoint = Vector3.Zero;
return;
} }
// Transform back to the local space of the object to work when moving it // Transform back to the local space of the object to work when moving it
_vertexSnapPoint = closestObject.Transform.WorldToLocal(_vertexSnapPoint); _vertexSnapPoint = closestObject.Transform.WorldToLocal(_vertexSnapPoint);
} }
@@ -619,10 +600,9 @@ namespace FlaxEditor.Gizmo
for (int i = 0; i < SelectionCount; i++) for (int i = 0; i < SelectionCount; i++)
rayCast.ExcludeObjects.Add(GetSelectedObject(i)); rayCast.ExcludeObjects.Add(GetSelectedObject(i));
var hit = Owner.SceneGraphRoot.RayCast(ref rayCast, out var distance, out var _); var hit = Owner.SceneGraphRoot.RayCast(ref rayCast, out var distance, out var _);
if (hit != null && hit.CanVertexSnap) if (hit != null)
{ {
var point = rayCast.Ray.GetPoint(distance); if (hit.OnVertexSnap(ref rayCast.Ray, distance, out var pointSnapped)
if (hit.OnVertexSnap(ref point, out var pointSnapped)
//&& Vector3.Distance(point, pointSnapped) <= 25.0f //&& Vector3.Distance(point, pointSnapped) <= 25.0f
) )
{ {
@@ -712,5 +692,11 @@ namespace FlaxEditor.Gizmo
protected virtual void OnDuplicate() protected virtual void OnDuplicate()
{ {
} }
/// <inheritdoc />
public override void OnSelectionChanged(List<SceneGraphNode> newSelection)
{
EndVertexSnapping();
UpdateGizmoPosition();
}
} }
} }

View File

@@ -23,20 +23,23 @@ namespace FlaxEditor.SceneGraph.Actors
: base(actor) : base(actor)
{ {
} }
/// <inheritdoc /> /// <inheritdoc />
public override bool OnVertexSnap(ref Vector3 point, out Vector3 result) public override bool OnVertexSnap(ref Ray ray, float hitDistance, out Vector3 result)
{ {
result = point; // Find the closest vertex to bounding box point (collision detection approximation)
result = ray.GetPoint(hitDistance);
var model = ((StaticModel)Actor).Model; var model = ((StaticModel)Actor).Model;
if (model && !model.WaitForLoaded()) if (model && !model.WaitForLoaded())
{ {
// TODO: move to C++ and use cached vertex buffer internally inside the Mesh // TODO: move to C++ and use cached vertex buffer internally inside the Mesh
if (_vertices == null) if (_vertices == null)
_vertices = new(); _vertices = new();
var pointLocal = (Float3)Actor.Transform.WorldToLocal(point); var pointLocal = (Float3)Actor.Transform.WorldToLocal(result);
var minDistance = float.MaxValue; var minDistance = float.MaxValue;
foreach (var lod in model.LODs) foreach (var lod in model.LODs) //[ToDo] fix it [Nori_SC note] this is wrong it should get current lod level going it throw all lods will create ghost snaping points
{ {
var hit = false; var hit = false;
foreach (var mesh in lod.Meshes) foreach (var mesh in lod.Meshes)

View File

@@ -94,18 +94,6 @@ namespace FlaxEditor.SceneGraph
/// </summary> /// </summary>
public virtual bool CanTransform => true; public virtual bool CanTransform => true;
/// <summary>
/// Gets a value indicating whether this node can be used for the vertex snapping feature.
/// </summary>
public bool CanVertexSnap
{
get
{
var v = Vector3.Zero;
return OnVertexSnap(ref v, out _);
}
}
/// <summary> /// <summary>
/// Gets a value indicating whether this <see cref="SceneGraphNode"/> is active. /// Gets a value indicating whether this <see cref="SceneGraphNode"/> is active.
/// </summary> /// </summary>
@@ -365,14 +353,15 @@ namespace FlaxEditor.SceneGraph
} }
/// <summary> /// <summary>
/// Performs the vertex snapping of a given point on the object surface that is closest to a given location. /// Performs the vertex snapping for a given ray and hitDistance.
/// </summary> /// </summary>
/// <param name="point">The position to snap.</param> /// <param name="ray">Raycasted ray</param>
/// <param name="hitDistance">Hit distance from ray to object bounding box</param>
/// <param name="result">The result point on the object mesh that is closest to the specified location.</param> /// <param name="result">The result point on the object mesh that is closest to the specified location.</param>
/// <returns>True if got a valid result value, otherwise false (eg. if missing data or not initialized).</returns> /// <returns>True if got a valid result value, otherwise false (eg. if missing data or not initialized).</returns>
public virtual bool OnVertexSnap(ref Vector3 point, out Vector3 result) public virtual bool OnVertexSnap(ref Ray ray,float hitDistance, out Vector3 result) // [NoriSC note] ray and hit Distance will be needed for a future use, in mesh types for proper collision detection
{ {
result = point; result = Vector3.Zero;
return false; return false;
} }