UnityMol  0.9.6-875
UnityMol viewer / In developement
BondMeshStyle.cs
Go to the documentation of this file.
1 
2 /* TODO : -Add copyright
3  -Use Quads instead of cubes to reduce the number of vertices = Impostors
4  -Use a texture to map in the shader (-> texture atlas)
5  -Don't use already created sticks but directly create one mesh
6 
7 Explanations : Merge Meshes into one or several big meshes. The shader is modified to not only draw 1 stick but multiple sticks.
8 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
9 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.
10 
11 */
12 
13 
14 namespace Molecule.View.DisplayBond {
15  using UnityEngine;
16  using System;
17  using System.Collections;
18  using System.Collections.Generic;
19  using Molecule.Model;
20  using Molecule.Control;
21  using UnityEngine.Rendering;
22 
23  using UI;
25 
26 
27  public class BondMeshStyle:IBondStyle {
28  public List<int[]> bondList;
29  public List<int[]> bondEPList;
30 
31  public static GameObject BondMeshParent = new GameObject("BondMeshParent");
32  public List<GameObject> meshesGO;
33  private Dictionary<int,KeyValuePair<int,int> > coordStickTexture;
34 
35  public BondMeshStyle() {
36  }
37 
38  public void DisplayBonds(){
39  UIData.shadow = false;
40 
41  GameObject hsmeshManagerObj = GameObject.FindGameObjectWithTag("HStickMeshManager");
42  HStickMeshManager hsmeshManager = hsmeshManagerObj.GetComponent<HStickMeshManager>();
43  hsmeshManager.enabled = true;
44 
45  if(BondMeshParent.transform.Find("BondMesh0")){
46  hsmeshManager.EnableRenderers();
47  return;
48 
49  }
51  bondEPList=MoleculeModel.bondCAList;
52  else
53  bondEPList=MoleculeModel.bondEPList;
54 
55  MoleculeModel.bondsnumber=bondEPList.Count;
56  meshesGO = new List<GameObject>();
57  DisplayBondsMethodByMesh(bondEPList.Count);
58 
59 
60  hsmeshManager.hstick_meshes = meshesGO.ToArray();
61  hsmeshManager.coordStickTexture = coordStickTexture;
62  hsmeshManager.Init();
63  hsmeshManager.enabled = true;
64 
65 
66  }
67 
68  private void DisplayBondsMethodByMesh(int nb_sticks){
69 
70  if(nb_sticks==0)
71  return;
72 
73  int idmesh = 0;
74  int cptSticks = 0;
75  int currentVertex = 0;
76  int NBPARAM = 20; //Number of parameters in the texture
77 
78  GameObject currentGO = GameObject.CreatePrimitive(PrimitiveType.Cube);
79  currentGO.transform.name = "BondMesh0";
80  currentGO.transform.parent = BondMeshParent.transform;
81  GameObject.Destroy(currentGO.GetComponent<Collider>());
82 
83  GameObject tmp = GameObject.CreatePrimitive(PrimitiveType.Cube);
84  Mesh tmpMesh = tmp.GetComponent<MeshFilter>().mesh;
85  GameObject.Destroy(tmp.GetComponent<Collider>());
86 
87 
88  int VERTICES_IN_CUBE = tmpMesh.vertices.Length;//24 vertices by cube
89  int LIMIT_VERTICES_IN_MESH = 65536;//Unity limit : number of vertices in a mesh
90  int totalVertices = nb_sticks*VERTICES_IN_CUBE;
91  int maxSticksinMesh = (int)LIMIT_VERTICES_IN_MESH/VERTICES_IN_CUBE;
92  int currentSticksinMesh = (int)Mathf.Min(maxSticksinMesh,nb_sticks - (idmesh*maxSticksinMesh));
93 
94  //Compute the number of meshes needed to store all the sticks
95  int nb_meshes_needed = (int)Mathf.Ceil(totalVertices/(float)LIMIT_VERTICES_IN_MESH);
96 
97  Mesh[] combinedMeshes = new Mesh[nb_meshes_needed];
98  combinedMeshes[idmesh] = new Mesh();
99  // int[] atoms_by_mesh = new int[nb_meshes_needed];
100  List<Vector3> newVertices = new List<Vector3>();
101  List<Vector2> newUV = new List<Vector2>();
102  List<int> newTriangles = new List<int>();
103 
104  coordStickTexture = new Dictionary<int,KeyValuePair<int,int> >();
105 
106  //Create a texture to store parameters of sticks (20 parameters to store)
107  //It is used to fetch parameters for each stick in the shader
108  Texture2D[] newTextures = new Texture2D[nb_meshes_needed];
109  newTextures[idmesh] = new Texture2D(NBPARAM,currentSticksinMesh,TextureFormat.ARGB32, false);
110  float brightness=1.0f,attenuation=0.0f,shrink=0.4f,visibility=1.0f,scale=1.0f,ellipse=1.0f;
111 
112  // Vector4 equation = new Vector4(1.0f,1.0f,1.0f,1.0f);
113 
114 
115 
116  for(int i=0;i<nb_sticks;i++){
117 
118  //If the current mesh is full, create a new texture
119  if(currentVertex + tmpMesh.vertices.Length >= LIMIT_VERTICES_IN_MESH){
120  //Fill the mesh with the arrays
121  combinedMeshes[idmesh].vertices = newVertices.ToArray();
122  combinedMeshes[idmesh].uv = newUV.ToArray();
123  combinedMeshes[idmesh].triangles = newTriangles.ToArray();
124  combinedMeshes[idmesh].Optimize();
125  currentGO.GetComponent<MeshFilter>().mesh.Clear();
126  currentGO.GetComponent<MeshFilter>().mesh = combinedMeshes[idmesh];
127  meshesGO.Add(currentGO);
128 
129  //Upload the texture to the GPU
130  newTextures[idmesh].Apply(false,false);//DO NOT REMOVE !!!!!!!!!!!!!!!!!!
131  newTextures[idmesh].wrapMode = TextureWrapMode.Clamp;//Mandatory to access the data in the shader
132  newTextures[idmesh].filterMode = FilterMode.Point;//Texture will be used reading pixels
133 
134  Material curMat = currentGO.GetComponent<Renderer>().material;
135  curMat.shader = Shader.Find("FvNano/Sticks HyperBalls Merged");
136  //Set fixed parameters for the shader
137  curMat.SetTexture("_MainTex",newTextures[idmesh]);
138  curMat.SetTexture("_MatCap",(Texture)Resources.Load("lit_spheres/divers/daphz05"));
139  curMat.SetTexture("_MatCap2",(Texture)Resources.Load("lit_spheres/divers/daphz05"));
140  curMat.SetFloat("_Brightness",brightness);
141  curMat.SetFloat("_Attenuation",attenuation);
142  curMat.SetFloat("_NBParam",(float)NBPARAM);
143  curMat.SetFloat("_NBSticks",(float)currentSticksinMesh);
144  curMat.SetFloat("_Shrink",shrink);
145  curMat.SetFloat("_Visibility",visibility);
146  curMat.SetFloat("_Scale",scale);
147  curMat.SetFloat("_EllipseFactor",ellipse);
148  currentGO.GetComponent<Renderer>().shadowCastingMode = ShadowCastingMode.Off;
149  currentGO.GetComponent<Renderer>().receiveShadows = false;
150 
151  currentGO = GameObject.CreatePrimitive(PrimitiveType.Cube);
152  currentGO.transform.name = "BondMesh"+(idmesh+1).ToString();
153  currentGO.transform.parent = BondMeshParent.transform;
154  GameObject.Destroy(currentGO.GetComponent<Collider>());
155 
156  newVertices.Clear();
157  newUV.Clear();
158  newTriangles.Clear();
159  idmesh++;
160  currentSticksinMesh = (int)Mathf.Min(maxSticksinMesh,nb_sticks - (idmesh*maxSticksinMesh));
161  newTextures[idmesh] = new Texture2D(NBPARAM,currentSticksinMesh,TextureFormat.ARGB32, false);
162  combinedMeshes[idmesh] = new Mesh();
163  currentVertex = 0;
164  cptSticks = 0;
165  }
166 
167 
168 
169  int[] atomsIds = bondEPList[i] as int[];
170 
171  /*
172  //Temporary Fix the problem when showing optimized hyperballs
173  if(atomsIds[0]<0 || atomsIds[0]>=MoleculeModel.atoms.Count){
174  Debug.LogError("Probleme avec "+atomsIds[0]);
175  GameObject.Destroy(tmp);
176  GameObject.Destroy(currentGO);
177  return;
178  }
179  if(atomsIds[1]<0 || atomsIds[1]>=MoleculeModel.atoms.Count){
180  Debug.LogError("Probleme (2) avec "+atomsIds[1]);
181  GameObject.Destroy(tmp);
182  GameObject.Destroy(currentGO);
183  return;
184  }*/
185 
186 
187  // GameObject atom1 = (GameObject)MoleculeModel.atoms[atomsIds[0]];
188  // GameObject atom2 = (GameObject)MoleculeModel.atoms[atomsIds[1]];
189  AtomModel a1Model = (AtomModel)MoleculeModel.atomsTypelist[atomsIds[0]];
190  AtomModel a2Model = (AtomModel)MoleculeModel.atomsTypelist[atomsIds[1]];
191 
192 
193  float [] a1=MoleculeModel.atomsLocationlist[atomsIds[0]] as float[];
194  float [] a2=MoleculeModel.atomsLocationlist[atomsIds[1]] as float[];
195  Vector3 posAtom1 = new Vector3();
196  Vector3 posAtom2 = new Vector3();
197  posAtom1.x = a1[0];
198  posAtom1.y = a1[1];
199  posAtom1.z = a1[2];
200  posAtom2.x = a2[0];
201  posAtom2.y = a2[1];
202  posAtom2.z = a2[2];
203 
204 
205 
206  //Store the vertices
207  foreach(Vector3 v in tmpMesh.vertices){
208  newVertices.Add(Vector3.Scale(v,new Vector3(a1Model.scale/100,a1Model.scale/100,a1Model.scale/100))+posAtom1);
209  //IMPORTANT : Add the id of the stick in each vertex (used to fetch data in the texture)
210  newUV.Add(new Vector2(cptSticks,0f));
211  }
212  //Store the triangles
213  foreach(int tri in tmpMesh.triangles)
214  newTriangles.Add(tri+currentVertex);
215 
216 
217  coordStickTexture.Add(i,new KeyValuePair<int,int>(idmesh,cptSticks));
218 
219  //Encoded Radii
220  newTextures[idmesh].SetPixel(0,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(a1Model.radius/3.0f));//Radius sphere 1
221  newTextures[idmesh].SetPixel(1,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(a2Model.radius/3.0f));//Radius sphere 2
222 
223  newTextures[idmesh].SetPixel(2,cptSticks ,a1Model.baseColor);//Color sphere 1
224  newTextures[idmesh].SetPixel(3,cptSticks ,a2Model.baseColor);//Color sphere 2
225 
226 
227  newTextures[idmesh].SetPixel(4,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(posAtom1.x));//Sphere 1 position x
228  newTextures[idmesh].SetPixel(5,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(posAtom1.y));//Sphere 1 position y
229  newTextures[idmesh].SetPixel(6,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(posAtom1.z));//Sphere 1 position z
230 
231  newTextures[idmesh].SetPixel(7,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(posAtom2.x));//Sphere 2 position x
232  newTextures[idmesh].SetPixel(8,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(posAtom2.y));//Sphere 2 position y
233  newTextures[idmesh].SetPixel(9,cptSticks ,EncodeFloatToColor.EncodeFloatRGBA(posAtom2.z));//Sphere 2 position z
234 
235  newTextures[idmesh].SetPixel(10,cptSticks ,new Vector4(visibility,0f,0f,0f));
236 
237  Vector3 light = Vector3.zero;
238  //Light
239  newTextures[idmesh].SetPixel(11,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(light.x));
240  newTextures[idmesh].SetPixel(12,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(light.y));
241  newTextures[idmesh].SetPixel(13,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(light.z));
242 
243  newTextures[idmesh].SetPixel(14,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(posAtom1.x));//Base Sphere 1 position x
244  newTextures[idmesh].SetPixel(15,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(posAtom1.y));//Base Sphere 1 position y
245  newTextures[idmesh].SetPixel(16,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(posAtom1.z));//Base Sphere 1 position z
246 
247  newTextures[idmesh].SetPixel(17,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(posAtom2.x));//Base Sphere 2 position x
248  newTextures[idmesh].SetPixel(18,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(posAtom2.y));//Base Sphere 2 position y
249  newTextures[idmesh].SetPixel(19,cptSticks,EncodeFloatToColor.EncodeFloatRGBA(posAtom2.z));//Base Sphere 2 position z
250 
251 
252  cptSticks++;
253  currentVertex+=tmpMesh.vertices.Length;
254 
255  }
256  //Fill the mesh with the arrays
257  combinedMeshes[idmesh].vertices = newVertices.ToArray();
258  combinedMeshes[idmesh].uv = newUV.ToArray();
259  combinedMeshes[idmesh].triangles = newTriangles.ToArray();
260  combinedMeshes[idmesh].Optimize();
261  currentGO.GetComponent<MeshFilter>().mesh.Clear();
262  currentGO.GetComponent<MeshFilter>().mesh = combinedMeshes[idmesh];
263  meshesGO.Add(currentGO);
264 
265  //Upload the texture to the GPU
266  newTextures[idmesh].Apply(false,false);//DO NOT REMOVE !!!!!!!!!!!!!!!!!!
267  newTextures[idmesh].wrapMode = TextureWrapMode.Clamp;//Mandatory to access the data in the shader
268  newTextures[idmesh].filterMode = FilterMode.Point;//Texture will be used reading pixels
269 
270  Material lastMat = currentGO.GetComponent<Renderer>().material;
271  lastMat.shader = Shader.Find("FvNano/Sticks HyperBalls Merged");
272  //Set fixed parameters for the shader
273  lastMat.SetTexture("_MainTex",newTextures[idmesh]);
274  lastMat.SetTexture("_MatCap",(Texture)Resources.Load("lit_spheres/divers/daphz05"));
275  lastMat.SetTexture("_MatCap2",(Texture)Resources.Load("lit_spheres/divers/daphz05"));
276  lastMat.SetFloat("_Brightness",brightness);
277  lastMat.SetFloat("_Attenuation",attenuation);
278  lastMat.SetFloat("_NBParam",(float)NBPARAM);
279  lastMat.SetFloat("_NBSticks",(float)currentSticksinMesh);
280  lastMat.SetFloat("_Shrink",shrink);
281  lastMat.SetFloat("_Visibility",visibility);
282  lastMat.SetFloat("_Scale",scale);
283  lastMat.SetFloat("_EllipseFactor",ellipse);
284  currentGO.GetComponent<Renderer>().receiveShadows = false;
285  currentGO.GetComponent<Renderer>().shadowCastingMode = ShadowCastingMode.Off;
286  GameObject.Destroy(tmp);
287 
288  }
289  }
290 }
static List< int[]> bondCAList
The bonds between carbon alpha in the CA-Spline.
void DisplayBondsMethodByMesh(int nb_sticks)
static bool secondarystruct
Switch between all atoms and C-alpha trace or BFactor secondary structure representation.
Definition: UIData.cs:176
GameObject[] hstick_meshes
override void Init()
Initalizes this instance.
Dictionary< int, KeyValuePair< int, int > > coordStickTexture
static List< AtomModel > atomsTypelist
The type of each atom.
static Vector4 EncodeFloatRGBA(float v)
override void EnableRenderers()
Enables the renderers for the entire set of balls and sticks.
Dictionary< int, KeyValuePair< int, int > > coordStickTexture
!WiP Includes FLAGS of GUI.
Definition: UIData.cs:78
static List< int[]> bondEPList
The bonds between atoms.
static bool shadow
Definition: UIData.cs:198
Definition: GUIDisplay.cs:66
static List< float[]> atomsLocationlist
The coordinates of each atom.