diff options
Diffstat (limited to 'release/scripts/vrml97_export.py')
-rw-r--r-- | release/scripts/vrml97_export.py | 1300 |
1 files changed, 0 insertions, 1300 deletions
diff --git a/release/scripts/vrml97_export.py b/release/scripts/vrml97_export.py deleted file mode 100644 index bd1a35f7c3b..00000000000 --- a/release/scripts/vrml97_export.py +++ /dev/null @@ -1,1300 +0,0 @@ -#!BPY -""" Registration info for Blender menus: -Name: 'VRML97 (.wrl)...' -Blender: 241 -Group: 'Export' -Tooltip: 'Export to VRML97 file (.wrl)' -""" - -__author__ = ("Rick Kimball", "Ken Miller", "Steve Matthews", "Bart") -__url__ = ["blender", "blenderartists.org", -"Author's (Rick) homepage, http://kimballsoftware.com/blender", -"Author's (Bart) homepage, http://www.neeneenee.de/vrml"] -__email__ = ["Bart, bart:neeneenee*de"] -__version__ = "2006/01/17" -__bpydoc__ = """\ -This script exports to VRML97 format. - -Usage: - -Run this script from "File->Export" menu. A pop-up will ask whether you -want to export only selected or all relevant objects. -""" - - -# $Id$ -# -#------------------------------------------------------------------------ -# VRML97 exporter for blender 2.36 or above -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# ***** END GPL LICENCE BLOCK ***** -# - -#################################### -# Library dependancies -#################################### - -import Blender -from Blender import Object, Mesh, Lamp, Draw, BGL, \ - Image, Text, sys, Mathutils, Registry -from Blender.Scene import Render - -import math - -#################################### -# Global Variables -#################################### - -scene = Blender.Scene.getCurrent() -world = Blender.World.GetCurrent() -worldmat = Blender.Texture.Get() -filename = Blender.Get('filename') -_safeOverwrite = True -extension = '' - -# Matrices below are used only when export_rotate_z_to_y.val: -# -# Blender is Z up, VRML is Y up, both are right hand coordinate -# systems, so to go from Blender coords to VRML coords we rotate -# by 90 degrees around the X axis. In matrix notation, we have a -# matrix, and it's inverse, as: -M_blen2vrml = Mathutils.Matrix([1,0,0,0], \ - [0,0,1,0], \ - [0,-1,0,0], \ - [0,0,0,1]) -M_vrml2blen = Mathutils.Matrix([1,0,0,0], \ - [0,0,-1,0], \ - [0,1,0,0], \ - [0,0,0,1]) - - -class DrawTypes: - """Object DrawTypes enum values - BOUNDS - draw only the bounding box of the object - WIRE - draw object as a wire frame - SOLID - draw object with flat shading - SHADED - draw object with OpenGL shading -""" - BOUNDBOX = 1 - WIRE = 2 - SOLID = 3 - SHADED = 4 - TEXTURE = 5 - -if not hasattr(Blender.Object,'DrawTypes'): - Blender.Object.DrawTypes = DrawTypes() - -########################################################## -# Functions for writing output file -########################################################## - -class VRML2Export: - - def __init__(self, filename): - #--- public you can change these --- - self.wire = 0 - self.proto = 1 - self.facecolors = 0 - self.vcolors = 0 - self.billnode = 0 - self.halonode = 0 - self.collnode = 0 - self.tilenode = 0 - self.wire = 0 - self.twosided = 0 - - # level of verbosity in console 0-none, 1-some, 2-most - try: - rt = Blender.Get('rt') - if (rt == 42): - self.verbose = 1 - elif (rt == 43): - self.verbose = 2 - else: - self.verbose = 0 - except: - self.verbose = 0 - - # decimals for material color values 0.000 - 1.000 - self.cp=7 - # decimals for vertex coordinate values 0.000 - n.000 - self.vp=7 - # decimals for texture coordinate values 0.000 - 1.000 - self.tp=7 - - #--- class private don't touch --- - self.texNames={} # dictionary of textureNames - self.matNames={} # dictionary of materialNames - self.meshNames={} # dictionary of meshNames - self.coordNames={} # dictionary of coordNames - self.indentLevel=0 # keeps track of current indenting - self.filename=filename - self.file = open(filename, "w") - self.bNav=0 - self.nodeID=0 - self.namesReserved=[ "Anchor", "Appearance", "AudioClip", - "Background","Billboard", "Box", - "Collision", "Color", "ColorInterpolator", - "Cone", "Coordinate", - "CoordinateInterpolator", "Cylinder", - "CylinderSensor", - "DirectionalLight", - "ElevationGrid", "Extrustion", - "Fog", "FontStyle", "Group", - "ImageTexture", "IndexedFaceSet", - "IndexedLineSet", "Inline", - "LOD", "Material", "MovieTexture", - "NavigationInfo", "Normal", - "NormalInterpolator", - "OrientationInterpolator", "PixelTexture", - "PlaneSensor", "PointLight", "PointSet", - "PositionInterpolator", "ProxmimitySensor", - "ScalarInterpolator", "Script", "Shape", - "Sound", "Sphere", "SphereSensor", - "SpotLight", "Switch", "Text", - "TextureCoordinate", "TextureTransform", - "TimeSensor", "TouchSensor", "Transform", - "Viewpoint", "VisibilitySensor", "WorldInfo" ] - self.namesStandard=[ "Empty", "Empty.000", "Empty.001", - "Empty.002", "Empty.003", "Empty.004", - "Empty.005", "Empty.006", "Empty.007", - "Empty.008", "Empty.009", "Empty.010", - "Empty.011", "Empty.012", - "Scene.001", "Scene.002", "Scene.003", - "Scene.004", "Scene.005", "Scene.06", - "Scene.013", "Scene.006", "Scene.007", - "Scene.008", "Scene.009", "Scene.010", - "Scene.011","Scene.012", - "World", "World.000", "World.001", - "World.002", "World.003", "World.004", - "World.005" ] - self.namesFog=[ "", "LINEAR"," EXPONENTIAL", "" ] - -########################################################## -# Writing nodes routines -########################################################## - - def writeHeader(self): - bfile = sys.expandpath(Blender.Get('filename')) - self.file.write("#VRML V2.0 utf8\n\n") - self.file.write("# This file was authored with Blender " \ - "(http://www.blender.org/)\n") - self.file.write("# Blender version %s\n" % Blender.Get('version')) - self.file.write("# Blender file %s\n" % sys.basename(bfile)) - self.file.write("# Exported using VRML97 exporter " \ - "v1.55 (2006/01/17)\n\n") - - def writeInline(self): - inlines = Blender.Scene.Get() - allinlines = len(inlines) - if scene != inlines[0]: - return - else: - for i in xrange(allinlines): - nameinline=inlines[i].getName() - if (nameinline not in self.namesStandard) and (i > 0): - self.writeIndented("DEF %s Inline {\n" % \ - (self.cleanStr(nameinline)), 1) - nameinline = nameinline+".wrl" - self.writeIndented("url \"%s\" \n" % nameinline) - self.writeIndented("}\n", -1) - self.writeIndented("\n") - - def writeScript(self): - textEditor = Blender.Text.Get() - alltext = len(textEditor) - for i in xrange(alltext): - nametext = textEditor[i].getName() - nlines = textEditor[i].getNLines() - if (self.proto == 1): - if (nametext == "proto" or nametext == "proto.js" or \ - nametext == "proto.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.writeIndented(alllines[j] + "\n") - elif (self.proto == 0): - if (nametext == "route" or nametext == "route.js" or \ - nametext == "route.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.writeIndented(alllines[j] + "\n") - self.writeIndented("\n") - - def writeViewpoint(self, thisObj): - # NOTE: The transform node above this will take care of - # the position and orientation of the camera - context = scene.getRenderingContext() - ratio = float(context.imageSizeY()) / float(context.imageSizeX()) - temp = ratio * 16 / thisObj.data.getLens() - lens = 2 * math.atan(temp) - lens = min(lens, math.pi) - - self.writeIndented("DEF %s Viewpoint {\n" % \ - (self.cleanStr(thisObj.name)), 1) - self.writeIndented('description "%s" \n' % thisObj.name) - self.writeIndented("position 0.0 0.0 0.0\n") - # Need camera to point to -y in local space to accomodate - # the transforma node above - self.writeIndented("orientation 1.0 0.0 0.0 %f\n" % (-math.pi/2.0)) - self.writeIndented("fieldOfView %.3f\n" % (lens)) - self.writeIndented("}\n", -1) - self.writeIndented("\n") - - def writeFog(self): - if world: - mtype = world.getMistype() - mparam = world.getMist() - grd = world.getHor() - grd0, grd1, grd2 = grd[0], grd[1], grd[2] - else: - return - if (mtype == 1 or mtype == 2): - self.writeIndented("Fog {\n",1) - self.writeIndented('fogType "%s"\n' % self.namesFog[mtype]) - self.writeIndented("color %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("visibilityRange %s\n" % \ - round(mparam[2],self.cp)) - self.writeIndented("}\n",-1) - self.writeIndented("\n") - else: - return - - def writeNavigationInfo(self, scene): - allObj = [] - allObj = list(scene.objects) - headlight = "TRUE" - vislimit = 0.0 - for thisObj in allObj: - objType=thisObj.type - if objType == "Camera": - vislimit = thisObj.data.getClipEnd() - elif objType == "Lamp": - headlight = "FALSE" - self.writeIndented("NavigationInfo {\n",1) - self.writeIndented("headlight %s\n" % headlight) - self.writeIndented("visibilityLimit %s\n" % \ - (round(vislimit,self.cp))) - self.writeIndented("type [\"EXAMINE\", \"ANY\"]\n") - self.writeIndented("avatarSize [0.25, 1.75, 0.75]\n") - self.writeIndented("} \n",-1) - self.writeIndented(" \n") - - def writeSpotLight(self, object, lamp): - # Note: location and orientation are handled by the - # transform node above this object - if world: - ambi = world.getAmb() - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - - # compute cutoff and beamwidth - intensity=min(lamp.energy/1.75,1.0) - beamWidth=((lamp.spotSize*math.pi)/180.0)*.37; - cutOffAngle=beamWidth*1.3 - - radius = lamp.dist*math.cos(beamWidth) - self.writeIndented("DEF %s SpotLight {\n" % \ - self.cleanStr(object.name),1) - self.writeIndented("radius %s\n" % (round(radius,self.cp))) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambientIntensity,self.cp))) - self.writeIndented("intensity %s\n" % (round(intensity,self.cp))) - self.writeIndented("color %s %s %s\n" % \ - (round(lamp.col[0],self.cp), \ - round(lamp.col[1],self.cp), \ - round(lamp.col[2],self.cp))) - self.writeIndented("beamWidth %s\n" % (round(beamWidth,self.cp))) - self.writeIndented("cutOffAngle %s\n" % \ - (round(cutOffAngle,self.cp))) - # Note: point down -Y axis, transform node above will rotate - self.writeIndented("direction 0.0 -1.0 0.0\n") - self.writeIndented("location 0.0 0.0 0.0\n") - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def writeDirectionalLight(self, object, lamp): - # Note: location and orientation are handled by the - # transform node above this object - if world: - ambi = world.getAmb() - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - - intensity=min(lamp.energy/1.75,1.0) - self.writeIndented("DEF %s DirectionalLight {\n" % \ - self.cleanStr(object.name),1) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambientIntensity,self.cp))) - self.writeIndented("color %s %s %s\n" % \ - (round(lamp.col[0],self.cp), \ - round(lamp.col[1],self.cp), \ - round(lamp.col[2],self.cp))) - self.writeIndented("intensity %s\n" % \ - (round(intensity,self.cp))) - # Note: point down -Y axis, transform node above will rotate - self.writeIndented("direction 0.0 -1.0 0.0\n") - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def writePointLight(self, object, lamp): - # Note: location is at origin because parent transform node - # takes care of this - if world: - ambi = world.getAmb() - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - om = object.getMatrix() - intensity=min(lamp.energy/1.75,1.0) - radius = lamp.dist - self.writeIndented("DEF %s PointLight {\n" % \ - self.cleanStr(object.name),1) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambientIntensity,self.cp))) - self.writeIndented("color %s %s %s\n" % \ - (round(lamp.col[0],self.cp), \ - round(lamp.col[1],self.cp), \ - round(lamp.col[2],self.cp))) - self.writeIndented("intensity %s\n" % (round(intensity,self.cp))) - self.writeIndented("location 0.0 0.0 0.0\n") - self.writeIndented("radius %s\n" % radius ) - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def writeNode(self, thisObj): - # Note: location and orientation are handled by the - # transform node above this object - objectname=str(thisObj.getName()) - if objectname in self.namesStandard: - return - else: - self.writeIndented("%s {\n" % objectname,1) - # May need to check that the direction is done right - self.writeIndented("direction 0.0 -1.0 0.0\n") - self.writeIndented("location 0.0 0.0 0.0\n") - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def secureName(self, name): - name = name + str(self.nodeID) - self.nodeID += 1 - if len(name) <= 3: - newname = "_" + str(self.nodeID) - return "%s" % (newname) - else: - for bad in ['"','#',"'",',','.','[','\\',']','{','}']: - name=name.replace(bad,'_') - if name in self.namesReserved: - newname = name[0:3] + "_" + str(self.nodeID) - return "%s" % (newname) - elif name[0].isdigit(): - newname = "_" + name + str(self.nodeID) - return "%s" % (newname) - else: - newname = name - return "%s" % (newname) - - def classifyMesh(self, me, ob): - self.halonode = 0 - self.billnode = 0 - self.facecolors = 0 - self.vcolors = 0 - self.tilenode = 0 - self.colnode = 0 - self.wire = 0 - if me.faceUV: - for face in me.faces: - if (face.mode & Mesh.FaceModes['HALO']): - self.halonode = 1 - if (face.mode & Mesh.FaceModes['BILLBOARD']): - self.billnode = 1 - if (face.mode & Mesh.FaceModes['OBCOL']): - self.facecolors = 1 - if (face.mode & Mesh.FaceModes['SHAREDCOL']): - self.vcolors = 1 - if (face.mode & Mesh.FaceModes['TILES']): - self.tilenode = 1 - if not (face.mode & Mesh.FaceModes['DYNAMIC']): - self.collnode = 1 - if (face.mode & Mesh.FaceModes['TWOSIDE']): - self.twosided = 1 - - # Bit of a crufty trick, but if mesh has vertex colors - # (as a non-face property) and if first material has - # vcol paint set, we export the vertex colors - if (me.vertexColors): - if len(me.materials) > 0: - mat = me.materials[0] - if mat: - if (mat.mode & Blender.Material.Modes['VCOL_PAINT']): - self.vcolors = 1 - else: - self.vcolors = 0 - - # check if object is wireframe only - if ob.drawType == Blender.Object.DrawTypes.WIRE: - # user selected WIRE=2 on the Drawtype=Wire on (F9) Edit page - self.wire = 1 - - ### - ### The next few functions nest Collision/Billboard/Halo nodes. - ### For real mesh data export, jump down to writeMeshData() - ### - def writeMesh(self, ob, normals = 0): - - imageMap={} # set of used images - sided={} # 'one':cnt , 'two':cnt - vColors={} # 'multi':1 - - if (len(ob.modifiers) > 0): - me = Mesh.New() - me.getFromObject(ob.name) - # Careful with the name, the temporary mesh may - # reuse the default name for other meshes. So we - # pick our own name. - me.name = "MOD_%s" % (ob.name) - else: - me = ob.getData(mesh = 1) - - self.classifyMesh(me, ob) - - if (self.collnode): - self.writeCollisionMesh(me, ob, normals) - return - else: - self.writeRegularMesh(me, ob, normals) - return - - def writeCollisionMesh(self, me, ob, normals = 0): - self.writeIndented("Collision {\n",1) - self.writeIndented("collide FALSE\n") - self.writeIndented("children [\n") - - self.writeRegularMesh(me, ob, normals) - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - def writeRegularMesh(self, me, ob, normals = 0): - if (self.billnode): - self.writeBillboardMesh(me, ob, normals) - elif (self.halonode): - self.writeHaloMesh(me, ob, normals) - else: - self.writeMeshData(me, ob, normals) - - def writeBillboardMesh(self, me, ob, normals = 0): - self.writeIndented("Billboard {\n",1) - self.writeIndented("axisOfRotation 0 1 0\n") - self.writeIndented("children [\n") - - self.writeMeshData(me, ob, normals) - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - def writeHaloMesh(self, me, ob, normals = 0): - self.writeIndented("Billboard {\n",1) - self.writeIndented("axisOfRotation 0 0 0\n") - self.writeIndented("children [\n") - - self.writeMeshData(me, ob, normals) - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - ### - ### Here is where real mesh data is written - ### - def writeMeshData(self, me, ob, normals = 0): - meshName = self.cleanStr(me.name) - - if self.meshNames.has_key(meshName): - self.writeIndented("USE ME_%s\n" % meshName, 0) - self.meshNames[meshName]+=1 - if (self.verbose == 1): - print " Using Mesh %s (Blender mesh: %s)\n" % \ - (meshName, me.name) - return - self.meshNames[meshName]=1 - - if (self.verbose == 1): - print " Writing Mesh %s (Blender mesh: %s)\n" % \ - (meshName, me.name) - return - - self.writeIndented("DEF ME_%s Group {\n" % meshName,1) - self.writeIndented("children [\n", 1) - - hasImageTexture = 0 - issmooth = 0 - - maters = me.materials - nummats = len(me.materials) - - # Vertex and Face colors trump materials and image textures - if (self.facecolors or self.vcolors): - if nummats > 0: - self.writeShape(ob, me, 0, None) - else: - self.writeShape(ob, me, -1, None) - - # Do meshes with materials, possibly with image textures - elif nummats > 0: - for matnum in xrange(len(maters)): - images = [] - if me.faceUV: - images = self.getImages(me, matnum) - if len(images) > 0: - for image in images: - self.writeShape(ob, me, matnum, image) - else: - self.writeShape(ob, me, matnum, None) - else: - self.writeShape(ob, me, matnum, None) - else: - if me.faceUV: - images = self.getImages(me, -1) - if len(images) > 0: - for image in images: - self.writeShape(ob, me, -1, image) - else: - self.writeShape(ob, me, -1, None) - else: - self.writeShape(ob, me, -1, None) - - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - def getImages(self, me, matnum): - imageNames = {} - images = [] - for face in me.faces: - if (matnum == -1) or (face.mat == matnum): - if (face.image): - imName = self.cleanStr(face.image.name) - if not imageNames.has_key(imName): - images.append(face.image) - imageNames[imName]=1 - return images - - def writeCoordinates(self, me, meshName): - coordName = "coord_%s" % (meshName) - # look up coord name, use it if available - if self.coordNames.has_key(coordName): - self.writeIndented("coord USE %s\n" % coordName, 0) - self.coordNames[coordName]+=1 - return; - - self.coordNames[coordName]=1 - - #-- vertices - self.writeIndented("coord DEF %s Coordinate {\n" % (coordName), 1) - self.writeIndented("point [\n", 1) - meshVertexList = me.verts - - for vertex in meshVertexList: - vrmlvert = blenvert = Mathutils.Vector(vertex.co) - if export_rotate_z_to_y.val: - vrmlvert = M_blen2vrml * vrmlvert - self.writeUnindented("%s %s %s\n " % \ - (vrmlvert[0], \ - vrmlvert[1], \ - vrmlvert[2])) - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - self.writeIndented("\n") - - def testShape(self, ob, me, matnum, image): - if ( (matnum == -1) and (image == None) ): - if ( len(me.faces) > 0 ): - return True - # Check if any faces the material or image - for face in me.faces: - if (matnum == -1): - if (face.image == image): - return True - elif (image == None): - if (face.mat == matnum): - return True - else: - if ((face.image == image) and (face.mat == matnum)): - return True - - return False - - def writeShape(self, ob, me, matnum, image): - # matnum == -1 means don't check the face.mat - # image == None means don't check face.image - - if ( not self.testShape(ob, me, matnum, image) ): - return False - - self.writeIndented("Shape {\n",1) - - self.writeIndented("appearance Appearance {\n", 1) - if (matnum != -1): - mater = me.materials[matnum] - if (mater): - self.writeMaterial(mater, self.cleanStr(mater.name,'')) - if (mater.mode & Blender.Material.Modes['TEXFACE']): - if image != None: - self.writeImageTexture(image.name, image.filename) - else: - self.writeDefaultMaterial() - else: - if image != None: - self.writeImageTexture(image.name, image.filename) - - self.writeIndented("}\n", -1) - - self.writeGeometry(ob, me, matnum, image) - - self.writeIndented("}\n", -1) - - return True - - def writeGeometry(self, ob, me, matnum, image): - - #-- IndexedFaceSet or IndexedLineSet - meshName = self.cleanStr(me.name) - - # check if object is wireframe only - if (self.wire): - ifStyle="IndexedLineSet" - else: - # user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5 - ifStyle="IndexedFaceSet" - - self.writeIndented("geometry %s {\n" % ifStyle, 1) - if not self.wire: - if self.twosided == 1: - self.writeIndented("solid FALSE\n") - else: - self.writeIndented("solid TRUE\n") - - self.writeCoordinates(me, meshName) - self.writeCoordIndex(me, meshName, matnum, image) - self.writeTextureCoordinates(me, meshName, matnum, image) - if self.facecolors: - self.writeFaceColors(me) - elif self.vcolors: - self.writeVertexColors(me) - self.writeIndented("}\n", -1) - - def writeCoordIndex(self, me, meshName, matnum, image): - meshVertexList = me.verts - self.writeIndented("coordIndex [\n", 1) - coordIndexList=[] - for face in me.faces: - if (matnum == -1) or (face.mat == matnum): - if (image == None) or (face.image == image): - cordStr="" - for v in face.verts: - indx=v.index - cordStr = cordStr + "%s " % indx - self.writeUnindented(cordStr + "-1, \n") - self.writeIndented("]\n", -1) - - def writeTextureCoordinates(self, me, meshName, matnum, image): - if (image == None): - return - - texCoordList=[] - texIndexList=[] - j=0 - - for face in me.faces: - coordStr = "" - indexStr = "" - if (matnum == -1) or (face.mat == matnum): - if (face.image == image): - for i in xrange(len(face.verts)): - uv = face.uv[i] - indexStr += "%s " % (j) - coordStr += "%s %s, " % \ - (round(uv[0], self.tp), \ - round(uv[1], self.tp)) - j=j+1 - indexStr += "-1" - texIndexList.append(indexStr) - texCoordList.append(coordStr) - - self.writeIndented("texCoord TextureCoordinate {\n", 1) - self.writeIndented("point [\n", 1) - for coord in texCoordList: - self.writeUnindented("%s\n" % (coord)) - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - self.writeIndented("texCoordIndex [\n", 1) - for ind in texIndexList: - self.writeUnindented("%s\n" % (ind)) - self.writeIndented("]\n", -1) - - def writeFaceColors(self, me): - self.writeIndented("colorPerVertex FALSE\n") - self.writeIndented("color Color {\n",1) - self.writeIndented("color [\n", 1) - - for face in me.faces: - if face.col: - c=face.col[0] - if self.verbose >= 2: - print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b) - - aColor = self.rgbToFS(c) - self.writeUnindented("%s,\n" % aColor) - self.writeIndented("]\n",-1) - self.writeIndented("}\n",-1) - - def writeVertexColors(self, me): - self.writeIndented("colorPerVertex TRUE\n") - self.writeIndented("color Color {\n",1) - self.writeIndented("color [\n\t\t\t\t\t\t", 1) - - cols = [None] * len(me.verts) - - for face in me.faces: - for vind in xrange(len(face.v)): - vertex = face.v[vind] - i = vertex.index - if cols[i] == None: - cols[i] = face.col[vind] - - for i in xrange(len(me.verts)): - aColor = self.rgbToFS(cols[i]) - self.writeUnindented("%s\n" % aColor) - - self.writeIndented("\n", 0) - self.writeIndented("]\n",-1) - self.writeIndented("}\n",-1) - - def writeDefaultMaterial(self): - matName = "default" - - # look up material name, use it if available - if self.matNames.has_key(matName): - self.writeIndented("material USE MA_%s\n" % matName) - self.matNames[matName]+=1 - return; - - self.matNames[matName]=1 - self.writeIndented("material DEF MA_%s Material {\n" % matName, 1) - self.writeIndented("diffuseColor 0.8 0.8 0.8\n") - self.writeIndented("specularColor 1.0 1.0 1.0\n") - self.writeIndented("shininess 0.5\n") - self.writeIndented("transparency 0.0\n") - self.writeIndented("}\n",-1) - - def writeMaterial(self, mat, matName): - # look up material name, use it if available - if self.matNames.has_key(matName): - self.writeIndented("material USE MA_%s\n" % matName) - self.matNames[matName]+=1 - return; - - self.matNames[matName]=1 - - ambient = mat.amb/3 - diffuseR, diffuseG, diffuseB = \ - mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2] - if world: - ambi = world.getAmb() - ambi0, ambi1, ambi2 = (ambi[0]*mat.amb) * 2, \ - (ambi[1]*mat.amb) * 2, \ - (ambi[2]*mat.amb) * 2 - else: - ambi0, ambi1, ambi2 = 0, 0, 0 - emisR, emisG, emisB = (diffuseR*mat.emit+ambi0) / 2, \ - (diffuseG*mat.emit+ambi1) / 2, \ - (diffuseB*mat.emit+ambi2) / 2 - - shininess = mat.hard/512.0 - specR = (mat.specCol[0]+0.001) / (1.25/(mat.getSpec()+0.001)) - specG = (mat.specCol[1]+0.001) / (1.25/(mat.getSpec()+0.001)) - specB = (mat.specCol[2]+0.001) / (1.25/(mat.getSpec()+0.001)) - transp = 1 - mat.alpha - matFlags = mat.getMode() - if matFlags & Blender.Material.Modes['SHADELESS']: - ambient = 1 - shine = 1 - specR = emitR = diffuseR - specG = emitG = diffuseG - specB = emitB = diffuseB - self.writeIndented("material DEF MA_%s Material {\n" % matName, 1) - self.writeIndented("diffuseColor %s %s %s\n" % \ - (round(diffuseR,self.cp), \ - round(diffuseG,self.cp), \ - round(diffuseB,self.cp))) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambient,self.cp))) - self.writeIndented("specularColor %s %s %s\n" % \ - (round(specR,self.cp), \ - round(specG,self.cp), \ - round(specB,self.cp))) - self.writeIndented("emissiveColor %s %s %s\n" % \ - (round(emisR,self.cp), \ - round(emisG,self.cp), \ - round(emisB,self.cp))) - self.writeIndented("shininess %s\n" % (round(shininess,self.cp))) - self.writeIndented("transparency %s\n" % (round(transp,self.cp))) - self.writeIndented("}\n",-1) - - def writeImageTexture(self, name, filename): - if self.texNames.has_key(name): - self.writeIndented("texture USE %s\n" % self.cleanStr(name)) - self.texNames[name] += 1 - return - else: - self.writeIndented("texture DEF %s ImageTexture {\n" % \ - self.cleanStr(name), 1) - self.writeIndented('url "%s"\n' % \ - filename.split("\\")[-1].split("/")[-1]) - self.writeIndented("}\n",-1) - self.texNames[name] = 1 - - def writeBackground(self): - if world: - worldname = world.getName() - else: - return - blending = world.getSkytype() - grd = world.getHor() - grd0, grd1, grd2 = grd[0], grd[1], grd[2] - sky = world.getZen() - sky0, sky1, sky2 = sky[0], sky[1], sky[2] - mix0, mix1, mix2 = grd[0]+sky[0], grd[1]+sky[1], grd[2]+sky[2] - mix0, mix1, mix2 = mix0/2, mix1/2, mix2/2 - if worldname in self.namesStandard: - self.writeIndented("Background {\n",1) - else: - self.writeIndented("DEF %s Background {\n" % \ - self.secureName(worldname),1) - # No Skytype - just Hor color - if blending == 0: - self.writeIndented("groundColor %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("skyColor %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - # Blend Gradient - elif blending == 1: - self.writeIndented("groundColor [ %s %s %s, " % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("groundAngle [ 1.57, 1.57 ]\n") - self.writeIndented("skyColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("skyAngle [ 1.57, 1.57 ]\n") - # Blend+Real Gradient Inverse - elif blending == 3: - self.writeIndented("groundColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("groundAngle [ 1.57, 1.57 ]\n") - self.writeIndented("skyColor [ %s %s %s, " % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("skyAngle [ 1.57, 1.57 ]\n") - # Paper - just Zen Color - elif blending == 4: - self.writeIndented("groundColor %s %s %s\n" % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("skyColor %s %s %s\n" % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - # Blend+Real+Paper - komplex gradient - elif blending == 7: - self.writeIndented("groundColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("groundAngle [ 1.57, 1.57 ]\n") - self.writeIndented("skyColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(grd0,self.cp), - round(grd1,self.cp), - round(grd2,self.cp))) - self.writeIndented("skyAngle [ 1.57, 1.57 ]\n") - # Any Other two colors - else: - self.writeIndented("groundColor %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("skyColor %s %s %s\n" % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - alltexture = len(worldmat) - for i in xrange(alltexture): - namemat = worldmat[i].getName() - pic = worldmat[i].getImage() - if pic: - # Stripped path. - pic_path= pic.filename.split('\\')[-1].split('/')[-1] - if namemat == "back": - self.writeIndented('backUrl "%s"\n' % pic_path) - elif namemat == "bottom": - self.writeIndented('bottomUrl "%s"\n' % pic_path) - elif namemat == "front": - self.writeIndented('frontUrl "%s"\n' % pic_path) - elif namemat == "left": - self.writeIndented('leftUrl "%s"\n' % pic_path) - elif namemat == "right": - self.writeIndented('rightUrl "%s"\n' % pic_path) - elif namemat == "top": - self.writeIndented('topUrl "%s"\n' % pic_path) - self.writeIndented("}",-1) - self.writeIndented("\n\n") - - def writeLamp(self, ob): - la = ob.data - laType = la.getType() - - if laType == Lamp.Types.Lamp: - self.writePointLight(ob, la) - elif laType == Lamp.Types.Spot: - self.writeSpotLight(ob, la) - elif laType == Lamp.Types.Sun: - self.writeDirectionalLight(ob, la) - else: - self.writeDirectionalLight(ob, la) - - def writeObject(self, ob): - - obname = self.cleanStr(ob.name) - - try: - obtype=ob.getType() - except AttributeError: - print "Error: Unable to get type info for %s" % obname - return - - if self.verbose >= 1: - print "++ Writing %s object %s (Blender name: %s)\n" % \ - (obtype, obname, ob.name) - - # Note: I am leaving empties out for now -- the original - # script does some really weird stuff with empties - if ( (obtype != "Camera") and \ - (obtype != "Mesh") and \ - (obtype != "Lamp") ): - print "Info: Ignoring [%s], object type [%s] " \ - "not handle yet" % (obname, obtype) - return - - ob_matrix = Mathutils.Matrix(ob.getMatrix('worldspace')) - if export_rotate_z_to_y.val: - matrix = M_blen2vrml * ob_matrix * M_vrml2blen - else: - matrix = ob_matrix - e = matrix.rotationPart().toEuler() - - v = matrix.translationPart() - (axis, angle) = self.eulToVecRot(self.deg2rad(e.x), \ - self.deg2rad(e.y), \ - self.deg2rad(e.z)) - - mrot = e.toMatrix().resize4x4() - try: - mrot.invert() - except: - print "Warning: %s has degenerate transformation!" % (obname) - return - - diag = matrix * mrot - sizeX = diag[0][0] - sizeY = diag[1][1] - sizeZ = diag[2][2] - - if self.verbose >= 1: - print " Transformation:\n" \ - " loc: %f %f %f\n" \ - " size: %f %f %f\n" \ - " Rot: (%f %f %f), %f\n" % \ - (v.x, v.y, v.z, \ - sizeX, sizeY, sizeZ, \ - axis[0], axis[1], axis[2], angle) - - self.writeIndented("DEF OB_%s Transform {\n" % (obname), 1) - self.writeIndented("translation %f %f %f\n" % \ - (v.x, v.y, v.z) ) - - self.writeIndented("rotation %f %f %f %f\n" % \ - (axis[0],axis[1],axis[2],angle) ) - - self.writeIndented("scale %f %f %f\n" % \ - (sizeX, sizeY, sizeZ) ) - - self.writeIndented("children [\n", 1) - - self.writeObData(ob) - - self.writeIndented("]\n", -1) # end object - self.writeIndented("}\n", -1) # end object - - def writeObData(self, ob): - - obtype = ob.getType() - - if obtype == "Camera": - self.writeViewpoint(ob) - elif obtype == "Mesh": - self.writeMesh(ob) - elif obtype == "Lamp": - self.writeLamp(ob) - elif obtype == "Empty": - self.writeNode(ob) - - -########################################################## -# export routine -########################################################## - - def export(self, scene, world, worldmat): - print "Info: starting VRML97 export to " + self.filename + "..." - self.writeHeader() - self.writeScript() - self.writeNavigationInfo(scene) - self.writeBackground() - self.writeFog() - self.proto = 0 - allObj = [] - if export_selection_only.val: - allObj = list(scene.objects.context) - else: - allObj = list(scene.objects) - self.writeInline() - - for thisObj in allObj: - self.writeObject(thisObj) - - if not export_selection_only.val: - self.writeScript() - self.cleanup() - -########################################################## -# Utility methods -########################################################## - - def cleanup(self): - self.file.close() - self.texNames={} - self.matNames={} - self.indentLevel=0 - print "Info: finished VRML97 export to %s\n" % self.filename - - def cleanStr(self, name, prefix='rsvd_'): - """cleanStr(name,prefix) - try to create a valid VRML DEF \ - name from object name""" - - newName=name[:] - if len(newName) == 0: - self.nNodeID+=1 - return "%s%d" % (prefix, self.nNodeID) - - if newName in self.namesReserved: - newName='%s%s' % (prefix,newName) - - if newName[0].isdigit(): - newName='%s%s' % ('_',newName) - - for bad in (' ','"','#',"'",',','.','[','\\',']','{','}'): - newName=newName.replace(bad,'_') - return newName - - def rgbToFS(self, c): - s = "%s %s %s" % \ - (round(c.r/255.0,self.cp), \ - round(c.g/255.0,self.cp), \ - round(c.b/255.0,self.cp)) - return s - - def rad2deg(self, v): - return round(v*180.0/math.pi,4) - - def deg2rad(self, v): - return (v*math.pi)/180.0; - - def eulToVecRot(self, RotX, RotY, RotZ): - - ti = RotX*0.5 - tj = RotY*0.5 - th = RotZ*0.5 - - ci = math.cos(ti) - cj = math.cos(tj) - ch = math.cos(th) - si = math.sin(ti) - sj = math.sin(tj) - sh = math.sin(th) - cc = ci*ch - cs = ci*sh - sc = si*ch - ss = si*sh - - q0 = cj*cc + sj*ss - q1 = cj*sc - sj*cs - q2 = cj*ss + sj*cc - q3 = cj*cs - sj*sc - - angle = 2 * math.acos(q0) - if (math.fabs(angle) < 0.000001): - axis = [1.0, 0.0, 0.0] - else: - sphi = 1.0/math.sqrt(1.0 - (q0*q0)) - axis = [q1 * sphi, q2 * sphi, q3 * sphi] - - a = Mathutils.Vector(axis) - a.normalize() - return ([a.x, a.y, a.z], angle) - - - # For writing well formed VRML code - #---------------------------------- - def writeIndented(self, s, inc=0): - if inc < 1: - self.indentLevel = self.indentLevel + inc - - self.file.write( self.indentLevel*"\t" + s) - - if inc > 0: - self.indentLevel = self.indentLevel + inc - - # Sometimes better to not have too many - # tab characters in a long list, for file size - #---------------------------------- - def writeUnindented(self, s): - self.file.write(s) - -########################################################## -# Callbacks, needed before Main -########################################################## - -def select_file(filename): - if sys.exists(filename) and _safeOverwrite: - result = \ - Draw.PupMenu("File Already Exists, Overwrite?%t|Yes%x1|No%x0") - if(result != 1): - return - - if not filename.endswith(extension): - filename += extension - - wrlexport=VRML2Export(filename) - wrlexport.export(scene, world, worldmat) - -######################################################### -# UI and Registry utilities -######################################################### - -export_selection_only = Draw.Create(0) -export_rotate_z_to_y = Draw.Create(1) -export_compressed = Draw.Create(0) - -def save_to_registry(): - d = {} - d['selection_only'] = export_selection_only.val - d['rotate_z_to_y'] = export_rotate_z_to_y.val - d['compressed'] = export_compressed.val - Registry.SetKey('vrml97_export', d, True) - -def load_from_registry(): - d = Registry.GetKey('vrml97_export', True) - if d: - try: - export_selection_only.val = d['selection_only'] - export_rotate_z_to_y.val = d['rotate_z_to_y'] - export_compressed.val = d['compressed'] - except: save_to_registry() # If data is not valid, rewrite it. - -def show_popup(): - pup_block = [ - ('Selection Only', export_selection_only, 'Only export objects in visible selection. Else export whole scene.'), - ('Rotate +Z to +Y', export_rotate_z_to_y, 'Rotate such that +Z axis (Blender up) becomes +Y (VRML up).'), - ('Compress', export_compressed, 'Generate a .wrz file (normal VRML compressed by gzip).') - ] - return Draw.PupBlock('Export VRML 97...', pup_block) - -######################################################### -# main routine -######################################################### - -load_from_registry() - -# Note that show_popup must be done before Blender.Window.FileSelector, -# because export_compressed affects the suggested extension of resulting -# file. - -if show_popup(): - save_to_registry() - if export_compressed.val: - extension=".wrz" - from gzip import * - else: - extension=".wrl" - Blender.Window.FileSelector(select_file, "Export VRML97", \ - sys.makename(ext=extension)) |