シンプルなモデリングツール 2 にTimeノードを追加して、アニメーションデータを作成できるようにしてみます。
以下のスクリプトでは、Timeノードの追加以外に以下の変更を加えています。
import sys
import copy
class ObjectSet(object):
def __init__(self, sobjs=None):
self.objs = []
self.saveobjs = sobjs
def setObj(self, obj):
self.objs.append(obj)
def save(self, fn):
if self.saveobjs == None:
return
self.saveobjs(self.objs, fn)
class Point(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y
class TriPoly(object):
def __init__(self, p1, p2, p3):
self.p = [[p1, p2, p3]]
class Observer(object):
def __init__(self):
self.observer = {}
def append(self, src, node, dest):
if self.observer.has_key(src):
self.observer[src].append([node, dest])
else:
self.observer[src] = [[node, dest]]
def get(self, src):
if self.observer.has_key(src):
return self.observer[src]
return {}
def delete(self, src, node, dest):
if not self.observer.has_key(src):
return
nlist = []
for nd in self.observer[src]:
if node is nd[0] and src is nd[1]:
continue
nlist.append(nd)
self.observer[src] = nlist
class Nodebase(object):
def __init__(self, attr={}):
self.attr = attr
self.observer = Observer()
def update(self, node, src, dest):
if node != self:
self.setAttr(dest, node.getAttr(src))
self.compute()
def notify_observers(self, src):
for obs in self.observer.get(src):
obs[0].update(self, src, obs[1])
def compute(self):
pass
def attributeAffects(self, src, dest):
self.connectAttr(src, self, dest)
def connectAttr(self, src, node, dest):
self.observer.append(src, node, dest)
self.notify_observers(src)
def getAttr(self, aname):
return copy.deepcopy(self.attr[aname])
def setAttr(self, aname, val):
self.attr[aname] = val
self.notify_observers(aname)
def addAttr(self, aname, default=0.0):
self.attr[aname] = default
class MakeTriPoly(Nodebase):
def __init__(self):
tp = TriPoly(Point(0, 0), Point(0, 1), Point(1, 0))
attr = {'out': tp}
Nodebase.__init__(self, attr)
class MoveTriPoly(Nodebase):
def __init__(self, n=0, x=0.0, y=0.0):
attr = {'in': None, 'out': None, 'num': n, 'mx': x, 'my': y}
Nodebase.__init__(self, attr)
self.attributeAffects('num', 'out')
self.attributeAffects('mx', 'out')
self.attributeAffects('my', 'out')
self.attributeAffects('in', 'out')
def compute(self):
tp = self.getAttr('in')
if(tp == None):
return
f = tp.p[0]
num = self.getAttr('num')
f[num].x += self.getAttr('mx')
f[num].y += self.getAttr('my')
self.setAttr('out', tp)
self.notify_observers('out')
class Shape(Nodebase):
objset = None
def __init__(self):
if self.objset:
self.objset.setObj(self)
attr = {'in': None, 'out': None}
Nodebase.__init__(self, attr)
self.attributeAffects('in', 'out')
def compute(self):
tp = self.getAttr('in')
self.setAttr('out', tp)
self.notify_observers('out')
class Time(Nodebase):
def __init__(self):
attr = {'outTime': 0}
Nodebase.__init__(self, attr)
def saveAllObjs(objs, fn):
fp = open(fn, 'w')
n = 0
for o in objs:
fp.write('g tri' + str(n) + '\n')
fs = o.getAttr('out')
for p in fs.p:
fp.write('vn 0 1 0\n')
fp.write('v ' + str(p[0].x) + ' 0 ' + str(p[0].y) + '\n')
fp.write('v ' + str(p[1].x) + ' 0 ' + str(p[1].y) + '\n')
fp.write('v ' + str(p[2].x) + ' 0 ' + str(p[2].y) + '\n')
face = 'f '
for i in range(1, 4):
face += str(3*n+i) + '//' + str(n+1) + ' '
face += '\n'
fp.write(face)
n += 1
fp.close()
Shape.objset = ObjectSet(saveAllObjs)
time1 = Time()
def saveAnimData(s, e, fn):
for f in range(s, e+1):
time1.setAttr('outTime', f)
Shape.objset.save(fn + str(f) + '.obj')
execfile(sys.argv[1])
m1 = MakeTriPoly()
mv1 = MoveTriPoly(0)
m1.connectAttr('out', mv1, 'in')
mv2 = MoveTriPoly(1)
mv1.connectAttr('out', mv2, 'in')
mv3 = MoveTriPoly(2)
mv2.connectAttr('out', mv3, 'in')
s1 = Shape()
mv3.connectAttr('out', s1, 'in')
time1.connectAttr('outTime', mv1, 'mx')
time1.connectAttr('outTime', mv2, 'mx')
time1.connectAttr('outTime', mv3, 'mx')
saveAnimData(1, 3, "tmp")
後からnmaya4.py にノードを追加したいときは、Nodebaseを親クラスとするクラスを作成し、必要なメソッドを上書きします。
# python nmaya4_1.py spoly8.py
m1 = MakeTriPoly()
mv1 = MoveTriPoly(0)
m1.connectAttr('out', mv1, 'in')
mv2 = MoveTriPoly(1)
mv1.connectAttr('out', mv2, 'in')
mv3 = MoveTriPoly(2)
mv2.connectAttr('out', mv3, 'in')
s1 = Shape()
mv3.connectAttr('out', s1, 'in')
mul1 = Multi(0.1)
time1.connectAttr('outTime', mul1, 'input')
mul1.connectAttr('output', mv1, 'mx')
mul1.connectAttr('output', mv2, 'mx')
mul1.connectAttr('output', mv3, 'mx')
saveAnimData(1, 3, "tmp")
startframe = 1
endframe = 10
m1 = MakeTriPoly()
mv1 = MoveTriPoly(0)
m1.connectAttr('out', mv1, 'in')
mv2 = MoveTriPoly(1)
mv1.connectAttr('out', mv2, 'in')
mv3 = MoveTriPoly(2)
mv2.connectAttr('out', mv3, 'in')
s1 = Shape()
mv3.connectAttr('out', s1, 'in')
e1 = Expression()
e1.setAttr('expression', 'self.output = (math.sin((2*math.pi)*self.input/float(' + str(endframe) + ')) + 1.0)/2.0')
time1.connectAttr('outTime', e1, 'input')
e1.connectAttr('output', mv1, 'mx')
e1.connectAttr('output', mv2, 'mx')
e1.connectAttr('output', mv3, 'mx')
saveAnimData(startframe, endframe, "expression")
(ヒント)