Skip to content

Commit

Permalink
clean up and refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
bozmir committed Feb 11, 2025
1 parent 6d348f8 commit 91b95b0
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 139 deletions.
37 changes: 20 additions & 17 deletions Assets/_Functionalities/ObjectInformation/Scripts/BagInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public class BagInspector : MonoBehaviour
private FeatureSelector featureSelector;
private SubObjectSelector subObjectSelector;

private List<GameObject> orderedMappings = new List<GameObject>();
private List<IMapping> orderedMappings = new List<IMapping>();
private float minClickDistance = 10;
private float minClickTime = 0.5f;
private float lastTimeClicked = 0;
Expand Down Expand Up @@ -113,7 +113,15 @@ private void Awake()
HideObjectInformation();
}


private void Start()
{
//baginspector could be enabled later on, so it would be missing the already instantiated mappings
ObjectMapping[] alreadyActiveMappings = FindObjectsOfType<ObjectMapping>();
foreach (ObjectMapping mapping in alreadyActiveMappings)
{
OnAddObjectMapping(mapping);
}
}

private void OnAddObjectMapping(ObjectMapping mapping)
{
Expand Down Expand Up @@ -179,15 +187,10 @@ private bool IsClicked()
/// </summary>
private void FindObjectMapping()
{
Deselect();

// Raycast from pointer position using main camera
var position = Pointer.current.position.ReadValue();
var ray = mainCamera.ScreenPointToRay(position);
Deselect();

//the following method calls need to run in order!
string bagId = subObjectSelector.FindSubObject();
//if (hit.collider == null) return;
string bagId = subObjectSelector.FindSubObject();

bool clickedSamePosition = Vector3.Distance(lastWorldClickedPosition, pointerToWorldPosition.WorldPoint) < minClickDistance;
lastWorldClickedPosition = pointerToWorldPosition.WorldPoint;
Expand All @@ -197,14 +200,14 @@ private void FindObjectMapping()

if (!clickedSamePosition || refreshSelection)
{
featureSelector.SetBlockingObjectMapping(subObjectSelector.Object, lastWorldClickedPosition);
featureSelector.SetBlockingObjectMapping(subObjectSelector.Object.ObjectMapping, lastWorldClickedPosition);

//no features are imported yet if mappingTreeInstance is null
if (mappingTreeInstance != null)
featureSelector.FindFeature(mappingTreeInstance);

orderedMappings.Clear();
Dictionary<GameObject, int> mappings = new Dictionary<GameObject, int>();
Dictionary<IMapping, int> mappings = new Dictionary<IMapping, int>();
//lets order all mappings by layerorder (rootindex) from layerdata
if (featureSelector.HasFeatureMapping)
{
Expand All @@ -221,17 +224,17 @@ private void FindObjectMapping()
continue;
}

mappings.TryAdd(feature.gameObject, feature.VisualisationParent.LayerData.RootIndex);
mappings.TryAdd(feature, feature.VisualisationParent.LayerData.RootIndex);
}
}
}
if (subObjectSelector.HasObjectMapping)
{
LayerGameObject subObjectParent = subObjectSelector.Object.transform.GetComponentInParent<LayerGameObject>();
LayerGameObject subObjectParent = subObjectSelector.Object.ObjectMapping.transform.GetComponentInParent<LayerGameObject>();
if (subObjectParent != null)
{
if(subObjectParent.LayerData.ActiveInHierarchy)
mappings.TryAdd(subObjectSelector.Object.gameObject, subObjectParent.LayerData.RootIndex);
mappings.TryAdd(subObjectSelector.Object, subObjectParent.LayerData.RootIndex);
}
}

Expand All @@ -251,14 +254,14 @@ private void FindObjectMapping()

//Debug.Log(orderedMappings[currentSelectedMappingIndex]);

GameObject selection = orderedMappings[currentSelectedMappingIndex];
if (selection.GetComponent<ObjectMapping>())
IMapping selection = orderedMappings[currentSelectedMappingIndex];
if (selection is MeshMapping)
{
SelectBuildingOnHit(bagId);
}
else
{
SelectFeatureOnHit(selection.GetComponent<FeatureMapping>());
SelectFeatureOnHit(selection as FeatureMapping);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class FeatureMapping : MonoBehaviour, IMapping
{
public string DebugID;

public object MappingObject => feature;
public string FeatureID => feature.Id;
public IGeoJsonVisualisationLayer VisualisationLayer { get { return visualisationLayer; } }
public GeoJsonLayerGameObject VisualisationParent { get { return geoJsonLayerParent; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace Netherlands3D.Functionalities.ObjectInformation
{
public interface IMapping
{
public object MappingObject { get; }
public BoundingBox BoundingBox { get; }
}
}
142 changes: 34 additions & 108 deletions Assets/_Functionalities/ObjectInformation/Scripts/MeshMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Netherlands3D.Functionalities.ObjectInformation
/// </summary>
public class MeshMapping : MonoBehaviour, IMapping
{
public object MappingObject => objectMapping;
public ObjectMapping ObjectMapping => objectMapping;
public BoundingBox BoundingBox => boundingBox;
public List<MeshMappingItem> Items => items;
Expand Down Expand Up @@ -88,25 +89,25 @@ public void RemoveItems()

}

void OnDrawGizmos()
{
if(items != null)
{
foreach (MeshMappingItem item in items)
{
item.BoundingBox.Debug(Color.blue);
item.Debug(Color.red);
}
}
}
//void Debug(Color color)
//{
// if(items != null)
// {
// foreach (MeshMappingItem item in items)
// {
// item.BoundingBox.Debug(color);
// }
// }
//}
}

public class MeshMappingItem : IMapping
public class MeshMappingItem
{
public BoundingBox BoundingBox => boundingBox;
public ObjectMappingItem ObjectMappingItem => item;
private BoundingBox boundingBox;
private ObjectMappingItem item;
private const float kEpsilon = 0.000001f;

public MeshMappingItem(ObjectMappingItem item, Vector3[] vertices, Transform meshTransform)
{
Expand All @@ -119,32 +120,26 @@ public void UpdateBoundingBox(Vector3[] vertices, Transform meshTransform)
if (item.firstVertex < 0 || item.firstVertex + item.verticesLength > vertices.Length)
return;

// Initialize min and max as the first vertex (in world space)
//get worldspace bounds
Vector3 firstVertexWorld = meshTransform.TransformPoint(vertices[item.firstVertex]);
Vector3 min = firstVertexWorld;
Vector3 max = firstVertexWorld;

// Iterate through the vertices and update min/max bounds
for (int i = item.firstVertex + 1; i < item.firstVertex + item.verticesLength; i++)
{
Vector3 vertexWorld = meshTransform.TransformPoint(vertices[i]);
min = Vector3.Min(min, vertexWorld); // Update min
max = Vector3.Max(max, vertexWorld); // Update max
}

// Create the bounding box from the world-space min/max
min = Vector3.Min(min, vertexWorld);
max = Vector3.Max(max, vertexWorld);
}
Bounds bounds = new Bounds();
bounds.SetMinMax(min, max); // Sets the min and max based on the world space vertices

// Convert to coordinate system as needed
bounds.SetMinMax(min, max);
Coordinate bottomLeft = new Coordinate(CoordinateSystem.Unity, bounds.min.x, bounds.min.y, bounds.min.z);
Coordinate topRight = new Coordinate(CoordinateSystem.Unity, bounds.max.x, bounds.max.y, bounds.max.z);
Coordinate blWgs84 = bottomLeft.Convert(CoordinateSystem.WGS84_LatLon);
Coordinate trWgs84 = topRight.Convert(CoordinateSystem.WGS84_LatLon);
boundingBox = new BoundingBox(blWgs84, trWgs84);
}

private Vector3[] testVertices = new Vector3[4];
public bool IsPositionHit(Vector3 worldPosition, Vector3[] vertices, int[] triangles, Transform meshTransform)
{
Vector3 localPosition = meshTransform.InverseTransformPoint(worldPosition);
Expand All @@ -165,7 +160,7 @@ public bool IsPositionHit(Vector3 worldPosition, Vector3[] vertices, int[] trian
}
if (firstTriangleIndex == -1) return false;

//debugSubmeshVertices.Clear();
//start at the first triangle index found and check if the corresponding triangles of this submehs intersect with the camray towards the optical point
int triMax = item.firstVertex + item.verticesLength;
for (int j = firstTriangleIndex; j < triangles.Length; j += 3)
{
Expand All @@ -177,29 +172,23 @@ public bool IsPositionHit(Vector3 worldPosition, Vector3[] vertices, int[] trian
Vector3 v1 = meshTransform.TransformPoint(vertices[triangles[j + 1]]);
Vector3 v2 = meshTransform.TransformPoint(vertices[triangles[j + 2]]);

//debugSubmeshVertices.Add(v0);
//debugSubmeshVertices.Add(v1);
//debugSubmeshVertices.Add(v2);

float dist;
float dist; //TODO we could check based on distance which triangle is closest, but works for now, checking that would be slower
if (IntersectRayTriangle(camRay, v0, v1, v2, out dist))
{
testVertices[0] = v0;
testVertices[1] = v1;
testVertices[2] = v2;
testVertices[3] = worldPosition;
return true;
}
}
return false;
}

private const float kEpsilon = 0.000001f;
/// <returns><c>The distance along the ray to the intersection</c> if one exists, <c>NaN</c> if one does not.</returns>
/// <param name="ray">Le ray.</param>
/// <param name="v0">A vertex of the triangle.</param>
/// <param name="v1">A vertex of the triangle.</param>
/// <param name="v2">A vertex of the triangle.</param>

/// <summary>
/// if it hits a triangle it returns a length towards the triangle (distance from the ray origin to the hit point)
/// </summary>
/// <param name="ray"></param>
/// <param name="v0"></param>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <param name="length"></param>
/// <returns></returns>
public static bool IntersectRayTriangle(Ray ray, Vector3 v0, Vector3 v1, Vector3 v2, out float length)
{
// edges from v1 & v2 to v0.
Expand All @@ -208,84 +197,21 @@ public static bool IntersectRayTriangle(Ray ray, Vector3 v0, Vector3 v1, Vector3
length = 0;
Vector3 h = Vector3.Cross(ray.direction, e2);
float a = Vector3.Dot(e1, h);
if ((a > -kEpsilon) && (a < kEpsilon))
{
return false;
}

if ((a > -kEpsilon) && (a < kEpsilon)) return false;
float f = 1.0f / a;

Vector3 s = ray.origin - v0;
float u = f * Vector3.Dot(s, h);
if ((u < 0.0f) || (u > 1.0f))
{
return false;
}

if ((u < 0.0f) || (u > 1.0f)) return false;
Vector3 q = Vector3.Cross(s, e1);
float v = f * Vector3.Dot(ray.direction, q);
if ((v < 0.0f) || (u + v > 1.0f))
{
return false;
}

if ((v < 0.0f) || (u + v > 1.0f)) return false;
float t = f * Vector3.Dot(e2, q);
if (t > kEpsilon)
{
length = t;
return true;
}
else
{
return false;
}
}
private List<Vector3> debugSubmeshVertices = new List<Vector3>();

public void Debug(Color color)
{

for (int i = 0; i < testVertices.Length; i++)
{
testVertices[i].y = 50;
}
//UnityEngine.Debug.DrawLine(testVertices[0], testVertices[1], color);
//UnityEngine.Debug.DrawLine(testVertices[1], testVertices[2], color);
//UnityEngine.Debug.DrawLine(testVertices[2], testVertices[0], color);

//UnityEngine.Debug.DrawLine(testVertices[0], testVertices[3], color);
//UnityEngine.Debug.DrawLine(testVertices[1], testVertices[3], color);
//UnityEngine.Debug.DrawLine(testVertices[2], testVertices[3], color);

for (int i = 0; i < debugSubmeshVertices.Count - 1; i++)
{
UnityEngine.Debug.DrawLine(debugSubmeshVertices[i], debugSubmeshVertices[i + 1], color);
}
return false;
}

//private bool IsPointInTriangle(Vector3 p, Vector3 v0, Vector3 v1, Vector3 v2)
//{
// // Calculate vectors from point p to vertices v0, v1, v2
// Vector3 v0v1 = v1 - v0;
// Vector3 v0v2 = v2 - v0;
// Vector3 v0p = p - v0;

// float dot00 = Vector3.Dot(v0v1, v0v1);
// float dot01 = Vector3.Dot(v0v1, v0v2);
// float dot02 = Vector3.Dot(v0v1, v0p);
// float dot11 = Vector3.Dot(v0v2, v0v2);
// float dot12 = Vector3.Dot(v0v2, v0p);

// float invDenom = 1f / (dot00 * dot11 - dot01 * dot01);

// float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
// float v = (dot00 * dot12 - dot01 * dot02) * invDenom;

// // Tolerance for floating-point precision errors (can be adjusted)
// const float tolerance = 1e-6f;

// // Check if the point is inside the triangle
// return (u >= -tolerance) && (v >= -tolerance) && (u + v <= 1 + tolerance);
//}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ namespace Netherlands3D.Functionalities.ObjectInformation
public class SubObjectSelector : MonoBehaviour, IObjectSelector
{
public bool HasObjectMapping => foundObject != null;
public ObjectMapping Object => foundObject;
public string ObjectID => foundId;
public MeshMapping Object => foundObject;

[SerializeField] private float hitDistance = 100000f;
private ColorSetLayer ColorSetLayer { get; set; } = new(0, new());
private ObjectMapping foundObject;
private string foundId;
private MeshMapping foundObject;

private PointerToWorldPosition pointerToWorldPosition;

Expand Down Expand Up @@ -46,13 +43,6 @@ public string FindSubObject()
{
foundObject = null;
string bagId = null;
//if (!Physics.Raycast(ray, out hit, hitDistance)) return null;

//// lets use a capsule cast here to ensure objects are hit (some objects for features are really small) and
//// use a nonalloc to prevent memory allocations
//var objectMapping = hit.collider.gameObject.GetComponent<ObjectMapping>();
//if (!objectMapping) return null;

Vector3 groundPosition = pointerToWorldPosition.WorldPoint;
Coordinate coord = new Coordinate(groundPosition);
List<IMapping> mappings = BagInspector.MappingTree.QueryMappingsContainingNode<MeshMapping>(coord);
Expand All @@ -62,11 +52,10 @@ public string FindSubObject()
foreach (MeshMapping mapping in mappings)
{
ObjectMapping objectMapping = mapping.ObjectMapping;
//var bagId = objectMapping.getObjectID(hit.triangleIndex);
MeshMappingItem item = mapping.FindItemForPosition(groundPosition);
if (item != null)
{
foundObject = objectMapping;
foundObject = mapping;
bagId = item.ObjectMappingItem.objectID;
break;
}
Expand Down

0 comments on commit 91b95b0

Please sign in to comment.