home *** CD-ROM | disk | FTP | other *** search
- # ***** BEGIN LICENSE BLOCK *****
- # Version: MPL 1.1/GPL 2.0/LGPL 2.1
- #
- # The contents of this file are subject to the Mozilla Public License Version
- # 1.1 (the "License"); you may not use this file except in compliance with
- # the License. You may obtain a copy of the License at
- # http://www.mozilla.org/MPL/
- #
- # Software distributed under the License is distributed on an "AS IS" basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- #
- # The Original Code is the Python Computer Graphics Kit.
- #
- # The Initial Developer of the Original Code is Matthias Baas.
- # Portions created by the Initial Developer are Copyright (C) 2004
- # the Initial Developer. All Rights Reserved.
- #
- # Contributor(s):
- #
- # Alternatively, the contents of this file may be used under the terms of
- # either the GNU General Public License Version 2 or later (the "GPL"), or
- # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- # in which case the provisions of the GPL or the LGPL are applicable instead
- # of those above. If you wish to allow use of your version of this file only
- # under the terms of either the GPL or the LGPL, and not to allow others to
- # use your version of this file under the terms of the MPL, indicate your
- # decision by deleting the provisions above and replace them with the notice
- # and other provisions required by the GPL or the LGPL. If you do not delete
- # the provisions above, a recipient may use your version of this file under
- # the terms of any one of the MPL, the GPL or the LGPL.
- #
- # ***** END LICENSE BLOCK *****
- # $Id: maimport.py,v 1.12 2005/06/15 19:20:29 mbaas Exp $
-
- import sys
- import mayaascii, cmds
- import pluginmanager
- import freecamera
- import quadrics, box, plane, polyhedron, joint, trimesh, trimeshgeom
- import glpointlight, glfreespotlight, glfreedistantlight
- import mayaspotlight
- from geomobject import *
- from cgtypes import *
- from worldobject import WorldObject
- from sl import *
- from math import *
-
-
-
- # MAImporter
- class MAImporter(mayaascii.DefaultMAReader):
- """MA import.
- """
-
- _protocols = ["Import"]
-
- def __init__(self):
- mayaascii.DefaultMAReader.__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, parent=None):
- """Import a MA file."""
-
- self.root_parent = parent
-
- f = file(filename)
- self.read(f)
-
- # begin
- def begin(self):
- mayaascii.DefaultMAReader.begin(self)
- # A dict with created WorldObjects (key = name)
- self.worldobjects = {}
-
- # end
- def end(self):
- mayaascii.DefaultMAReader.end(self)
-
- issued_warnings = {}
- # Process the nodes by calling an appropriate handler method
- # onNode<Type>(node) for each node type...
- for node in self.nodelist:
- s = node.nodetype
- handlername = "onNode%s%s"%(s[0].upper(), s[1:])
- handler = getattr(self, handlername, None)
- if handler!=None:
- handler(node)
- else:
- if node.nodetype not in issued_warnings:
- print >>sys.stderr, "WARNING: %s nodes are ignored."%node.nodetype
- issued_warnings[node.nodetype] = 1
-
- #################################################
-
- ### High level callbacks:
-
- # Each node callback takes the current Node object as argument.
- # Whenever a new WorldObject is created, the method has to call
- # the newWorldObject() method to tell the importer about the new object
- # (so that it is known when someone else uses it as parent).
-
- def ignoreWarning(self, node):
- """(this is just a dummy callback so that no warning is issued)"""
- pass
- onNodeTransform = ignoreWarning
- onNodePolySphere = ignoreWarning
- onNodePolyCube = ignoreWarning
- onNodePolyPlane = ignoreWarning
- onNodeRigidBody = ignoreWarning
-
- def onNodePointLight(self, node):
- """PointLight node.
- """
- args = self.fillWorldObjectArgs(node)
-
- cl = vec3(node.getAttrValue("color", "cl", "float3", 1, vec3(1)))
- intensity = node.getAttrValue("intensity", "in", "float", 1, 1.0)
- de = node.getAttrValue("decayRate", "de", "int", 1, 0)
- if de==0:
- catt = 1.0
- latt = 0.0
- qatt = 0.0
- elif de==1:
- catt = 0.0
- latt = 1.0
- qatt = 0.0
- else:
- catt = 0.0
- latt = 0.0
- qatt = 1.0
-
- lgt = glpointlight.GLPointLight(diffuse = cl,
- intensity = intensity,
- constant_attenuation = catt,
- linear_attenuation = latt,
- quadratic_attenuation = qatt,
- enabled = args["visible"],
- **args)
- self.newWorldObject(lgt, node.getParentName())
-
- def onNodeSpotLight(self, node):
- """SpotLight node.
- """
- args = self.fillWorldObjectArgs(node)
-
- cl = vec3(node.getAttrValue("color", "cl", "float3", 1, vec3(1)))
- intensity = node.getAttrValue("intensity", "in", "float", 1, 1.0)
- de = node.getAttrValue("decayRate", "de", "int", 1, 0)
- ca = node.getAttrValue("coneAngle", "ca", "float", 1, 40.0)
- pa = node.getAttrValue("penumbraAngle", "pa", "float", 1, 0.0)
- dro = node.getAttrValue("dropoff", "dro", "float", 1, 0.0)
-
- dms = node.getAttrValue("useDepthMapShadows", "dms", "bool", 1, False)
- dr = node.getAttrValue("dmapResolution", "dr", "int", 1, 512)
- md = node.getAttrValue("useMidDistDmap", "md", "bool", 1, True)
- af = node.getAttrValue("useDmapAutoFocus", "af", "bool", 1, True)
- df = node.getAttrValue("dmapFocus", "df", "float", 1, 90.0)
- fs = node.getAttrValue("dmapFilterSize", "fs", "int", 1, 1)
- db = node.getAttrValue("dmapBias", "db", "float", 1, 0.001)
-
- args["transform"] = args["transform"]
-
- lgt = mayaspotlight.MayaSpotLight(color = cl,
- intensity = intensity,
- decayRate = de,
- coneAngle = ca,
- penumbraAngle = pa,
- dropoff = dro,
- useDepthMapShadows = dms,
- dmapResolution = dr,
- useMidDistDmap = md,
- useDmapAutoFocus = af,
- dmapFocus = df,
- dmapFilterSize = fs,
- dmapBias = db,
- enabled = args["visible"],
- **args)
- self.newWorldObject(lgt, node.getParentName())
-
- def onNodeDirectionalLight(self, node):
- """DirectionalLight node.
- """
- args = self.fillWorldObjectArgs(node)
-
- cl = vec3(node.getAttrValue("color", "cl", "float3", 1, vec3(1)))
- intensity = node.getAttrValue("intensity", "in", "float", 1, 1.0)
-
- args["transform"] = args["transform"]*mat4(1).rotation(pi, vec3(1,0,0))
-
- lgt = glfreedistantlight.GLFreeDistantLight(diffuse = cl,
- intensity = intensity,
- enabled = args["visible"],
- **args)
- self.newWorldObject(lgt, node.getParentName())
-
- def onNodeJoint(self, node):
- """Joint node.
- """
- args = self.fillWorldObjectArgs(node)
-
- # Compute transform
- t = vec3(node.getAttrValue("translate", "t", "double3", 1, vec3(0)))
- r = vec3(node.getAttrValue("rotate", "r", "double3", 1, vec3(0)))
- s = vec3(node.getAttrValue("scale", "s", "double3", 1, vec3(1)))
- ra = vec3(node.getAttrValue("rotateAxis", "ra", "double3", 1, vec3(0)))
- roi = node.getAttrValue("rotationInterpolation", "roi", "int", 1, 1)
- ro = node.getAttrValue("rotateOrder", "ro", "int", 1, default=0)
- jo = vec3(node.getAttrValue("jointOrient", "jo", "double3", 1, vec3(0)))
- is_ = vec3(node.getAttrValue("inverseScale", "is", "double3", 1, vec3(1)))
- jot = node.getAttrValue("jointOrientType", "jot", "string", 1, default="xyz")
-
- S = mat4().scaling(s)
- T = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, t.x,t.y,t.z,1)
- IS = mat4().scaling(is_)
-
- 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)
-
- sx = sin(radians(jo.x))
- cx = cos(radians(jo.x))
- sy = sin(radians(jo.y))
- cy = cos(radians(jo.y))
- sz = sin(radians(jo.z))
- cz = cos(radians(jo.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)
- a,b,c = jot.upper()
- exec "JO=A%s*A%s*A%s"%(a,b,c)
-
- WT = S*RA*R*IS*T
-
- # WT = S*RA*R*IS*T
- # WT = T
- WT = WT.transpose()
- args["transform"] = WT
-
- jnt = joint.Joint(radius = 0.5*node.getAttrValue("radius", "radi", "float", 1, 1.0),
- offsetTransform = JO.inverse(),
- **args)
- jnt.freezePivot()
- # Reset offset transform (so that pivot frame and local frame coincide)
- jnt.setOffsetTransform(mat4(1))
- self.newWorldObject(jnt, node.getName())
-
-
- def onNodeCamera(self, node):
- """Camera node.
- """
- args = self.fillWorldObjectArgs(node)
- self.getCameraArgs(node, args)
- args["transform"] = args["transform"]*mat4(1).rotation(pi, vec3(0,1,0))
- cam = freecamera.FreeCamera(**args)
- self.newWorldObject(cam, node.getParentName())
-
- def onNodeMesh(self, node):
- args = self.fillWorldObjectArgs(node)
- parentnode = node.getParent()
-
- # 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
- verts = node.getAttrValue("vrts", "vt", "float3", None, [])
- edges = node.getAttrValue("edge", "ed", "long3", None, [])
- faces = node.getAttrValue("face", "fc", "polyFaces", None, [])
- polyobj = polyhedron.Polyhedron(verts=verts, **args)
- geom = polyobj.geom
- # Initialize the polygons...
- geom.setNumPolys(len(faces))
- valid_st = True
- for i, face in enumerate(faces):
- valid_st &= face.hasValidTexCoords()
- poly = []
- # Iterate over all "loop" (i.e. the outer loop and the holes)
- # and create the vertex id list for each loop
- for loop in [face.f]+face.h:
- p = []
- for e in loop:
- if e>=0:
- p.append(edges[e][0])
- else:
- p.append(edges[-e-1][1])
- poly.append(p)
- geom.setPoly(i, poly)
-
- # Set texture coordinates...
- uvset = node.getAttrValue("uvSet", "uvst", type=None, n=None)
- if uvset!=None:
- stlst = list(uvset[0].uvsp)
- if valid_st and len(stlst)>0:
- geom.newVariable("st", USER, FLOAT, 2, len(stlst))
- st = geom.slot("st")
- for i,stval in enumerate(stlst):
- st[i] = stval
- # Set the tex coord faces...
- geom.newVariable("stfaces", FACEVARYING, INT)
- stfaces = geom.slot("stfaces")
- i = 0
- for face in faces:
- for mulst in face.mu:
- for id in mulst[0][1]:
- stfaces[i] = id
- i+=1
-
- # Set colors...
- colattr = node.getAttrValue("colors", "clr", type="float4", n=None)
- if colattr!=None:
- collst = list(colattr)
- geom.newVariable("Cs", USER, COLOR, 1, len(collst))
- Cs = geom.slot("Cs")
- for i,Csval in enumerate(collst):
- Cs[i] = vec3(Csval[:3])
- # Set the color faces...
- geom.newVariable("Csfaces", FACEVARYING, INT)
- Csfaces = geom.slot("Csfaces")
- i = 0
- for face in faces:
- for fclst in face.fc:
- for id in fclst:
- Csfaces[i] = id
- i+=1
-
- # Apply vertex tweaks...
- pnts = node.getAttrValue("pnts", "pt", "float3", None, [])
- pnts = list(pnts)
- for i,v in enumerate(geom.verts):
- if i>=len(pnts):
- break
- p = pnts[i]
- if p!=None:
- if type(p)==list:
- p = p[0]
- v += vec3(p)
- geom.verts[i] = v
-
- # Convert the poly to a trimesh if it's a rigid body
- self.getRigidBodyArgs(parentnode, args)
- if args["dynamics"]:
- tm = trimeshgeom.TriMeshGeom()
- polyobj.geom.convert(tm)
- cmds.delete(polyobj)
- polyobj = trimesh.TriMesh(**args)
- polyobj.geom = tm
-
- self.newWorldObject(polyobj, node.getParentName())
- else:
- creator = self.findNode(n)
- meshtype = creator.nodetype
- # Sphere?
- if meshtype=="polySphere":
- self.createSphere(node, creator, args)
- # Cube?
- elif meshtype=="polyCube":
- self.createBox(node, creator, args)
- # Plane?
- elif meshtype=="polyPlane":
- self.createPlane(node, creator, args)
-
- def createSphere(self, mesh, creator, args):
- """Creates a true sphere from a polySphere node.
-
- mesh is the mesh node that takes its input from creator.
- creator is an import Node which must be of type polySphere.
- args is a dictionary that already contains the basic WorldObject
- arguments that can be passed to the constructor.
- """
- parentnode = mesh.getParent()
- nod,attr = parentnode.getOutAttr("worldMatrix", "wm", "rigidBody")
- dynamics = (nod!=None)
- r = creator.getAttrValue("radius", "r", "float", 1, 1.0)
- segsu = creator.getAttrValue("subdivisionAxis", "sa", "int", 1, 20)
- segsv = creator.getAttrValue("subdivisionHeight", "sh", "int", 1, 20)
- ax = vec3(creator.getAttrValue("axis", "ax", "double3", 1, 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)
- s = quadrics.Sphere(radius=r,
- segmentsu=segsu, segmentsv=segsv,
- **args)
- self.newWorldObject(s, parentnode.getName())
-
- def createBox(self, mesh, creator, args):
- """Creates a true box from a polyCube node.
-
- mesh is the mesh node that takes its input from creator.
- creator is an import Node which must be of type polyCube.
- args is a dictionary that already contains the basic WorldObject
- arguments that can be passed to the constructor.
- """
- parentnode = mesh.getParent()
- w = creator.getAttrValue("width", "w", "float", 1, 1.0)
- h = creator.getAttrValue("height", "h", "float", 1, 1.0)
- d = creator.getAttrValue("depth", "d", "float", 1, 1.0)
- sw = creator.getAttrValue("subdivisionWidth", "sw", "int", 1, 1)
- sh = creator.getAttrValue("subdivisionHeight", "sh", "int", 1, 1)
- sd = creator.getAttrValue("subdivisionDepth", "sd", "int", 1, 1)
- ax = vec3(creator.getAttrValue("axis", "ax", "double3", 1, vec3(0,1,0)))
-
- # "Rename" width/height/depth to match the axis setting...
- if ax==vec3(1,0,0):
- tmp = d
- d = w
- w = h
- h = tmp
- tmp = sd
- sd = sw
- sw = sh
- sh = tmp
- elif ax==vec3(0,1,0):
- tmp = d
- d = h
- h = tmp
- tmp = sd
- sd = sh
- sh = tmp
-
- self.getRigidBodyArgs(parentnode, args)
- b = box.Box(lx=w, ly=d, lz=h,
- segmentsx=sw, segmentsy=sd, segmentsz=sh,
- **args)
- self.newWorldObject(b, parentnode.getName())
-
- def createPlane(self, mesh, creator, args):
- """Creates a true plane from a polyPlane node.
-
- mesh is the mesh node that takes its input from creator.
- creator is an import Node which must be of type polyPlane.
- args is a dictionary that already contains the basic WorldObject
- arguments that can be passed to the constructor.
- """
- parentnode = mesh.getParent()
- w = creator.getAttrValue("width", "w", "float", 1, 1.0)
- h = creator.getAttrValue("height", "h", "float", 1, 1.0)
- sw = creator.getAttrValue("subdivisionWidth", "sw", "int", 1, 1)
- sh = creator.getAttrValue("subdivisionHeight", "sh", "int", 1, 1)
- ax = vec3(creator.getAttrValue("axis", "ax", "double3", 1, vec3(0,1,0)))
-
- if ax!=vec3(0,0,1):
- print "WARNING: Plane %s ignored because axis!=z"%node.getName()
- return
-
- # args["transform"] *= self.axisToTransform(ax)
- self.getRigidBodyArgs(parentnode, args)
- if "static" in args:
- del args["static"]
- p = plane.Plane(lx=w, ly=h,
- segmentsx=sw, segmentsy=sh,
- **args)
- self.newWorldObject(p, parentnode.getName())
-
-
- 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.getAttrValue("mass", "mas", "float", 1, 1.0)
- res["static"] = not rbnode.getAttrValue("active", "act", "bool", 1, 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:
-
- def newWorldObject(self, obj, mayanodename):
- """Notify about the creation of a new world object.
-
- This method has to be called whenever a new WorldObject is created.
- This is needed to later find the object when it is used as parent.
- """
- if mayanodename in self.worldobjects:
- print "WARNING: Duplicate node name '%s'"%mayanodename
-
- self.worldobjects[mayanodename] = obj
-
- # 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.getAttrValue("focalLength", "fl", "float", 1, 35.0)
- res["focallength"] = fl
- cap = node.getAttrValue("cameraAperture", "cap", "double2", 1, (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.getAttrValue("fStop", "fs", "float", 1, 5.6)
- return res
-
- # fillWorldObjectArgs
- def fillWorldObjectArgs(self, node, args=None):
- """Fill the argument dict for the WorldObject constructor.
-
- node must be a Node object containing either the transform node
- or the shape node (whose parent must then be a transform node).
- args must be a dictionary which is filled with the arguments
- for a WorldObject constructor. It can also be None in which case
- a new dictionary is created and returned.
- The following attributes are written into args:
-
- - name: The name of the transform node
- - parent: The parent WorldObject (or self.root_parent)
- - transform: The transform matrix (pos rot may come from a rigidBody node)
-
- The return value is the args dictionary or the newly created dict.
- """
- # Obtain the transform node -> tnode
- if node.nodetype in ["transform", "joint"]:
- tnode = node
- else:
- tnode = node.getParent()
- if tnode==None or tnode.nodetype!="transform":
- raise ValueError, "transform node not found for node %s."%node.getFullName()
-
- if args==None:
- args = {}
-
- # Name
- args["name"] = tnode.getName()
-
- # Parent
- parentnode = tnode.getParent()
- if parentnode!=None:
- parentname = parentnode.getFullName()
- if parentname!=None:
- parent = self.worldobjects.get(parentname, None)
- if parent==None:
- print "WARNING: Parent '%s' not found."%parentname
- parent = self.root_parent
- else:
- parent = self.root_parent
- args["parent"] = parent
-
- # Check if the world matrix is connected to a rigid body.
- # In this case, the rigid body stores the initial position and
- # orientation
- rbnode,attr = tnode.getOutAttr("worldMatrix", "wm", "rigidBody")
-
- # Compute transform
- if rbnode==None:
- t = vec3(tnode.getAttrValue("translate", "t", "double3", 1, vec3(0)))
- r = vec3(tnode.getAttrValue("rotate", "r", "double3", 1, vec3(0)))
- else:
- t = vec3(rbnode.getAttrValue("initialPosition", "ip", "double3", 1, vec3(0)))
- r = vec3(rbnode.getAttrValue("initialOrientation", "ior", "double3", 1, vec3(0)))
- s = vec3(tnode.getAttrValue("scale", "s", "double3", 1, vec3(1)))
- sp = vec3(tnode.getAttrValue("scalePivot", "sp", "double3", 1, vec3(0)))
- spt = vec3(tnode.getAttrValue("scalePivotTranslate", "spt", "double3", 1, vec3(0)))
- sh = vec3(tnode.getAttrValue("shear", "sh", "double3", 1, vec3(0)))
- rp = vec3(tnode.getAttrValue("rotatePivot", "rp", "double3", 1, vec3(0)))
- rpt = vec3(tnode.getAttrValue("rotatePivotTranslate", "rpt", "double3", 1, vec3(0)))
- ra = vec3(tnode.getAttrValue("rotateAxis", "ra", "double3", 1, vec3(0)))
- roi = tnode.getAttrValue("rotationInterpolation", "roi", "int", 1, 1)
- ro = tnode.getAttrValue("rotateOrder", "ro", "int", 1, default=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()
- args["transform"] = WT
-
- # Visibility
- args["visible"] = tnode.getAttrValue("visibility", "v", "bool", 1, True)
-
- return args
-
-
- ######################################################################
-
- # Register the importer class as a plugin class
- pluginmanager.register(MAImporter)
-