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]); }
// 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(); }
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(); }
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); }
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; }
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. } }
public PatchTree(PatchTree t1, PatchTree t2) { this.subtree1 = t1; this.subtree2 = t2; }
public RenderQuery(PatchSkeletalMesh patch, PatchTree patchTree, List <string> patchKeys) { this.patch = patch; this.patchKeys = new List <string>(patchKeys); }