Houdini : 稲妻 Lightning Bolts
稲妻を制作しようと思います。
電撃びりびりっすね。
サンプルを探してみたのですが、このサイトにありました。
Approaches to Lightning in Houdini
Tool
・Houdini 13
大まかな内容
・Nullを二つ用意 ・L-System の最初、最後の頂点の位置をNullに合わせる
vopsopノード
上流が、Nullの位置
下流が、LSystemのポイントの位置です
- それぞれの距離を算出
- スケール
- それぞれのベクトルのノーマルを算出
- Alignでそろえる
と言った所がポイントのようです
Python Script
スクリプト化してみました
#Create Lightning Bolts #Ver0.1 #2014 11 20 import hou #Global gPosA = (3,0,0) gPosB = (0,0,0) isGrow = True isRender = True gCicle = 30 gLineWidth = 0.02 #L-SystemParam gLSParamContext = "F+-" gLSParamPremise = "A" gLSParamRule = ['A=-F+A:0.45',"A=+F-A:0.45",'A=~(30)[--"!A]A:0.05','A=[++"!A]A:0.05'] def setVopSopParameters(n,null1,null2): g = n.node("global1") o = n.node("output1") #Add Nodes add1 = n.createNode("add") ali1 = n.createNode("align") div1 = n.createNode("divide") imp1 = n.createNode("importattrib") imp2 = n.createNode("importattrib") len1 = n.createNode("length") len2 = n.createNode("length") mul1 = n.createNode("multiply") mul2 = n.createNode("multiply") nor1 = n.createNode("normalize") nor2 = n.createNode("normalize") pos1 = n.createNode("parameter","pos1") pos2 = n.createNode("parameter","pos2") ptnum = n.createNode("constant","ptnum") subc1 = n.createNode("subconst") sub1 = n.createNode("subtract") sub3 = n.createNode("subtract") sub4 = n.createNode("subtract") #Connect Nodes o.setInput(0,add1,0) add1.setInput(0,pos2,0) add1.setInput(1,mul1,0) mul1.setInput(0,mul2,0) mul1.setInput(1,ali1,0) mul2.setInput(0,sub3,0) mul2.setInput(1,div1,0) div1.setInput(0,len1,0) div1.setInput(1,len2,0) len1.setInput(0,sub4,0) len2.setInput(0,sub1,0) sub4.setInput(0,pos1,0) sub4.setInput(1,pos2,0) ali1.setInput(0,nor1,0) ali1.setInput(1,nor2,0) nor2.setInput(0,sub4,0) nor1.setInput(0,sub1,0) sub1.setInput(0,imp2,1) sub1.setInput(1,imp1,1) imp2.setInput(2,subc1,0) imp1.setInput(2,ptnum,0) subc1.setInput(0,g,11) sub3.setInput(0,g,0) sub3.setInput(1,imp1,1) #SetParameter ptnum.parm("consttype").set(1) #integer ptnum.parm("constname").set("ptnum") imp1.parm("attrib").set("P") imp2.parm("attrib").set("P") pos1.parm("parmname").set("Pos1") pos1.parm("parmlabel").set("Pos1") pos1.parm("parmtype").set(6) #Vector pos2.parm("parmname").set("Pos2") pos2.parm("parmlabel").set("Pos2") pos2.parm("parmtype").set(6) #Vector #setVopSopParam n.parm("Pos11").setExpression('origin("","' + null1.path() + '","TX")') n.parm("Pos12").setExpression('origin("","' + null1.path() + '","TY")') n.parm("Pos13").setExpression('origin("","' + null1.path() + '","TZ")') n.parm("Pos21").setExpression('origin("","' + null2.path() + '","TX")') n.parm("Pos22").setExpression('origin("","' + null2.path() + '","TY")') n.parm("Pos23").setExpression('origin("","' + null2.path() + '","TZ")') return True def setLSystemParameters(lSys): lSys.parm("generations").set(30) lSys.parm("randseed").setExpression('int(($F - 1)/ ' + str(gCicle) + ")" ) #int( ($F - 1) / 5 ) if(isGrow): lSys.parm("pointwidth").set(1) lSys.parm("stepinit").set(0.03) lSys.parm("stepscale").set(0.9) lSys.parm("angleinit").set(13) lSys.parm("anglescale").set(0.9) lSys.parm("context").set(gLSParamContext) lSys.parm("premise").set(gLSParamPremise) lSys.parm("rule1").set(gLSParamRule[0]) lSys.parm("rule2").set(gLSParamRule[1]) lSys.parm("rule3").set(gLSParamRule[2]) lSys.parm("rule4").set(gLSParamRule[3]) return True; def createBrastOp(n): folderName = "folder" gNode = n.createOutputNode("blast","grow") p = hou.FloatParmTemplate("grow_dist","Grow Dist",1) folder = hou.FolderParmTemplate("myfolder","myfolder") folder.addParmTemplate( p ) group = gNode.parmTemplateGroup() group.append(folder) gNode.setParmTemplateGroup(group) #"@arc>`ch('./grow_dist')`" gNode.parm("group").set("@arc>`ch('./grow_dist')`") gNode.parm("grouptype").set(3) gNode.parm("grow_dist").setExpression( "($F -1) %" + str(gCicle) +" * " + str( 1.0 / (gCicle) ) + "+" + str( + 1.0 / (gCicle) ) ) gNode.setDisplayFlag(True) return True def setRenderNode(vopsopNode): node = vopsopNode if(isGrow): node = node.outputs()[0] node = node.createOutputNode("ends") node = node.createOutputNode("attribcreate::2.0") node.parm("name1").set("width") node.parm("value1v1").set(gLineWidth) return True def main(): obj = hou.node("/obj") #nullを作成する null1 = obj.createNode("null","null_to") null2 = obj.createNode("null","null_from") null1.setPosition([1,2]) null2.setPosition([3,2]) null1.parmTuple("t").set(gPosA) null2.parmTuple("t").set(gPosB) #Lsystemを作成する geo = obj.createNode("geo","lightningBolts") geo.node("file1").destroy() lSys = geo.createNode("lsystem") setLSystemParameters(lSys) geo.setPosition([2,0]) #Vop Sopを作成する vopsop = lSys.createOutputNode("vopsop") vopsop.setDisplayFlag(True) setVopSopParameters(vopsop,null1,null2) vopsop.setPosition([0,-1]) #GrowChack if(isGrow): createBrastOp(vopsop) #Render if(isRender): setRenderNode(vopsop) return True; main()
感想
とりあえず作っただけで、制御らしいことは出来てないですね。
L-Systemも良くわかってないし
Houdini Procedural Animation Techniques
という有償チュートリアルのは、
ポリメッシュに生成するので都合が良さそうです。
0 件のコメント:
コメントを投稿