Beispiel #1
0
    public PatchTree(Vector3 Up, Vector3 Front, PatchSphere Sphere)
    {
        this.Sphere = Sphere;

        this.Up    = UpProjected = Up;
        this.Front = FrontProjected = Front;
        this.Right = -Vector3.Cross(this.Up, this.Front);

        Parent     = null;
        SplitLevel = 0;
        Size       = this.Sphere.Radius * 2;

        Neighbors[0].Node    = Neighbors[1].Node = Neighbors[2].Node = Neighbors[3].Node = null;
        Neighbors[0].isFixed = Neighbors[1].isFixed = Neighbors[2].isFixed = Neighbors[3].isFixed = false;
        Children[0]          = Children[1] = Children[2] = Children[3] = null;

        NeedsRejoinCount = 0;
        HasChildren      = false;
        NeedsReedge      = true;
        NeedsTerrain     = true;
        GapFixMask       = 15;

        GenerateVolume();

        Plane = new Plane(Volume.Vertices[0], Volume.Vertices[2], Volume.Vertices[1]);
    }
Beispiel #2
0
        // selectingPatchesをすべて結合する
        private void combineCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string newKey = "combined" + combinedCount;

            HashSet <string> patchKeySet = new HashSet <string>();

            for (int i = 0; i < selectingQueries.Count; i++)
            {
                foreach (string k in selectingQueries[i].patchKeys)
                {
                    patchKeySet.Add(k);
                }
            }

            PatchSkeletalMesh newMesh = PatchConnector.Connect(selectingQueries.Select(q => q.patch).ToList(), refSkeleton, resources);


            PatchTree newTree = new PatchTree(null, null);

            if (newMesh == null)
            {
                return;
            }

            newMesh.Mesh.BeginDeformation();

            renderQueryPool.Add(newKey, new RenderQuery(newMesh, newTree, patchKeySet.ToList()));
            combinedCount++;


            foreach (var q in selectingQueries)
            {
                renderQueries.Remove(q);
            }
            renderQueries.Add(renderQueryPool[newKey]);

            selectingQueries.Clear();
        }
Beispiel #3
0
    private void Split()
    {
        //discard parent's resources
        if (Parent != null)
        {
            Parent.DestroyNode();
        }

        //force too coarse neighbors to split as well
        for (byte i = 0; i < 4; i++)
        {
            if (SplitLevel > Neighbors[i].Node.SplitLevel && !Neighbors[i].Node.HasChildren)
            {
                Neighbors[i].Node.Split();

                return;
            }
        }

        #region TOP LEFT

        var volume1 = new PatchAABB();

        volume1.Vertices.Add(Volume.Vertices[0]);
        volume1.Vertices.Add(Vector3.Lerp(Volume.Vertices[0], Volume.Vertices[1], 0.5f));
        volume1.Vertices.Add(Middle);
        volume1.Vertices.Add(Vector3.Lerp(Volume.Vertices[3], Volume.Vertices[0], 0.5f));

        var uv1a = Volume.UVs[0];
        var uv1b = Vector3.Lerp(Volume.UVs[0], Volume.UVs[1], 0.5f);
        var uv1d = Vector3.Lerp(Volume.UVs[3], Volume.UVs[0], 0.5f);
        var uv1c = new Vector3(uv1b.x, uv1d.y, 0);

        volume1.UVs.Add(uv1a);
        volume1.UVs.Add(uv1b);
        volume1.UVs.Add(uv1c);
        volume1.UVs.Add(uv1d);

        #endregion

        #region TOP RIGHT

        //second child - top right
        var volume2 = new PatchAABB();
        volume2.Vertices.Add(Vector3.Lerp(Volume.Vertices[0], Volume.Vertices[1], 0.5f));
        volume2.Vertices.Add(Volume.Vertices[1]);
        volume2.Vertices.Add(Vector3.Lerp(Volume.Vertices[1], Volume.Vertices[2], 0.5f));
        volume2.Vertices.Add(Middle);

        var uv2a = Vector3.Lerp(Volume.UVs[0], Volume.UVs[1], 0.5f);
        var uv2b = Volume.UVs[1];
        var uv2c = Vector3.Lerp(Volume.UVs[1], Volume.UVs[2], 0.5f);
        var uv2d = new Vector3(uv2a.x, uv2c.y, 0);

        volume2.UVs.Add(uv2a);
        volume2.UVs.Add(uv2b);
        volume2.UVs.Add(uv2c);
        volume2.UVs.Add(uv2d);

        #endregion

        #region BOTTOM RIGHT

        //third child - bottom right
        var volume3 = new PatchAABB();

        volume3.Vertices.Add(Middle);
        volume3.Vertices.Add(Vector3.Lerp(Volume.Vertices[1], Volume.Vertices[2], 0.5f));
        volume3.Vertices.Add(Volume.Vertices[2]);
        volume3.Vertices.Add(Vector3.Lerp(Volume.Vertices[3], Volume.Vertices[2], 0.5f));

        var uv3b = Vector3.Lerp(Volume.UVs[1], Volume.UVs[2], 0.5f);
        var uv3c = Volume.UVs[2];
        var uv3d = Vector3.Lerp(Volume.UVs[3], Volume.UVs[2], 0.5f);
        var uv3a = new Vector3(uv3d.x, uv3b.y, 0);

        volume3.UVs.Add(uv3a);
        volume3.UVs.Add(uv3b);
        volume3.UVs.Add(uv3c);
        volume3.UVs.Add(uv3d);

        #endregion

        #region BOTTOM LEFT

        //fourth child - bottom left
        var volume4 = new PatchAABB();

        volume4.Vertices.Add(Vector3.Lerp(Volume.Vertices[3], Volume.Vertices[0], 0.5f));
        volume4.Vertices.Add(Middle);
        volume4.Vertices.Add(Vector3.Lerp(Volume.Vertices[3], Volume.Vertices[2], 0.5f));
        volume4.Vertices.Add(Volume.Vertices[3]);

        var uv4a = Vector3.Lerp(Volume.UVs[3], Volume.UVs[0], 0.5f);
        var uv4c = Vector3.Lerp(Volume.UVs[3], Volume.UVs[2], 0.5f);
        var uv4d = Volume.UVs[3];
        var uv4b = new Vector3(uv4c.x, uv4a.y, 0);

        volume4.UVs.Add(uv4a);
        volume4.UVs.Add(uv4b);
        volume4.UVs.Add(uv4c);
        volume4.UVs.Add(uv4d);

        #endregion

        var q1 = new PatchTree(this, volume1);
        var q2 = new PatchTree(this, volume2);
        var q3 = new PatchTree(this, volume3);
        var q4 = new PatchTree(this, volume4);

        //set internal neighbors
        q1.SetNeighbor(PatchNeighborDirection.Bottom, q4, PatchNeighborDirection.Top);
        q1.SetNeighbor(PatchNeighborDirection.Right, q2, PatchNeighborDirection.Left);

        //set internal neighbors
        q2.SetNeighbor(PatchNeighborDirection.Bottom, q3, PatchNeighborDirection.Top);
        q2.SetNeighbor(PatchNeighborDirection.Left, q1, PatchNeighborDirection.Right);

        //set internal neighbors
        q3.SetNeighbor(PatchNeighborDirection.Top, q2, PatchNeighborDirection.Bottom);
        q3.SetNeighbor(PatchNeighborDirection.Left, q4, PatchNeighborDirection.Right);

        //set internal neighbors
        q4.SetNeighbor(PatchNeighborDirection.Top, q1, PatchNeighborDirection.Bottom);
        q4.SetNeighbor(PatchNeighborDirection.Right, q3, PatchNeighborDirection.Left);

        //store as children of the current node
        Children[0] = q1;
        Children[1] = q2;
        Children[2] = q3;
        Children[3] = q4;

        Sphere.Splitted = true;

        HasChildren = true;

        ReLink();
    }
Beispiel #4
0
    void CalculateGapError(PatchNeighborDirection direction, PatchNeighborDirection neighborDirection, ref PatchTree neighborNode, out short add)
    {
        var node   = Neighbors[(int)neighborDirection].Node;
        var parent = node.Parent;

        bool trueParent = (parent != null && Parent != null && parent == Parent);

        add = (short)(trueParent && node.Neighbors[(int)direction].Node == neighborNode ? 0 : PatchSettings.VerticesPerSide >> 1);
    }
Beispiel #5
0
    public PatchTree(PatchTree Parent, PatchAABB Volume)
    {
        this.Parent = Parent;
        this.Volume = Volume;
        this.Sphere = Parent.Sphere;

        SplitLevel = (ushort)(this.Parent.SplitLevel + 1);

        if (SplitLevel > Sphere.HighestSplitLevel)
        {
            Sphere.HighestSplitLevel = SplitLevel;
        }

        Size = this.Parent.Size / 2;

        var v1 = this.Volume.Vertices[0];
        var v2 = this.Volume.Vertices[1];
        var v3 = this.Volume.Vertices[2];
        var v4 = this.Volume.Vertices[3];

        var uv1 = this.Volume.UVs[0];
        var uv2 = this.Volume.UVs[1];
        var uv3 = this.Volume.UVs[2];
        var uv4 = this.Volume.UVs[3];

        VolumeProjected = new PatchAABB();

        VolumeProjected.Vertices.Add(v1.NormalizeToRadius(Sphere.Radius));
        VolumeProjected.Vertices.Add(v2.NormalizeToRadius(Sphere.Radius));
        VolumeProjected.Vertices.Add(v3.NormalizeToRadius(Sphere.Radius));
        VolumeProjected.Vertices.Add(v4.NormalizeToRadius(Sphere.Radius));

        VolumeProjected.UVs.Add(uv1);
        VolumeProjected.UVs.Add(uv2);
        VolumeProjected.UVs.Add(uv3);
        VolumeProjected.UVs.Add(uv4);

        Neighbors[0].Node    = Neighbors[1].Node = Neighbors[2].Node = Neighbors[3].Node = null;
        Neighbors[0].isFixed = Neighbors[1].isFixed = Neighbors[2].isFixed = Neighbors[3].isFixed = false;
        Children[0]          = Children[1] = Children[2] = Children[3] = null;

        NeedsRejoinCount = 0;
        HasChildren      = false;
        NeedsReedge      = true;
        NeedsTerrain     = true;
        GapFixMask       = 15;

        Normal = this.Parent.Normal;

        Middle          = (Volume.Vertices[0] + Volume.Vertices[1] + Volume.Vertices[2] + Volume.Vertices[3]) / 4;
        MiddleProjected = Middle;
        MiddleProjected = MiddleProjected.NormalizeToRadius(Sphere.Radius);

        UpProjected = MiddleProjected;
        UpProjected.Normalize();

        FrontProjected = Vector3.Lerp(VolumeProjected.Vertices[0], VolumeProjected.Vertices[1], 0.5f) - MiddleProjected;
        FrontProjected.Normalize();

        Plane = this.Parent.Plane;

        Front = this.Parent.Front;
        Up    = this.Parent.Up;
        Right = this.Parent.Right;
    }
Beispiel #6
0
    public void SetNeighbor(PatchNeighborDirection direction, PatchTree tree, PatchNeighborDirection directionFromThere)
    {
        if (tree.HasChildren)
        {
            //the other node has children, which means this node was in coarse resolution,
            //so find correct child to link to...
            //need to find which two of the 4 children
            //of the other node that links to the parent of this node or to this node itself
            //then, decide which of the two children is closer to this node
            //and update the correct (nearest) child to link to this node

            PatchTree correctNode = null;

            float dist = 0;

            byte neighDirection = 0;

            //for each child of that node...
            for (byte i = 0; i < 4; i++)
            {
                var child = tree.Children[i];

                //for each direction of that child of that node...
                for (byte j = 0; j < 4; j++)
                {
                    //check if that child links from that direction to our parent
                    if (child.Neighbors[j].Node.Equals(Parent))
                    {
                        if (correctNode == null)
                        {
                            //as there is no best correct child yet,
                            //temporarily selects that child as the correct
                            correctNode    = child;
                            neighDirection = j;
                            dist           = VectorHelper.QuickDistance(child.Middle, Middle);
                            break;
                        }
                        else
                        {
                            //check if this child is closer than
                            //the currently selected as the closer child
                            if (VectorHelper.QuickDistance(child.Middle, Middle) < dist)
                            {
                                correctNode    = child;
                                neighDirection = j;

                                //as we can have only two childs
                                //pointing to our own parent, and the other child has been scanned already,
                                //we can safely bail out of the outer loop and stop searching
                                i = 4;
                                break;
                            }
                        }
                    }
                    else if (child.Neighbors[j].Node == this)
                    {
                        //that child relinked to this node first
                        //which means both nodes are at same level
                        //so just get it and bail out
                        correctNode    = child;
                        neighDirection = j;

                        //link back to that node
                        Neighbors[(int)direction].Node      = correctNode;
                        Neighbors[(int)direction].Direction = (PatchNeighborDirection)neighDirection;

                        //update edges of this node
                        NeedsReedge = true;

                        //bail out
                        return;
                    }
                }
            }

            if (correctNode != null)
            {
                //link to that node
                Neighbors[(int)direction].Node      = correctNode;
                Neighbors[(int)direction].Direction = (PatchNeighborDirection)neighDirection;

                //link that node back to this node
                correctNode.Neighbors[neighDirection].Node      = this;
                correctNode.Neighbors[neighDirection].Direction = direction;

                //update edges and gaps
                NeedsReedge             = true;
                correctNode.NeedsReedge = true;

                //the other node was discarding resolution
                //because this node was at coarse level
                //now that both are at same level,
                //lets force the other node to use full mesh at the edge that links to this node
                correctNode.GapFixMask |= (byte)(1 << neighDirection);
                correctNode.Neighbors[neighDirection].isFixed = false;
            }
        }
        else
        {
            //the other node has no children...
            //so, the other node is at a coarse level
            //or at same level (a brother node);
            //link directly to that node
            Neighbors[(int)direction].Node             = tree;
            Neighbors[(int)direction].Direction        = directionFromThere;
            Neighbors[(int)direction].Node.NeedsReedge = true;

            //only this node needs to update edges and fix gaps
            NeedsReedge = true;
            GapFixMask |= (byte)(1 << (int)direction);
            Neighbors[(int)direction].isFixed = false;

            //the other node stays linked to the node it is already linked to.
        }
    }
Beispiel #7
0
 public PatchTree(PatchTree t1, PatchTree t2)
 {
     this.subtree1 = t1;
     this.subtree2 = t2;
 }
Beispiel #8
0
 public RenderQuery(PatchSkeletalMesh patch, PatchTree patchTree, List <string> patchKeys)
 {
     this.patch     = patch;
     this.patchKeys = new List <string>(patchKeys);
 }