public virtual void CopyPoints() { int i = 0; int ii = 0; NucleusPoint[] ps = new NucleusPoint[NucleusSpacing.points.Length]; i = 0; while (i < ps.Length) { NucleusPoint p = new NucleusPoint(); p.index = i; p.neighbors = new int[12]; ii = 0; while (ii < 12) { p.neighbors[ii] = NucleusSpacing.points[i].neighbors[ii]; ii++; } p.pos = this.flipPositions ? -NucleusSpacing.points[i].pos : NucleusSpacing.points[i].pos; p.distRank = NucleusSpacing.points[i].distRank; ps[i] = p; i++; } int maxRank = ps[ps.Length - 1].distRank; NucleusRank[] rs = new NucleusRank[maxRank + 1]; int[] rankCounts = new int[rs.Length]; i = 0; while (i < ps.Length) { rankCounts[ps[i].distRank]++; i++; } int curRank = 0; i = 0; while (i < rs.Length) { NucleusRank r = new NucleusRank(); r.points = new NucleusPoint[rankCounts[i]]; rs[i] = r; i++; } rankCounts = new int[rs.Length]; i = 0; while (i < rs.Length) { rankCounts[i] = 0; i++; } i = 0; while (i < ps.Length) { rs[ps[i].distRank].points[rankCounts[ps[i].distRank]] = ps[i]; rankCounts[ps[i].distRank]++; i++; } this.points = ps; this.ranks = rs; }
public virtual void Rebuild() { //Debug.Log(Time.time); UserAtom.p = this.p; UserAtom.n = this.n; int i = 0; int ii = 0; i = 0; while (i < this.points.Length) { this.colliders[i].SetActive(false); this.points[i].state = PType.Empty; i++; } int curRank = 0; int curP = this.p; int curN = this.n; Vector3 centerPoint = Vector3.zero; int added = 0; NucleusDisplay.Nucleon[] displayNucleons = new NucleusDisplay.Nucleon[this.p + this.n]; while ((curP > 0) || (curN > 0)) { bool nextIsProton = (curP > 0) && ((curN == 0) || ((((curP + 0.01f) / (curN + 0.01f)) + ((this.randomizeOrder - 0.5f) * 0.2f)) > ((this.p + 0.01f) / (this.n + 0.01f)))); int maxNeighbors = -1; float maxRatio = -1f; int bestFit = -1; int availableInRank = 0; i = 0; while (i < this.ranks[curRank].points.Length) { NucleusPoint point = this.ranks[curRank].points[i]; if (point.state == PType.Empty) { availableInRank++; float prs = 0f; float nus = 0f; ii = 0; while (ii < point.neighbors.Length) { if ((point.neighbors[ii] != -1) && (this.points[point.neighbors[ii]].state == PType.P)) { prs++; } if ((point.neighbors[ii] != -1) && (this.points[point.neighbors[ii]].state == PType.N)) { nus++; } ii++; } if (maxNeighbors <= (prs + nus)) { if (maxNeighbors < (prs + nus)) { maxNeighbors = (int)(prs + nus); bestFit = point.index; } float ratio = nextIsProton ? (nus + 0.01f) / (prs + 0.01f) : (prs + 0.01f) / (nus + 0.01f); if (maxRatio < ratio) { maxRatio = ratio; bestFit = point.index; } } } i++; } this.points[bestFit].state = nextIsProton ? PType.P : PType.N; this.colliders[bestFit].SetActive(true);//GameObject NucleusDisplay.Nucleon np = new NucleusDisplay.Nucleon(); np.pos = this.points[bestFit].pos; np.color = nextIsProton ? this.protonColor : this.neutronColor; displayNucleons[added] = np; added++; centerPoint = centerPoint + this.points[bestFit].pos; if (nextIsProton) { curP--; } else { curN--; } if (availableInRank == 1) { curRank++; } } centerPoint = centerPoint / (this.p + this.n); this.transform.position = -centerPoint * this.overallScale; this.display.SetNucleons(displayNucleons); this.transform.localScale = Vector3.one * this.overallScale; }
public virtual void Awake() { if (NucleusSpacing.points != null) { return; } // Copy all the points from the mesh to a new list which we will work on MeshFilter meshFilter = (MeshFilter)this.GetComponent(typeof(MeshFilter)); Vector3[] verts = meshFilter.mesh.vertices; Dictionary <string, VertexMapping> vertHash = new Dictionary <string, VertexMapping>(); Dictionary <int, int> vertexIdMapping = new Dictionary <int, int>(); for (int vi = 0; vi < verts.Length; vi++) { string key = Mathf.RoundToInt(verts[vi].x / vertexDictionaryUnit) + "," + Mathf.RoundToInt(verts[vi].y / vertexDictionaryUnit) + "," + Mathf.RoundToInt(verts[vi].z / vertexDictionaryUnit); if (!vertHash.ContainsKey(key)) { vertHash[key] = new VertexMapping(); vertHash[key].pos = verts[vi]; vertHash[key].ids = new ArrayList(); } vertHash[key].ids.Add(vi); } int i = 0; int ii = 0; NucleusPoint[] allPoints = new NucleusPoint[vertHash.Count]; i = 0; foreach (KeyValuePair <string, VertexMapping> entry in vertHash) { NucleusPoint np = new NucleusPoint(); np.neighbors = new int[this.prefilterNeighborSpaces]; np.pos = entry.Value.pos; np.dist = entry.Value.pos.sqrMagnitude; for (int j = 0; j < entry.Value.ids.Count; j++) { vertexIdMapping[(int)entry.Value.ids[j]] = i; } allPoints[i] = np; i++; } // Copy all neighbor relationships from the triangles to the new list int[] tris = meshFilter.mesh.triangles; i = 0; while (i < tris.Length) { int t0 = vertexIdMapping[tris[i]]; int t1 = vertexIdMapping[tris[i + 1]]; int t2 = vertexIdMapping[tris[i + 2]]; NucleusPoint p0 = allPoints[t0]; NucleusPoint p1 = allPoints[t1]; NucleusPoint p2 = allPoints[t2]; p0.neighbors[p0.tempIndex] = t1; p0.neighbors[p0.tempIndex + 1] = t2; p1.neighbors[p1.tempIndex] = t0; p1.neighbors[p1.tempIndex + 1] = t2; p2.neighbors[p2.tempIndex] = t1; p2.neighbors[p2.tempIndex + 1] = t0; p0.tempIndex = p0.tempIndex + 2; p1.tempIndex = p1.tempIndex + 2; p2.tempIndex = p2.tempIndex + 2; i = i + 3; } // reset tempIndex to -1 so we can later identify neighbor references to unused points i = 0; while (i < allPoints.Length) { allPoints[i].tempIndex = -1; i++; } // copy the needed points to the final list, and store the new index in tempIndex int added = 0; float lastDistance = -1f; int distRank = 0; NucleusSpacing.points = new NucleusPoint[this.maxTotalNucleons]; while (added < this.maxTotalNucleons) { float nextDistance = 1000f; i = 0; while (i < allPoints.Length) { if ((allPoints[i].dist < nextDistance) && (allPoints[i].dist > (lastDistance + this.smallFudge))) { nextDistance = allPoints[i].dist; } i++; } i = 0; while (i < allPoints.Length) { float delta = allPoints[i].dist - nextDistance; if (delta < 0) { delta = -delta; } if ((delta < this.smallFudge) && (added < this.maxTotalNucleons)) { allPoints[i].dist = -10; allPoints[i].distRank = distRank; allPoints[i].tempIndex = added; NucleusSpacing.points[added] = allPoints[i]; added++; } i++; } lastDistance = nextDistance; distRank++; } // Remove redundant neighbor relationships and update neighbor relationships to new index. points on the edge will have some neighbor spaces == -1 i = 0; while (i < NucleusSpacing.points.Length) { int nni = 0; int nnAdded = 0; int[] nn = new int[12]; // 12 neighbors in 3d hexagonal closest packing ii = 0; while (ii < NucleusSpacing.points[i].neighbors.Length) { if (NucleusSpacing.points[i].neighbors[ii] != 0) { bool found = false; nni = 0; while (nni < 12) { if (NucleusSpacing.points[i].neighbors[ii] == nn[nni]) { found = true; } nni++; } if (!found) { nn[nnAdded] = NucleusSpacing.points[i].neighbors[ii]; nnAdded++; } } ii++; } nni = 0; while (nni < 12) { nn[nni] = allPoints[nn[nni]].tempIndex; nni++; } NucleusSpacing.points[i].neighbors = nn; i++; } }