UnityMol  0.9.6-875
UnityMol viewer / In developement
VertexTree.cs
Go to the documentation of this file.
1 using UnityEngine;
2 using System.Collections;
3 using System.Collections.Generic;
4 
5 public class VertexTree {
6  private Vector3 bound0, bound1, split;
7 
8  private List<Vector3> vertices;
9  private List<int> indices;
10  private VertexTree[] children;
11  private bool isLeaf = true;
12 
13  // Holes appear with larger thresholds. I'm not really sure why.
14  private static float THRESHOLD = 0.01f;
15  private static float SQ_THRESHOLD = THRESHOLD * THRESHOLD;
16  private static int MAX_VERTICES = 16;
17  //private static int MIN_NEIGHBORS = 3;
18  //private static float NEIGHBOR_THRESHOLD = 2.0f;
19 
20  public VertexTree(Vector3 b0, Vector3 b1) {
21  split = 0.5f * (b0 + b1); // Middle of the cube
22  bound0 = b0;
23  bound1 = b1;
24  vertices = new List<Vector3>();
25  indices = new List<int>();
26  children = new VertexTree[8];
27  }
28 
29  private void AddVertexToLeaf(Vector3 v, int i) {
30  vertices.Add(v);
31  indices.Add(i);
32 
33  // If the addition brings the cube to the limit of vertices
34  if(vertices.Count >= MAX_VERTICES)
35  Subdivide();
36  }
37 
38  private Vector3 GetOffset(Vector3 b0, Vector3 b1, int i) {
39  Vector3 result;
40  switch(i) {
41  case 0:
42  result = Vector3.zero;
43  break;
44  case 1:
45  result = new Vector3(b1.x, 0, 0);
46  break;
47  case 2:
48  result = new Vector3(0, b1.y, 0);
49  break;
50  case 3:
51  result = new Vector3(b1.x, b1.y, 0);
52  break;
53  case 4:
54  result = new Vector3(0, 0, b1.z);
55  break;
56  case 5:
57  result = new Vector3(b1.x, 0, b1.z);
58  break;
59  case 6:
60  result = new Vector3(0, b1.y, b1.z);
61  break;
62  case 7:
63  result = b1;
64  break;
65  default:
66  Debug.Log("VertexTree::Offset() > Something is very, very wrong here.");
67  result = Vector3.zero;
68  break;
69  }
70  return 0.5f * result;
71  }
72 
73  private int GetChildIndex(Vector3 v) {
74  int childIndex = 0;
75 
76  if(v.x > split.x)
77  childIndex |= 1;
78  if(v.y > split.y)
79  childIndex |= 2;
80  if(v.z > split.z)
81  childIndex |= 4;
82 
83  return childIndex;
84  }
85 
86  private void Subdivide() {
87  Vector3 oppositeBound = bound1 - bound0;
88  Vector3 offset;
89 
90  // Creating the sub-cubes.
91  for(int i=0; i<8; i++) {
92  offset = GetOffset(bound0, oppositeBound, i);
93  children[i] = new VertexTree(bound0+offset, split+offset);
94  }
95 
96  // Sending the vertices (and corresponding indices) to the correct sub-cubes.
97  int childIndex;
98  for(int i=0; i<MAX_VERTICES; i++) {
99  childIndex = GetChildIndex(vertices[i]);
100  children[childIndex].AddVertexToLeaf(vertices[i], indices[i]);
101  }
102 
103  // Now this cube is not a leaf anymore, but a node.
104  // It must be cleared, and no more vertices should be added to it.
105  vertices.Clear();
106  indices.Clear();
107 
108  isLeaf = false;
109  }
110 
111  public int AddVertex(Vector3 v, int ind) {
112  if(isLeaf) {
113  float distance;
114  for(int i=0; i<vertices.Count; i++) {
115  distance = Vector3.SqrMagnitude(v - vertices[i]);
116  if(distance <= SQ_THRESHOLD) // A similar vertex was found, no need to add it.
117  return indices[i];
118  }
119  // If this is a leaf and the function has not returned yet,
120  // no similar vertex was found, and we must add it.
121  AddVertexToLeaf(v, ind);
122 
123  // And finally return its index.
124  return ind;
125  }
126 
127  // If the function has not returned yet, then this is a node, not a leaf.
128  // So we just find the correct sub-cube for the recursive call.
129  int childIndex = GetChildIndex(v);
130 
131  return children[childIndex].AddVertex(v, ind);
132  }
133 
134 
135  public bool FindOrAddVertex(Vector3 v, int ind) {
136  if(isLeaf) {
137  float distance;
138  for(int i=0; i<vertices.Count; i++) {
139  distance = Vector3.SqrMagnitude(v - vertices[i]);
140  if(distance <= SQ_THRESHOLD) // A similar vertex was found, no need to add it.
141  return true;
142  }
143  // If this is a leaf and the function has not returned yet,
144  // no similar vertex was found, and we must add it.
145  AddVertexToLeaf(v, ind);
146 
147  // And finally return false, because no similar vertex was found.
148  return false;
149  }
150 
151  // If the function has not returned yet, then this is a node, not a leaf.
152  // So we just find the correct sub-cube for the recursive call.
153  int childIndex = GetChildIndex(v);
154 
155  return children[childIndex].FindOrAddVertex(v, ind);
156  }
157 
158  public int GetIndex(Vector3 v) {
159  if(isLeaf) {
160  float distance;
161  for(int i=0; i<vertices.Count; i++) {
162  distance = Vector3.SqrMagnitude(v - vertices[i]);
163  if(distance <= SQ_THRESHOLD) // A similar vertex was found, no need to add it.
164  return indices[i];
165  }
166  // If this is a leaf and the function has not returned yet,
167  // there is a problem.
168  Debug.Log("VertexTree::GetIndex() > Error! No vertex found when rebuilding triangles.");
169  return -1; // should crash
170  }
171 
172  // If the function has not returned yet, then this is a node, not a leaf.
173  // So we just find the correct sub-cube for the recursive call.
174  int childIndex = GetChildIndex(v);
175 
176  return children[childIndex].GetIndex(v);
177  }
178 
179 
180 
181  /*
182  // Was written for an alternative smoothing method. Not used.
183  private void AddNeighborsInNode(List<Vector3> neighbors, Vector3 v) {
184  foreach(VertexTree vTree in children)
185  vTree.AddVectorsInLeaf(neighbors, v);
186  }
187 
188  private void AddVectorsInLeaf(List<Vector3> neighbors, Vector3 v) {
189  foreach(Vector3 vert in vertices)
190  if( (v != vert) && (Vector3.Distance(v, vert) < NEIGHBOR_THRESHOLD) )
191  neighbors.Add(vert);
192  }
193 
194 
195  public List<Vector3> GetNeighbors(List<Vector3> neighbors, VertexTree daddy, Vector3 v) {
196  if(isLeaf) {
197  if(vertices.Count < MIN_NEIGHBORS + 1) // Not enough vertices in this leaf
198  daddy.AddNeighborsInNode(neighbors, v);
199  else // Enough vertices in this leaf
200  AddVectorsInLeaf(neighbors, v);
201 
202  return neighbors;
203  } else {
204  int childIndex = GetChildIndex(v);
205  return children[childIndex].GetNeighbors(neighbors, this, v);
206  }
207  }
208  */
209 
210 }
VertexTree(Vector3 b0, Vector3 b1)
Definition: VertexTree.cs:20
Vector3 bound1
Definition: VertexTree.cs:6
Vector3 GetOffset(Vector3 b0, Vector3 b1, int i)
Definition: VertexTree.cs:38
List< Vector3 > vertices
Definition: VertexTree.cs:8
int AddVertex(Vector3 v, int ind)
Definition: VertexTree.cs:111
void AddVertexToLeaf(Vector3 v, int i)
Definition: VertexTree.cs:29
VertexTree[] children
Definition: VertexTree.cs:10
bool FindOrAddVertex(Vector3 v, int ind)
Definition: VertexTree.cs:135
static float THRESHOLD
Definition: VertexTree.cs:14
int GetChildIndex(Vector3 v)
Definition: VertexTree.cs:73
void Subdivide()
Definition: VertexTree.cs:86
bool isLeaf
Definition: VertexTree.cs:11
static int MAX_VERTICES
Definition: VertexTree.cs:16
Vector3 split
Definition: VertexTree.cs:6
List< int > indices
Definition: VertexTree.cs:9
Vector3 bound0
Definition: VertexTree.cs:6
static float SQ_THRESHOLD
Definition: VertexTree.cs:15
int GetIndex(Vector3 v)
Definition: VertexTree.cs:158