public MeshKDTree(int MaxNestingLevel, Vector3[] vertices, int[] indices) { //this.vertices = vertices; //this.indices = indices; this.MaxNestingLevel = MaxNestingLevel; Vector3 AA = vertices[0]; Vector3 BB = vertices[0]; for (int i = 0; i < indices.Length; i++) this.indices.Add(indices[i]); for (int i = 0; i < vertices.Length; i++) { this.vertices.Add(vertices[i]); if (vertices[i].X > AA.X) AA.X = vertices[i].X; if (vertices[i].Y > AA.Y) AA.Y = vertices[i].Y; if (vertices[i].Z > AA.Z) AA.Z = vertices[i].Z; if (vertices[i].X < BB.X) BB.X = vertices[i].X; if (vertices[i].Y < BB.Y) BB.Y = vertices[i].Y; if (vertices[i].Z < BB.Z) BB.Z = vertices[i].Z; } BSPAABBMax = AA; BSPAABBMin = BB; Root = new MeshNode(null, AA, BB, MaxNestingLevel); int Lll = indices.Length; for (int i = 0; i < Lll; i = i + 3) { AA = vertices[indices[i]]; BB = vertices[indices[i]]; for (int j = 0; j < 3; j++) { if (vertices[indices[i + j]].X > AA.X) AA.X = vertices[indices[i + j]].X; if (vertices[indices[i + j]].Y > AA.Y) AA.Y = vertices[indices[i + j]].Y; if (vertices[indices[i + j]].Z > AA.Z) AA.Z = vertices[indices[i + j]].Z; if (vertices[indices[i + j]].X < BB.X) BB.X = vertices[indices[i + j]].X; if (vertices[indices[i + j]].Y < BB.Y) BB.Y = vertices[indices[i + j]].Y; if (vertices[indices[i + j]].Z < BB.Z) BB.Z = vertices[indices[i + j]].Z; } Add(i, Root, AA, BB); } }
public MeshNode(MeshNode parent, Vector3 AABBMax, Vector3 AABBMin, int nestingLevel) { Parent = parent; this.AABBMax = AABBMax; this.AABBMin = AABBMin; NestingLevel = nestingLevel; ListTrInd = new List<int>(); Children = new List<MeshNode>(); }
private void TestIntercept(MeshNode N) { Vector3 OutPos = new Vector3(); if (HitBoundingBox(N.AABBMin, N.AABBMax, StartPosition, StopPosition - StartPosition, out OutPos)) { ////////////////////////////////////////////////////////////////////////// if (LastDistance > (StartPosition - OutPos).Length()) { Vector3 Pos = new Vector3(); Vector3 Norm = new Vector3(); foreach (int Index in N.ListTrInd) { if (GetInterceptPoint(out Pos, out Norm, vertices[indices[Index + 0]], vertices[indices[Index + 1]], vertices[indices[Index + 2]], StartPosition, StopPosition)) { float d = (StartPosition - Pos).Length(); if (d < LastDistance) { StopPosition = Pos; LastNormal = Norm; LastDistance = d; } } } ////////////////////////////////////////////////////////////////////////// if (N.Children.Count > 0) { TestIntercept(N.Children[0]); TestIntercept(N.Children[1]); } } } }
private bool Add(int TrInd, MeshNode N, Vector3 AA_2, Vector3 BB_2) { //Достигнут минимальный уровень if (N.NestingLevel < 1) { N.Parent.ListTrInd.Add(TrInd); return true; } int rez = TestTwoAABB(N.AABBMax, N.AABBMin, AA_2, BB_2); //Не поподает if (rez == 0) return false; float X = N.AABBMax.X - N.AABBMin.X; float Y = N.AABBMax.Y - N.AABBMin.Y; float Z = N.AABBMax.Z - N.AABBMin.Z; //Попадает частично if (rez == 1) { ////////////////////////////////////////////////////////////////////////// N.Parent.ListTrInd.Add(TrInd); return true; } //Поподает полностью //Нужно создать потомков if (N.Children.Count < 1) { int Level = N.NestingLevel - 1; if (X > Math.Max(Y, Z)) { N.Children.Add(new MeshNode(N, N.AABBMax, new Vector3(N.AABBMax.X - X / 2f, N.AABBMin.Y, N.AABBMin.Z), Level)); N.Children.Add(new MeshNode(N, new Vector3(N.AABBMax.X - X / 2f, N.AABBMax.Y, N.AABBMax.Z), N.AABBMin, Level)); if ((AA_2.X + BB_2.X) / 2f > N.AABBMax.X - X / 2f) { if (Add(TrInd, N.Children[0], AA_2, BB_2)) return true; if (Add(TrInd, N.Children[1], AA_2, BB_2)) return true; } else { if (Add(TrInd, N.Children[1], AA_2, BB_2)) return true; if (Add(TrInd, N.Children[0], AA_2, BB_2)) return true; } } else { if (Y > Math.Max(X, Z)) { N.Children.Add(new MeshNode(N, N.AABBMax, new DVector3(N.AABBMin.X, N.AABBMax.Y - Y / 2f, N.AABBMin.Z), Level)); N.Children.Add(new MeshNode(N, new DVector3(N.AABBMax.X, N.AABBMax.Y - Y / 2f, N.AABBMax.Z), N.AABBMin, Level)); if ((AA_2.Y + BB_2.Y) / 2f > N.AABBMax.Y - Y / 2f) { if (Add(TrInd, N.Children[0], AA_2, BB_2)) return true; if (Add(TrInd, N.Children[1], AA_2, BB_2)) return true; } else { if (Add(TrInd, N.Children[1], AA_2, BB_2)) return true; if (Add(TrInd, N.Children[0], AA_2, BB_2)) return true; } } else { N.Children.Add(new MeshNode(N, N.AABBMax, new DVector3(N.AABBMin.X, N.AABBMin.Y, N.AABBMax.Z - Z / 2f), Level)); N.Children.Add(new MeshNode(N, new DVector3(N.AABBMax.X, N.AABBMax.Y, N.AABBMax.Z - Z / 2f), N.AABBMin, Level)); if ((AA_2.Z + BB_2.Z) / 2f > N.AABBMax.Z - Z / 2f) { if (Add(TrInd, N.Children[0], AA_2, BB_2)) return true; if (Add(TrInd, N.Children[1], AA_2, BB_2)) return true; } else { if (Add(TrInd, N.Children[1], AA_2, BB_2)) return true; if (Add(TrInd, N.Children[0], AA_2, BB_2)) return true; } } } } //потомки уже есть if (Add(TrInd, N.Children[0], AA_2, BB_2)) return true; if (Add(TrInd, N.Children[1], AA_2, BB_2)) return true; return false; }