2014年11月21日金曜日

Houdini : 稲妻 Lightning Bolts

Houdini 稲妻 Lightning Bolts.md—/Users/kawabata_imac/Dropbox/Blog/Houdini

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 件のコメント:

コメントを投稿