soc-2008-mxcurioni: merged changes to revision 14798, compilation works for rendering...
[blender-staging.git] / release / scripts / vrml97_export.py
1 #!BPY
2 """ Registration info for Blender menus:
3 Name: 'VRML97 (.wrl)...'
4 Blender: 241
5 Group: 'Export'
6 Submenu: 'All Objects...' all
7 Submenu: 'All Objects compressed...' comp
8 Submenu: 'Selected Objects...' selected
9 Tooltip: 'Export to VRML97 file (.wrl)'
10 """
11
12 __author__ = ("Rick Kimball", "Ken Miller", "Steve Matthews", "Bart")
13 __url__ = ["blender", "elysiun",
14 "Author's (Rick) homepage, http://kimballsoftware.com/blender",
15 "Author's (Bart) homepage, http://www.neeneenee.de/vrml"]
16 __email__ = ["Bart, bart:neeneenee*de"]
17 __version__ = "2006/01/17"
18 __bpydoc__ = """\
19 This script exports to VRML97 format.
20
21 Usage:
22
23 Run this script from "File->Export" menu.  A pop-up will ask whether you
24 want to export only selected or all relevant objects.
25 """
26
27
28 # $Id$
29 #
30 #------------------------------------------------------------------------
31 # VRML97 exporter for blender 2.36 or above
32 #
33 # ***** BEGIN GPL LICENSE BLOCK *****
34 #
35 # This program is free software; you can redistribute it and/or
36 # modify it under the terms of the GNU General Public License
37 # as published by the Free Software Foundation; either version 2
38 # of the License, or (at your option) any later version.
39 #
40 # This program is distributed in the hope that it will be useful,
41 # but WITHOUT ANY WARRANTY; without even the implied warranty of
42 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43 # GNU General Public License for more details.
44 #
45 # You should have received a copy of the GNU General Public License
46 # along with this program; if not, write to the Free Software Foundation,
47 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
48 #
49 # ***** END GPL LICENCE BLOCK *****
50 #
51
52 ####################################
53 # Library dependancies
54 ####################################
55
56 import Blender
57 from Blender import Object, Mesh, Lamp, Draw, BGL, \
58          Image, Text, sys, Mathutils
59 from Blender.Scene import Render
60
61 import math
62
63 ####################################
64 # Global Variables
65 ####################################
66
67 scene = Blender.Scene.getCurrent()
68 world = Blender.World.GetCurrent() 
69 worldmat = Blender.Texture.Get()
70 filename = Blender.Get('filename')
71 _safeOverwrite = True
72 extension = ''
73 ARG=''
74
75 # Blender is Z up, VRML is Y up, both are right hand coordinate
76 # systems, so to go from Blender coords to VRML coords we rotate
77 # by 90 degrees around the X axis. In matrix notation, we have a
78 # matrix, and it's inverse, as:
79 M_blen2vrml = Mathutils.Matrix([1,0,0,0], \
80                                                            [0,0,1,0], \
81                                                            [0,-1,0,0], \
82                                                            [0,0,0,1])
83 M_vrml2blen = Mathutils.Matrix([1,0,0,0], \
84                                                            [0,0,-1,0], \
85                                                            [0,1,0,0], \
86                                                            [0,0,0,1])
87
88
89 class DrawTypes:
90         """Object DrawTypes enum values
91     BOUNDS - draw only the bounding box of the object
92     WIRE - draw object as a wire frame
93     SOLID - draw object with flat shading
94     SHADED - draw object with OpenGL shading
95 """
96         BOUNDBOX  = 1
97         WIRE      = 2
98         SOLID     = 3
99         SHADED    = 4
100         TEXTURE   = 5
101
102 if not hasattr(Blender.Object,'DrawTypes'):
103         Blender.Object.DrawTypes = DrawTypes()
104
105 ##########################################################
106 # Functions for writing output file
107 ##########################################################
108
109 class VRML2Export:
110
111         def __init__(self, filename):
112                 #--- public you can change these ---
113                 self.wire = 0
114                 self.proto = 1
115                 self.facecolors = 0
116                 self.vcolors = 0
117                 self.billnode = 0
118                 self.halonode = 0
119                 self.collnode = 0
120                 self.tilenode = 0
121                 self.wire     = 0
122                 self.twosided = 0
123
124                 # level of verbosity in console 0-none, 1-some, 2-most
125                 try:
126                         rt = Blender.Get('rt')
127                         if (rt == 42):
128                                 self.verbose = 1
129                         elif (rt == 43):
130                                 self.verbose = 2
131                         else:
132                                 self.verbose = 0
133                 except:
134                         self.verbose = 0
135                         
136                 # decimals for material color values     0.000 - 1.000
137                 self.cp=7
138                 # decimals for vertex coordinate values  0.000 - n.000
139                 self.vp=7
140                 # decimals for texture coordinate values 0.000 - 1.000
141                 self.tp=7
142                 
143                 #--- class private don't touch ---
144                 self.texNames={}   # dictionary of textureNames
145                 self.matNames={}   # dictionary of materialNames
146                 self.meshNames={}   # dictionary of meshNames
147                 self.coordNames={}   # dictionary of coordNames
148                 self.indentLevel=0 # keeps track of current indenting
149                 self.filename=filename
150                 self.file = open(filename, "w")
151                 self.bNav=0
152                 self.nodeID=0
153                 self.namesReserved=[ "Anchor", "Appearance", "AudioClip",
154                                                          "Background","Billboard", "Box",
155                                                          "Collision", "Color", "ColorInterpolator",
156                                                          "Cone", "Coordinate",
157                                                          "CoordinateInterpolator", "Cylinder",
158                                                          "CylinderSensor",
159                                                          "DirectionalLight",
160                                                          "ElevationGrid", "Extrustion",
161                                                          "Fog", "FontStyle", "Group",
162                                                          "ImageTexture", "IndexedFaceSet",
163                                                          "IndexedLineSet", "Inline",
164                                                          "LOD", "Material", "MovieTexture",
165                                                          "NavigationInfo", "Normal",
166                                                          "NormalInterpolator",
167                                                          "OrientationInterpolator", "PixelTexture",
168                                                          "PlaneSensor", "PointLight", "PointSet",
169                                                          "PositionInterpolator", "ProxmimitySensor",
170                                                          "ScalarInterpolator", "Script", "Shape",
171                                                          "Sound", "Sphere", "SphereSensor",
172                                                          "SpotLight", "Switch", "Text",
173                                                          "TextureCoordinate", "TextureTransform",
174                                                          "TimeSensor", "TouchSensor", "Transform",
175                                                          "Viewpoint", "VisibilitySensor", "WorldInfo" ]
176                 self.namesStandard=[ "Empty", "Empty.000", "Empty.001",
177                                                          "Empty.002", "Empty.003", "Empty.004",
178                                                          "Empty.005", "Empty.006", "Empty.007",
179                                                          "Empty.008", "Empty.009", "Empty.010",
180                                                          "Empty.011", "Empty.012",
181                                                          "Scene.001", "Scene.002", "Scene.003",
182                                                          "Scene.004", "Scene.005", "Scene.06",
183                                                          "Scene.013", "Scene.006", "Scene.007",
184                                                          "Scene.008", "Scene.009", "Scene.010",
185                                                          "Scene.011","Scene.012",
186                                                          "World", "World.000", "World.001",
187                                                          "World.002", "World.003", "World.004",
188                                                          "World.005" ]
189                 self.namesFog=[ "", "LINEAR"," EXPONENTIAL", "" ]
190
191 ##########################################################
192 # Writing nodes routines
193 ##########################################################
194
195         def writeHeader(self):
196                 bfile = sys.expandpath(Blender.Get('filename'))
197                 self.file.write("#VRML V2.0 utf8\n\n")
198                 self.file.write("# This file was authored with Blender " \
199                                                 "(http://www.blender.org/)\n")
200                 self.file.write("# Blender version %s\n" % Blender.Get('version'))
201                 self.file.write("# Blender file %s\n" % sys.basename(bfile))
202                 self.file.write("# Exported using VRML97 exporter " \
203                                                 "v1.55 (2006/01/17)\n\n")
204
205         def writeInline(self):
206                 inlines = Blender.Scene.Get()
207                 allinlines = len(inlines)
208                 if scene != inlines[0]:
209                         return
210                 else:
211                         for i in range(allinlines):
212                                 nameinline=inlines[i].getName()
213                                 if (nameinline not in self.namesStandard) and (i > 0):
214                                         self.writeIndented("DEF %s Inline {\n" % \
215                                                                            (self.cleanStr(nameinline)), 1)
216                                         nameinline = nameinline+".wrl"
217                                         self.writeIndented("url \"%s\" \n" % nameinline)
218                                         self.writeIndented("}\n", -1)
219                                         self.writeIndented("\n")
220
221         def writeScript(self):
222                 textEditor = Blender.Text.Get() 
223                 alltext = len(textEditor)
224                 for i in range(alltext):
225                         nametext = textEditor[i].getName()
226                         nlines = textEditor[i].getNLines()
227                         if (self.proto == 1):
228                                 if (nametext == "proto" or nametext == "proto.js" or \
229                                         nametext == "proto.txt") and (nlines != None):
230                                         nalllines = len(textEditor[i].asLines())
231                                         alllines = textEditor[i].asLines()
232                                         for j in range(nalllines):
233                                                 self.writeIndented(alllines[j] + "\n")
234                         elif (self.proto == 0):
235                                 if (nametext == "route" or nametext == "route.js" or \
236                                         nametext == "route.txt") and (nlines != None):
237                                         nalllines = len(textEditor[i].asLines())
238                                         alllines = textEditor[i].asLines()
239                                         for j in range(nalllines):
240                                                 self.writeIndented(alllines[j] + "\n")
241                 self.writeIndented("\n")
242
243         def writeViewpoint(self, thisObj):
244                 # NOTE: The transform node above this will take care of
245                 # the position and orientation of the camera
246                 context = scene.getRenderingContext()
247                 ratio = float(context.imageSizeY()) / float(context.imageSizeX())
248                 temp  = ratio * 16 / thisObj.data.getLens()
249                 lens = 2 * math.atan(temp)
250                 lens = min(lens, math.pi) 
251
252                 self.writeIndented("DEF %s Viewpoint {\n" % \
253                                                    (self.cleanStr(thisObj.name)), 1)
254                 self.writeIndented('description "%s" \n' % thisObj.name)
255                 self.writeIndented("position 0.0 0.0 0.0\n")
256                 # Need camera to point to -y in local space to accomodate
257                 # the transforma node above
258                 self.writeIndented("orientation 1.0 0.0 0.0 %f\n" % (-math.pi/2.0))
259                 self.writeIndented("fieldOfView %.3f\n" % (lens))
260                 self.writeIndented("}\n", -1)
261                 self.writeIndented("\n")
262
263         def writeFog(self):
264                 if world:
265                         mtype = world.getMistype()
266                         mparam = world.getMist()
267                         grd = world.getHor()
268                         grd0, grd1, grd2 = grd[0], grd[1], grd[2]
269                 else:
270                         return
271                 if (mtype == 1 or mtype == 2):
272                         self.writeIndented("Fog {\n",1)
273                         self.writeIndented('fogType "%s"\n' % self.namesFog[mtype])
274                         self.writeIndented("color %s %s %s\n" % \
275                                                            (round(grd0,self.cp), \
276                                                                 round(grd1,self.cp), \
277                                                                 round(grd2,self.cp)))
278                         self.writeIndented("visibilityRange %s\n" % \
279                                                            round(mparam[2],self.cp))  
280                         self.writeIndented("}\n",-1)
281                         self.writeIndented("\n")   
282                 else:
283                         return
284
285         def writeNavigationInfo(self, scene):
286                 allObj = []
287                 allObj = list(scene.objects)
288                 headlight = "TRUE"
289                 vislimit = 0.0
290                 for thisObj in allObj:
291                         objType=thisObj.type
292                         if objType == "Camera":
293                                 vislimit = thisObj.data.getClipEnd()
294                         elif objType == "Lamp":
295                                 headlight = "FALSE"
296                 self.writeIndented("NavigationInfo {\n",1)
297                 self.writeIndented("headlight %s\n" % headlight)
298                 self.writeIndented("visibilityLimit %s\n" % \
299                                                    (round(vislimit,self.cp)))
300                 self.writeIndented("type [\"EXAMINE\", \"ANY\"]\n")            
301                 self.writeIndented("avatarSize [0.25, 1.75, 0.75]\n")
302                 self.writeIndented("} \n",-1)
303                 self.writeIndented(" \n")
304
305         def writeSpotLight(self, object, lamp):
306                 # Note: location and orientation are handled by the
307                 # transform node above this object
308                 if world:
309                         ambi = world.getAmb()
310                         ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5
311                 else:
312                         ambi = 0
313                         ambientIntensity = 0
314
315                 # compute cutoff and beamwidth
316                 intensity=min(lamp.energy/1.75,1.0)
317                 beamWidth=((lamp.spotSize*math.pi)/180.0)*.37;
318                 cutOffAngle=beamWidth*1.3
319
320                 radius = lamp.dist*math.cos(beamWidth)
321                 self.writeIndented("DEF %s SpotLight {\n" % \
322                                                    self.cleanStr(object.name),1)
323                 self.writeIndented("radius %s\n" % (round(radius,self.cp)))
324                 self.writeIndented("ambientIntensity %s\n" % \
325                                                    (round(ambientIntensity,self.cp)))
326                 self.writeIndented("intensity %s\n" % (round(intensity,self.cp)))
327                 self.writeIndented("color %s %s %s\n" % \
328                                                    (round(lamp.col[0],self.cp), \
329                                                         round(lamp.col[1],self.cp), \
330                                                         round(lamp.col[2],self.cp)))
331                 self.writeIndented("beamWidth %s\n" % (round(beamWidth,self.cp)))
332                 self.writeIndented("cutOffAngle %s\n" % \
333                                                    (round(cutOffAngle,self.cp)))
334                 # Note: point down -Y axis, transform node above will rotate
335                 self.writeIndented("direction 0.0 -1.0 0.0\n")
336                 self.writeIndented("location 0.0 0.0 0.0\n")
337                 self.writeIndented("}\n",-1)
338                 self.writeIndented("\n")
339                 
340         def writeDirectionalLight(self, object, lamp):
341                 # Note: location and orientation are handled by the
342                 # transform node above this object
343                 if world:
344                         ambi = world.getAmb()
345                         ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5
346                 else:
347                         ambi = 0
348                         ambientIntensity = 0
349
350                 intensity=min(lamp.energy/1.75,1.0) 
351                 self.writeIndented("DEF %s DirectionalLight {\n" % \
352                                                    self.cleanStr(object.name),1)
353                 self.writeIndented("ambientIntensity %s\n" % \
354                                                    (round(ambientIntensity,self.cp)))
355                 self.writeIndented("color %s %s %s\n" % \
356                                                    (round(lamp.col[0],self.cp), \
357                                                         round(lamp.col[1],self.cp), \
358                                                         round(lamp.col[2],self.cp)))
359                 self.writeIndented("intensity %s\n" % \
360                                                    (round(intensity,self.cp)))
361                 # Note: point down -Y axis, transform node above will rotate
362                 self.writeIndented("direction 0.0 -1.0 0.0\n")
363                 self.writeIndented("}\n",-1)
364                 self.writeIndented("\n")
365
366         def writePointLight(self, object, lamp):
367                 # Note: location is at origin because parent transform node
368                 # takes care of this
369                 if world:
370                         ambi = world.getAmb()
371                         ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5
372                 else:
373                         ambi = 0
374                         ambientIntensity = 0
375                 om = object.getMatrix()
376                 intensity=min(lamp.energy/1.75,1.0) 
377                 radius = lamp.dist
378                 self.writeIndented("DEF %s PointLight {\n" % \
379                                                    self.cleanStr(object.name),1)
380                 self.writeIndented("ambientIntensity %s\n" % \
381                                                    (round(ambientIntensity,self.cp)))
382                 self.writeIndented("color %s %s %s\n" % \
383                                                    (round(lamp.col[0],self.cp), \
384                                                         round(lamp.col[1],self.cp), \
385                                                         round(lamp.col[2],self.cp)))
386                 self.writeIndented("intensity %s\n" % (round(intensity,self.cp)))
387                 self.writeIndented("location 0.0 0.0 0.0\n")
388                 self.writeIndented("radius %s\n" % radius )
389                 self.writeIndented("}\n",-1)
390                 self.writeIndented("\n")
391
392         def writeNode(self, thisObj):
393                 # Note: location and orientation are handled by the
394                 # transform node above this object
395                 objectname=str(thisObj.getName())
396                 if objectname in self.namesStandard:
397                         return
398                 else:
399                         self.writeIndented("%s {\n" % objectname,1)
400                         # May need to check that the direction is done right
401                         self.writeIndented("direction 0.0 -1.0 0.0\n")
402                         self.writeIndented("location 0.0 0.0 0.0\n")
403                         self.writeIndented("}\n",-1)
404                         self.writeIndented("\n")
405
406         def secureName(self, name):
407                 name = name + str(self.nodeID)
408                 self.nodeID += 1
409                 if len(name) <= 3:
410                         newname = "_" + str(self.nodeID)
411                         return "%s" % (newname)
412                 else:
413                         for bad in ['"','#',"'",',','.','[','\\',']','{','}']:
414                                 name=name.replace(bad,'_')
415                         if name in self.namesReserved:
416                                 newname = name[0:3] + "_" + str(self.nodeID)
417                                 return "%s" % (newname)
418                         elif name[0].isdigit():
419                                 newname = "_" + name + str(self.nodeID)
420                                 return "%s" % (newname)
421                         else:
422                                 newname = name
423                                 return "%s" % (newname)
424
425         def classifyMesh(self, me, ob):
426                 self.halonode = 0
427                 self.billnode = 0
428                 self.facecolors = 0
429                 self.vcolors = 0
430                 self.tilenode = 0
431                 self.colnode = 0
432                 self.wire = 0
433                 if me.faceUV:
434                         for face in me.faces:
435                                 if (face.mode & Mesh.FaceModes['HALO']):
436                                         self.halonode = 1
437                                 if (face.mode & Mesh.FaceModes['BILLBOARD']):
438                                         self.billnode = 1
439                                 if (face.mode & Mesh.FaceModes['OBCOL']):
440                                         self.facecolors = 1
441                                 if (face.mode & Mesh.FaceModes['SHAREDCOL']):
442                                         self.vcolors = 1
443                                 if (face.mode & Mesh.FaceModes['TILES']):
444                                         self.tilenode = 1
445                                 if not (face.mode & Mesh.FaceModes['DYNAMIC']):
446                                         self.collnode = 1
447                                 if (face.mode & Mesh.FaceModes['TWOSIDE']):
448                                         self.twosided = 1
449
450                 # Bit of a crufty trick, but if mesh has vertex colors
451                 # (as a non-face property) and if first material has
452                 # vcol paint set, we export the vertex colors
453                 if (me.vertexColors):
454                         if len(me.materials) > 0:
455                                 mat = me.materials[0]
456                                 if mat:
457                                         if (mat.mode & Blender.Material.Modes['VCOL_PAINT']):
458                                                 self.vcolors = 1
459                         
460                 # check if object is wireframe only
461                 if ob.drawType == Blender.Object.DrawTypes.WIRE:
462                         # user selected WIRE=2 on the Drawtype=Wire on (F9) Edit page
463                         self.wire = 1
464
465         ###
466         ### The next few functions nest Collision/Billboard/Halo nodes.
467         ### For real mesh data export, jump down to writeMeshData()
468         ###
469         def writeMesh(self, ob, normals = 0):
470
471                 imageMap={}   # set of used images
472                 sided={}      # 'one':cnt , 'two':cnt
473                 vColors={}    # 'multi':1
474
475                 if (len(ob.modifiers) > 0):
476                         me = Mesh.New()
477                         me.getFromObject(ob.name)
478                         # Careful with the name, the temporary mesh may
479                         # reuse the default name for other meshes. So we
480                         # pick our own name.
481                         me.name = "MOD_%s" % (ob.name)
482                 else:
483                         me = ob.getData(mesh = 1)
484
485                 self.classifyMesh(me, ob)
486
487                 if (self.collnode):
488                         self.writeCollisionMesh(me, ob, normals)
489                         return
490                 else:
491                         self.writeRegularMesh(me, ob, normals)
492                         return
493
494         def writeCollisionMesh(self, me, ob, normals = 0):
495                 self.writeIndented("Collision {\n",1)
496                 self.writeIndented("collide FALSE\n")
497                 self.writeIndented("children [\n")
498
499                 self.writeRegularMesh(me, ob, normals)
500
501                 self.writeIndented("]\n", -1)
502                 self.writeIndented("}\n", -1)
503                 
504         def writeRegularMesh(self, me, ob, normals = 0):
505                 if (self.billnode):
506                         self.writeBillboardMesh(me, ob, normals)
507                 elif (self.halonode):
508                         self.writeHaloMesh(me, ob, normals)
509                 else:
510                         self.writeMeshData(me, ob, normals)
511
512         def writeBillboardMesh(self, me, ob, normals = 0):
513                 self.writeIndented("Billboard {\n",1)
514                 self.writeIndented("axisOfRotation 0 1 0\n")
515                 self.writeIndented("children [\n")
516
517                 self.writeMeshData(me, ob, normals)
518
519                 self.writeIndented("]\n", -1)
520                 self.writeIndented("}\n", -1)
521                 
522         def writeHaloMesh(self, me, ob, normals = 0):
523                 self.writeIndented("Billboard {\n",1)
524                 self.writeIndented("axisOfRotation 0 0 0\n")
525                 self.writeIndented("children [\n")
526
527                 self.writeMeshData(me, ob, normals)
528
529                 self.writeIndented("]\n", -1)
530                 self.writeIndented("}\n", -1)
531
532         ###
533         ### Here is where real mesh data is written
534         ### 
535         def writeMeshData(self, me, ob, normals = 0):
536                 meshName = self.cleanStr(me.name)
537
538                 if self.meshNames.has_key(meshName):
539                         self.writeIndented("USE ME_%s\n" % meshName, 0)
540                         self.meshNames[meshName]+=1
541                         if (self.verbose == 1):
542                                 print "  Using Mesh %s (Blender mesh: %s)\n" % \
543                                           (meshName, me.name)
544                         return
545                 self.meshNames[meshName]=1
546
547                 if (self.verbose == 1):
548                         print "  Writing Mesh %s (Blender mesh: %s)\n" % \
549                                   (meshName, me.name)
550                         return
551
552                 self.writeIndented("DEF ME_%s Group {\n" % meshName,1)
553                 self.writeIndented("children [\n", 1)
554                         
555                 hasImageTexture = 0
556                 issmooth = 0
557
558                 maters = me.materials
559                 nummats = self.getNumMaterials(me)
560
561                 # Vertex and Face colors trump materials and image textures
562                 if (self.facecolors or self.vcolors):
563                         if nummats > 0:
564                                 if maters[0]:
565                                         self.writeShape(ob, me, 0, None)
566                                 else:
567                                         self.writeShape(ob, me, -1, None)
568                         else:
569                                 self.writeShape(ob, me, -1, None)
570                 # Do meshes with materials, possible with image textures
571                 elif nummats > 0:
572                         for matnum in range(len(maters)):
573                                 if maters[matnum]:
574                                         images = []
575                                         if me.faceUV:
576                                                 images = self.getImages(me, matnum)
577                                                 if len(images) > 0:
578                                                         for image in images:
579                                                                 self.writeShape(ob, me, matnum, image)
580                                                 else:
581                                                         self.writeShape(ob, me, matnum, None)
582                                         else:
583                                                 self.writeShape(ob, me, matnum, None)
584                 else:
585                         if me.faceUV:
586                                 images = self.getImages(me, -1)
587                                 if len(images) > 0:
588                                         for image in images:
589                                                 self.writeShape(ob, me, -1, image)
590                                 else:
591                                         self.writeShape(ob, me, -1, None)
592                         else:
593                                 self.writeShape(ob, me, -1, None)
594
595                         
596                 self.writeIndented("]\n", -1)
597                 self.writeIndented("}\n", -1)
598
599         def getImages(self, me, matnum):
600                 imageNames = {}
601                 images = []
602                 for face in me.faces:
603                         if (matnum == -1) or (face.mat == matnum):
604                                 if (face.image):
605                                         imName = self.cleanStr(face.image.name)
606                                         if not imageNames.has_key(imName):
607                                                 images.append(face.image)
608                                                 imageNames[imName]=1
609                 return images
610
611         def getNumMaterials(self, me):
612                 # Oh silly Blender, why do you sometimes have 'None' as
613                 # a member of the me.materials array?
614                 num = 0
615                 for mat in me.materials:
616                         if mat:
617                                 num = num + 1
618                 return num
619
620         def writeCoordinates(self, me, meshName):
621                 coordName = "coord_%s" % (meshName)
622                 # look up coord name, use it if available
623                 if self.coordNames.has_key(coordName):
624                         self.writeIndented("coord USE %s\n" % coordName, 0)
625                         self.coordNames[coordName]+=1
626                         return;
627         
628                 self.coordNames[coordName]=1
629
630                 #-- vertices
631                 self.writeIndented("coord DEF %s Coordinate {\n" % (coordName), 1)
632                 self.writeIndented("point [\n", 1)
633                 meshVertexList = me.verts
634
635                 for vertex in meshVertexList:
636                         blenvert = Mathutils.Vector(vertex.co)
637                         vrmlvert = M_blen2vrml * blenvert
638                         self.writeUnindented("%s %s %s\n " % \
639                                                                  (vrmlvert[0], \
640                                                                   vrmlvert[1], \
641                                                                   vrmlvert[2]))
642                 self.writeIndented("]\n", -1)
643                 self.writeIndented("}\n", -1)
644                 self.writeIndented("\n")
645
646         def writeShape(self, ob, me, matnum, image):
647                 # Note: at this point it is assumed for matnum!=-1 that the 
648                 # material in me.materials[matnum] is not equal to 'None'.
649                 # Such validation should be performed by the function that
650                 # calls this one.
651                 self.writeIndented("Shape {\n",1)
652
653                 self.writeIndented("appearance Appearance {\n", 1)
654                 if (matnum != -1):
655                         mater = me.materials[matnum]
656                         self.writeMaterial(mater, self.cleanStr(mater.name,''))
657                         if (mater.mode & Blender.Material.Modes['TEXFACE']):
658                                 if image != None:
659                                         self.writeImageTexture(image.name, image.filename)
660                 else:
661                         if image != None:
662                                 self.writeImageTexture(image.name, image.filename)
663
664                 self.writeIndented("}\n", -1)
665
666                 self.writeGeometry(ob, me, matnum, image)
667
668                 self.writeIndented("}\n", -1)
669
670         def writeGeometry(self, ob, me, matnum, image):
671
672                 #-- IndexedFaceSet or IndexedLineSet
673                 meshName = self.cleanStr(me.name)
674
675                 # check if object is wireframe only
676                 if (self.wire):
677                         ifStyle="IndexedLineSet"
678                 else:
679                         # user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5
680                         ifStyle="IndexedFaceSet"
681
682                 self.writeIndented("geometry %s {\n" % ifStyle, 1)
683                 if not self.wire:
684                         if self.twosided == 1:
685                                 self.writeIndented("solid FALSE\n")
686                         else:
687                                 self.writeIndented("solid TRUE\n")
688
689                 self.writeCoordinates(me, meshName)
690                 self.writeCoordIndex(me, meshName, matnum, image)
691                 self.writeTextureCoordinates(me, meshName, matnum, image)
692                 if self.facecolors:
693                         self.writeFaceColors(me)
694                 elif self.vcolors:
695                         self.writeVertexColors(me)
696                 self.writeIndented("}\n", -1)
697
698         def writeCoordIndex(self, me, meshName, matnum, image):
699                 meshVertexList = me.verts
700                 self.writeIndented("coordIndex [\n", 1)
701                 coordIndexList=[]  
702                 for face in me.faces:
703                         if (matnum == -1) or (face.mat == matnum):
704                                 if (image == None) or (face.image == image):
705                                         cordStr=""
706                                         for v in face.verts:
707                                                 indx=v.index
708                                                 cordStr = cordStr + "%s " % indx
709                                         self.writeUnindented(cordStr + "-1, \n")
710                 self.writeIndented("]\n", -1)
711
712         def writeTextureCoordinates(self, me, meshName, matnum, image):
713                 if (image == None):
714                         return
715                 
716                 texCoordList=[] 
717                 texIndexList=[]
718                 j=0
719
720                 for face in me.faces:
721                         coordStr = ""
722                         indexStr = ""
723                         if (matnum == -1) or (face.mat == matnum):
724                                 if (face.image == image):
725                                         for i in range(len(face.verts)):
726                                                 uv = face.uv[i]
727                                                 indexStr += "%s " % (j)
728                                                 coordStr += "%s %s, " % \
729                                                                         (round(uv[0], self.tp), \
730                                                                          round(uv[1], self.tp))
731                                                 j=j+1
732                                         indexStr += "-1"
733                         texIndexList.append(indexStr)
734                         texCoordList.append(coordStr)
735
736                 self.writeIndented("texCoord TextureCoordinate {\n", 1)
737                 self.writeIndented("point [\n", 1)
738                 for coord in texCoordList:
739                         self.writeUnindented("%s\n" % (coord))
740                 self.writeIndented("]\n", -1)
741                 self.writeIndented("}\n", -1)
742
743                 self.writeIndented("texCoordIndex [\n", 1)
744                 for ind in texIndexList:
745                         self.writeUnindented("%s\n" % (ind))
746                 self.writeIndented("]\n", -1)
747
748         def writeFaceColors(self, me):
749                 self.writeIndented("colorPerVertex FALSE\n")
750                 self.writeIndented("color Color {\n",1)
751                 self.writeIndented("color [\n", 1)
752
753                 for face in me.faces:
754                         if face.col:
755                                 c=face.col[0]
756                                 if self.verbose >= 2:
757                                         print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b)
758
759                                 aColor = self.rgbToFS(c)
760                                 self.writeUnindented("%s,\n" % aColor)
761                 self.writeIndented("]\n",-1)
762                 self.writeIndented("}\n",-1)
763
764         def writeVertexColors(self, me):
765                 self.writeIndented("colorPerVertex TRUE\n")
766                 self.writeIndented("color Color {\n",1)
767                 self.writeIndented("color [\n\t\t\t\t\t\t", 1)
768
769                 cols = [None] * len(me.verts)
770
771                 for face in me.faces:
772                         for vind in range(len(face.v)):
773                                 vertex = face.v[vind]
774                                 i = vertex.index
775                                 if cols[i] == None:
776                                         cols[i] = face.col[vind]
777                                         
778                 for i in range(len(me.verts)):
779                         aColor = self.rgbToFS(cols[i])
780                         self.writeUnindented("%s\n" % aColor)
781
782                 self.writeIndented("\n", 0)
783                 self.writeIndented("]\n",-1)
784                 self.writeIndented("}\n",-1)
785
786         def writeMaterial(self, mat, matName):
787                 # look up material name, use it if available
788                 if self.matNames.has_key(matName):
789                         self.writeIndented("material USE MA_%s\n" % matName)
790                         self.matNames[matName]+=1
791                         return;
792         
793                 self.matNames[matName]=1
794
795                 ambient = mat.amb/3
796                 diffuseR, diffuseG, diffuseB = \
797                                   mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2]
798                 if world:
799                         ambi = world.getAmb()
800                         ambi0, ambi1, ambi2 = (ambi[0]*mat.amb) * 2, \
801                                                                   (ambi[1]*mat.amb) * 2, \
802                                                                   (ambi[2]*mat.amb) * 2
803                 else:
804                         ambi0, ambi1, ambi2 = 0, 0, 0
805                 emisR, emisG, emisB = (diffuseR*mat.emit+ambi0) / 2, \
806                                                           (diffuseG*mat.emit+ambi1) / 2, \
807                                                           (diffuseB*mat.emit+ambi2) / 2
808
809                 shininess = mat.hard/512.0
810                 specR = (mat.specCol[0]+0.001) / (1.25/(mat.getSpec()+0.001))
811                 specG = (mat.specCol[1]+0.001) / (1.25/(mat.getSpec()+0.001))
812                 specB = (mat.specCol[2]+0.001) / (1.25/(mat.getSpec()+0.001))
813                 transp = 1 - mat.alpha
814                 matFlags = mat.getMode()
815                 if matFlags & Blender.Material.Modes['SHADELESS']:
816                         ambient = 1
817                         shine = 1
818                         specR = emitR = diffuseR
819                         specG = emitG = diffuseG
820                         specB = emitB = diffuseB
821                 self.writeIndented("material DEF MA_%s Material {\n" % matName, 1)
822                 self.writeIndented("diffuseColor %s %s %s\n" % \
823                                                    (round(diffuseR,self.cp), \
824                                                         round(diffuseG,self.cp), \
825                                                         round(diffuseB,self.cp)))
826                 self.writeIndented("ambientIntensity %s\n" % \
827                                                    (round(ambient,self.cp)))
828                 self.writeIndented("specularColor %s %s %s\n" % \
829                                                    (round(specR,self.cp), \
830                                                         round(specG,self.cp), \
831                                                         round(specB,self.cp)))
832                 self.writeIndented("emissiveColor  %s %s %s\n" % \
833                                                    (round(emisR,self.cp), \
834                                                         round(emisG,self.cp), \
835                                                         round(emisB,self.cp)))
836                 self.writeIndented("shininess %s\n" % (round(shininess,self.cp)))
837                 self.writeIndented("transparency %s\n" % (round(transp,self.cp)))
838                 self.writeIndented("}\n",-1)
839
840         def writeImageTexture(self, name, filename):
841                 if self.texNames.has_key(name):
842                         self.writeIndented("texture USE %s\n" % self.cleanStr(name))
843                         self.texNames[name] += 1
844                         return
845                 else:
846                         self.writeIndented("texture DEF %s ImageTexture {\n" % \
847                                                            self.cleanStr(name), 1)
848                         self.writeIndented('url "%s"\n' % \
849                                                            filename.split("\\")[-1].split("/")[-1])
850                         self.writeIndented("}\n",-1)
851                         self.texNames[name] = 1
852
853         def writeBackground(self):
854                 if world:
855                         worldname = world.getName()
856                 else:
857                         return
858                 blending = world.getSkytype()   
859                 grd = world.getHor()
860                 grd0, grd1, grd2 = grd[0], grd[1], grd[2]
861                 sky = world.getZen()
862                 sky0, sky1, sky2 = sky[0], sky[1], sky[2]
863                 mix0, mix1, mix2 = grd[0]+sky[0], grd[1]+sky[1], grd[2]+sky[2]
864                 mix0, mix1, mix2 = mix0/2, mix1/2, mix2/2
865                 if worldname in self.namesStandard:
866                         self.writeIndented("Background {\n",1)
867                 else:
868                         self.writeIndented("DEF %s Background {\n" % \
869                                                            self.secureName(worldname),1)
870                 # No Skytype - just Hor color
871                 if blending == 0:
872                         self.writeIndented("groundColor %s %s %s\n" % \
873                                                            (round(grd0,self.cp), \
874                                                                 round(grd1,self.cp), \
875                                                                 round(grd2,self.cp)))
876                         self.writeIndented("skyColor %s %s %s\n" % \
877                                                            (round(grd0,self.cp), \
878                                                                 round(grd1,self.cp), \
879                                                                 round(grd2,self.cp)))
880                 # Blend Gradient
881                 elif blending == 1:
882                         self.writeIndented("groundColor [ %s %s %s, " % \
883                                                            (round(grd0,self.cp), \
884                                                                 round(grd1,self.cp), \
885                                                                 round(grd2,self.cp)))
886                         self.writeIndented("%s %s %s ]\n" % \
887                                                            (round(mix0,self.cp), \
888                                                                 round(mix1,self.cp), \
889                                                                 round(mix2,self.cp)))
890                         self.writeIndented("groundAngle [ 1.57, 1.57 ]\n")
891                         self.writeIndented("skyColor [ %s %s %s, " % \
892                                                            (round(sky0,self.cp), \
893                                                                 round(sky1,self.cp), \
894                                                                 round(sky2,self.cp)))
895                         self.writeIndented("%s %s %s ]\n" % \
896                                                            (round(mix0,self.cp), \
897                                                                 round(mix1,self.cp), \
898                                                                 round(mix2,self.cp)))
899                         self.writeIndented("skyAngle [ 1.57, 1.57 ]\n")
900                 # Blend+Real Gradient Inverse
901                 elif blending == 3:
902                         self.writeIndented("groundColor [ %s %s %s, " % \
903                                                            (round(sky0,self.cp), \
904                                                                 round(sky1,self.cp), \
905                                                                 round(sky2,self.cp)))
906                         self.writeIndented("%s %s %s ]\n" % \
907                                                            (round(mix0,self.cp), \
908                                                                 round(mix1,self.cp), \
909                                                                 round(mix2,self.cp)))
910                         self.writeIndented("groundAngle [ 1.57, 1.57 ]\n")
911                         self.writeIndented("skyColor [ %s %s %s, " % \
912                                                            (round(grd0,self.cp), \
913                                                                 round(grd1,self.cp), \
914                                                                 round(grd2,self.cp)))
915                         self.writeIndented("%s %s %s ]\n" % \
916                                                            (round(mix0,self.cp), \
917                                                                 round(mix1,self.cp), \
918                                                                 round(mix2,self.cp)))
919                         self.writeIndented("skyAngle [ 1.57, 1.57 ]\n")
920                 # Paper - just Zen Color
921                 elif blending == 4:
922                         self.writeIndented("groundColor %s %s %s\n" % \
923                                                            (round(sky0,self.cp), \
924                                                                 round(sky1,self.cp), \
925                                                                 round(sky2,self.cp)))
926                         self.writeIndented("skyColor %s %s %s\n" % \
927                                                            (round(sky0,self.cp), \
928                                                                 round(sky1,self.cp), \
929                                                                 round(sky2,self.cp)))
930                 # Blend+Real+Paper - komplex gradient
931                 elif blending == 7:
932                         self.writeIndented("groundColor [ %s %s %s, " % \
933                                                            (round(sky0,self.cp), \
934                                                                 round(sky1,self.cp), \
935                                                                 round(sky2,self.cp)))
936                         self.writeIndented("%s %s %s ]\n" % \
937                                                            (round(grd0,self.cp), \
938                                                                 round(grd1,self.cp), \
939                                                                 round(grd2,self.cp)))
940                         self.writeIndented("groundAngle [ 1.57, 1.57 ]\n")
941                         self.writeIndented("skyColor [ %s %s %s, " % \
942                                                            (round(sky0,self.cp), \
943                                                                 round(sky1,self.cp), \
944                                                                 round(sky2,self.cp)))
945                         self.writeIndented("%s %s %s ]\n" % \
946                                                            (round(grd0,self.cp),
947                                                                 round(grd1,self.cp),
948                                                                 round(grd2,self.cp)))
949                         self.writeIndented("skyAngle [ 1.57, 1.57 ]\n")
950                 # Any Other two colors
951                 else:
952                         self.writeIndented("groundColor %s %s %s\n" % \
953                                                            (round(grd0,self.cp), \
954                                                                 round(grd1,self.cp), \
955                                                                 round(grd2,self.cp)))
956                         self.writeIndented("skyColor %s %s %s\n" % \
957                                                            (round(sky0,self.cp), \
958                                                                 round(sky1,self.cp), \
959                                                                 round(sky2,self.cp)))
960                 alltexture = len(worldmat)
961                 for i in xrange(alltexture):
962                         namemat = worldmat[i].getName()
963                         pic = worldmat[i].getImage()
964                         if pic:
965                                 # Stripped path.
966                                 pic_path= pic.filename.split('\\')[-1].split('/')[-1]
967                                 if namemat == "back":
968                                         self.writeIndented('backUrl "%s"\n' % pic_path)
969                                 elif namemat == "bottom":
970                                         self.writeIndented('bottomUrl "%s"\n' % pic_path)
971                                 elif namemat == "front":
972                                         self.writeIndented('frontUrl "%s"\n' % pic_path)
973                                 elif namemat == "left":
974                                         self.writeIndented('leftUrl "%s"\n' % pic_path)
975                                 elif namemat == "right":
976                                         self.writeIndented('rightUrl "%s"\n' % pic_path)
977                                 elif namemat == "top":
978                                         self.writeIndented('topUrl "%s"\n' % pic_path)
979                 self.writeIndented("}",-1)
980                 self.writeIndented("\n\n")
981
982         def writeLamp(self, ob):
983                 la = ob.data
984                 laType = la.getType()
985
986                 if laType == Lamp.Types.Lamp:
987                         self.writePointLight(ob, la)
988                 elif laType == Lamp.Types.Spot:
989                         self.writeSpotLight(ob, la)
990                 elif laType == Lamp.Types.Sun:
991                         self.writeDirectionalLight(ob, la)
992                 else:
993                         self.writeDirectionalLight(ob, la)
994
995         def writeObject(self, ob):
996
997                 obname = self.cleanStr(ob.name)
998
999                 try:
1000                         obtype=ob.getType()
1001                 except AttributeError:
1002                         print "Error: Unable to get type info for %s" % obname
1003                         return
1004
1005                 if self.verbose >= 1:
1006                         print "++ Writing %s object %s (Blender name: %s)\n" % \
1007                                   (obtype, obname, ob.name)
1008
1009                 # Note: I am leaving empties out for now -- the original
1010                 # script does some really weird stuff with empties
1011                 if ( (obtype != "Camera") and \
1012                          (obtype != "Mesh") and \
1013                          (obtype != "Lamp") ):
1014                         print "Info: Ignoring [%s], object type [%s] " \
1015                                   "not handle yet" % (obname, obtype)
1016                         return
1017
1018                 ob_matrix = Mathutils.Matrix(ob.getMatrix('worldspace'))
1019                 matrix = M_blen2vrml * ob_matrix * M_vrml2blen
1020                 e      = matrix.rotationPart().toEuler()
1021
1022                 v = matrix.translationPart()
1023                 (axis, angle) = self.eulToVecRot(self.deg2rad(e.x), \
1024                                                                                  self.deg2rad(e.y), \
1025                                                                                  self.deg2rad(e.z))
1026
1027                 mrot = e.toMatrix().resize4x4()
1028                 try:
1029                         mrot.invert()
1030                 except:
1031                         print "Warning: %s has degenerate transformation!" % (obname)
1032                         return
1033                 
1034                 diag = matrix * mrot
1035                 sizeX = diag[0][0]
1036                 sizeY = diag[1][1]
1037                 sizeZ = diag[2][2]
1038
1039                 if self.verbose >= 1:
1040                         print "  Transformation:\n" \
1041                                   "    loc:  %f %f %f\n" \
1042                                   "    size: %f %f %f\n" \
1043                                   "    Rot:  (%f %f %f), %f\n" % \
1044                                   (v.x, v.y, v.z, \
1045                                    sizeX, sizeY, sizeZ, \
1046                                    axis[0], axis[1], axis[2], angle)
1047
1048                 self.writeIndented("DEF OB_%s Transform {\n" % (obname), 1)
1049                 self.writeIndented("translation %f %f %f\n" % \
1050                                                    (v.x, v.y, v.z) )
1051
1052                 self.writeIndented("rotation %f %f %f %f\n" % \
1053                                                    (axis[0],axis[1],axis[2],angle) )
1054                 
1055                 self.writeIndented("scale %f %f %f\n" % \
1056                                                    (sizeX, sizeY, sizeZ) )
1057
1058                 self.writeIndented("children [\n", 1)
1059
1060                 self.writeObData(ob)
1061
1062                 self.writeIndented("]\n", -1) # end object
1063                 self.writeIndented("}\n", -1) # end object
1064
1065         def writeObData(self, ob):
1066
1067                 obtype = ob.getType()
1068
1069                 if obtype == "Camera":
1070                         self.writeViewpoint(ob)
1071                 elif obtype == "Mesh":
1072                         self.writeMesh(ob)
1073                 elif obtype == "Lamp":
1074                         self.writeLamp(ob)
1075                 elif obtype == "Empty":
1076                         self.writeNode(ob)
1077
1078
1079 ##########################################################
1080 # export routine
1081 ##########################################################
1082
1083         def export(self, scene, world, worldmat):
1084                 print "Info: starting VRML97 export to " + self.filename + "..."
1085                 self.writeHeader()
1086                 self.writeScript()
1087                 self.writeNavigationInfo(scene)
1088                 self.writeBackground()
1089                 self.writeFog()
1090                 self.proto = 0
1091                 allObj = []
1092                 if ARG == 'selected':
1093                         allObj = list(scene.objects.context)
1094                 else:
1095                         allObj = list(scene.objects)
1096                         self.writeInline()
1097
1098                 for thisObj in allObj:
1099                         self.writeObject(thisObj)
1100
1101                 if ARG != 'selected':
1102                         self.writeScript()
1103                 self.cleanup()
1104
1105 ##########################################################
1106 # Utility methods
1107 ##########################################################
1108
1109         def cleanup(self):
1110                 self.file.close()
1111                 self.texNames={}
1112                 self.matNames={}
1113                 self.indentLevel=0
1114                 print "Info: finished VRML97 export to %s\n" % self.filename
1115
1116         def cleanStr(self, name, prefix='rsvd_'):
1117                 """cleanStr(name,prefix) - try to create a valid VRML DEF \
1118                 name from object name"""
1119
1120                 newName=name[:]
1121                 if len(newName) == 0:
1122                         self.nNodeID+=1
1123                         return "%s%d" % (prefix, self.nNodeID)
1124                 
1125                 if newName in self.namesReserved:
1126                         newName='%s%s' % (prefix,newName)
1127                 
1128                 if newName[0].isdigit():
1129                         newName='%s%s' % ('_',newName)
1130
1131                 for bad in (' ','"','#',"'",',','.','[','\\',']','{','}'):
1132                         newName=newName.replace(bad,'_')
1133                 return newName
1134
1135         def rgbToFS(self, c):
1136                 s = "%s %s %s" % \
1137                         (round(c.r/255.0,self.cp), \
1138                          round(c.g/255.0,self.cp), \
1139                          round(c.b/255.0,self.cp))
1140                 return s
1141
1142         def rad2deg(self, v):
1143                 return round(v*180.0/math.pi,4)
1144
1145         def deg2rad(self, v):
1146                 return (v*math.pi)/180.0;
1147
1148         def eulToVecRot(self, RotX, RotY, RotZ):
1149                 
1150                 ti = RotX*0.5
1151                 tj = RotY*0.5
1152                 th = RotZ*0.5
1153
1154                 ci = math.cos(ti)
1155                 cj = math.cos(tj)
1156                 ch = math.cos(th)
1157                 si = math.sin(ti)
1158                 sj = math.sin(tj)
1159                 sh = math.sin(th)
1160                 cc = ci*ch
1161                 cs = ci*sh
1162                 sc = si*ch
1163                 ss = si*sh
1164         
1165                 q0 = cj*cc + sj*ss
1166                 q1 = cj*sc - sj*cs
1167                 q2 = cj*ss + sj*cc
1168                 q3 = cj*cs - sj*sc
1169
1170                 angle = 2 * math.acos(q0)
1171                 if (math.fabs(angle) < 0.000001):
1172                         axis = [1.0, 0.0, 0.0]
1173                 else:
1174                         sphi = 1.0/math.sqrt(1.0 - (q0*q0))
1175                         axis = [q1 * sphi, q2 * sphi, q3 * sphi]
1176
1177                 a = Mathutils.Vector(axis)
1178                 a.normalize()
1179                 return ([a.x, a.y, a.z], angle)
1180
1181
1182         # For writing well formed VRML code
1183         #----------------------------------
1184         def writeIndented(self, s, inc=0):
1185                 if inc < 1:
1186                         self.indentLevel = self.indentLevel + inc
1187                 
1188                 self.file.write( self.indentLevel*"\t" + s)
1189
1190                 if inc > 0:
1191                         self.indentLevel = self.indentLevel + inc
1192
1193         # Sometimes better to not have too many
1194         # tab characters in a long list, for file size
1195         #----------------------------------
1196         def writeUnindented(self, s):
1197                 self.file.write(s)
1198
1199 ##########################################################
1200 # Callbacks, needed before Main
1201 ##########################################################
1202
1203 def select_file(filename):
1204         if sys.exists(filename) and _safeOverwrite:
1205                 result = \
1206                         Draw.PupMenu("File Already Exists, Overwrite?%t|Yes%x1|No%x0")
1207                 if(result != 1):
1208                         return
1209
1210         if not filename.endswith(extension):
1211                 filename += extension
1212
1213         wrlexport=VRML2Export(filename)
1214         wrlexport.export(scene, world, worldmat)
1215
1216
1217 #########################################################
1218 # main routine
1219 #########################################################
1220
1221 try:
1222         ARG = __script__['arg'] # user selected argument
1223 except:
1224         print "older version"
1225
1226 if Blender.Get('version') < 235:
1227         print "Warning: VRML97 export failed, wrong blender version!"
1228         print " You aren't running blender version 2.35 or greater"
1229         print " download a newer version from http://blender3d.org/"
1230 else:
1231         if ARG == 'comp':
1232                 extension=".wrz"
1233                 from gzip import *
1234         else:
1235                 extension=".wrl"
1236         Blender.Window.FileSelector(select_file, "Export VRML97", \
1237                                                                 sys.makename(ext=extension))
1238