maimport.py :  » Game-2D-3D » CGKit » cgkit-2.0.0alpha9 » cgkit » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Game 2D 3D » CGKit 
CGKit » cgkit 2.0.0alpha9 » cgkit » maimport.py
# ***** 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))
        filmFit = node.getAttrValue("filmFit", "ff", "int", 1, 1)

        xfov = degrees(2*atan((cap[0]*25.4)/(2*fl)))
        yfov = degrees(2*atan((cap[1]*25.4)/(2*fl)))
        
        # Horizontal
        if filmFit==1:
            # Convert the FOV from horizontal to vertical direction
            # (Todo: What aspect ratio to use?)
            yfov = degrees(atan(480/640.0*tan(radians(xfov/2.0))))*2.0
            yfov = xfov
        # Vertical
        elif filmFit==2:
            pass
        # Fill and overscan not supported yet
        else:
            pass
        
        res["fov"] = yfov
        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)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.