public void AddProteinIngredient(string path, Bounds bounds, List <Vector4> atomSpheres, Color color, List <float> clusterLevels = null, bool nolod = false) { if (SceneHierarchy.Contains(path)) { throw new Exception("Invalid protein path: " + path); } if (ProteinIngredientNames.Contains(path)) { throw new Exception("Invalid protein path: " + path); } if (clusterLevels != null) { if (NumLodLevels != 0 && NumLodLevels != clusterLevels.Count) { throw new Exception("Uneven cluster levels number: " + path); } } if (color == null) { color = MyUtility.GetRandomColor(); } AddIngredientToHierarchy(path); ProteinColors.Add(color); ProteinToggleFlags.Add(1); ProteinIngredientNames.Add(path); ProteinRadii.Add(AtomHelper.ComputeRadius(atomSpheres)); ProteinAtomCount.Add(atomSpheres.Count); ProteinAtomStart.Add(ProteinAtoms.Count); ProteinAtoms.AddRange(atomSpheres); if (clusterLevels != null) { NumLodLevels = clusterLevels.Count; foreach (var level in clusterLevels) { var numClusters = Math.Max(atomSpheres.Count * level, 5); List <Vector4> clusterSpheres; if (!nolod) { clusterSpheres = KMeansClustering.GetClusters(atomSpheres, (int)numClusters); } else { clusterSpheres = new List <Vector4>(atomSpheres); } ProteinAtomClusterCount.Add(clusterSpheres.Count); ProteinAtomClusterStart.Add(ProteinAtomClusters.Count); ProteinAtomClusters.AddRange(clusterSpheres); } } }