grow.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. # This code is called when instances of this SOP cook.
  2. #scaleFactor = node.parm("scaleFactor").eval()
  3. import random
  4. import os
  5. import sys
  6. from os import path
  7. node = hou.pwd()
  8. geo = node.geometry()
  9. # the "seed"
  10. point=geo.createPoint()
  11. pointers=[point]
  12. initVector=hou.Vector3([0,0,0])
  13. # init the point attributes to store the values in
  14. NAttr = geo.addAttrib(hou.attribType.Point, "N", initVector)
  15. BAttr = geo.addAttrib(hou.attribType.Point, "Branch", 0)
  16. GAttr = geo.addAttrib(hou.attribType.Point, "Generation", 0)
  17. BNAttr = geo.addAttrib(hou.attribType.Point, "BranchPoint", 0)
  18. BTNAttr = geo.addAttrib(hou.attribType.Point, 'NormalizedPosition', 0.0)
  19. DAttr = geo.addAttrib(hou.attribType.Point, 'Diameter', 1.0)
  20. point.setAttribValue("N", hou.Vector3([0,1,0]))
  21. point.setAttribValue("Branch", 0)
  22. point.setAttribValue('NormalizedPosition', 0.5)
  23. defaultGrp=geo.createPointGroup('name')
  24. defaultGrp.add(point)
  25. #print point.attribValue("N")
  26. def duplicatePoint(p):
  27. # hmm. maybe there is sth like this already, but i missed it...
  28. dupe=geo.createPoint()
  29. dupe.setPosition(p.position())
  30. allAttr=geo.pointAttribs()
  31. for i in allAttr:
  32. #print i
  33. holder=None
  34. holder=p.attribValue(i)
  35. #print holder
  36. dupe.setAttribValue(i, holder)
  37. return dupe
  38. #dupe=duplicatePoint(point)
  39. def tropism(pt,vector,factor):
  40. '''Move point towards another point, as in growing towards a light source (sun)
  41. or a food source (roots)
  42. '''
  43. P = pt.position()
  44. pt.setPosition( P + 1 * vector)
  45. def moveAlongNormal(pt,factor):
  46. P = pt.position()
  47. #P = hou.Vector3(P)
  48. # be careful - this returns a value you cant simply add to P, must convert it to a hou.Vector3
  49. N = pt.attribValue("N")
  50. N = hou.Vector3(N)
  51. pt.setPosition( P + (1*factor) * N )
  52. def createRandomVector():
  53. rx = (random.random()-0.5)*2
  54. ry = (random.random()-0.5)*2
  55. rz = (random.random()-0.5)*2
  56. return hou.Vector3([rx,ry,rz])
  57. def addNoiseToNormal(pt,factor):
  58. N = pt.attribValue("N")
  59. N = hou.Vector3(N)
  60. rx = (random.random()-0.5)*2
  61. ry = (random.random()-0.5)*2
  62. rz = (random.random()-0.5)*2
  63. rvec = hou.Vector3([rx*factor,ry*factor,rz*factor])
  64. newN = rvec + 1 * N
  65. pt.setAttribValue("N", newN)
  66. return pt
  67. def rotateNormal(pt,factor):
  68. N = pt.attribValue("N")
  69. N = hou.Vector3(N)
  70. rx = (random.random()-0.5)*2
  71. ry = (random.random()-0.5)*2
  72. rz = (random.random()-0.5)*2
  73. rvec = hou.Vector3([rx*factor,ry*factor,rz*factor])
  74. newN = rvec + 1 * N
  75. pt.setAttribValue("N", newN)
  76. return pt
  77. def getPointsByAttribValue(attr,val):
  78. plist=[]
  79. for p in geo.iterPoints():
  80. if p.attribValue(attr)==val:
  81. plist.append(p)
  82. return plist
  83. def getHighestNumericAttrVal(points,attr):
  84. val=0.0
  85. for p in points:
  86. v=float(p.attribValue(attr))
  87. if v > val:val=v
  88. return val
  89. branchgroups=[]
  90. branchNum=0
  91. def step(pointers):
  92. updatedPointers=[]
  93. for p in pointers:
  94. n=p.attribValue("N")
  95. #print 'pointer is point w/ # ' + str(p.number())
  96. newP=duplicatePoint(p)
  97. #print 'copy is point w/ # ' + str(newP.number())
  98. updatedPointers.append(newP)
  99. newP.setAttribValue('BranchPoint',newP.attribValue('BranchPoint')+1)
  100. # Should we branch?
  101. # TODO allow multiple branches at once
  102. rnd=random.random()
  103. if rnd > 0.7:
  104. # Dirty, find a better way soon!
  105. global branchNum
  106. branchNum+=1
  107. global treeInfo
  108. #treeInfo['totalbranches']+=1
  109. #print 'branch'
  110. branchP=duplicatePoint(p)
  111. branchP.setAttribValue('BranchPoint',0)
  112. b=branchP.attribValue('Branch')
  113. branchP.setAttribValue('Branch',branchNum)
  114. #branchP.setAttribValue('Branch',b+1)
  115. g=branchP.attribValue('Generation')
  116. branchP.setAttribValue('Generation',g+1)
  117. updatedPointers.append(branchP)
  118. newP=rotateNormal(newP,0.4)
  119. # now move along normal
  120. moveAlongNormal(newP,1)
  121. v=hou.Vector3(0,1,1)
  122. tropism(newP,v,1)
  123. newP.setAttribValue('Diameter',newP.attribValue('Diameter')*0.9 )
  124. return updatedPointers
  125. x=step(pointers)
  126. for arsch in range(15):
  127. x = step(x)
  128. # until there is a better way, 'postprocess' the tree to gain info that is not present at runtime.
  129. def postprocess():
  130. tInfo={}
  131. '''
  132. for n in range(0,branchNum):
  133. for p in geo.iterPoints():
  134. #print p
  135. print p.attribValue('BranchPoint')
  136. #if p.attribValue('Branch') == n:
  137. # print p.attribValue('BranchPoint')
  138. '''
  139. for p in geo.iterPoints():
  140. curBranch=p.attribValue('Branch')
  141. tInfo['branch']=curBranch
  142. print '[[[[[[[[[[***]]]]]]]]]]'
  143. totalBranches=int(getHighestNumericAttrVal(geo.iterPoints(),'Branch'))
  144. #print geo.points()
  145. for i in range(0,totalBranches):
  146. # go through all branches
  147. max=0
  148. for p in getPointsByAttribValue('Branch',i):
  149. v=p.attribValue('BranchPoint')
  150. if v>max: max=v
  151. for p in getPointsByAttribValue('Branch',i):
  152. bp=p.attribValue('BranchPoint')
  153. print max
  154. print bp
  155. try:
  156. relpos=float(bp)/float(max)
  157. except:
  158. relpos=0
  159. #p.setAttribValue('NormalizedPosition',1)
  160. p.setAttribValue('NormalizedPosition', float(relpos))
  161. print '---'
  162. #print bp + max
  163. #print 'branch {0} points {1}'.format(i,max)
  164. # TODO and thoughts
  165. # in addition to the branch 'id' we need a distance of each point of a branch towards it's parent.
  166. # useful: how many 'levels' are we away from the main parent? > point needs to have parent id, increment on branch
  167. # roots