• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/blender/rvg.py

Go to the documentation of this file.
00001 #!BPY
00002 
00003 """
00004 Name: 'Geometry (.rvl)...'
00005 Blender: 249
00006 Group: 'Export'
00007 Tip: 'Export the current scene to the level format'
00008 """
00009 
00010 __author__ = "Michael Hecher"
00011 __version__ = "01"
00012 
00013 import Blender as bl
00014 import Blender.Mathutils as blmath
00015 import BPyMessages as BMsg
00016 import struct
00017 import math
00018 import time
00019 from time import localtime, strftime
00020         
00021 fps = 1
00022 smoothDegree = 0.5
00023 uvEpsilon = 0.00001
00024 vertexEpsilon = 0.00001
00025 vertexTransf = blmath.Matrix([1,0,0],[0,0,1],[0,-1,0])
00026 normalTransf = blmath.Matrix(vertexTransf)
00027 normalTransf.invert().transpose()
00028 
00029 ## compute center of object
00030 #################################################################
00031 def computeCenter(object):
00032         bbox = object.getBoundBox()
00033         min = bbox[0]
00034         max = bbox[0]
00035         for point in bbox:
00036                 if point.x < min.x or point.y < min.y or point.z < min.z:
00037                         min = point
00038                 if point.x > max.x or point.y > max.y or point.z > max.z:
00039                         max = point
00040         return blmath.Vector(min*0.5 + max*0.5)
00041                 
00042 ## compute bounding box size
00043 #################################################################
00044 def computeBBox(object):
00045         mat = blmath.Matrix(object.mat)
00046         object.mat.identity()
00047         bbox = object.getBoundBox()
00048         min = blmath.Vector(bbox[0])
00049         max = blmath.Vector(min)
00050         for point in bbox:
00051                 if point.x < min.x:
00052                         min.x = point.x
00053                 if point.y < min.y:
00054                         min.y = point.y
00055                 if point.z < min.z:
00056                         min.z = point.z
00057                 if point.x > max.x:
00058                         max.x = point.x
00059                 if point.y > max.y:
00060                         max.y = point.y
00061                 if point.z > max.z:
00062                         max.z = point.z
00063         object.setMatrix(mat)
00064         return [max.x - min.x, max.y - min.y, max.z - min.z]
00065 
00066 ## Quaternion Class
00067 #################################################################
00068 class quat:
00069         __slots__ = "w","x","y","z"
00070         def __init__(self):
00071                 self.w = 1.0
00072                 self.x = 0.0
00073                 self.y = 0.0
00074                 self.z = 0.0
00075                 
00076         def __print__(self, file):
00077                 file.write("["+self.w+","+self.x+","+self.y+","+self.z+"]")
00078         
00079         def set(self, w, x, y, z):
00080                 self.w = w
00081                 self.x = x
00082                 self.y = y
00083                 self.z = z
00084         
00085         def save(self, outFile):
00086                 outFile.writeFloat(self.w)
00087                 outFile.writeFloat(self.x)
00088                 outFile.writeFloat(self.y)
00089                 outFile.writeFloat(self.z)
00090 
00091         def mul(self, b):
00092                 rs = quat()
00093                 rs.w = self.w*b.w - self.x*b.x - self.y*b.y - self.z*b.z
00094                 rs.x = self.w*b.x + self.x*b.w + self.y*b.z - self.z*b.y
00095                 rs.y = self.w*b.y - self.x*b.z + self.y*b.w + self.z*b.x
00096                 rs.z = self.w*b.z + self.x*b.y - self.y*b.x + self.z*b.w
00097                 return rs
00098         
00099         def transform(self, p):
00100                 W = -self.x*p[0] - self.y*p[1] - self.z*p[2]
00101                 X =  self.w*p[0] - self.z*p[1] + self.y*p[2]
00102                 Y =  self.z*p[0] + self.w*p[1] - self.x*p[2]
00103                 Z = -self.y*p[0] + self.x*p[1] + self.w*p[2]
00104                 n = 1.0/math.sqrt(self.w*self.w + self.x*self.x + self.y*self.y + self.z*self.z)
00105                 r = [0.0,0.0,0.0]
00106                 r[0] = (X*self.w - W*self.x + Z*self.y - Y*self.z)*n
00107                 r[1] = (Y*self.w - Z*self.x - W*self.y + X*self.z)*n
00108                 r[2] = (Z*self.w + Y*self.x - X*self.y - W*self.z)*n
00109                 return r
00110                 
00111         def debug(self, str):
00112                 print str,"[",self.w,self.x,self.y,self.z,"]"
00113 
00114 ## Dual Quaternion Class
00115 #################################################################
00116 class dualQuat:
00117         __slots__ = "real","dual"
00118         
00119         def __init__(self):
00120                 self.real = quat()
00121                 self.dual = quat()
00122                 
00123         def __print__(self, file):
00124                 file.write("["+self.real+","+self.dual+"]")
00125         
00126         def set(self, q, p):
00127                 self.real.w = q.w
00128                 self.real.x = q.x
00129                 self.real.y = q.y
00130                 self.real.z = q.z
00131                 self.dual.w = -0.5 * ( p[0] * q.x + p[1] * q.y + p[2] * q.z)
00132                 self.dual.x =  0.5 * ( p[0] * q.w + p[1] * q.z - p[2] * q.y)
00133                 self.dual.y =  0.5 * (-p[0] * q.z + p[1] * q.w + p[2] * q.x)
00134                 self.dual.z =  0.5 * ( p[0] * q.y - p[1] * q.x + p[2] * q.w)
00135         
00136         def transform(self, p):
00137                 point = [0.0, 0.0, 0.0]
00138                 W = -self.real.x*p[0] - self.real.y*p[1] - self.real.z*p[2];
00139                 X =  self.real.w*p[0] - self.real.z*p[1] + self.real.y*p[2];
00140                 Y =  self.real.z*p[0] + self.real.w*p[1] - self.real.x*p[2];
00141                 Z = -self.real.y*p[0] + self.real.x*p[1] + self.real.w*p[2];
00142                 point[0]  = X*self.real.w - W*self.real.x + Z*self.real.y - Y*self.real.z;
00143                 point[1]  = Y*self.real.w - Z*self.real.x - W*self.real.y + X*self.real.z;
00144                 point[2]  = Z*self.real.w + Y*self.real.x - X*self.real.y - W*self.real.z;
00145                 point[0] += 2.0*(-self.dual.w*self.real.x + self.dual.x*self.real.w - self.dual.y*self.real.z + self.dual.z*self.real.y);
00146                 point[1] += 2.0*(-self.dual.w*self.real.y + self.dual.x*self.real.z + self.dual.y*self.real.w - self.dual.z*self.real.x);
00147                 point[2] += 2.0*(-self.dual.w*self.real.z - self.dual.x*self.real.y + self.dual.y*self.real.x + self.dual.z*self.real.w);
00148                 invsqrt = 1.0/math.sqrt(self.real.w*self.real.w + self.real.x*self.real.x + self.real.y*self.real.y + self.real.z*self.real.z)
00149                 point[0] *= invsqrt
00150                 point[1] *= invsqrt
00151                 point[2] *= invsqrt
00152                 return point
00153         
00154         def save(self, outFile):
00155                 self.real.save(outFile)
00156                 self.dual.save(outFile)
00157         
00158         def debug(self, str):
00159                 print str,"[",self.real.w,self.real.x,self.real.y,self.real.z,",",self.dual.w,self.dual.x,self.dual.y,self.dual.z,"]"
00160 
00161 ## Bone Class
00162 #################################################################
00163 class Bone:
00164         __slots__ = "name","parent","keys","quat","pos","DQ","kids"
00165         
00166         def __init__(self, name, parent):
00167                 self.name = name
00168                 self.parent = parent
00169                 self.keys = []
00170                 self.quat = []
00171                 self.pos = []
00172                 self.DQ = []
00173                 self.kids = 0
00174         
00175         # Add key frame to bone
00176         def addKey(self, k, q, p):
00177                 rot = quat()
00178                 rot.set(q.w, q.x, q.y, q.z)
00179                 self.keys.append(k)
00180                 self.quat.append(rot)
00181                 self.pos.append([p[0], p[1], p[2]])
00182                 self.DQ.append(dualQuat())
00183 
00184         # Compute dual quaternion for keyframe
00185         def computeDQ(self, k, pDQ):
00186                 # absolute rotation
00187                 pRot = pDQ.real.mul(self.quat[k])
00188                 # position when rotating with absolute rotation
00189                 A = pRot.transform(self.pos[0])
00190                 # needed position in the keyframe
00191                 B = self.pos[k]
00192                 # store delta rot and pos as dual quaternion
00193                 self.DQ[k].set(pRot, [B[0]-A[0], B[1]-A[1], B[2]-A[2]])
00194         
00195         def debug(self,str):
00196                 print str,"Bone ", self.name
00197                 print str,"    Key Frames:", self.keys
00198                 print str,"    Key Times:", [(frame-1)/float(fps) for frame in self.keys]
00199                 print str,"    Kids:", self.kids
00200                 print str,"    Parent:", self.parent
00201                 print str,"    dRot:"
00202                 for q in self.quat:
00203                         q.debug(str+"        ")
00204                 print str,"    dPos:"
00205                 for p in self.pos:
00206                         print str,"       ",p
00207                 print str,"    dDualQuat:"
00208                 for q in self.DQ:
00209                         q.debug(str+"        ")
00210                 
00211 
00212 ## Armature Class
00213 #################################################################
00214 class Armature:
00215         __slots__ = "bones","keys"
00216         
00217         def __init__(self, object = None):
00218                 curFrame = bl.Get("curframe")
00219                 startFrame = bl.Get("staframe")
00220                 bl.Set("curframe",startFrame)
00221                 self.bones = []
00222                 self.keys = []
00223                 if object == None: return
00224                 action = object.getAction()
00225                 self.keys = [frame for frame in action.getFrameNumbers()]
00226                 bones = object.getPose().bones.values()
00227                 # iterate through bones
00228                 for bone in bones:
00229                         parentName = None
00230                         if bone.parent:
00231                                 parentName = bone.parent.name
00232                         b = Bone(bone.name, parentName)
00233                         # iterate through key frame marks
00234                         for key in self.keys:
00235                                 bl.Set("curframe",key)
00236                                 b.addKey(key, bone.quat, [object.loc[0]+bone.head.x, object.loc[1]+bone.head.y, object.loc[2]+bone.head.z])
00237                         self.bones.append(b)
00238                 bl.Set("curframe",curFrame)
00239                 # sort the list of bones
00240                 self.sort()
00241                 # compute dual quaternions
00242                 self.computeDQs()
00243         
00244         def getBoneID(self, boneName):
00245                 for i in range(len(self.bones)):
00246                         if self.bones[i].name == boneName:
00247                                 return i
00248                 return 0
00249 
00250         # Compute dual quaternions
00251         def computeDQs(self):
00252                 numKeys = len(self.keys)
00253                 numBones = len(self.bones)
00254                 pDQ = dualQuat()
00255                 pDQ.set(quat(), [0.0,0.0,0.0])
00256                 for index in range(numBones):
00257                         bone = self.bones[index]
00258                         if bone.parent == None:
00259                                 for k in range(numKeys): bone.computeDQ(k, pDQ)
00260                                 index = self.computeChildDQ(index, bone)
00261 
00262         def computeChildDQ(self, index, parent):
00263                 numKids = self.bones[index].kids
00264                 numKeys = len(self.keys)
00265                 for kid in range(numKids):
00266                         index += 1
00267                         bone = self.bones[index]
00268                         for k in range(numKeys): bone.computeDQ(k, parent.DQ[k])
00269                         index = self.computeChildDQ(index, bone)
00270                         return index
00271         
00272         # Sort the bone array
00273         def sort(self):
00274                 # reset kid numbers
00275                 for b in self.bones:
00276                         b.kids = 0
00277                 # move root bones to the start
00278                 sorted = []
00279                 self.sortBoneList(self.bones, sorted, None, None)
00280                 self.bones = sorted
00281         
00282         # Function to sort a list of bones
00283         def sortBoneList(self, fromList, toList, parent, parentName):
00284                 for b in fromList:
00285                         if b.parent == parentName:
00286                                 if parent:
00287                                         parent.kids += 1
00288                                 toList.append(b)
00289                                 self.sortBoneList(fromList, toList, b, b.name)
00290         
00291         def save(self, outFile):
00292                 numBones = len(self.bones) if self.bones != None else 0
00293                 numKeys = len(self.keys) if self.keys != None else 0
00294                 
00295                 outFile.writeInt(numBones)
00296                 outFile.writeInt(numKeys)
00297                 if numBones > 0:
00298                         # number of children for each bone
00299                         for i in range(0,numBones):
00300                                 outFile.writeInt(self.bones[i].kids)
00301                         # for each key frame save the bone list
00302                         for i in range(0,numKeys):
00303                                 for j in range(0,numBones):
00304                                         self.bones[j].DQ[i].save(outFile)
00305                 if numKeys > 0:
00306                         # keys and time
00307                         for i in range(0,numKeys):
00308                                 outFile.writeInt(self.keys[i])
00309                                 outFile.writeFloat((self.keys[i]-1)/float(fps))
00310         
00311         def debug(self,str):
00312                 print str,"Armature"
00313                 for bone in self.bones:
00314                         bone.debug(str+"    ")
00315         
00316 ## Vertex Class
00317 #################################################################
00318 class Vertex:
00319         __slots__ = "baseNor","pos","nor","tan","bitan","color","uv","bones","weigths"
00320         
00321         def __init__(self, pos, color = None, uv = None):
00322                 self.baseNor = None
00323                 self.pos = pos
00324                 self.nor = blmath.Vector([0.0, 0.0, 0.0])
00325                 self.tan = blmath.Vector([0.0, 0.0, 0.0])
00326                 self.bitan = blmath.Vector([0.0, 0.0, 0.0])
00327                 self.color = color
00328                 self.uv = uv
00329                 self.bones = [0.0, 0.0, 0.0, 0.0]
00330                 self.weights = [0.0, 0.0, 0.0, 0.0]
00331                 
00332         def setColor(self, color):
00333                 self.color = [color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0]
00334         
00335         def setUV(self, uv):
00336                 self.uv = uv
00337         
00338         def setBones(self, bones):
00339                 self.bones = bones
00340         
00341         def setWeights(self, weights):
00342                 self.weights = weights
00343         
00344         def accumulateNormal(self, normal):
00345                 normal.normalize()
00346                 if self.baseNor == None:
00347                         self.baseNor = normal
00348                         self.baseNor.normalize()
00349                 self.nor += normal
00350         
00351         def accumulateTangents(self, uTangent, vTangent):
00352                 self.tan += uTangent
00353                 self.bitan += vTangent
00354         
00355         def normalize(self):
00356                 self.nor.normalize()
00357                 self.tan.normalize()
00358                 self.bitan.normalize()
00359         
00360         def equalPos(self, pos):
00361                 global vertexEpsilon
00362                 delta = self.pos - pos
00363                 return delta*delta < vertexEpsilon
00364         
00365         def equalNor(self, nor):
00366                 global smoothDegree
00367                 nor.normalize()
00368                 return self.baseNor * nor >= smoothDegree if self.baseNor != None else True
00369         
00370         def equalUV(self, uv):
00371                 global uvEpsilon
00372                 if self.uv != None and uv != None:
00373                         delta = self.uv - uv
00374                         return delta[0]*delta[0] + delta[1]*delta[1] < uvEpsilon
00375                 return True
00376         
00377         def equals(self, vertex, normal):
00378                 return self.equalPos(vertex.pos) and self.equalNor(normal) and self.equalUV(vertex.uv)
00379         
00380         def save(self, outFile):
00381                 global vertexTransf
00382                 global normalTransf
00383                 
00384                 self.normalize()
00385                 self.pos = vertexTransf * self.pos;
00386                 self.nor = normalTransf * self.nor;
00387                 self.tan = normalTransf * self.tan;
00388                 self.bitan = normalTransf * self.bitan;
00389                 
00390                 outFile.writeFloat(self.pos[0])
00391                 outFile.writeFloat(self.pos[1])
00392                 outFile.writeFloat(self.pos[2])
00393                 outFile.writeFloat(1.0)
00394                 
00395                 outFile.writeFloat(self.nor[0])
00396                 outFile.writeFloat(self.nor[1])
00397                 outFile.writeFloat(self.nor[2])
00398                 outFile.writeFloat(1.0)
00399                 
00400                 outFile.writeFloat(self.tan[0])
00401                 outFile.writeFloat(self.tan[1])
00402                 outFile.writeFloat(self.tan[2])
00403                 outFile.writeFloat(1.0)
00404                 
00405                 outFile.writeFloat(self.bitan[0])
00406                 outFile.writeFloat(self.bitan[1])
00407                 outFile.writeFloat(self.bitan[2])
00408                 outFile.writeFloat(1.0)
00409                 
00410                 if self.color != None:
00411                         outFile.writeFloat(self.color[0])
00412                         outFile.writeFloat(self.color[1])
00413                         outFile.writeFloat(self.color[2])
00414                         outFile.writeFloat(16.0)
00415                 else:
00416                         outFile.writeFloat(1.0)
00417                         outFile.writeFloat(1.0)
00418                         outFile.writeFloat(1.0)
00419                         outFile.writeFloat(16.0)
00420                 
00421                 if self.uv != None:
00422                         outFile.writeFloat(self.uv[0])
00423                         outFile.writeFloat(self.uv[1])
00424                 else:
00425                         outFile.writeFloat(0.0)
00426                         outFile.writeFloat(0.0)
00427                 outFile.writeFloat(0.0)
00428                 outFile.writeFloat(0.0)
00429         
00430                 numBones = len(self.bones)
00431                 outFile.writeFloat(self.bones[0] if 0<numBones else 0.0)
00432                 outFile.writeFloat(self.bones[1] if 1<numBones else 0.0)
00433                 outFile.writeFloat(self.bones[2] if 2<numBones else 0.0)
00434                 outFile.writeFloat(self.bones[3] if 3<numBones else 0.0)
00435                 
00436                 outFile.writeFloat(self.weights[0] if 0<numBones else 0.0)
00437                 outFile.writeFloat(self.weights[1] if 1<numBones else 0.0)
00438                 outFile.writeFloat(self.weights[2] if 2<numBones else 0.0)
00439                 outFile.writeFloat(self.weights[3] if 3<numBones else 0.0)
00440                 return
00441         
00442         def debug(self, str):
00443                 global vertexTransf
00444                 global normalTransf
00445                 
00446                 self.normalize()
00447                 self.pos = vertexTransf * self.pos;
00448                 self.nor = normalTransf * self.nor;
00449                 self.tan = normalTransf * self.tan;
00450                 self.bitan = normalTransf * self.bitan;
00451                 
00452                 print str,"---p",self.pos
00453                 print str,"   n",self.nor
00454                 print str,"   t",self.tan
00455                 print str,"  bt",self.bitan
00456                 print str,"   c",self.color
00457                 print str,"  uv",self.uv
00458                 print str,"   b",self.bones
00459                 print str,"   w",self.weights
00460 
00461 ## Vertices Class
00462 #################################################################
00463 class Vertices:
00464         __slots__ = "blMesh","armature","data"
00465         
00466         def __init__(self, blMesh, armature):
00467                 self.blMesh = blMesh
00468                 self.armature = armature
00469                 self.data = []
00470                 # prefill vertex array with position
00471                 # data, so the vertices can be compared
00472                 # in the addFaceVertex method
00473                 for vertex in blMesh.verts:
00474                         self.data.append(Vertex(vertex.co))
00475                 return
00476         
00477         def addFaceVertex(self, vertex, normal, uTangent, vTangent, uv, color):
00478                 index = -1
00479                 bones = [0.0, 0.0, 0.0, 0.0]
00480                 weights = [0.0, 0.0, 0.0, 0.0]
00481                 influences = self.blMesh.getVertexInfluences(vertex.index)
00482                 if influences != None:
00483                         bones = [self.armature.getBoneID(influence[0]) for influence in influences]
00484                         weights = [influence[1] for influence in influences]
00485                 
00486                 foundVertex = Vertex(vertex.co, color, uv)
00487                 
00488                 # is vertex already in list
00489                 # look at the same index
00490                 if self.data[vertex.index].equals(foundVertex, normal) == True:
00491                         foundVertex = self.data[vertex.index]
00492                         index = vertex.index
00493                 # look in the whole array
00494                 if index == -1:
00495                         for i in range(len(self.blMesh.verts), len(self.data)):
00496                                 if self.data[i].equals(foundVertex, normal) == True:
00497                                         foundVertex = self.data[i]
00498                                         index = i
00499                                         break
00500                 
00501                 foundVertex.accumulateNormal(normal)
00502                 foundVertex.accumulateTangents(uTangent, vTangent)
00503                 foundVertex.setUV(uv)
00504                 foundVertex.setColor(color)
00505                 foundVertex.setBones(bones)
00506                 foundVertex.setWeights(weights)
00507                 
00508                 # new vertex
00509                 if index == -1:
00510                         index = len(self.data)
00511                         self.data.append(foundVertex)
00512                 
00513                 return index
00514         
00515         def center(self):
00516                 min = blmath.Vector(self.data[0].pos)
00517                 max = blmath.Vector(self.data[0].pos)
00518                 for vertex in self.data:
00519                         if vertex.pos.x < min.x:
00520                                 min.x = vertex.pos.x
00521                         elif vertex.pos.x > max.x:
00522                                 max.x = vertex.pos.x
00523                         if vertex.pos.y < min.y:
00524                                 min.y = vertex.pos.y
00525                         elif vertex.pos.y > max.y:
00526                                 max.y = vertex.pos.y
00527                         if vertex.pos.z < min.z:
00528                                 min.z = vertex.pos.z
00529                         elif vertex.pos.z > max.z:
00530                                 max.z = vertex.pos.z
00531                 c = min + (max-min)*0.5
00532                 print c
00533                 for vertex in self.data:
00534                         vertex.pos -= c
00535         
00536         def getVertexSize(self):
00537                 return 16+16+16+16+16+16+16+16
00538         
00539         def getVertexCount(self):
00540                 return len(self.data)
00541         
00542         def save(self, outFile):
00543                 for vertex in self.data:
00544                         vertex.save(outFile)
00545         
00546         def debug(self, str):
00547                 print str,"Vertices(",len(self.data),")"
00548 
00549 ## Indices Class
00550 #################################################################
00551 class Indices:
00552         __slots__ = "blMesh","data"
00553         
00554         def __init__(self, blMesh, vertices):
00555                 self.blMesh = blMesh
00556                 self.data = []
00557                 for face in blMesh.faces:
00558                         self.addFace(face, vertices)
00559         
00560         def addFace(self, face, vertices):
00561                 numVerts = len(face.verts)
00562                 uvs    = [blmath.Vector([0.0, 0.0]),blmath.Vector([0.0, 0.0]),blmath.Vector([0.0, 0.0]),blmath.Vector([0.0, 0.0])]
00563                 colors = [[255.0, 255.0, 255.0, 255.0], [255.0, 255.0, 255.0, 255.0], [255.0, 255.0, 255.0, 255.0], [255.0, 255.0, 255.0, 255.0]]
00564                 index  = [None, None, None, None]
00565                 uTangent = blmath.Vector([0.0, 0.0, 1.0])
00566                 vTangent = blmath.Vector([0.0, 0.0, 1.0])
00567                 
00568                 if self.blMesh.vertexColors:
00569                         for i in range(0,numVerts):
00570                                 colors[i] = face.col[i]
00571                 if self.blMesh.faceUV:
00572                         for i in range(0,numVerts):
00573                                 uvs[i] = face.uv[i]
00574                         uTangent, vTangent = self.computeTangent(face.verts[0].co, face.verts[1].co, face.verts[2].co, uvs[0], uvs[1], uvs[2])
00575                 
00576                 normal = blmath.CrossVecs(face.verts[2].co - face.verts[1].co, face.verts[0].co - face.verts[1].co)
00577                 index[0] = vertices.addFaceVertex(face.verts[0], normal, uTangent, vTangent, uvs[0], colors[0])
00578                 index[1] = vertices.addFaceVertex(face.verts[1], normal, uTangent, vTangent, uvs[1], colors[1])
00579                 index[2] = vertices.addFaceVertex(face.verts[2], normal, uTangent, vTangent, uvs[2], colors[2])
00580                 self.addIndex(index[0])
00581                 self.addIndex(index[1])
00582                 self.addIndex(index[2])
00583                 
00584                 if numVerts >= 4:
00585                         normal = blmath.CrossVecs(face.verts[0].co - face.verts[3].co, face.verts[2].co - face.verts[3].co)
00586                         index[3] = vertices.addFaceVertex(face.verts[3], normal, uTangent, vTangent, uvs[3], colors[3])
00587                         self.addIndex(index[0])
00588                         self.addIndex(index[2])
00589                         self.addIndex(index[3])
00590                         
00591         def computeTangent(self, v0, v1, v2, uv0, uv1, uv2):
00592                 d1 = v1 - v0
00593                 d2 = v2 - v0
00594                 
00595                 t1 = uv1 - uv0
00596                 t2 = uv2 - uv0
00597                 t = t1[0] * t2[1] - t2[0] * t1[1]
00598                 
00599                 r = 1.0 / (t1[0] * t2[1] - t2[0] * t1[1]) if t != 0.0 else 0.0
00600                 uTangent = blmath.Vector([(t2[1] * d1.x - t1[1] * d2.x) * r, (t2[1] * d1.y - t1[1] * d2.y) * r, (t2[1] * d1.z - t1[1] * d2.z) * r])
00601                 vTangent = blmath.Vector([(t1[0] * d2.x - t2[0] * d1.x) * r, (t1[0] * d2.y - t2[0] * d1.y) * r, (t1[0] * d2.z - t2[0] * d1.z) * r])
00602                 
00603                 return uTangent, vTangent
00604         
00605         def addIndex(self, index):
00606                 self.data.append(index)
00607         
00608         def getIndexCount(self):
00609                 return len(self.data)
00610         
00611         def save(self, outFile):
00612                 for i in self.data:
00613                         outFile.writeUShort(i)
00614         
00615         def debug(self, str):
00616                 print str,"Indices(",len(self.data),")"
00617                 #for i in range(0, len(self.data), 3):
00618                 #       print str,"    ",self.data[i],",",self.data[i+1],",",self.data[i+2]
00619 
00620 ## Mesh Class
00621 #################################################################
00622 class Mesh:
00623         __slots__ = "name","blMesh","vData","iData","aData"
00624         
00625         def __init__(self, object):
00626                 self.blMesh = object.getData(False, True)
00627                 self.name = self.blMesh.name
00628                 if object.parent and object.parent.type == "Armature" and object.parent.getPose() and object.parent.getAction():
00629                         self.aData = Armature(object.parent)
00630                 else:
00631                         self.aData = Armature()
00632                 center = computeCenter(object)
00633                 self.vData = Vertices(self.blMesh, self.aData)
00634                 self.iData = Indices(self.blMesh, self.vData)
00635                 #self.vData.center()
00636         
00637         def getName(self):
00638                 return self.name
00639         
00640         def save(self, outFile):
00641                 # data header
00642                 outFile.writeInt(self.vData.getVertexSize())
00643                 outFile.writeInt(self.vData.getVertexCount())
00644                 outFile.writeInt(self.iData.getIndexCount())
00645                 outFile.writeExpand(self.name, 32);
00646                 # data
00647                 self.vData.save(outFile)
00648                 self.iData.save(outFile)
00649                 #self.aData.save(outFile)
00650         
00651         def debug(self, str):
00652                 print str,"Mesh(",self.name,")"
00653                 self.vData.debug(str+"    ")
00654                 self.iData.debug(str+"    ")
00655                 self.aData.debug(str+"    ")
00656 
00657 ## Meshes Class
00658 #################################################################
00659 class Meshes:
00660         __slots__ = "meshes"
00661         
00662         def __init__(self, scene):
00663                 global fps
00664                 fps = scene.getRenderingContext().fps
00665                 self.meshes = []
00666                 
00667                 for object in scene.objects:
00668                         if object.type != "Mesh":
00669                                 continue
00670                         meshData = object.getData(False, True)
00671                         if self.getMeshID(meshData.name) >= 0:
00672                                 continue
00673                         curFrame = bl.Get("curframe")
00674                         mesh = Mesh(object)
00675                         bl.Set("curframe",curFrame)
00676                         self.meshes.append(mesh)
00677         
00678         def getMeshID(self, name):
00679                 for i in range(len(self.meshes)):
00680                         if name == self.meshes[i].getName():
00681                                 return i
00682                 return -1
00683         
00684         def getNumMeshes(self):
00685                 return len(self.meshes)
00686         
00687         def save(self, outFile):
00688                 for mesh in self.meshes:
00689                         mesh.save(outFile)
00690                 
00691         def debug(self, str):
00692                 print str,"Meshes"
00693                 for mesh in self.meshes:
00694                         mesh.debug(str+"   ")
00695 
00696 ## Material Class
00697 #################################################################
00698 class Material:
00699         __slots__ = "name","color","normal","height"
00700         
00701         def __init__(self, material):
00702                 self.name = material.name
00703                 self.color = ""
00704                 self.normal = ""
00705                 self.height = ""
00706                 textures = material.getTextures()
00707                 for tex in textures:
00708                         if tex == None:
00709                                 continue
00710                         if tex.mapto == bl.Texture.MapTo.COL:
00711                                 self.color = tex.tex.name
00712                         elif tex.mapto == bl.Texture.MapTo.NOR:
00713                                 self.normal = tex.tex.name
00714                         elif tex.mapto == bl.Texture.MapTo.CSP:
00715                                 self.height = tex.tex.name
00716         
00717         def getName(self):
00718                 return self.name
00719         
00720         def save(self, outFile):
00721                 outFile.writeExpand(self.color, 32)
00722                 outFile.writeExpand(self.normal, 32)
00723                 outFile.writeExpand(self.height, 32)
00724                 
00725         def debug(self, str):
00726                 print str,"Material(",self.name,")"
00727                 print str,"    ",self.color
00728                 print str,"    ",self.normal
00729                 print str,"    ",self.height
00730 
00731 ## Materials Class
00732 #################################################################
00733 class Materials:
00734         __slots__ = "materials"
00735         
00736         def __init__(self, scene):
00737                 self.materials = []
00738                 materials = bl.Material.Get()
00739                 for material in materials:
00740                         self.materials.append(Material(material))
00741                         
00742         def getMaterialID(self, name):
00743                 for i in range(len(self.materials)):
00744                         if self.materials[i].getName() == name:
00745                                 return i
00746                 return -1
00747         
00748         def getNumMaterials(self):
00749                 return len(self.materials)
00750         
00751         def save(self, outFile):
00752                 for material in self.materials:
00753                         material.save(outFile)
00754                 
00755         def debug(self, str):
00756                 print str,"Materials"
00757                 for material in self.materials:
00758                         material.debug(str+"    ")
00759 
00760 ## Body Class
00761 #################################################################
00762 class Body:
00763         name = None
00764         phBody = 0
00765         phType = 0
00766         pos = None
00767         rot = None
00768         width = 0.0
00769         height = 0.0
00770         depth = 0.0
00771         phDensity = 1.0
00772         phMaterial = 0
00773         phGroup = 0
00774         textureID = -1
00775         geometryID = -1
00776         
00777         def __init__(self, object, meshes, materials):
00778                 self.name = object.name
00779                 self.pos = blmath.Vector(object.loc)
00780                 self.rot = blmath.Vector(object.rot)
00781                 [self.width, self.height, self.depth] = computeBBox(object)
00782                 
00783                 properties = object.getAllProperties()
00784                 for prop in properties:
00785                         if prop.name == "dummy":
00786                                 self.phBody = 0
00787                         elif prop.name == "sphere":
00788                                 self.phBody = 1
00789                         elif prop.name == "box":
00790                                 self.phBody = 2
00791                         elif prop.name == "mesh":
00792                                 self.phBody = 3
00793                         elif prop.name == "density":
00794                                 self.phDensity = prop.data
00795                         elif prop.name == "static":
00796                                 self.phType = 0
00797                         elif prop.name == "dynamic":
00798                                 self.phType = 1
00799                         elif prop.name == "extern":
00800                                 self.phType = 2
00801                         elif prop.name == "group":
00802                                 self.phGroup = prop.data
00803                         elif prop.name == "material":
00804                                 self.phMaterial = prop.data
00805                                 
00806                 meshData = object.getData(False, True)
00807                 self.geometryID = meshes.getMeshID(meshData.name)
00808                 
00809                 mats = meshData.materials
00810                 if len(mats) > 0 and mats[0] != None:
00811                         self.textureID = materials.getMaterialID(mats[0].name)
00812         
00813         def save(self, outFile):
00814                 global vertexTransf
00815                 global normalTransf
00816                 self.pos = vertexTransf * self.pos;
00817                 self.rot = normalTransf * self.rot;
00818                 
00819                 outFile.writeUInt(self.phBody)
00820                 outFile.writeUInt(self.phType)
00821                 outFile.writeFloat(self.pos[0])
00822                 outFile.writeFloat(self.pos[1])
00823                 outFile.writeFloat(self.pos[2])
00824                 outFile.writeFloat(-self.rot[0])
00825                 outFile.writeFloat(-self.rot[1])
00826                 outFile.writeFloat(-self.rot[2])
00827                 outFile.writeFloat(self.width)
00828                 outFile.writeFloat(self.depth)
00829                 outFile.writeFloat(self.height)
00830                 outFile.writeFloat(self.phDensity)
00831                 outFile.writeInt(self.phGroup)
00832                 outFile.writeInt(self.phMaterial)
00833                 outFile.writeInt(self.textureID)
00834                 outFile.writeInt(self.geometryID)
00835         
00836         def debug(self, str):
00837                 global vertexTransf
00838                 global normalTransf
00839                 self.pos = vertexTransf * self.pos;
00840                 self.rot = vertexTransf * self.rot;
00841                 print str,"Body(tex",self.textureID,"mesh",self.geometryID,"body",self.phBody,")",self.name
00842                 print str,"    ",self.pos
00843                 print str,"    ",self.rot
00844                 print str,"    ",self.width,self.height,self.depth
00845 
00846 ## Bodies Class
00847 #################################################################
00848 class Bodies:
00849         __slots__ = "bodies"
00850         
00851         def __init__(self, scene, meshes, materials):
00852                 self.bodies = []
00853                 
00854                 for object in scene.objects:
00855                         if object.type != "Mesh":
00856                                 continue
00857                         self.bodies.append(Body(object, meshes, materials))
00858         
00859         def getNumBodies(self):
00860                 return len(self.bodies)
00861         
00862         def save(self, outFile):
00863                 for body in self.bodies:
00864                         body.save(outFile)
00865                 
00866         def debug(self, str):
00867                 print str,"Bodies"
00868                 for body in self.bodies:
00869                         body.debug(str+"    ")
00870 
00871 ## Emptie Class
00872 #################################################################
00873 class Empty:
00874         name = None
00875         pos = None
00876         type = -1
00877         item = -1
00878         value = 0
00879         
00880         def __init__(self, object):
00881                 self.name = object.name
00882                 self.pos = blmath.Vector(object.loc)
00883                 
00884                 properties = object.getAllProperties()
00885                 for prop in properties:
00886                         if prop.name == "type":
00887                                 self.type = prop.data
00888                         elif prop.name == "cannonball":
00889                                 self.type = 2
00890                                 self.item = 0
00891                                 self.value = prop.data
00892                         elif prop.name == "fast":
00893                                 self.type = 2
00894                                 self.item = 1
00895                                 self.value = prop.data
00896                         elif prop.name == "strong":
00897                                 self.type = 2
00898                                 self.item = 2
00899                                 self.value = prop.data
00900                         elif prop.name == "bomb":
00901                                 self.type = 2
00902                                 self.item = 3
00903                                 self.value = prop.data
00904                         elif prop.name == "start":
00905                                 self.type = 0
00906                         elif prop.name == "end":
00907                                 self.type = 1
00908         
00909         def save(self, outFile):
00910                 global vertexTransf
00911                 self.pos = vertexTransf * self.pos;
00912                 
00913                 outFile.writeFloat(self.pos[0])
00914                 outFile.writeFloat(self.pos[1])
00915                 outFile.writeFloat(self.pos[2])
00916                 outFile.writeInt(self.type)
00917                 outFile.writeInt(self.item)
00918                 outFile.writeFloat(self.value)
00919         
00920         def debug(self, str):
00921                 global vertexTransf
00922                 self.pos = vertexTransf * self.pos;
00923                 print str,"Empty(type",self.type,"item",self.item,"value",self.value,")",self.name
00924                 print str,"    ",self.pos
00925 
00926 ## Empties Class
00927 #################################################################
00928 class Empties:
00929         empties = []
00930         
00931         def __init__(self, scene):
00932                 for object in scene.objects:
00933                         if object.type != "Empty":
00934                                 continue
00935                         self.empties.append(Empty(object))
00936         
00937         def getNumEmpties(self):
00938                 return len(self.empties)
00939         
00940         def save(self, outFile):
00941                 for empty in self.empties:
00942                         empty.save(outFile)
00943                 
00944         def debug(self, str):
00945                 print str,"Empties"
00946                 for empty in self.empties:
00947                         empty.debug(str+"    ")
00948                         
00949                         
00950 ## Light Class
00951 #################################################################
00952 class Light:
00953         name = None
00954         type = 0
00955         pos = None
00956         dir = None
00957         color = None
00958         radius = 0.0
00959         angle = 0.0
00960         
00961         def __init__(self, object):
00962                 lightData = object.getData(False, True)
00963                 self.name = lightData.name
00964                 if lightData.type == 1:
00965                         self.type = 1 # direct
00966                 elif lightData.type == 0:
00967                         self.type = 2 # point
00968                 elif lightData.type == 2:
00969                         self.type = 3 # spot
00970                 self.pos = blmath.Vector(object.loc)
00971                 self.rot = blmath.Vector(object.rot)
00972                 self.color = [lightData.R,lightData.G,lightData.B]
00973                 self.radius = lightData.dist
00974                 self.angle = (lightData.spotSize*math.pi)/180.0
00975         
00976         def save(self, outFile):
00977                 global vertexTransf
00978                 global normalTransf
00979                 self.pos = vertexTransf * self.pos;
00980                 self.rot = normalTransf * self.rot;
00981                 
00982                 outFile.writeFloat(self.pos[0])
00983                 outFile.writeFloat(self.pos[1])
00984                 outFile.writeFloat(self.pos[2])
00985                 outFile.writeFloat(self.color[0])
00986                 outFile.writeFloat(self.color[1])
00987                 outFile.writeFloat(self.color[2])
00988                 outFile.writeFloat(1.0/self.radius)
00989         
00990         def debug(self, str):
00991                 print str,self.name,"(Type:",self.type,"p",self.pos,"r",self.radius,")"
00992                 
00993 ## Lights Class
00994 #################################################################
00995 class Lights:
00996         lights = None
00997         
00998         def __init__(self, scene):
00999                 self.lights = []
01000                 for object in scene.objects:
01001                         if object.type != "Lamp":
01002                                 continue
01003                         self.lights.append(Light(object))
01004         
01005         def getNumLights(self):
01006                 return len(self.lights)
01007         
01008         def save(self, outFile):
01009                 for light in self.lights:
01010                         light.save(outFile)
01011                 
01012         def debug(self, str):
01013                 print str,"Lights"
01014                 for light in self.lights:
01015                         light.debug(str+"    ")
01016 
01017 ## File Class
01018 #################################################################
01019 class File:
01020         __slots__ = "outFile"
01021         
01022         def __init__(self, filename, ext = None):
01023                 # add extension if needed
01024                 if ext != None:
01025                         if not filename.lower().endswith(ext):
01026                                 filename += ext
01027                 # ask user if file should be
01028                 # saved over the current file
01029                 if not BMsg.Warning_SaveOver(filename):
01030                         return
01031                 # open file
01032                 self.outFile = open(filename, "wb")
01033         
01034         def close(self):
01035                 if self.outFile:
01036                         self.outFile.close()
01037                         self.outFile = None
01038         
01039         def writeInt(self, i):
01040                 self.outFile.write(struct.pack("<i",i))
01041         
01042         def writeUInt(self, i):
01043                 self.outFile.write(struct.pack("<I",i))
01044         
01045         def writeLong(self, i):
01046                 self.outFile.write(struct.pack("<l",i))
01047         
01048         def writeULong(self, i):
01049                 self.outFile.write(struct.pack("<L",i))
01050         
01051         def writeShort(self, s):
01052                 self.outFile.write(struct.pack("<h",s))
01053         
01054         def writeUShort(self, s):
01055                 self.outFile.write(struct.pack("<H",s))
01056         
01057         def writeFloat(self, f):
01058                 self.outFile.write(struct.pack("<f",f))
01059         
01060         def writeDouble(self, d):
01061                 self.outFile.write(struct.pack("<d",d))
01062         
01063         def writeChar(self, c):
01064                 self.outFile.write(struct.pack("<c",c))
01065         
01066         def writeUChar(self, c):
01067                 self.outFile.write(struct.pack("<B",c))
01068         
01069         def writeBool(self, b):
01070                 self.outFile.write(struct.pack("<B",1 if b else 0))
01071         
01072         def writeExpand(self, o, l, c = "\0"):
01073                 s = len(o)
01074                 self.outFile.write(o)
01075                 for i in range(l-s):
01076                         self.writeChar(c)
01077         
01078         def write(self, o):
01079                 self.outFile.write(o)
01080                         
01081 
01082 ## Starting Point of the Script
01083 #################################################################
01084 #################################################################
01085 def save(filename):
01086         
01087         print strftime("%a, %d %b %Y %H:%M:%S", localtime())
01088         
01089         scene = bl.Scene.GetCurrent()
01090         meshes = Meshes(scene)
01091         materials = Materials(scene)
01092         bodies = Bodies(scene, meshes, materials)
01093         empties = Empties(scene)
01094         lights = Lights(scene)
01095         
01096         # file header
01097         if filename != None:
01098                 outFile = File(filename, ".rvl")
01099                 
01100                 outFile.write("RVL ")
01101                 outFile.writeInt(1)
01102                 outFile.writeInt(meshes.getNumMeshes())
01103                 outFile.writeInt(materials.getNumMaterials())
01104                 outFile.writeInt(bodies.getNumBodies())
01105                 outFile.writeInt(lights.getNumLights())
01106                 
01107                 meshes.save(outFile)
01108                 materials.save(outFile)
01109                 bodies.save(outFile)
01110                 lights.save(outFile)
01111                 
01112                 outFile.close()
01113                 
01114                 #seve def file
01115                 outFile = File(filename, ".def")
01116                 outFile.writeInt(empties.getNumEmpties())
01117                 empties.save(outFile)
01118                 outFile.close();
01119         else:
01120                 meshes.debug("")
01121                 materials.debug("")
01122                 bodies.debug("")
01123                 empties.debug("")
01124                 lights.debug("")
01125 
01126         bl.Redraw()
01127         
01128         print "Done!"
01129 
01130 if __name__=='__main__':
01131         bl.Window.FileSelector(save, "Export RVL", bl.sys.makename(ext='.rvl'))
01132 #save(None)

Generated on Fri Jun 18 2010 17:48:39 for Cannonball by  doxygen 1.7.0