Thread: [cgkit-commits] cgkit2/cgkit maimport.py,NONE,1.1 __init__.py,1.12,1.13
Brought to you by:
mbaas
From: Matthias B. <mb...@us...> - 2005-04-21 17:28:45
|
Update of /cvsroot/cgkit/cgkit2/cgkit In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8175/cgkit Modified Files: __init__.py Added Files: maimport.py Log Message: Experimental Maya ASCII importer --- NEW FILE: maimport.py --- ########################################################################### # cgkit - Python Computer Graphics Kit # Copyright (C) 2004 Matthias Baas (ba...@ir...) # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # cgkit homepage: http://cgkit.sourceforge.net ########################################################################### # $Id: maimport.py,v 1.1 2005/04/21 17:28:37 mbaas Exp $ import mayaascii import pluginmanager import freecamera import quadrics, box, plane from cgtypes import * from worldobject import WorldObject from sl import * from math import * # NodeData class NodeData: """Store all the data belonging to a node. """ def __init__(self, nodetype, createopts): # The node type (string) self.nodetype = nodetype # The options of the createNode command (options dict) self.createopts = createopts # A dictionary with attributes (each setAttr command creates one entry) # Key is the attribute name, value is a tuple (vals, opts). self.setattr = {} # A list of new attributes (each element is the opts dict from the # addAttr call) self.addattr = [] # Key: Local attribute / Value: (nodename, attrname) of source self.in_connections = {} # Key: Local attribute / Value: List of (node, nodename, attrname) tuples self.out_connections = {} ### Creation methods: # setAttr def setAttr(self, attr, vals, opts): """Set an attribute. """ self.setattr[attr] = (vals, opts) # addAttr def addAttr(self, opts): """Set an attribute. """ self.addattr.append(opts) # addInConnection def addInConnection(self, localattr, node, attr): """Add an 'in' connection. 'in' = node.attr is connected to localattr """ self.in_connections[localattr] = (node, attr) # addutConnection def addOutConnection(self, localattr, node, nodename, attrname): """Add an 'out' connection. 'out' = localattr is connected to node.attr """ if self.out_connections.has_key(localattr): self.out_connections[localattr].append((node, nodename, attrname)) else: self.out_connections[localattr] = [(node, nodename, attrname)] ### Query methods: def getInNode(self, localattr_long, localattr_short): """Return the node and attribute that serves as input for localattr. The return value is a 2-tuple (nodename, attrname) that specifies the input connection for localattr. (None, None) is returned if there is no connection. """ node, attr = self.in_connections.get(localattr_long, (None, None)) if node==None: node, attr = self.in_connections.get(localattr_short, (None, None)) return node, attr # getOutAttr def getOutAttr(self, localattr_long, localattr_short, dstnodetype): """Check if a local attribute is connected to a particular type of node. Returns a tuple (node, attrname) where node is the NodeData object of the destination node and attrname the name of the destination attribute. If there is no connection with a node of type dstnodetype, the method returns (None,None). """ cs = self.out_connections.get(localattr_long, None) if cs==None: cs = self.out_connections.get(localattr_short, None) if cs==None: return None,None for node,nodename,attrname in cs: if node.nodetype==dstnodetype: return node, attrname return None,None def getIntAttr(self, longname, shortname, default=None): """Get an integer attribute.""" i = self.setattr.get(shortname, None) if i==None: i = self.setattr.get(longname, None) if i==None: return default return int(i[0][0]) def getFloatAttr(self, longname, shortname, default=None): """Get a float attribute.""" f = self.setattr.get(shortname, None) if f==None: f = self.setattr.get(longname, None) if f==None: return default return float(f[0][0]) def getFloatNAttr(self, longname, shortname, default=None): """Get a float array attribute.""" f = self.setattr.get(shortname, None) if f==None: f = self.setattr.get(longname, None) if f==None: return default return map(lambda x: float(x), f[0]) def getBoolAttr(self, longname, shortname, default=None): """Get a bool attribute.""" b = self.setattr.get(shortname, None) if b==None: b = self.setattr.get(longname, None) if b==None: return default return b[0][0] in ["true", "on", "yes"] def getVec3Attr(self, longname, shortname, default): """Get a vec3 attribute. """ v = self.setattr.get(shortname, None) if v==None: v = self.setattr.get(longname, None) if v==None: v = (default, None) v = vec3(map(lambda x: float(x), v[0])) tx = self.getFloatAttr(longname+"x", shortname+"x", None) if tx!=None: v.x = tx ty = self.getFloatAttr(longname+"y", shortname+"y", None) if ty!=None: v.y = ty tz = self.getFloatAttr(longname+"z", shortname+"z", None) if tz!=None: v.z = tz return v # MAImporter class MAImporter(mayaascii.MAReader): """MA import. """ _protocols = ["Import"] def __init__(self): mayaascii.MAReader.__init__(self) # extension def extension(): """Return the file extensions for this format.""" return ["ma"] extension = staticmethod(extension) # description def description(self): """Return a short description for the file dialog.""" return "Maya ASCII file" description = staticmethod(description) # importFile def importFile(self, filename): """Import a MA file.""" f = file(filename) self.read(f) # begin def begin(self): self.nodes = {} self.currentnode = None # end def end(self): for nodename in self.nodes: n = self.nodes[nodename] handlername = "onNode%s%s"%(n.nodetype[0].upper(), n.nodetype[1:]) handler = getattr(self, handlername, None) if handler!=None: name = n.createopts.get("name", [None])[0] parent = n.createopts.get("parent", [None])[0] handler(n, name, parent) ### Low level callbacks: def onCreateNode(self, nodetype, opts): """Create a new node and make it current. """ node = NodeData(nodetype, opts) nodename = opts.get("name", ["MayaNode"])[0] self.nodes[nodename] = node self.currentnode = node def onSelect(self, objects, opts): """dummy implementation""" self.currentnode = None def onSetAttr(self, attr, vals, opts): """Set an attribute.""" if self.currentnode==None: return if attr[0]=='.': attr = attr[1:] self.currentnode.setAttr(attr, vals, opts) def onAddAttr(self, opts): """Add a dynamic attribute.""" if self.currentnode==None: return self.currentnode.addAttr(opts) def onConnectAttr(self, srcattr, dstattr, opts): """Make a connection. """ a = srcattr.split(".") snode = a[0] sattr = a[1] b = dstattr.split(".") dnode = b[0] dattr = b[1] sn = self.nodes.get(snode, None) dn = self.nodes.get(dnode, None) if sn!=None: sn.addOutConnection(sattr, dn, dnode, dattr) if dn!=None: dn.addInConnection(dattr, snode, sattr) ################################################# ### High level callbacks: def onNodeCamera(self, node, name, parent): """Camera node. """ parentnode = self.nodes[parent] args = {} self.getWorldObjectArgs(parentnode, args) self.getCameraArgs(node, args) args["transform"] = args["transform"]*mat4(1).rotation(pi, vec3(0,1,0)) cam = freecamera.FreeCamera(**args) def onNodeMesh(self, node, name, parent): parentnode = self.nodes[parent] args = {} self.getWorldObjectArgs(parentnode, args) print "MESH",name # Check if the mesh is just a regular mesh or if it's created by # a "creator" node (cube, sphere, ...). n,a = node.getInNode("inMesh", "i") if n==None: meshtype = None else: creator = self.nodes.get(n) meshtype = creator.nodetype # Sphere? if meshtype=="polySphere": node,attr = parentnode.getOutAttr("worldMatrix", "wm", "rigidBody") dynamics = (node!=None) r = creator.getFloatAttr("radius", "r", 1.0) segsu = creator.getIntAttr("subdivisionAxis", "sa", 20) segsv = creator.getIntAttr("subdivisionHeight", "sh", 20) ax = creator.getVec3Attr("axis", "ax", vec3(0,1,0)) args["transform"] *= self.axisToTransform(ax) if ax==vec3(1,0,0): args["transform"] *= mat4(1).rotation(pi/4, vec3(0,0,1)) self.getRigidBodyArgs(parentnode, args) quadrics.Sphere(radius=r, segmentsu=segsu, segmentsv=segsv, **args) # Cube? elif meshtype=="polyCube": w = creator.getFloatAttr("width", "w", 1.0) h = creator.getFloatAttr("height", "h", 1.0) d = creator.getFloatAttr("depth", "d", 1.0) sw = creator.getIntAttr("subdivisionWidth", "sw", 1) sh = creator.getIntAttr("subdivisionHeight", "sh", 1) sd = creator.getIntAttr("subdivisionDepth", "sd", 1) ax = creator.getVec3Attr("axis", "ax", vec3(0,1,0)) args["transform"] *= self.axisToTransform(ax) if ax==vec3(1,0,0): args["transform"] *= mat4(1).rotation(pi/2, vec3(0,0,1)) self.getRigidBodyArgs(parentnode, args) box.Box(lx=w, ly=d, lz=h, segmentsx=sw, segmentsy=sd, segmentsz=sh, **args) # Plane? elif meshtype=="polyPlane": w = creator.getFloatAttr("width", "w", 1.0) h = creator.getFloatAttr("height", "h", 1.0) sw = creator.getIntAttr("subdivisionWidth", "sw", 1) sh = creator.getIntAttr("subdivisionHeight", "sh", 1) ax = creator.getVec3Attr("axis", "ax", vec3(0,1,0)) args["transform"] *= self.axisToTransform(ax) self.getRigidBodyArgs(parentnode, args) if "static" in args: del args["static"] plane.Plane(lx=w, ly=h, segmentsx=sw, segmentsy=sh, **args) def getRigidBodyArgs(self, transform, res): """Retrieve rigid body information. transform is the transform node as NodeData object. """ rbnode,attr = transform.getOutAttr("worldMatrix", "wm", "rigidBody") # No rigid body node? then don't add any arguments if rbnode==None: res["dynamics"] = False return res res["dynamics"] = True res["mass"] = rbnode.getFloatAttr("mass", "mas", 1.0) res["static"] = not rbnode.getBoolAttr("active", "act", True) return res def axisToTransform(self, axis): if axis==vec3(1,0,0): return mat4(1).rotation(pi/2, vec3(0,1,0)) elif axis==vec3(0,1,0): return mat4(1).rotation(pi/2, vec3(1,0,0)) else: return mat4(1) ### Helpers: # getCameraArgs def getCameraArgs(self, node, res): """Create the argument dict for the WorldObject constructor. node must contain the data from a Maya transform node. """ fl = node.getFloatAttr("focalLength", "fl", 35.0) res["focallength"] = fl cap = node.getFloatNAttr("cameraAperture", "cap", (1.41732, 0.94488)) fov = degrees(2*atan((cap[0]*25.4)/(2*fl))) # Convert the FOV from horizontal to vertical direction # (Todo: What aspect ratio to use?) fov = degrees(atan(480/640.0*tan(radians(fov/2.0))))*2.0 res["fov"] = fov res["fstop"] = node.getFloatAttr("fstop", "fs", 5.6) return res # getWorldObjectArgs def getWorldObjectArgs(self, node, res): """Create the argument dict for the WorldObject constructor. node must contain the data from a Maya transform node. """ # Name res["name"] = node.createopts.get("name", [None])[0] # Compute transform t = node.getVec3Attr("translate", "t", vec3(0)) r = node.getVec3Attr("rotate", "r", vec3(0)) s = node.getVec3Attr("scale", "s", vec3(1)) sp = node.getVec3Attr("scalePivot", "sp", vec3(0)) spt = node.getVec3Attr("scalePivotTranslate", "spt", vec3(0)) sh = node.getVec3Attr("shear", "sh", vec3(0)) rp = node.getVec3Attr("rotatePivot", "rp", vec3(0)) rpt = node.getVec3Attr("rotatePivotTranslate", "rpt", vec3(0)) ra = node.getVec3Attr("rotateAxis", "ra", vec3(0)) roi = node.getIntAttr("rotationInterpolation", "roi", 1) ro = node.getIntAttr("rotateOrder", "ro", 0) SP = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, sp.x,sp.y,sp.z,1) ST = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, spt.x,spt.y,spt.z,1) S = mat4().scaling(s) SH = mat4(1,0,0,0, sh.x,1,0,0, sh.y,sh.z,1,0, 0,0,0,1) RP = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, rp.x,rp.y,rp.z,1) RT = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, rpt.x,rpt.y,rpt.z,1) T = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, t.x,t.y,t.z,1) sx = sin(radians(ra.x)) cx = cos(radians(ra.x)) sy = sin(radians(ra.y)) cy = cos(radians(ra.y)) sz = sin(radians(ra.z)) cz = cos(radians(ra.z)) AX = mat4(1,0,0,0, 0,cx,sx,0, 0,-sx,cx,0, 0,0,0,1) AY = mat4(cy,0,-sy,0, 0,1,0,0, sy,0,cy,0, 0,0,0,1) AZ = mat4(cz,sz,0,0, -sz,cz,0,0, 0,0,1,0, 0,0,0,1) RA = AX*AY*AZ # Euler-angle rotation (todo: quat) sx = sin(radians(r.x)) cx = cos(radians(r.x)) sy = sin(radians(r.y)) cy = cos(radians(r.y)) sz = sin(radians(r.z)) cz = cos(radians(r.z)) RX = mat4(1,0,0,0, 0,cx,sx,0, 0,-sx,cx,0, 0,0,0,1) RY = mat4(cy,0,-sy,0, 0,1,0,0, sy,0,cy,0, 0,0,0,1) RZ = mat4(cz,sz,0,0, -sz,cz,0,0, 0,0,1,0, 0,0,0,1) a,b,c = ["XYZ", "YZX", "ZXY", "XZY", "YXZ", "ZYX"][ro] exec "R=R%s*R%s*R%s"%(a,b,c) WT = SP.inverse()*S*SH*SP*ST*RP.inverse()*RA*R*RP*RT*T WT = WT.transpose() res["transform"] = WT # Visibility res["visible"] = node.getBoolAttr("visibility", "v", True) return res ###################################################################### # Register the importer class as a plugin class pluginmanager.register(MAImporter) Index: __init__.py =================================================================== RCS file: /cvsroot/cgkit/cgkit2/cgkit/__init__.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** __init__.py 14 Apr 2005 17:24:36 -0000 1.12 --- __init__.py 21 Apr 2005 17:28:37 -0000 1.13 *************** *** 140,143 **** --- 140,144 ---- import asfamcimport import bvhimport + import maimport # Exporter import ribexport *************** *** 145,148 **** import objexport ! from rmshader import RMMaterial, RMShader --- 146,149 ---- import objexport ! from rmshader import RMMaterial, RMLightSource, RMShader |