diff options
Diffstat (limited to 'intern/python/modules/Converter/importer/VRMLimporter.py')
-rw-r--r-- | intern/python/modules/Converter/importer/VRMLimporter.py | 988 |
1 files changed, 988 insertions, 0 deletions
diff --git a/intern/python/modules/Converter/importer/VRMLimporter.py b/intern/python/modules/Converter/importer/VRMLimporter.py new file mode 100644 index 00000000000..e2bcea6a51e --- /dev/null +++ b/intern/python/modules/Converter/importer/VRMLimporter.py @@ -0,0 +1,988 @@ +# VRML import prototype +# +# strubi@blender.nl +# + +"""VRML import module + + This is a prototype for VRML97 file import + + Supported: + + - Object hierarchies, transform collapsing (optional) + + - Meshes (IndexedFaceSet, no Basic primitives yet) + + - Materials + + - Textures (jpg, tga), conversion option from alien formats + +""" + +import Blender.sys as os # Blender os emulation +from beta import Scenegraph + +Transform = Scenegraph.Transform + +import beta.Objects + +_b = beta.Objects + +#from Blender import Mesh +Color = _b.Color +DEFAULTFLAGS = _b.DEFAULTFLAGS +FACEFLAGS = _b.FACEFLAGS +shadowNMesh = _b.shadowNMesh + +quat = Scenegraph.quat # quaternion math +vect = quat.vect # vector math module +from vrml import loader + +#### GLOBALS + +OB = Scenegraph.Object.Types # CONST values +LA = Scenegraph.Lamp.Types + +g_level = 1 +g_supported_fileformats = ["jpg", "jpeg", "tga"] + +#### OPTIONS + +OPTIONS = {'cylres' : 16, # resolution of cylinder + 'flipnormals' : 0, # flip normals (force) + 'mat_as_vcol' : 0, # material as vertex color - warning, this increases mem usage drastically on big files + 'notextures' : 0, # no textures - saves some memory + 'collapseDEFs' : 0, # collapse DEF nodes + 'collapseTF' : 0, # collapse Transforms (as far as possible, + # i.e. currently to Object transform level) + } + +#### CONSTANTS + +LAYER_EMPTY = (1 << 2) +LAYER_LAMP = (1 << 4) +LAYER_CAMERA = 1 + (1 << 4) + +CREASE_ANGLE_THRESHOLD = 0.45 # radians + +PARSE_TIME = (loader.parser.IMPORT_PARSE_TIME ) +PROCESS_TIME = (1.0 - PARSE_TIME ) +PROGRESS_DEPTH = loader.parser.PROGRESS_DEPTH +VERBOSE_DEPTH = PROGRESS_DEPTH + +#### DEBUG + +def warn(text): + print "###", text + +def debug2(text): + print (g_level - 1) * 4 * " " + text + +def verbose(text): + print text + +def quiet(text): + pass + +debug = quiet + +#### ERROR message filtering: + +g_error = {} # dictionary for non-fatal errors to mark whether an error + # was already reported + +def clrError(): + global g_error + g_error['toomanyfaces'] = 0 + +def isError(name): + return g_error[name] + +def setError(name): + global g_error + g_error[name] = 1 + +#### ERROR handling + +class baseError: + def __init__(self, value): + self.value = value + def __str__(self): + return `self.value` + +class MeshError(baseError): + pass + +UnfinishedError = loader.parser.UnfinishedError + +########################################################## +# HELPER ROUTINES + +def assignImage(f, img): + f.image = img + +def assignUV(f, uv): + if len(uv) != len(f.v): + uv = uv[:len(f.v)] + #raise MeshError, "Number of UV coordinates does not match number of vertices in face" + f.uv = [] + for u in uv: + f.uv.append((u[0], u[1])) # make sure it's a tuple + + +#### VRML STUFF + +# this is used for transform collapsing +class TransformStack: + def __init__(self): + self.stack = [Transform()] + def push(self, t): + self.stack.append(t) + def pop(self): + return self.stack.pop() + def last(self): + return self.stack[-1] + +def fromVRMLTransform(tfnode): + t = Transform() + s = tfnode.scale + t.scale = (s[0], s[1], s[2]) + r = tfnode.rotation + if r[0] == 0.0 and r[1] == 0.0 and r[2] == 0.0: + rotaxis = (0.0, 0.0, 1.0) + ang = 0.0 + else: + rotaxis = vect.norm3(r[:3]) + ang = r[3] + + #t.rotation = (rotaxis, ang) + t.calcRotfromAxis((rotaxis, ang)) + tr = tfnode.translation + t.translation = (tr[0], tr[1], tr[2]) + # XXX more to come.. + return t + + +### TODO: enable material later on +#class dummyMaterial: + #def setMode(self, *args): + #pass + +def fromVRMLMaterial(mat): + name = mat.DEF + from Blender import Material + m = Material.New(name) + + m.rgbCol = mat.diffuseColor + m.alpha = 1.0 - mat.transparency + m.emit = vect.len3(mat.emissiveColor) + if m.Emit > 0.01: + if vect.cross(mat.diffuseColor, mat.emissiveColor) > 0.01 * m.Emit: + m.rgbCol = mat.emissiveColor + + m.ref = 1.0 + m.spec = mat.shininess + m.specCol = mat.specularColor + m.amb = mat.ambientIntensity + return m + +# override: +#def fromVRMLMaterial(mat): +# return dummyMaterial() + +def buildVRMLTextureMatrix(tr): + from math import sin, cos + newMat = vect.Matrix + newVec = vect.Vector + # rotmatrix + s = tr.scale + t = tr.translation + c = tr.center + + phi = tr.rotation + + SR = newMat() + C = newMat() + C[2] = newVec(c[0], c[1], 1.0) + + if abs(phi) > 0.00001: + SR[0] = newVec(s[0] * cos(phi), s[1] * sin(phi), 0.0) + SR[1] = newVec(-s[0] * sin(phi), s[1] * cos(phi), 0.0) + else: + SR[0] = newVec(s[0], 0.0, 0.0) + SR[1] = newVec(0.0, s[1], 0.0) + + SR = C * SR * C.inverse() # rotate & scale about rotation center + + T = newMat() + T[2] = newVec(t[0], t[1], 1.0) + return SR * T # texture transform matrix + +def imageConvert(fromfile, tofile): + """This should convert from a image file to another file, type is determined +automatically (on extension). It's currently just a stub - users can override +this function to implement their own converters""" + return 0 # we just fail in general + +def addImage(path, filename): + "returns a possibly existing image which is imported by Blender" + from Blender import Image + img = None + try: + r = filename.rindex('.') + except: + return None + + naked = filename[:r] + ext = filename[r+1:].lower() + + if path: + name = os.sep.join([path, filename]) + file = os.sep.join([path, naked]) + else: + name = filename + file = naked + + if not ext in g_supported_fileformats: + tgafile = file + '.tga' + jpgfile = file + '.jpg' + for f in tgafile, jpgfile: # look for jpg, tga + try: + img = Image.Load(f) + if img: + verbose("couldn't load %s (unsupported).\nFound %s instead" % (name, f)) + return img + except IOError, msg: + pass + try: + imgfile = open(name, "rb") + imgfile.close() + except IOError, msg: + warn("Image %s not found" % name) + return None + + verbose("Format unsupported, trying to convert to %s" % tgafile) + if not imageConvert(name, tgafile): + warn("image conversion failed") + return None + else: + return Image.Load(tgafile) + return None # failed + try: + img = Image.Load(name) + except IOError, msg: + warn("Image %s not found" % name) + return img + # ok, is supported + +def callMethod(_class, method, vnode, newnode, warn = 1): + meth = None + try: + meth = getattr(_class, method) + except AttributeError: + if warn: + unknownType(method) + return None, None + if meth: + return meth(vnode, parent = newnode) + +def unknownType(type): + warn("unsupported:" + repr(type)) + +def getChildren(vnode): + try: + children = vnode.children + except: + children = None + return children + +def getNodeType(vnode): + return vnode.__gi__ + +GroupingNodeTypes = ["Group", "Collision", "Anchor", "Billboard", "Inline", + "LOD", "Switch", "Transform"] + +################################################################################ +# +#### PROCESSING CLASSES + + +class NullProcessor: + def __init__(self, tstack = TransformStack()): + self.stack = tstack + self.walker = None + self.mesh = None + self.ObjectNode = Scenegraph.NodefromData # may be altered... + self.MaterialCache = {} + self.ImageCache = {} + +# This is currently not used XXX +class DEFcollapser(NullProcessor): + """This is for collapsing DEF Transform nodes into a single object""" + def __init__(self): + self.collapsedNodes = [] + + def Transform(self, curnode, parent, **kw): + name = curnode.DEF + if not name: # node is a DEF node + return None, None + + return children, None + + +class Processor(NullProcessor): + """The processor class defines the handler for a VRML Scenegraph node. +Definition of a handler method simply happens by use of the VRML Scenegraph +entity name. + +A handler usually creates a new Scenegraph node in the target scenegraph, +converting the data from the given VRML node. + +A handler takes the arguments: + + curnode: the currently visited VRML node + parent: the previously generated target scenegraph parent node + **kw: additional keywords + +It MUST return: (children, newBnode) where: + children: the children of the current VRML node. These will be further + processed by the processor. If this is not wanted (because they + might have been processed by the handler), None must be returned. + newBnode: the newly created target node or None. + """ + + def _handleProto(self, curnode, parent, **kw): + p = curnode.PROTO + if not p.sceneGraph: + print curnode.__gi__, "unsupported" + return None, None + + def _dummy(self, curnode, parent, **kw): + print curnode.sceneGraph + return None, None + + #def __getattr__(self, name): + #"""If method is not statically defined, look up prototypes""" + #return self._handleProto + + def _currentTransform(self): + return self.stack.last() + + def _parent(self, curnode, parent, trans): + name = curnode.DEF + children = getChildren(curnode) + debug("children: %s" % children) + objects = [] + transforms = [] + groups = [] + isempty = 0 + for c in children: + type = getNodeType(c) + if type == 'Transform': + transforms.append(c) + elif type in GroupingNodeTypes: + groups.append(c) + #else: + elif hasattr(self, type): + objects.append(c) + if transforms or groups or len(objects) != 1: + # it's an empty + if not name: + name = 'EMPTY' + Bnode = self.ObjectNode(None, OB.EMPTY, name) # empty Blender Object node + if options['layers']: + Bnode.object.Layer = LAYER_EMPTY + Bnode.transform = trans + Bnode.update() + isempty = 1 + parent.insert(Bnode) + else: # don't insert extra empty if only one object has children + Bnode = parent + + for node in objects: + c, new = self.walker.walk(node, Bnode) + if not isempty: # only apply transform if no extra transform empty in hierarchy + new.transform = trans + Bnode.insert(new) + for node in transforms: + self.walker.walk(node, Bnode) + for node in groups: + self.walker.walk(node, Bnode) + + return None, None + + def sceneGraph(self, curnode, parent, **kw): + parent.type = 'ROOT' + return curnode.children, None + + def Transform(self, curnode, parent, **kw): + # we support 'center' and 'scaleOrientation' by inserting + # another Empty in between the Transforms + + t = fromVRMLTransform(curnode) + cur = self._currentTransform() + + chainable = 0 + + if OPTIONS['collapseTF']: + try: + cur = cur * t # chain transforms + except: + cur = self._currentTransform() + chainable = 1 + + self.stack.push(cur) + + # here comes the tricky hacky transformation conversion + + # TODO: SR not supported yet + + if chainable == 1: # collapse, but not chainable + # insert extra transform: + Bnode = self.ObjectNode(None, OB.EMPTY, 'Transform') # Empty + Bnode.transform = cur + parent.insert(Bnode) + parent = Bnode + + c = curnode.center + if c != [0.0, 0.0, 0.0]: + chainable = 1 + trans = Transform() + trans.translation = (-c[0], -c[1], -c[2]) + tr = t.translation + t.translation = (tr[0] + c[0], tr[1] + c[1], tr[2] + c[2]) + + Bnode = self.ObjectNode(None, OB.EMPTY, 'C') # Empty + Bnode.transform = t + parent.insert(Bnode) + parent = Bnode + else: + trans = t + + if chainable == 2: # collapse and is chainable + # don't parent, insert into root node: + for c in getChildren(curnode): + dummy, node = self.walker.walk(c, parent) # skip transform node, insert into parent + if node: # a valid Blender node + node.transform = cur + else: + self._parent(curnode, parent, trans) + + + self.stack.pop() + return None, None + + def Switch(self, curnode, parent, **kw): + return None, None + + def Group(self, curnode, parent, **kw): + if OPTIONS['collapseTF']: + cur = self._currentTransform() + # don't parent, insert into root node: + children = getChildren(curnode) + for c in children: + dummy, node = self.walker.walk(c, parent) # skip transform node, insert into parent + if node: # a valid Blender node + node.transform = cur + else: + t = Transform() + self._parent(curnode, parent, t) + return None, None + + def Collision(self, curnode, parent, **kw): + return self.Group(curnode, parent) + +# def LOD(self, curnode, parent, **kw): +# c, node = self.walker.walk(curnode.level[0], parent) +# parent.insert(node) +# return None, None + + def Appearance(self, curnode, parent, **kw): + # material colors: + mat = curnode.material + self.curColor = mat.diffuseColor + + name = mat.DEF + if name: + if self.MaterialCache.has_key(name): + self.curmaterial = self.MaterialCache[name] + else: + m = fromVRMLMaterial(mat) + self.MaterialCache[name] = m + self.curmaterial = m + else: + if curnode.DEF: + name = curnode.DEF + if self.MaterialCache.has_key(name): + self.curmaterial = self.MaterialCache[name] + else: + m = fromVRMLMaterial(mat) + self.MaterialCache[name] = m + self.curmaterial = m + else: + self.curmaterial = fromVRMLMaterial(mat) + + try: + name = curnode.texture.url[0] + except: + name = None + if name: + if self.ImageCache.has_key(name): + self.curImage = self.ImageCache[name] + else: + self.ImageCache[name] = self.curImage = addImage(self.curpath, name) + else: + self.curImage = None + + tr = curnode.textureTransform + if tr: + self.curtexmatrix = buildVRMLTextureMatrix(tr) + else: + self.curtexmatrix = None + return None, None + + def Shape(self, curnode, parent, **kw): + name = curnode.DEF + debug(name) + #self.mesh = Mesh.rawMesh() + self.mesh = shadowNMesh() + self.mesh.name = name + + # don't mess with the order of these.. + if curnode.appearance: + self.walker.preprocess(curnode.appearance, self.walker.preprocessor) + else: + # no appearance, get colors from shape (vertex colors) + self.curColor = None + self.curImage = None + self.walker.preprocess(curnode.geometry, self.walker.preprocessor) + + if hasattr(self, 'curmaterial'): + self.mesh.assignMaterial(self.curmaterial) + + meshobj = self.mesh.write() # write mesh + del self.mesh + bnode = Scenegraph.ObjectNode(meshobj, OB.MESH, name) + if name: + curnode.setTargetnode(bnode) # mark as already processed + return None, bnode + + def Box(self, curnode, parent, **kw): + col = apply(Color, self.curColor) + + faces = [] + x, y, z = curnode.size + x *= 0.5; y *= 0.5; z *= 0.5 + name = curnode.DEF + m = self.mesh + v0 = m.addVert((-x, -y, -z)) + v1 = m.addVert(( x, -y, -z)) + v2 = m.addVert(( x, y, -z)) + v3 = m.addVert((-x, y, -z)) + v4 = m.addVert((-x, -y, z)) + v5 = m.addVert(( x, -y, z)) + v6 = m.addVert(( x, y, z)) + v7 = m.addVert((-x, y, z)) + + flags = DEFAULTFLAGS + if not self.curImage: + uvflag = 1 + else: + uvflag = 0 + + m.addFace([v3, v2, v1, v0], flags, uvflag) + m.addFace([v0, v1, v5, v4], flags, uvflag) + m.addFace([v1, v2, v6, v5], flags, uvflag) + m.addFace([v2, v3, v7, v6], flags, uvflag) + m.addFace([v3, v0, v4, v7], flags, uvflag) + m.addFace([v4, v5, v6, v7], flags, uvflag) + + for f in m.faces: + f.col = [col, col, col, col] + return None, None + + def Viewpoint(self, curnode, parent, **kw): + t = Transform() + r = curnode.orientation + name = 'View_' + curnode.description + t.calcRotfromAxis((r[:3], r[3])) + t.translation = curnode.position + Bnode = self.ObjectNode(None, OB.CAMERA, name) # Empty + Bnode.object.Layer = LAYER_CAMERA + Bnode.transform = t + return None, Bnode + + def DirectionalLight(self, curnode, parent, **kw): + loc = (0.0, 10.0, 0.0) + l = self._lamp(curnode, loc) + l.object.data.type = LA.SUN + return None, l + + def PointLight(self, curnode, parent, **kw): + l = self._lamp(curnode, curnode.location) + l.object.data.type = LA.LOCAL + return None, l + + def _lamp(self, curnode, location): + t = Transform() + name = curnode.DEF + energy = curnode.intensity + t.translation = location + Bnode = self.ObjectNode(None, OB.LAMP, "Lamp") + Bnode.object.data.energy = energy * 5.0 + if options['layers']: + Bnode.object.Layer = LAYER_LAMP + Bnode.transform = t + return Bnode + + def IndexedFaceSet(self, curnode, **kw): + matxvec = vect.matxvec + mesh = self.mesh + debug("IFS, read mesh") + + texcoo = curnode.texCoord + uvflag = 0 + + if curnode.color: + colors = curnode.color.color + if curnode.colorIndex: # we have color indices + colindex = curnode.colorIndex + else: + colindex = curnode.coordIndex + if not texcoo: + uvflag = 1 + else: + colors = None + + faceflags = DEFAULTFLAGS + + if not texcoo and OPTIONS['mat_as_vcol'] and self.curColor: + uvflag = 1 + col = apply(Color, self.curColor) + elif self.curImage: + faceflags += FACEFLAGS.TEX + +# MAKE VERTICES + + coo = curnode.coord + ncoo = len(coo.point) + + if curnode.normal: # normals defined + normals = curnode.normal.vector + if curnode.normalPerVertex and len(coo.point) == len(normals): + self.mesh.recalc_normals = 0 + normindex = curnode.normalIndex + i = 0 + for v in coo.point: + newv = mesh.addVert(v) + n = newv.no + n[0], n[1], n[2] = normals[normindex[i]] + i += 1 + else: + for v in coo.point: + mesh.addVert(v) + else: + for v in coo.point: + mesh.addVert(v) + if curnode.creaseAngle < CREASE_ANGLE_THRESHOLD: + self.mesh.smooth = 1 + + nvertices = len(mesh.vertices) + if nvertices != ncoo: + print "todo: %d, done: %d" % (ncoo, nvertices) + raise RuntimeError, "FATAL: could not create all vertices" + +# MAKE FACES + + index = curnode.coordIndex + vlist = [] + + flip = OPTIONS['flipnormals'] + facecount = 0 + vertcount = 0 + + cols = [] + if curnode.colorPerVertex: # per vertex colors + for i in index: + if i == -1: + if flip or (curnode.ccw == 0 and not flip): # counterclockwise face def + vlist.reverse() + f = mesh.addFace(vlist, faceflags, uvflag) + if uvflag or colors: + f.col = cols + cols = [] + vlist = [] + else: + if colors: + col = apply(Color, colors[colindex[vertcount]]) + cols.append(col) + vertcount += 1 + v = mesh.vertices[i] + vlist.append(v) + else: # per face colors + for i in index: + if i == -1: + if flip or (curnode.ccw == 0 and not flip): # counterclockwise face def + vlist.reverse() + f = mesh.addFace(vlist, faceflags, uvflag) + facecount += 1 + + if colors: + col = apply(Color, colors[colindex[facecount]]) + cols = len(f.v) * [col] + + if uvflag or colors: + f.col = cols + vlist = [] + else: + v = mesh.vertices[i] + vlist.append(v) + +# TEXTURE COORDINATES + + if not texcoo: + return None, None + + self.curmaterial.setMode("traceable", "shadow", "texFace") + m = self.curtexmatrix + if m: # texture transform exists: + for uv in texcoo.point: + v = (uv[0], uv[1], 1.0) + v1 = matxvec(m, v) + uv[0], uv[1] = v1[0], v1[1] + + UVindex = curnode.texCoordIndex + if not UVindex: + UVindex = curnode.coordIndex + # go assign UVs + self.mesh.hasFaceUV(1) + j = 0 + uv = [] + for i in UVindex: + if i == -1: # flush + if not curnode.ccw: + uv.reverse() + assignUV(f, uv) + assignImage(f, self.curImage) + uv = [] + j +=1 + else: + f = mesh.faces[j] + uv.append(texcoo.point[i]) + return None, None + +class PostProcessor(NullProcessor): + def Shape(self, curnode, **kw): + pass + return None, None + def Transform(self, curnode, **kw): + return None, None + +class Walker: + """The node visitor (walker) class for VRML nodes""" + def __init__(self, pre, post = NullProcessor(), progress = None): + self.scene = Scenegraph.BScene() + self.preprocessor = pre + self.postprocessor = post + pre.walker = self # processor knows about walker + post.walker = self + self.nodes = 1 + self.depth = 0 + self.progress = progress + self.processednodes = 0 + + def walk(self, vnode, parent): + """Essential walker routine. It walks along the scenegraph nodes and +processes them according to its pre/post processor methods. + +The preprocessor methods return the children of the node remaining +to be processed or None. Also, a new created target node is returned. +If the target node is == None, the current node will be skipped in the +target scenegraph generation. If it is a valid node, the walker routine +inserts it into the 'parent' node of the target scenegraph, which +must be a valid root node on first call, leading us to the example usage: + + p = Processor() + w = Walker(p, PostProcessor()) + root = Scenegraph.RootNode() + w.walk(SG, root) # SG is a VRML scenegraph + """ + global g_level #XXX + self.depth += 1 + g_level = self.depth + if self.depth < PROGRESS_DEPTH: + self.processednodes += 1 + if self.progress: + ret = self.progress(PARSE_TIME + PROCESS_TIME * float(self.processednodes) / self.nodes) + if not ret: + progress(1.0) + raise UnfinishedError, "User cancelled conversion" + + # if vnode has already been processed, call Linker method, Processor method otherwise + id = vnode.DEF # get name + if not id: + id = 'Object' + + processed = vnode.getTargetnode() + if processed: # has been processed ? + debug("linked obj: %s" % id) + children, bnode = self.link(processed, parent) + else: + children, bnode = self.preprocess(vnode, parent) + + if not bnode: + bnode = parent # pass on + else: + parent.insert(bnode) # insert into SG + + if children: + for c in children: + self.walk(c, bnode) + if not processed: + self.postprocess(vnode, bnode) + + self.depth -= 1 + + return children, bnode + + def link(self, bnode, parent): + """Link already processed data""" + # link data: + new = bnode.clone() + if not new: + raise RuntimeError, "couldn't clone object" + return None, new + + def preprocess(self, vnode, newnode = None): + """Processes a VRML node 'vnode' and returns a custom node. The processor must +be specified in 'p'. +Optionally, a custom parent node (previously created) is passed as 'newnode'.""" + + pre = "pre" + + nodetype = vnode.__gi__ + + debug(pre + "process:" + repr(nodetype) + " " + vnode.DEF) + return callMethod(self.preprocessor, nodetype, vnode, newnode) + + def postprocess(self, vnode, newnode = None): + """Postprocessing of a VRML node, see Walker.preprocess()""" + + nodetype = vnode.__gi__ + pre = "post" + + debug(pre + "process:" + repr(nodetype) + " " + vnode.DEF) + return callMethod(self.postprocessor, nodetype, vnode, newnode, 0) + +testfile2 = '/home/strubi/exotic/wrl/BrownTrout1.wrl' +testfile = '/home/strubi/exotic/wrl/examples/VRML_Model_HSL.wrl' + +def fix_VRMLaxes(root, scale): + from Blender import Object, Scene + q = quat.fromRotAxis((1.0, 0.0, 0.0), 1.57079) + empty = Object.New(OB.EMPTY) + empty.layer = LAYER_EMPTY + Scene.getCurrent().link(empty) + node = Scenegraph.ObjectNode(empty, None, "VRMLscene") + node.transform.rotation = q + if scale: + node.transform.scale = (0.01, 0.01, 0.01) + for c in root.children: + node.insert(c) + node.update() + root.children = [node] + +################################################################# +# these are the routines that must be provided for the importer +# interface in blender + +def checkmagic(name): + "check for file magic" + f = open(name, "r") + magic = loader.getFileType(f) + f.close() + if magic == 'vrml': + return 1 + elif magic == 'gzip': + verbose("gzipped file detected") + try: + import gzip + except ImportError, value: + warn("Importing gzip module: %s" % value) + return 0 + + f = gzip.open(name, 'rb') + header = f.readline() + f.close() + if header[:10] == "#VRML V2.0": + return 1 + else: + return 0 + print "unknown file" + return 0 + +g_infotxt = "" + +def progress(done): + from Blender import Window + ret = Window.draw_progressbar(done, g_infotxt) + return ret + +class Counter: + def __init__(self): + self._count = 0 + self.depth = 0 + def count(self, node): + if self.depth >= PROGRESS_DEPTH: + return 0 + + self.depth += 1 + self._count += 1 + if not getChildren(node): + self.depth -= 1 + return 0 + else: + for c in node.children: + self.count(c) + self.depth -= 1 + return self._count + +################################################################################ +# MAIN ROUTINE + +def importfile(name): + + global g_infotxt + global options + global DEFAULTFLAGS + + from Blender import Get # XXX + options = Get('vrmloptions') + DEFAULTFLAGS = FACEFLAGS.LIGHT + FACEFLAGS.DYNAMIC + if options['twoside']: + print "TWOSIDE" + DEFAULTFLAGS |= FACEFLAGS.TWOSIDE + clrError() + g_infotxt = "load & parse file..." + progress(0.0) + root = Scenegraph.RootNode() + try: + l = loader.Loader(name, progress) + SG = l.load() + p = Processor() + w = Walker(p, PostProcessor(), progress) + g_infotxt = "convert data..." + p.curpath = os.path.dirname(name) + print "counting nodes...", + c = Counter() + nodes = c.count(SG) + print "done." + w.nodes = nodes # let walker know about number of nodes parsed # XXX + w.walk(SG, root) + except UnfinishedError, msg: + print msg + + progress(1.0) + fix_VRMLaxes(root, options['autoscale']) # rotate coordinate system: in VRML, y is up! + root.update() # update baselist for proper display + return root |