00001
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
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
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
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
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
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
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
00185 def computeDQ(self, k, pDQ):
00186
00187 pRot = pDQ.real.mul(self.quat[k])
00188
00189 A = pRot.transform(self.pos[0])
00190
00191 B = self.pos[k]
00192
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
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
00228 for bone in bones:
00229 parentName = None
00230 if bone.parent:
00231 parentName = bone.parent.name
00232 b = Bone(bone.name, parentName)
00233
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
00240 self.sort()
00241
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
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
00273 def sort(self):
00274
00275 for b in self.bones:
00276 b.kids = 0
00277
00278 sorted = []
00279 self.sortBoneList(self.bones, sorted, None, None)
00280 self.bones = sorted
00281
00282
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
00299 for i in range(0,numBones):
00300 outFile.writeInt(self.bones[i].kids)
00301
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
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
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
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
00471
00472
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
00489
00490 if self.data[vertex.index].equals(foundVertex, normal) == True:
00491 foundVertex = self.data[vertex.index]
00492 index = vertex.index
00493
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
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
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
00618
00619
00620
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
00636
00637 def getName(self):
00638 return self.name
00639
00640 def save(self, outFile):
00641
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
00647 self.vData.save(outFile)
00648 self.iData.save(outFile)
00649
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
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
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
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
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
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
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
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
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
00966 elif lightData.type == 0:
00967 self.type = 2
00968 elif lightData.type == 2:
00969 self.type = 3
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
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
01018
01019 class File:
01020 __slots__ = "outFile"
01021
01022 def __init__(self, filename, ext = None):
01023
01024 if ext != None:
01025 if not filename.lower().endswith(ext):
01026 filename += ext
01027
01028
01029 if not BMsg.Warning_SaveOver(filename):
01030 return
01031
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
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
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
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