cookchar

Script to generate an obj file of a regular icosahedron

Apr 23rd, 2019
158
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import scipy.constants as spc
  2. import math
  3. import json
  4. # Compute u - v
  5. def vecDiff(u, v):
  6.     if type(u) is not list and type(v) is not list and len(u) != len(v):
  7.         raise TypeError("Arguements must be lists of the same size.")
  8.     return list( \
  9.         map( \
  10.             lambda m, n : m - n, \
  11.             u, \
  12.             v, \
  13.         ) \
  14.     )
  15. # Compute u . v
  16. def dotProd(u, v):
  17.     if type(u) is not list and type(v) is not list and len(u) != len(v):
  18.         raise TypeError("Arguements must be lists of the same size.")
  19.     return sum( \
  20.         map( \
  21.             lambda m, n : m * n, \
  22.             u, \
  23.             v, \
  24.         ) \
  25.     )
  26. # Compute ||v||
  27. def eucNorm(v):
  28.     return dotProd(v, v) ** 0.5
  29. # Compute v / ||v||
  30. def normalize(v):
  31.     n = eucNorm(v)
  32.     return list( \
  33.         map( \
  34.             lambda i : round(i / n, 10), \
  35.             v \
  36.         ) \
  37.     )
  38. # Compute u x v
  39. def crossProd(u, v):
  40.     # Remember: x:0, y:1, z:2
  41.     return [\
  42.         u[1] * v[2] - u[2] * v[1], \
  43.         - (u[0] * v[2] - u[2] * v[0]), \
  44.         u[0] * v[1] - u[1] * v[0] \
  45.     ]
  46. # Get the vertex IDs neighboring a given vertex
  47. def getNeighbors(n):
  48.     global edges
  49.     pairsNFirst = edges[5*n:5*n+5]
  50.     return tuple( \
  51.         map( \
  52.             lambda p : p[1], \
  53.             pairsNFirst
  54.         ) \
  55.     )
  56. # Get the angle between two vectors
  57. def vecAngle(u, v):
  58.     return math.degrees(
  59.         math.acos(
  60.             dotProd(u, v) / (eucNorm(u) * eucNorm(v))
  61.         )
  62.     )
  63.  
  64. v = [spc.golden, 1, 0]
  65. vertices = []
  66. for j in range(4):
  67.     for k in range(3):
  68.         vertices.append(v.copy())
  69.         t = v.pop()
  70.         v.insert(0, t)
  71.     v[(j + 2) % 2] *= -1
  72. vertices.sort(key = lambda v : v[1])
  73. for u in vertices:
  74.     print(vertices.index(u), ':', u)
  75.  
  76. edges = []
  77. for u in vertices:
  78.     for w in vertices:
  79.         if w != u:
  80.             d = vecDiff(u, w)
  81.             n = eucNorm(d)
  82.             if round(n, 4) != 2.0000:
  83.                 continue
  84.             edges.append((vertices.index(u), vertices.index(w)))
  85. edges.sort()
  86. for e in edges:
  87.     i = edges.index(e)
  88.     print( \
  89.         i, ':',  e, \
  90.         end = '\n' if (i + 1) % 5 == 0 else '\t' \
  91.     )
  92.  
  93. triangles = []
  94. for n in range(12):
  95.     neighborsN = getNeighbors(n)
  96.     for m in neighborsN:
  97.         neighborsM = getNeighbors(m)
  98.         for k in neighborsM:
  99.             if n in getNeighbors(k):
  100.                 t = tuple(sorted([n, m, k]))
  101.                 if t not in triangles:
  102.                     triangles.append(t)
  103.                 else:
  104.                     continue
  105.             else:
  106.                 continue
  107. for t in triangles:
  108.     print(triangles.index(t), ':', t)
  109.  
  110. triangleData = {}
  111. neededCrossProdRedo = []
  112. for t in triangles:
  113.     e1 = vecDiff(vertices[t[1]], vertices[t[0]])
  114.     e2 = vecDiff(vertices[t[2]], vertices[t[0]])
  115.     n = normalize(crossProd(e1, e2))
  116.     if vecAngle(n, vertices[t[0]]) > 90.0:
  117.         n = normalize(crossProd(e2, e1))
  118.         neededCrossProdRedo.append(triangles.index(t))
  119.     triangleData[triangles.index(t)] = { \
  120.         "vertices" : t, \
  121.         "normal": tuple(n) \
  122.     }
  123.  
  124. for k in neededCrossProdRedo:
  125.     temp = list(triangleData[k]["vertices"])
  126.     a = temp[2]
  127.     temp[2] = temp[1]
  128.     temp[1] = a
  129.     triangleData[k]["vertices"] = tuple(temp)
  130.  
  131. for n in triangleData.keys():
  132.     print( \
  133.         n, ':', \
  134.         "vertices:", triangleData[n]["vertices"], \
  135.         "; normal:", triangleData[n]["normal"] \
  136.     )
  137.  
  138. if input("Write a new .obj file? [Y/n]: ").upper() == 'Y':
  139.     objFile = open("ccIcosahedron.obj", 'w')
  140.     for v in vertices:
  141.         objFile.write("v ")
  142.         s = 0
  143.         for c in v:
  144.             objFile.write(str(c))
  145.             if s < 2:
  146.                 objFile.write(' ')
  147.             s += 1
  148.         objFile.write('\n')
  149.     objFile.write("vt 0.0 0.0\nvt 0.5 1.0\nvt 1.0 0.0\n")
  150.     for k in range(20):
  151.         objFile.write("vn ")
  152.         s = 0
  153.         for c in triangleData[k]["normal"]:
  154.             objFile.write(str(c))
  155.             if s < 2:
  156.                 objFile.write(' ')
  157.             s += 1
  158.         objFile.write('\n')
  159.     for k in range(20):
  160.         objFile.write("f ")
  161.         s = 0
  162.         for c in triangleData[k]["vertices"]:
  163.             objFile.write(str(c + 1) + '/' + str(s + 1) + '/' + str(k + 1))
  164.             if s < 2:
  165.                 objFile.write(' ')
  166.             s += 1
  167.         objFile.write('\n')
  168.     objFile.close()
  169.     print("File created!")
  170.  
  171. jsonDumpFile = open("icosaGenDump.json", 'w')
  172. jsonDumpFile.write(json.dumps(vertices, indent = 4))
  173. jsonDumpFile.write('\n')
  174. jsonDumpFile.write(json.dumps(triangleData, indent = 4))
  175. jsonDumpFile.close()
RAW Paste Data