L-Systems 和 Maya 中的堆栈

L-Systems and the stack in Maya

所以我理解了 L 系统的规则并且我已经成功地创建了一个 Sierpinski 三角形。我现在开始制作不同风格的树木。

基本规则是:

F: Draw forward
+: Rotate right by angle
-: Rotate left by angle
[: Push stack 
]: Pop stack

我正在使用 Maya 执行此操作,但我不确定如何推动和弹出堆栈。我知道如何使用列表创建基本堆栈,因为 Maya 没有默认堆栈,但我究竟要推入/弹出什么?

我好像无法推动物体的世界矩阵。如果不先创建一个对象就无法做某事,L-System 进程就会出错。作为一个基本示例:

F[+F] 

...由于没有为 push/rotate 创建对象而无法工作。

任何提示都会非常有用,因为这已经困扰了我一段时间。

首先,让我向您指出,Maya 确实有这样的图形堆栈。只是因为 Maya 不是即时模式绘图工具,所以这个堆栈实际上是一棵树。这棵树称为 DAG 或换句话说对象父层次结构。此树与 L-system 描述的堆栈具有相同的用途。但是,这可能对您有帮助,也可能没有帮助,因为它对您的评估没有直接的用处。

那么让我们来看看在 Maya 中简单的 L 系统渲染会是什么样子。让我们从 How to Think Like a Computer Scientist 借用基本代码,让我们使用稍微更令人兴奋的规则:

F -> F[-<<<<F][+>>>>F]

其中 > 和 < 是绕轴的旋转。使用基本公理:

F

4 次迭代和 30 度角的结果:

请注意,生产规则集有点多余,并且往往会在每次迭代时绘制许多词干。但我的目标是理解的简单性而不是优雅。使用的代码:

import maya.cmds as cmds

def applyRules(lhch):
    rhstr = ""
    if lhch == 'F':
        rhstr = 'F[+F][<<<<+F][>>>>+F]'
    else:
        rhstr = lhch  # no rules apply so keep the character
    return rhstr


def processString(oldStr):
    newstr = ""
    for ch in oldStr:
        newstr = newstr + applyRules(ch)
    return newstr


def createLSystem(numIters, axiom):
    startString = axiom
    endString = ""
    for i in range(numIters):
        endString = processString(startString)
        startString = endString
    return endString

def drawLsystem(instructions, angle, distance):
    parent = cmds.createNode("transform", n="L_Root_#")
    saved=[]
    for act in instructions:
        if act == 'F':
           cyl = cmds.cylinder(r=0.1, ax=[0,1,0], hr=1/0.1*distance)
           cyl = cmds.parent( cyl[0], parent, r=1)
           cmds.move(0, (distance/2.0), 0, cyl[0], os=1) 
           parent = cmds.createNode("transform", p=parent)
           cmds.move(0, (distance), 0, parent, os=1) 
        if act == '-':
           parent = cmds.createNode("transform", p=parent)
           cmds.rotate(angle, 0, 0, parent, os=1) 
        if act == '+':
           parent = cmds.createNode("transform", p=parent)
           cmds.rotate(-angle, 0, 0, parent, os=1) 
        if act == '<':
           parent = cmds.createNode("transform", p=parent)
           cmds.rotate(0, angle, 0, parent, os=1) 
        if act == '>':
           parent = cmds.createNode("transform", p=parent)
           cmds.rotate(0, -angle, 0, parent, os=1) 
        if act == '[':
           saved.append(parent)
        if act == ']':
           parent = saved.pop()  


drawLsystem(createLSystem(4, "F"),30,1)     

PS:如果将公理更改为 FX 并将规则 X 更改为 [+FX][<<<<+FX][>>>>+FX],它会产生更少的冗余。 运行 由于 Maya 撤消的更新速度非常慢,因此没有撤消的代码使其速度快了数年。因此,您可以 运行 规则设置更多次以获得更复杂的结果。在生成规则中添加了一些缩放操作并得到了这个: