UnityMol  0.9.6-875
UnityMol viewer / In developement
GenerateMesh.cs
Go to the documentation of this file.
1 
66 using UnityEngine;
67 using System;
68 using System.Collections.Generic;
69 using System.Threading;
70 using Molecule.Model;
71 
72 public class GenerateMesh {
73 
74  private static Vector3 CENTER = new Vector3(0f,0f,0f);
75  private static float[,,] VOXELS;
76  private static Vector3 DELTA;
77  private static Vector3 ORIGIN;
78  private static Vector3 OFFSET_ORIGIN;
79  private static Transform DADDY;
80  private static string TAG;
81  private static int XDIM, YDIM, ZDIM;
82  private static int SLICE_WIDTH = 80;
83  private static float S_FUDGE_FACTOR = 18f;
84  private static Vector3 FUDGE_FACTOR = new Vector3(S_FUDGE_FACTOR, S_FUDGE_FACTOR, S_FUDGE_FACTOR);
85  private static bool ELECTRO = false;
86 
96  private static void ProperlyCalculateNormals(MeshData mData) {
97  Vector3[] vertices = mData.vertices;
98  int vCount = mData.vertices.Length;
99 
100  // this will contain the list of normals affecting each vertex
101  List<List<Vector3>> normal_buffer = new List<List<Vector3>>();
102 
103  // temporary storage for normals, you can't directly access mesh.normals[i]
104  Vector3[] myNormals = new Vector3[vCount];
105 
106  // initializing the buffer so we can access it by index and add stuff freely later
107  for(int i=0; i<vCount; i++) {
108  normal_buffer.Add(new List<Vector3>());
109  myNormals[i] = new Vector3(0f,0f,0f); // make sure we start with empty normals
110  }
111 
112  int[] triangles = mData.triangles;
113  int index = triangles.Length;
114 
115  // For each triangle
116  for(int i=0; i<index; i+=3) {
117  Vector3 p1 = vertices[triangles[i+0]];
118  Vector3 p2 = vertices[triangles[i+1]];
119  Vector3 p3 = vertices[triangles[i+2]];
120 
121  Vector3 edge1 = p2 - p1;
122  Vector3 edge2 = p3 - p1;
123  Vector3 normal = Vector3.Cross(edge1, edge2);
124  normal.Normalize();
125  //Debug.Log(normal.ToString());
126 
127  // Storing the normal for each vertex affected. We get the correct index from the triangles array
128  normal_buffer[triangles[i+0]].Add(normal);
129  normal_buffer[triangles[i+1]].Add(normal);
130  normal_buffer[triangles[i+2]].Add(normal);
131  }
132 
133  // Iterating over each vertex
134  for(int i=0; i<vCount; i++) {
135  int normalNumber = normal_buffer[i].Count; // number of normals affecting this vertex
136  //Debug.Log(normalNumber.ToString());
137 
138  for(int j=0; j<normalNumber; j++)
139  myNormals[i] += normal_buffer[i][j];
140 
141  //if(normal_buffer[i].Count != 0) // is this necessary? apparently not
142  myNormals[i].Normalize();
143  }
144  mData.normals = myNormals;
145  }
146 
147  private static Mesh GenerateTextureCoordinates(Mesh mesh) {
148  Vector3[] vertices = mesh.vertices;
149  Vector2[] uvs = new Vector2[vertices.Length];
150  int i = 0;
151  while (i < uvs.Length) {
152  uvs[i] = new Vector2(vertices[i].x, vertices[i].z);
153  i++;
154  }
155  mesh.uv = uvs;
156  return mesh;
157  }
158 
159  private static Mesh CalculateMeshTangents(Mesh mesh) {
160  //speed up math by copying the mesh arrays
161  int[] triangles = mesh.triangles;
162  Vector3[] vertices = mesh.vertices;
163  Vector2[] uv = mesh.uv;
164  Vector3[] normals = mesh.normals;
165 
166  //variable definitions
167  int triangleCount = triangles.Length;
168  int vertexCount = vertices.Length;
169 
170  Vector3[] tan1 = new Vector3[vertexCount];
171  Vector3[] tan2 = new Vector3[vertexCount];
172 
173  Vector4[] tangents = new Vector4[vertexCount];
174 
175  for (long a = 0; a < triangleCount; a += 3) {
176  long i1 = triangles[a + 0];
177  long i2 = triangles[a + 1];
178  long i3 = triangles[a + 2];
179 
180  Vector3 v1 = vertices[i1];
181  Vector3 v2 = vertices[i2];
182  Vector3 v3 = vertices[i3];
183 
184  Vector2 w1 = uv[i1];
185  Vector2 w2 = uv[i2];
186  Vector2 w3 = uv[i3];
187 
188  float x1 = v2.x - v1.x;
189  float x2 = v3.x - v1.x;
190  float y1 = v2.y - v1.y;
191  float y2 = v3.y - v1.y;
192  float z1 = v2.z - v1.z;
193  float z2 = v3.z - v1.z;
194 
195  float s1 = w2.x - w1.x;
196  float s2 = w3.x - w1.x;
197  float t1 = w2.y - w1.y;
198  float t2 = w3.y - w1.y;
199 
200  float r = 1.0f / (s1 * t2 - s2 * t1);
201 
202  Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
203  Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
204 
205  tan1[i1] += sdir;
206  tan1[i2] += sdir;
207  tan1[i3] += sdir;
208 
209  tan2[i1] += tdir;
210  tan2[i2] += tdir;
211  tan2[i3] += tdir;
212  }
213 
214  for (long a = 0; a < vertexCount; ++a) {
215  Vector3 n = normals[a];
216  Vector3 t = tan1[a];
217 
218  //Vector3 tmp = (t - n * Vector3.Dot(n, t)).normalized;
219  //tangents[a] = new Vector4(tmp.x, tmp.y, tmp.z);
220  Vector3.OrthoNormalize(ref n, ref t);
221  tangents[a].x = t.x;
222  tangents[a].y = t.y;
223  tangents[a].z = t.z;
224  tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
225  }
226 
227  mesh.tangents = tangents;
228  mesh.uv = uv;
229  return mesh;
230  }
231 
232  private static void FlipTriangles(MeshData mData) {
233  int[] triangles = new int[mData.triangles.Length];
234 
235  for(int i=0; i<mData.triangles.Length; i+=3) {
236  triangles[i] = mData.triangles[i+2];
237  triangles[i+1] = mData.triangles[i+1];
238  triangles[i+2] = mData.triangles[i];
239  }
240 
241  mData.triangles = triangles;
242  }
243 
244  private static void FlipNormals(MeshData mData) {
245  Vector3[] normals = mData.normals;
246  for(int i=0; i<normals.Length; i++)
247  normals[i] = -normals[i];
248 
249  mData.normals = normals;
250  }
251 
252  //private static Mesh OffsetVertices(Vector3 delta, Vector3 origin, Mesh mesh){
253  private static void OffsetVertices(MeshData mData){
254  Vector3[] vertices = mData.vertices;
255 
256  Vector3 invDelta = new Vector3(1f/DELTA.x, 1f/DELTA.y, 1f/DELTA.z);
257  for(int i=0; i<vertices.Length; i++) {
258  if(ELECTRO)
259  vertices[i] = Vector3.Scale(DELTA, vertices[i]) + OFFSET_ORIGIN;
260  else
261  vertices[i] = Vector3.Scale(invDelta, (vertices[i] - FUDGE_FACTOR)) + OFFSET_ORIGIN;
262  }
263  mData.vertices = vertices;
264  }
265 
266  /*
267  private static void CreateSurfaceObject( int xStart, int xEnd,
268  int yStart, int yEnd,
269  int zStart, int zEnd) {
270  MeshData mData = MarchingCubes.CreateMesh(VOXELS, xStart, xEnd, yStart, yEnd, zStart, zEnd);
271 
272  // Culling empty meshes
273  if(mData.vertices.Length == 0)
274  return;
275 
276  AdjacencySets adjacencySets = new AdjacencySets(mData.triangles.Length);
277  adjacencySets.AddAllTriangles(mData.triangles);
278  SmoothFilter.AdjSetsSmoother(mData, adjacencySets);
279 
280  GameObject surface = new GameObject("SurfaceOBJ");
281  surface.tag = TAG;
282  surface.transform.parent = DADDY;
283  surface.transform.localPosition = CENTER;
284 
285  OffsetVertices(mData);
286  Mesh mesh = new Mesh();
287  mesh.vertices = mData.vertices;
288  mesh.triangles = mData.triangles;
289  mesh.RecalculateNormals();
290  mesh.RecalculateBounds();
291  surface.AddComponent<MeshFilter>();
292  surface.AddComponent<MeshRenderer>();
293  surface.GetComponent<MeshFilter>().mesh = mesh;
294  surface.renderer.material = new Material(Shader.Find("Diffuse"));
295  // What about MoleculeModel.vertices?
296  }
297  */
298 
299  private static void CreateSurfaceObjects(List<Mesh> meshes,int isPos) {
300  foreach(Mesh mesh in meshes) {
301  GameObject surface = new GameObject("SurfaceOBJ");
302  if(isPos == 1)
304  else if(isPos == -1)
306  else
308 
309 // surface.tag = TAG;
310  surface.transform.parent = DADDY;
311  surface.transform.localPosition = CENTER;
312  //mesh.RecalculateNormals();
313  mesh.RecalculateBounds();
314  surface.AddComponent<MeshFilter>();
315  surface.AddComponent<MeshRenderer>();
316  surface.GetComponent<MeshFilter>().mesh = mesh;
317  //surface.renderer.material = new Material(Shader.Find("Diffuse"));
318 
319  if(ELECTRO)
320  surface.GetComponent<Renderer>().material = new Material(Shader.Find("Diffuse"));
321  /*else if(UI.UIData.toggleBfac){
322  surface.renderer.material = new Material(Shader.Find("Transparent/OIT_BLUE"));} */
323  else {
324  surface.GetComponent<Renderer>().material = new Material(Shader.Find("Mat Cap Cut"));
325  surface.GetComponent<Renderer>().material.SetTexture("_MatCap",(Texture)Resources.Load("lit_spheres/divers/daphz1"));
326  }
327  Debug.Log(surface.GetComponent<Renderer>().material.shader.name);
328  }
329  }
330 
331  private static void SetDims() {
332  XDIM = VOXELS.GetLength(0);
333  YDIM = VOXELS.GetLength(1);
334  ZDIM = VOXELS.GetLength(2);
335  }
336 
337  private static void DebugDims() {
338  Debug.Log(SLICE_WIDTH.ToString());
339  Debug.Log("GenerateMesh::CreateSurfaceObjects > Voxel grid dimensions (x,y,z):");
340  Debug.Log(XDIM.ToString());
341  Debug.Log(YDIM.ToString());
342  Debug.Log(ZDIM.ToString());
343  }
344 
345  private static void InitGenMesh(float[,,] vox, float thresh, Vector3 d, Vector3 o) {
346  VOXELS = vox;
347  DELTA = d;
348  ORIGIN = o;
349  OFFSET_ORIGIN = ORIGIN;
350  DADDY = UnityMolMain.getSurfaceManager().getParentGameObject().transform;
351  MarchingCubes.SetTarget(thresh);
353  // We could use MarchingCubes.SetWindingOrder here instead of flipping the triangles.
354 
355  }
356 
382  public static void CreateSurfaceObjects(float[,,] voxels, float threshold, Vector3 delta, Vector3 origin,
383  Color[] colors, int isPos,bool electro = false) {
384  ELECTRO = electro;
385  Debug.Log(ELECTRO.ToString());
386  if(ELECTRO) {
388  origin = readDX.GetOrigin();
389  delta = readDX.GetDelta();
390  }
391 
392  InitGenMesh(voxels, threshold, delta, origin);
393  SetDims();
394 
395  float bMCTime = Time.realtimeSinceStartup;
396  MeshData mData = MarchingCubes.CreateMesh(VOXELS, 0, XDIM, 0, YDIM, 0, ZDIM);
397  Debug.Log("Entire surface contains " + mData.vertices.Length.ToString() + " vertices.");
398  float elapsed = 10f * (Time.realtimeSinceStartup - bMCTime);
399  Debug.Log("GenerateMesh::MarchingCubes time: " + elapsed.ToString());
400  OffsetVertices(mData);
401 
402  float bSmooth = Time.realtimeSinceStartup;
403  AdjacencySets adjacencySets = new AdjacencySets(mData.triangles.Length);
404  adjacencySets.AddAllTriangles(mData.triangles);
405  SmoothFilter.AdjSetsSmoother(mData, adjacencySets);
406  elapsed = Time.realtimeSinceStartup - bSmooth;
407  Debug.Log("Smoothing time: " + elapsed.ToString());
408 
410 
411  // Necessary for electrostatic fields isosurfaces
412  Debug.Log(threshold.ToString());
413  if(threshold < 0)
414  FlipTriangles(mData);
415 
416  Splitting splitting = new Splitting();
417  List<Mesh> meshes = splitting.Split(mData);
418  CreateSurfaceObjects(meshes,isPos);
419  }
420 
421 
422  public void GM (Vector3[] Mvertices, int[] Mtriangles, Vector3 center, int surfaceNb, Color[] Colors) {
423  GameObject GOSurface = new GameObject("SurfaceOBJ");
425  GOSurface.transform.parent = UnityMolMain.getSurfaceManager().getParentGameObject().transform;
426  Mesh mesh = new Mesh();
427  GOSurface.AddComponent<MeshFilter>();
428  GOSurface.AddComponent<MeshRenderer>();
429  GOSurface.GetComponent<MeshFilter>().mesh = mesh;
430  //Material SurfaceShader = Resources.Load("SurfaceShader", typeof(Material)) as Material;
431  //GOSurface.renderer.material = SurfaceShader;
432 
433 
434  GOSurface.GetComponent<Renderer>().material = new Material(Shader.Find("Mat Cap Cut"));
435  GOSurface.GetComponent<Renderer>().material.SetTexture("_MatCap",(Texture)Resources.Load("lit_spheres/divers/daphz1"));
436 
437 
438  //GOSurface.renderer.material = new Material(Shader.Find("Diffuse"));
439 
440  //GOSurface.renderer.material = new Material(Shader.Find("Vertex Colored"));
441  //GOSurface.renderer.material.SetTexture("_MatCap",(Texture)Resources.Load("graypic/bruckner"));
442  GOSurface.transform.localPosition = center;
443  mesh.Clear();
444 
445  // //Unity has a left-handed coordinates system while Molecular obj are right-handed
446  // //So we have to negate the x axis and change the winding order
447  // for(int i=0; i < Mvertices.Length; i++)
448  // {
449  // Mvertices[i].x = -Mvertices[i].x;
450  // }
451 
452  // for(int tri=0; tri<Mtriangles.Length; tri=tri+3)
453  // {
454  // int tmp = Mtriangles[tri];
455  // Mtriangles[tri] = Mtriangles[tri+2];
456  // Mtriangles[tri+2] = tmp;
457  // }
458  mesh.vertices = Mvertices;
459  MoleculeModel.vertices= Mvertices;
460  Debug.Log("Exiting :: vertices filled");
461  mesh.triangles = Mtriangles;
462  mesh.colors = Colors;
463  mesh.RecalculateBounds();
464 // mesh.normals = Mnormals;
465  mesh.RecalculateNormals();
466  //mesh = ProperlyCalculateNormals(mesh);
467  //mesh = GenerateTextureCoordinates(mesh);
468  //mesh = CalculateMeshTangents(mesh);
469 // mesh.Optimize();
470 
471  }
472 
473 
474 
475 }
static Transform DADDY
Definition: GenerateMesh.cs:79
Vector3[] normals
Definition: MeshData.cs:7
static void CreateSurfaceObjects(List< Mesh > meshes, int isPos)
static void OffsetVertices(MeshData mData)
static void SetModeToCubes()
static Mesh CalculateMeshTangents(Mesh mesh)
static float S_FUDGE_FACTOR
Definition: GenerateMesh.cs:83
void AddAllTriangles(int[] triangles)
Vector3 GetDelta()
Definition: ReadDX.cs:103
static void FlipTriangles(MeshData mData)
Definition: ReadDX.cs:77
void addSurfaceNeg(GameObject surface)
List< Mesh > Split(MeshData mData)
Definition: Splitting.cs:15
static void SetDims()
static int SLICE_WIDTH
Definition: GenerateMesh.cs:82
static int YDIM
Definition: GenerateMesh.cs:81
static bool ELECTRO
Definition: GenerateMesh.cs:85
static Vector3 FUDGE_FACTOR
Definition: GenerateMesh.cs:84
static Vector3 ORIGIN
Definition: GenerateMesh.cs:77
static Mesh GenerateTextureCoordinates(Mesh mesh)
static void AdjSetsSmoother(MeshData mData, AdjacencySets adjacencySets)
static MeshData CreateMesh(float[,,] voxels, int xStart, int xEnd, int yStart, int yEnd, int zStart, int zEnd)
int[] triangles
Definition: MeshData.cs:5
Vector3[] vertices
Definition: MeshData.cs:6
static void FlipNormals(MeshData mData)
void GM(Vector3[] Mvertices, int[] Mtriangles, Vector3 center, int surfaceNb, Color[] Colors)
static float[,,] VOXELS
Definition: GenerateMesh.cs:75
static string TAG
Definition: GenerateMesh.cs:80
static Vector3 CENTER
Definition: GenerateMesh.cs:74
static void ProperlyCalculateNormals(MeshData mData)
This computes the normal vectors from a MeshData object, and adds them to it.
Definition: GenerateMesh.cs:96
Vector3 GetOrigin()
Definition: ReadDX.cs:108
static void SetTarget(float tar)
static int ZDIM
Definition: GenerateMesh.cs:81
static void InitGenMesh(float[,,] vox, float thresh, Vector3 d, Vector3 o)
GameObject getParentGameObject()
static void CreateSurfaceObjects(float[,,] voxels, float threshold, Vector3 delta, Vector3 origin, Color[] colors, int isPos, bool electro=false)
Creates the surface objects.
static int XDIM
Definition: GenerateMesh.cs:81
static SurfaceManager getSurfaceManager()
Definition: UnityMolMain.cs:24
void addSurfacePos(GameObject surface)
static Vector3 OFFSET_ORIGIN
Definition: GenerateMesh.cs:78
void addSurface(GameObject surface)
static Vector3 DELTA
Definition: GenerateMesh.cs:76
static void DebugDims()