Example #1
0
 public void Clear()
 {
     Url     = null;
     RawHtml = null;
     Title   = null;
     MetadataList.Clear();
     AnchorList.Clear();
     ImageList.Clear();
 }
Example #2
0
        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));
        }
Example #3
0
 /// <summary>
 /// resets for reuse
 /// </summary>
 public void Reset()
 {
     IterationType = null;
     AnchorList.Clear();
     Page = 0;
 }
Example #4
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);
    }