public void Clear() { Url = null; RawHtml = null; Title = null; MetadataList.Clear(); AnchorList.Clear(); ImageList.Clear(); }
public async Task <ActionResult> Post([FromBody] JsonElement body) { AnchorList anchorList = JsonSerializer.Deserialize <AnchorList>(body.GetRawText()); List <JSONAnchor> jSONAnchors = anchorList.anchors.ToList(); // define operator for this foreach (JSONAnchor anchor in jSONAnchors) { Anchor parsedAnchor; try { parsedAnchor = _anchorsCollection.Find(a => a._id == ObjectId.Parse(anchor._id)).FirstOrDefault(); } catch (Exception e) { parsedAnchor = new Anchor(); parsedAnchor._id = new ObjectId(); } parsedAnchor.AnchorID = anchor.AnchorID; parsedAnchor.AssetID = ObjectId.Parse(anchor.AssetID); parsedAnchor.SceneID = ObjectId.Parse(anchor.SceneID); parsedAnchor.Transform = anchor.Transform; parsedAnchor.Rotation = anchor.Rotation; parsedAnchor.Scale = anchor.Scale; if (parsedAnchor._id == default) { await _anchorsCollection.InsertOneAsync(parsedAnchor); } else { await _anchorsCollection.ReplaceOneAsync(a => a._id == parsedAnchor._id, parsedAnchor, new ReplaceOptions { IsUpsert = true }); } } return(CreatedAtAction("PostAnchors", jSONAnchors)); }
/// <summary> /// resets for reuse /// </summary> public void Reset() { IterationType = null; AnchorList.Clear(); Page = 0; }
public static IEnumerator Fragment(GameObject toFragmentObject, Stats returnedStats, bool areaInsteadOfSites = false) { returnedStats.totalTime = 0L; Debug.Log("Fragmentation started!"); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // Gather fragmentation properties for the current game object. The program checks the // current game object and the topmost game object of the hierarchy for such properties. // If none are found, assume default properties. FragmentsProperties fragmentsProperties = toFragmentObject.GetComponent <FragmentsProperties>(); if (fragmentsProperties == null) { GameObject root = toFragmentObject.transform.root.gameObject; FragmentsProperties rootFragmentsProperties = root.GetComponent <FragmentsProperties>(); fragmentsProperties = (rootFragmentsProperties == null) ? toFragmentObject.AddComponent <FragmentsProperties>() : rootFragmentsProperties; } // Create new game object as parent of future generated fragments. This game object will // replace the current game object in the hierarchy and will retain its fragmentation properties. GameObject parentObject = new GameObject(toFragmentObject.name + Constants.FragmentStr); CopyTransforms(parentObject.transform, toFragmentObject.transform); parentObject.transform.SetParent(toFragmentObject.transform.parent, false); FragmentsProperties.Copy(parentObject.AddComponent <FragmentsProperties>(), fragmentsProperties); // Iterate through the mesh's triangles and divide each triangle in separate Voronoi diagrams. // The generated fragments will retain the original mesh's materials, normals and uv coordinates. int totalFragments = 0; Mesh mesh = toFragmentObject.GetComponent <MeshFilter>().mesh; for (int subMeshIndex = 0; subMeshIndex < mesh.subMeshCount; ++subMeshIndex) { int[] triangles = mesh.GetTriangles(subMeshIndex); // TODO paralelize for (int ti = 0; ti < triangles.Length; ti += 3) { Vertex[] v = new Vertex[3]; for (int i = 0; i < 3; ++i) { v[i].position = mesh.vertices[triangles[ti + i]]; // Assume zero values if missing normal or uv coordinates v[i].normal = (mesh.normals.Length <= triangles[ti + i]) ? Vector3.zero : mesh.normals[triangles[ti + i]]; v[i].uv = (mesh.uv.Length <= triangles[ti + i]) ? Vector2.zero : mesh.uv[triangles[ti + i]]; } List <GameObject> fragments = GenerateVoronoiFragments(v[0], v[1], v[2], fragmentsProperties, areaInsteadOfSites); foreach (GameObject fragment in fragments) { if (fragment.GetComponent <MeshFilter>() != null) { // Create new game object with fragment's mesh fragment.name = Constants.FrozenFragmentStr + totalFragments; fragment.transform.SetParent(parentObject.transform, false); fragment.tag = Constants.FrozenFragmentStr; MeshRenderer goMeshRenderer = toFragmentObject.GetComponent <MeshRenderer>(); MeshRenderer fragmentMeshRenderer = fragment.AddComponent <MeshRenderer>(); int materialIdx = subMeshIndex % goMeshRenderer.materials.Length; fragmentMeshRenderer.material = goMeshRenderer.materials[materialIdx]; // Hide current fragment's mesh until the destruction of the initial game object // to prevent z-fighting effects. fragmentMeshRenderer.enabled = false; MeshCollider mc = fragment.AddComponent <MeshCollider>(); mc.convex = true; Rigidbody rb = fragment.AddComponent <Rigidbody>(); rb.detectCollisions = false; rb.isKinematic = true; rb.interpolation = RigidbodyInterpolation.Interpolate; rb.mass = fragmentsProperties.density * FragmentVolume(fragment); rb.angularDrag = Constants.FragmentRBodyAngDrag; rb.drag = Constants.FragmentRBodyDrag; fragment.AddComponent <JointBreakListener>(); ++totalFragments; } else { // Missing fragment Debug.Log($"Clipped site: {fragment.transform.localPosition}"); } } // Ensure the current function operation does not take a lot of time // in a single frame if (stopWatch.ElapsedMilliseconds > Constants.MaxTimeMs) { Debug.Log("Fragmenter Yield in voronoi generation"); returnedStats.totalTime += stopWatch.ElapsedMilliseconds; yield return(null); stopWatch.Restart(); } } // Ensure the current function operation does not take a lot of time // in a single frame if (stopWatch.ElapsedMilliseconds > Constants.MaxTimeMs) { Debug.Log("Fragmenter Yield submesh parsing"); returnedStats.totalTime += stopWatch.ElapsedMilliseconds; yield return(null); stopWatch.Restart(); } } Debug.Log($"Fragmentation Ended at: {returnedStats.totalTime / 1000.0f}"); // Create an undirected graph with all fragments. Each fragment represents a node in the // graph. The edges represent the connectivity between the fragments. Each node will have // a direct edge to each of its touching neighbours. var graph = new Graph <GameObject, HingeJoint>(); foreach (Transform child in parentObject.transform) { if (!child.CompareTag(Constants.FrozenFragmentStr)) { continue; } GameObject go = child.gameObject; List <GameObject> possibleNeighbours = new List <GameObject>(); // To find the touching neighbours, do a rough and fast bounding box intersection first. foreach (Transform child2 in parentObject.transform) { GameObject go2 = child2.gameObject; if (go != go2) { Bounds b1 = go.GetComponent <MeshCollider>().bounds; Bounds b2 = go2.GetComponent <MeshCollider>().bounds; if (b1 == null) { Debug.Log($"{go} does not have a Mesh Collider"); } if (b2 == null) { Debug.Log($"{go2} does not have a Mesh Collider"); } if (b1 != null && b2 != null && b1.Intersects(b2)) { possibleNeighbours.Add(go2); } } } // Do a more fine and more computational heavy intersection. To do so, the mesh collider's // size will be slightly increased. The actual mesh collider's size cannot be modified, // thus a new game object will be created with a bigger mesh and a mesh collider. GameObject biggerGo = new GameObject($"Big_{child.name}"); biggerGo.transform.SetParent(go.transform); CopyTransforms(biggerGo.transform, go.transform); biggerGo.AddComponent <MeshFilter>().mesh = ScaleMesh(go.GetComponent <MeshFilter>().mesh, Constants.MeshUpscaling); biggerGo.AddComponent <MeshCollider>().convex = true; if (!graph.ContainsNode(go)) { graph.AddNode(go); } foreach (GameObject neighbour in possibleNeighbours) { Collider colBigg = biggerGo.GetComponent <Collider>(); Collider colNeigh = neighbour.GetComponent <Collider>(); if (Physics.ComputePenetration( colBigg, go.transform.position, go.transform.rotation, colNeigh, neighbour.transform.position, neighbour.transform.rotation, out _, out _)) { if (graph.ContainsEdge(go, neighbour) || graph.ContainsEdge(neighbour, go)) { continue; } if (!graph.ContainsNode(neighbour)) { graph.AddNode(neighbour); } void CreateJoint(GameObject go1, GameObject go2) { Vector3 center1 = FragmentCenter(go1); Vector3 center2 = FragmentCenter(go2); HingeJoint hj = go1.AddComponent <HingeJoint>(); hj.connectedBody = go2.GetComponent <Rigidbody>(); hj.enableCollision = false; hj.breakForce = Constants.FragmentHingeBreakForce; hj.anchor = center2; hj.axis = center2 - center1; JointLimits hinjeLimits = hj.limits; hinjeLimits.min = Constants.FragmentHingeMinAngleDeg; hinjeLimits.bounciness = 0.0f; hinjeLimits.bounceMinVelocity = 0.0f; hinjeLimits.max = Constants.FragmentHingeMaxAngleDeg; hj.limits = hinjeLimits; hj.useLimits = true; graph.AddEdge(go1, go2, hj); } CreateJoint(go, neighbour); CreateJoint(neighbour, go); } } //empty.transform.SetParent(null); Object.Destroy(biggerGo); // Ensure the current function operation does not take a lot of time // in a single frame. if (stopWatch.ElapsedMilliseconds > Constants.MaxTimeMs) { Debug.Log("Fragmenter Yield in graph creating"); returnedStats.totalTime += stopWatch.ElapsedMilliseconds; yield return(null); stopWatch.Restart(); } } //Debug.Log($"Min Area: {minSurface}, Max Area: {maxSurface}"); FragmentsGraph fragmentsGraph = parentObject.AddComponent <FragmentsGraph>(); fragmentsGraph.graph = graph; // Chose anchor fragments. An anchor fragment is a fragment which is considered crucial in // a mesh structural stability. These have to be manually specified. The program decides // if a fragment is an anchor if it intersects a 3D object with "Anchor" tag and layer. AnchorList anchorList = toFragmentObject.GetComponent <AnchorList>(); if (anchorList == null) { anchorList = toFragmentObject.transform.parent.gameObject.GetComponent <AnchorList>(); } if (anchorList != null) { // Fast and rough intersection List <GameObject> possibleAnchored = new List <GameObject>(); foreach (Transform fragment in parentObject.transform) { foreach (GameObject anchor in anchorList.gameObjects) { Bounds b1 = fragment.GetComponent <Collider>().bounds; Bounds b2 = anchor.GetComponent <BoxCollider>().bounds; if (b1.Intersects(b2)) { possibleAnchored.Add(fragment.gameObject); } } } // Slow and accurate intersection HashSet <GameObject> anchoredFragments = new HashSet <GameObject>(); foreach (GameObject fragment in possibleAnchored) { Collider col1 = fragment.GetComponent <Collider>(); foreach (GameObject anchor in anchorList.gameObjects) { Collider col2 = anchor.GetComponent <Collider>(); if (Physics.ComputePenetration( col1, fragment.transform.position, fragment.transform.rotation, col2, anchor.transform.position, anchor.transform.rotation, out _, out _)) { anchoredFragments.Add(fragment); //Debug.Log($"Anchored {fragment.name}"); } } } fragmentsGraph.anchoredFragments = anchoredFragments; fragmentsGraph.initialAnchoredCount = anchoredFragments.Count; } foreach (Transform child in parentObject.transform) { child.gameObject.GetComponent <MeshRenderer>().enabled = true; Rigidbody rb = child.gameObject.GetComponent <Rigidbody>(); rb.isKinematic = fragmentsGraph.anchoredFragments != null && fragmentsGraph.anchoredFragments.Contains(rb.gameObject); rb.detectCollisions = true; } returnedStats.isDone = true; returnedStats.fragments = totalFragments; returnedStats.fragmentedGameObject = parentObject; fragmentsGraph.initialFragmentsCount = fragmentsGraph.currentFragmentsCount = totalFragments; Object.Destroy(toFragmentObject); }