UnityMol  0.9.6-875
UnityMol viewer / In developement
AtomMeshStyle.cs
Go to the documentation of this file.
1 
2 
3 
4 
5 /* TODO : -Add copyright
6  -Use Quads instead of cubes to reduce the number of vertices
7  -Use a texture to map in the shader (-> texture atlas)
8  -Don't use already created atoms but directly create one mesh
9 
10 Explanations : Merge Meshes into one or several big meshes. The shader is modified to not only draw 1 sphere but multiple spheres.
11 To do so we need to pass each sphere parameter to the shader using a texture2D. The data have to be encoded from a 32 bits float
12 to a 32 bits Color4. Two methods can be used. The chosen one is faster but with lower precision and data have to be ranged between -500 and 500.
13 
14 */
15 
16 namespace Molecule.View.DisplayAtom {
17  using System;
18  using UnityEngine;
19  using System.Collections;
20  using System.Collections.Generic;
21  using Molecule.Model;
22  using UI;
23  using UnityEngine.Rendering;
24 
25 
26  public class AtomMeshStyle : IAtomStyle {
27  public static GameObject AtomMeshParent = new GameObject("AtomMeshParent");
28  public List<GameObject> meshesGO;
29  public List<GameObject> collidersGO;
30  private Dictionary<int,KeyValuePair<int,int> > coordAtomTexture;
31  private GameObject collidersParent;
32 
33  public AtomMeshStyle() {
34  }
35 
36  public void DisplayAtoms(UIData.AtomType type_atom, bool force_display = false){
37  UIData.shadow = false;
38 
39  if(type_atom != UIData.AtomType.particleball || !UIData.isParticlesInitialized ||force_display){
40 
41  HBallMeshManager hbmeshManager = GameObject.FindGameObjectWithTag("HBallMeshManager").GetComponent<HBallMeshManager>();
42  hbmeshManager.enabled = true;
43  if(AtomMeshParent == null)
44  AtomMeshParent = new GameObject("AtomMeshParent");
45 
46 
47  if(AtomMeshParent.GetComponentsInChildren<Renderer>().Length > 0){
48  hbmeshManager.EnableRenderers();
49  return;
50  }
51 
52  // if(MoleculeModel.atoms != null) {
53  // MoleculeModel.atoms.Clear();
54  // MoleculeModel.atoms=null;
55  // }
56 
57  // MoleculeModel.atoms=new ArrayList();
58 
59  meshesGO = new List<GameObject>();
60  collidersGO = new List<GameObject>();
61  Debug.Log("DisplayAtoms :: ***clear MolecularModel**** " );
62 
64 
65  // GameObject HBcubesParent = GameObject.FindGameObjectWithTag("HBCubes");
66 
67  // foreach(Transform t in HBcubesParent.transform)
68  // MoleculeModel.atoms.Add(t.gameObject);
69 
70  // MoleculeModel.atomsnumber = MoleculeModel.atoms.Count;
71 
72  hbmeshManager.hball_meshes = (GameObject[]) meshesGO.ToArray();
73  hbmeshManager.collidersGO = (GameObject[]) collidersGO.ToArray();
74  hbmeshManager.collidersParent = collidersParent;
75  hbmeshManager.coordAtomTexture = coordAtomTexture;
76  hbmeshManager.Init();
77  hbmeshManager.enabled = true;
78 
79  }
80  }
81 
82  private void DisplayAtomMethodByMesh(IList alist, IList typelist){
83  Vector3 posAtom = new Vector3();
84  coordAtomTexture = new Dictionary<int,KeyValuePair<int,int> >();
85 
86  int idmesh = 0;
87  int cptAtoms = 0;
88  int currentVertex = 0;
89  int NBPARAM = 13; //Number of parameters in the texture
90 
91  collidersParent = new GameObject("Colliders");
92  collidersParent.transform.parent = AtomMeshParent.transform;
93 
94  GameObject currentGO = GameObject.CreatePrimitive(PrimitiveType.Cube);
95  currentGO.transform.name = "AtomMesh0";
96  currentGO.transform.parent = AtomMeshParent.transform;
97  GameObject.Destroy(currentGO.GetComponent<Collider>());
98 
99  GameObject tmp = GameObject.CreatePrimitive(PrimitiveType.Cube);
100  Mesh tmpMesh = tmp.GetComponent<MeshFilter>().mesh;
101  GameObject.Destroy(tmp.GetComponent<Collider>());
102 
103 
104  int VERTICES_IN_CUBE = tmpMesh.vertices.Length;//24 vertices by cube
105  int LIMIT_VERTICES_IN_MESH = 65536;//Unity limit : number of vertices in a mesh
106  int totalVertices = alist.Count*VERTICES_IN_CUBE;
107  int maxAtomsinMesh = (int)LIMIT_VERTICES_IN_MESH/VERTICES_IN_CUBE;
108  int currentAtomsinMesh = (int)Mathf.Min(maxAtomsinMesh,alist.Count - (idmesh*maxAtomsinMesh));
109 
110  //Compute the number of meshes needed to store all the atoms
111  int nb_meshes_needed = (int)Mathf.Ceil(totalVertices/(float)LIMIT_VERTICES_IN_MESH);
112 
113  // MoleculeModel.atomsnumber=nb_meshes_needed;//alist.Count;
114 
115  Mesh[] combinedMeshes = new Mesh[nb_meshes_needed];
116  combinedMeshes[idmesh] = new Mesh();
117  // int[] atoms_by_mesh = new int[nb_meshes_needed];
118  List<Vector3> newVertices = new List<Vector3>();
119  List<Vector2> newUV = new List<Vector2>();
120  List<int> newTriangles = new List<int>();
121 
122  //Create a texture to store parameters of spheres (13 parameters to store)
123  //It is used to fetch parameters for each atom in the shader
124  Texture2D[] newTextures = new Texture2D[nb_meshes_needed];
125  newTextures[idmesh] = new Texture2D(NBPARAM,currentAtomsinMesh,TextureFormat.ARGB32, false);
126  float brightness=1.0f,attenuation=0.0f;
127 
128  Vector4 equation = new Vector4(1.0f,1.0f,1.0f,1.0f);
129 
130 
131  for(int i=0;i<alist.Count;i++){
132 
133  //If the current mesh can't store the current atoms create a new mesh
134  if(currentVertex + tmpMesh.vertices.Length >= LIMIT_VERTICES_IN_MESH){
135  // atoms_by_mesh[idmesh] = cptAtoms;
136  //Fill the mesh with the arrays
137  combinedMeshes[idmesh].vertices = newVertices.ToArray();
138  combinedMeshes[idmesh].uv = newUV.ToArray();
139  combinedMeshes[idmesh].triangles = newTriangles.ToArray();
140  combinedMeshes[idmesh].Optimize();
141  currentGO.GetComponent<MeshFilter>().mesh.Clear();
142  currentGO.GetComponent<MeshFilter>().mesh = combinedMeshes[idmesh];
143  // MoleculeModel.atoms.Add(currentGO);
144  meshesGO.Add(currentGO);
145 
146 
147  //Upload the texture to the GPU
148  newTextures[idmesh].Apply(false,false);//DO NOT REMOVE !!!!!!!!!!!!!!!!!!
149  newTextures[idmesh].wrapMode = TextureWrapMode.Clamp;//Mandatory to access the data in the shader
150  newTextures[idmesh].filterMode = FilterMode.Point;//Texture will be used reading pixels
151 
152  Material curMat = currentGO.GetComponent<Renderer>().material;
153  curMat.shader = Shader.Find("FvNano/Ball HyperBalls Merged");
154  //Set fixed parameters for the shader
155  curMat.SetTexture("_MainTex",newTextures[idmesh]);
156  curMat.SetTexture("_MatCap",(Texture)Resources.Load("lit_spheres/divers/daphz05"));
157  curMat.SetFloat("_Brightness",brightness);
158  curMat.SetFloat("_Attenuation",attenuation);
159  curMat.SetFloat("_NBParam",(float)NBPARAM);
160  curMat.SetFloat("_NBAtoms",(float)currentAtomsinMesh);
161  currentGO.GetComponent<Renderer>().shadowCastingMode = ShadowCastingMode.Off;
162  currentGO.GetComponent<Renderer>().receiveShadows = false;
163 
164  currentGO = GameObject.CreatePrimitive(PrimitiveType.Cube);
165  currentGO.transform.name = "AtomMesh"+(idmesh+1).ToString();
166  currentGO.transform.parent = AtomMeshParent.transform;
167  GameObject.Destroy(currentGO.GetComponent<Collider>());
168 
169  newVertices.Clear();
170  newUV.Clear();
171  newTriangles.Clear();
172  idmesh++;
173  currentAtomsinMesh = (int)Mathf.Min(maxAtomsinMesh,alist.Count - (idmesh*maxAtomsinMesh));
174  newTextures[idmesh] = new Texture2D(NBPARAM,currentAtomsinMesh,TextureFormat.ARGB32, false);
175  combinedMeshes[idmesh] = new Mesh();
176  currentVertex = 0;
177  cptAtoms = 0;
178  }
179 
180  float [] a=alist[i] as float[];
181  AtomModel aModel = (AtomModel)typelist[i];
182 
183  posAtom.x = a[0];
184  posAtom.y = a[1];
185  posAtom.z = a[2];
186 
187  //Store the vertices
188  foreach(Vector3 v in tmpMesh.vertices){
189  newVertices.Add(Vector3.Scale(v,new Vector3(aModel.scale/100,aModel.scale/100,aModel.scale/100))+posAtom);
190  //IMPORTANT : Add the id of the atom in each vertex (used to fetch data in the texture)
191  newUV.Add(new Vector2(cptAtoms,0f));
192  }
193 
194  //Store the triangles
195  foreach(int tri in tmpMesh.triangles)
196  newTriangles.Add(tri+currentVertex);
197 
198 
199  newTextures[idmesh].SetPixel(0,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(aModel.radius/3.0f));//Encoded Radius
200 
201  newTextures[idmesh].SetPixel(1,cptAtoms,aModel.baseColor);//Color
202  newTextures[idmesh].SetPixel(2,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(posAtom.x));//Sphere position x (can be changed)
203  newTextures[idmesh].SetPixel(3,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(posAtom.y));//Sphere position y (can be changed)
204  newTextures[idmesh].SetPixel(4,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(posAtom.z));//Sphere position z (can be changed)
205 
206  newTextures[idmesh].SetPixel(5,cptAtoms,new Vector4(1.0f,0f,0f,0f));//Visibility
207 
208  newTextures[idmesh].SetPixel(6,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(posAtom.x));//Base sphere position (doesn't change)
209  newTextures[idmesh].SetPixel(7,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(posAtom.y));//Base sphere position (doesn't change)
210  newTextures[idmesh].SetPixel(8,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(posAtom.z));//Base sphere position (doesn't change)
211 
212  newTextures[idmesh].SetPixel(9,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(equation.x));//Equation parameters
213  newTextures[idmesh].SetPixel(10,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(equation.y));//Equation parameters
214  newTextures[idmesh].SetPixel(11,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(equation.z));//Equation parameters
215  newTextures[idmesh].SetPixel(12,cptAtoms,EncodeFloatToColor.EncodeFloatRGBA(equation.w));//Equation parameters
216 
217 
218  coordAtomTexture.Add(i,new KeyValuePair<int,int>(idmesh,cptAtoms));
219  //Create Collider for each atom
220  GameObject colGO = new GameObject("Collider_Atom_"+i);
221  SphereCollider sc = colGO.AddComponent<SphereCollider>();
222  sc.radius = aModel.radius/3.0f;
223  colGO.transform.parent = collidersParent.transform;
224  collidersGO.Add(colGO);
225  colGO.transform.position = posAtom;
226 
227 
228  // MoleculeModel.atoms.Add(colGO);
229 
230  // o.tag=aModel.type;
231  // MoleculeModel.atoms.Add(o);
232 
233  // GameObject dummy = new GameObject("Dummy");
234  // dummy.transform.parent = AtomMeshParent.transform;
235  // dummy.transform.position = posAtom;
236  // MoleculeModel.atoms.Add(dummy);
237 
238  currentVertex+=tmpMesh.vertices.Length;
239 
240  cptAtoms++;
241 
242 
243  }
244  //Fill the mesh with the arrays
245  // atoms_by_mesh[idmesh] = cptAtoms;
246  combinedMeshes[idmesh].vertices = newVertices.ToArray();
247  combinedMeshes[idmesh].uv = newUV.ToArray();
248  combinedMeshes[idmesh].triangles = newTriangles.ToArray();
249  combinedMeshes[idmesh].Optimize();
250  currentGO.GetComponent<MeshFilter>().mesh.Clear();
251  currentGO.GetComponent<MeshFilter>().mesh = combinedMeshes[idmesh];
252  // MoleculeModel.atoms.Add(currentGO);
253  meshesGO.Add(currentGO);
254 
255 
256  //Upload the texture to the GPU
257  newTextures[idmesh].Apply(false,false);//DO NOT REMOVE !!!!!!!!!!!!!!!!!!
258  newTextures[idmesh].wrapMode = TextureWrapMode.Clamp;//Mandatory to access the data in the shader
259  newTextures[idmesh].filterMode = FilterMode.Point;//Texture will be used reading pixels
260 
261  Material lastMat = currentGO.GetComponent<Renderer>().material;
262  lastMat.shader = Shader.Find("FvNano/Ball HyperBalls Merged");
263  //Set fixed parameters for the shader
264  lastMat.SetTexture("_MainTex",newTextures[idmesh]);
265  lastMat.SetTexture("_MatCap",(Texture)Resources.Load("lit_spheres/divers/daphz05"));
266  lastMat.SetFloat("_Brightness",brightness);
267  lastMat.SetFloat("_Attenuation",attenuation);
268  lastMat.SetFloat("_NBParam",(float)NBPARAM);
269  lastMat.SetFloat("_NBAtoms",(float)currentAtomsinMesh);
270  currentGO.GetComponent<Renderer>().shadowCastingMode = ShadowCastingMode.Off;
271  currentGO.GetComponent<Renderer>().receiveShadows = false;
272  GameObject.Destroy(tmp);
273  }
274  }
275 
276 }
override void Init()
Initalizes this instance.
void DisplayAtomMethodByMesh(IList alist, IList typelist)
void DisplayAtoms(UIData.AtomType type_atom, bool force_display=false)
Dictionary< int, KeyValuePair< int, int > > coordAtomTexture
GameObject[] hball_meshes
override void EnableRenderers()
Enables the renderers for the entire set of balls and sticks.
static List< AtomModel > atomsTypelist
The type of each atom.
GameObject collidersParent
static Vector4 EncodeFloatRGBA(float v)
!WiP Includes FLAGS of GUI.
Definition: UIData.cs:78
static bool isParticlesInitialized
Definition: UIData.cs:101
Dictionary< int, KeyValuePair< int, int > > coordAtomTexture
GameObject[] collidersGO
static bool shadow
Definition: UIData.cs:198
Definition: GUIDisplay.cs:66
static List< float[]> atomsLocationlist
The coordinates of each atom.