def run(self): """Run the tool. This method calls the init() and action() method. """ # Custom initialization self.init() # No input file given? Then print the help page and exit if len(self.args)==0: self.optparser.print_help() return # Load plugins self.loadPlugins() # Load the input files... for filename in self.args: if self.options.verbose: print ('Loading "%s"...'%filename) load(filename) # Convert global settings into command line options self.setOptionsFromGlobals() self.cam = self.getCamera() self.action() getScene().clear()
def run(self): """Run the tool. This method calls the init() and action() method. """ # Custom initialization self.init() # No input file given? Then print the help page and exit if len(self.args) == 0: self.optparser.print_help() return # Load plugins self.loadPlugins() # Load the input files... for filename in self.args: if self.options.verbose: print('Loading "%s"...' % filename) load(filename) # Convert global settings into command line options self.setOptionsFromGlobals() self.cam = self.getCamera() self.action() getScene().clear()
def onKeyPress(self, e): # Page down or Enter? if e.keycode == 281 or e.keycode == 13: self.transition_start = getScene().timer().time # Page up elif e.keycode == 280: pass # q (reset cam) elif e.key == "q": getScene().up = vec3(0, 1, 0) self.cam.pos = vec3(0, 0, 5.6) self.cam.target = vec3(0, 0, 0) self.cam.fov = 30 cmds.link(self.cam)
def onKeyPress(self, e): # Page down or Enter? if e.keycode==281 or e.keycode==13: self.transition_start = getScene().timer().time # Page up elif e.keycode==280: pass # q (reset cam) elif e.key=="q": getScene().up = vec3(0,1,0) self.cam.pos = vec3(0,0,5.6) self.cam.target = vec3(0,0,0) self.cam.fov = 30 cmds.link(self.cam)
def drawClear(): """Clear all drawing objects.""" # Clear all markers and lines try: drw = getScene().worldObject("Global_Draw") drw.clear() except KeyError: pass # Clear all texts try: drw = getScene().worldObject("Global_DrawText") drw.geom.clear() except KeyError: pass
def __init__(self, name = "FreeCamera", target = None, fov = 45.0, fstop = 0, focallength = 0, **params): camerabase.CameraBase.__init__(self, name=name, **params) # FOV self.fov_slot = slots.DoubleSlot(fov) self.addSlot("fov", self.fov_slot) # fstop self.fstop_slot = slots.DoubleSlot(fstop) self.addSlot("fstop", self.fstop_slot) # focal length self.focallength_slot = slots.DoubleSlot(focallength) self.addSlot("focallength", self.focallength_slot) # Initial targeting if target!=None: up = getScene().up self.transform = mat4().lookAt(self.pos, vec3(target), up)
def eyeRay(self, x0, y0, width, height): """Return a ray from the eye position through an image point. This method returns a ray whose origin is at the eye position and that goes through a given point on the image plane. The point on the plane is given by (x0, y0) which each ranges from 0 to 1. (0,0) is at the upper left and (1,1) at the lower right. The arguments width and height determine the ratio of the image plane (the absolute values of width and height are irrelevant). The return value is a 2-tuple (p,u) where p is the ray origin and u the normalized direction. Both vectors are given in world space. """ V = self.viewTransformation() P = self.projection(width, height, 1, 10) R = mat4().rotation(pi, vec3(0, 1, 0)) if getScene().handedness == 'l': S = mat4().scaling(vec3(-1, 1, 1)) I = (P * S * R * V).inverse() else: I = (P * R * V).inverse() x = 2.0 * x0 - 1.0 y = 1.0 - 2.0 * y0 q = I * vec3(x, y, 0) p = self.worldtransform[3] p = vec3(p.x, p.y, p.z) return (p, (q - p).normalize())
def onStepFrame(self): if not self.enabled: return t = getScene().timer().time if t < self.starttime or t > self.endtime: return for pd in self.plot_data: pd.data.append((t, pd.slot.getValue())) if self._delay == 0: a = [] for pd in self.plot_data: data = pd.data # There seems to be a bug in Gnuplot.py 1.7 that prevents # data arrays with only one item to be displayed. So the # following is a workaround (the point is just duplicated). if len(data) == 1: data = 2 * data data = Gnuplot.Data(data, title=pd.title) a.append(data) self.gp.plot(*a) self._delay = 0 else: self._delay -= 1
def importFile(self, filename): """Import a Python source file.""" file_globals = {} # Use all globals from the cgkit package # Commented out the following line as is imported from cgkit.all now # file_globals = copy.copy(cgkit.__dict__) # Add some modules... exec "from cgkit.all import *" in file_globals exec "from cgkit.sl import *" in file_globals exec "from math import *" in file_globals # ...and some special global names... scene = globalscene.getScene() file_globals["scene"] = scene file_globals["timer"] = scene.timer() file_globals["worldroot"] = scene.worldRoot() file_globals["eventmanager"] = eventmanager.eventManager() paths = sys.path # Add the directory of the input file to the module search paths # so that local imports do work sys.path = [os.path.abspath(os.path.dirname(filename))] + sys.path # Import the file execfile(filename, file_globals) # Restore the old search paths sys.path = paths
def onStepFrame(self): if not self.enabled: return t = getScene().timer().time if t<self.starttime or t>self.endtime: return for pd in self.plot_data: pd.data.append((t, pd.slot.getValue())) if self._delay==0: a = [] for pd in self.plot_data: data = pd.data # There seems to be a bug in Gnuplot.py 1.7 that prevents # data arrays with only one item to be displayed. So the # following is a workaround (the point is just duplicated). if len(data)==1: data = 2*data data = Gnuplot.Data(data, title=pd.title) a.append(data) self.gp.plot(*a) self._delay = 0 else: self._delay -= 1
def eyeRay(self, x0, y0, width, height): """Return a ray from the eye position through an image point. This method returns a ray whose origin is at the eye position and that goes through a given point on the image plane. The point on the plane is given by (x0, y0) which each ranges from 0 to 1. (0,0) is at the upper left and (1,1) at the lower right. The arguments width and height determine the ratio of the image plane (the absolute values of width and height are irrelevant). The return value is a 2-tuple (p,u) where p is the ray origin and u the normalized direction. Both vectors are given in world space. """ V = self.viewTransformation() P = self.projection(width, height, 1, 10) R = mat4().rotation(pi, vec3(0,1,0)) if getScene().handedness=='l': S = mat4().scaling(vec3(-1,1,1)) I = (P*S*R*V).inverse() else: I = (P*R*V).inverse() x = 2.0*x0-1.0 y = 1.0-2.0*y0 q = I*vec3(x,y,0) p = self.worldtransform[3] p = vec3(p.x, p.y, p.z) return (p, (q-p).normalize())
def onStepFrame(self): dt = getScene().timer().timestep diff = self.input - self.out if (diff.length() < 1.0): a = -0.75 * self.out_velocity else: a = self.accel_factor * (self.input - self.out) self.out_velocity += dt * a self.out = self.out + dt * self.out_velocity self.output = self.out + self.out_offset
def onStepFrame(self): dt = getScene().timer().timestep diff = self.input-self.out if (diff.length()<1.0): a = -0.75*self.out_velocity else: a = self.accel_factor*(self.input-self.out) self.out_velocity += dt*a self.out = self.out + dt*self.out_velocity self.output = self.out+self.out_offset
def __init__(self, name="ValueTable", type="vec3", values=[], modulo=None, tscale=1.0, auto_insert=True): """Constructor. \param name (\c str) Component name \param type (\c str) Value type \param values A list of tuples (time, value). \param modulo (\c float) Loop duration (None = no loop) \param tscale (\c float) Scaling factor for the time. A value of less than 1.0 makes the animation slower. """ component.Component.__init__(self, name=name, auto_insert=auto_insert) # Value list. Contains a sorted list of TableEntry objects self.values = [] # Time modulo value (or None) self.modulo = modulo # Scale factor for the time self.tscale = 1.0 # Type of the value slot self.type = type self.time_slot = DoubleSlot() self.addSlot("time", self.time_slot) typ = type.lower() exec "self.output_slot = Procedural%sSlot(self.computeValue)" % typ.capitalize( ) self.addSlot("output", self.output_slot) pytypes = {"double": "float"} exec "self.default_value = %s()" % pytypes.get(typ, typ) self.time_slot.addDependent(self.output_slot) getScene().timer().time_slot.connect(self.time_slot) for t, v in values: self.add(t, v)
def drawMarker(pos, color=(1, 1, 1), size=1): """Draw a marker. \param pos Marker position \param color Marker color \param size Marker size (radius) """ try: drw = getScene().worldObject("Global_Draw") except KeyError: drw = draw.Draw(name="Global_Draw") drw.marker(pos, color, size)
def getGroups(self, obj): """Get a list of "groups". Return a list that contains the names from the root to the object (excluding the world root). """ res = [] wr = getScene().worldRoot() while obj!=None: res = [obj.name]+res obj = obj.parent return res[1+self.group_offset:]
def getGroups(self, obj): """Get a list of "groups". Return a list that contains the names from the root to the object (excluding the world root). """ res = [] wr = getScene().worldRoot() while obj != None: res = [obj.name] + res obj = obj.parent return res[1 + self.group_offset:]
def drawMarker(pos, color=(1,1,1), size=1): """Draw a marker. \param pos Marker position \param color Marker color \param size Marker size (radius) """ try: drw = getScene().worldObject("Global_Draw") except KeyError: drw = draw.Draw(name="Global_Draw") drw.marker(pos, color, size)
def __init__(self, name = "ValueTable", type = "vec3", values = [], modulo = None, tscale = 1.0, auto_insert = True): """Constructor. \param name (\c str) Component name \param type (\c str) Value type \param values A list of tuples (time, value). \param modulo (\c float) Loop duration (None = no loop) \param tscale (\c float) Scaling factor for the time. A value of less than 1.0 makes the animation slower. """ component.Component.__init__(self, name=name, auto_insert=auto_insert) # Value list. Contains a sorted list of TableEntry objects self.values = [] # Time modulo value (or None) self.modulo = modulo # Scale factor for the time self.tscale = 1.0 # Type of the value slot self.type = type self.time_slot = DoubleSlot() self.addSlot("time", self.time_slot) typ = type.lower() exec "self.output_slot = Procedural%sSlot(self.computeValue)"%typ.capitalize() self.addSlot("output", self.output_slot) pytypes = {"double":"float"} exec "self.default_value = %s()"%pytypes.get(typ, typ) self.time_slot.addDependent(self.output_slot) getScene().timer().time_slot.connect(self.time_slot) for t,v in values: self.add(t,v)
def drawLine(pos1, pos2, color=(1, 1, 1), size=1): """Draw a line. \param pos1 First line point \param pos2 Second line point \param color Line color \param size Line width """ try: drw = getScene().worldObject("Global_Draw") except KeyError: drw = draw.Draw(name="Global_Draw") drw.line(pos1, pos2, color, size)
def worldObject(obj): """Return a world object. If \a obj is a string, the function returns the world object with that name. Otherwise \a obj is returned. \param obj An object or the name of an object. """ if isinstance(obj, types.StringTypes): return getScene().worldObject(obj) else: return obj
def drawLine(pos1, pos2, color=(1,1,1), size=1): """Draw a line. \param pos1 First line point \param pos2 Second line point \param color Line color \param size Line width """ try: drw = getScene().worldObject("Global_Draw") except KeyError: drw = draw.Draw(name="Global_Draw") drw.line(pos1, pos2, color, size)
def exportFile(self, filename, object=None, mode="ascii"): """Export a PLY file. object is the object to export. If it is None, it will be taken from the scene. If there is more than one object in the scene, an exception is thrown. mode specifies whether the output file will be ascii or binary. The values can be "ascii", "little_endian", "big_endian". """ if object==None: # Get a list of all objects that have a geom objs = list(getScene().walkWorld()) objs = filter(lambda obj: obj.geom!=None, objs) if len(objs)==0: raise ValueError("No object to export.") elif len(objs)>1: raise ValueError("Only a single object can be exported.") object = objs[0] object = cmds.worldObject(object) if object.geom==None: raise ValueError("No geometry attached to object %s"%object.name) geom = self.convertObject(object) if geom==None: raise ValueError("Cannot export geometry of type %s as a PLY file"%(object.geom.__class__.__name__)) # Open the file... ply = _core.PLYWriter() try: mode = eval ("_core.PlyStorageMode.%s"%mode.upper()) except: raise ValueError("Invalid mode: %s"%mode) ply.create(filename, mode) # Set comment var = geom.findVariable("comment") if var!=None and var[1]==CONSTANT and var[2]==STRING and var[3]==1: slot = geom.slot("comment") for s in slot[0].split("\n"): ply.addComment(s) # Set obj_info var = geom.findVariable("obj_info") if var!=None and var[1]==CONSTANT and var[2]==STRING and var[3]==1: slot = geom.slot("obj_info") for s in slot[0].split("\n"): ply.addObjInfo(s) # Write the model ply.write(geom, object.worldtransform) ply.close()
def replaceMaterial(name, newmat): """Iterate over all world objects and replace a material with a new one. \param name (\c str) The name of an already assigned material \param newmat (\c Material) The new material """ for obj in getScene().walkWorld(): # Check all materials... for i in range(obj.getNumMaterials()): mat = obj.getMaterial(i) if mat==None: continue if mat.name==name: obj.setMaterial(newmat, i)
def replaceMaterial(name, newmat): """Iterate over all world objects and replace a material with a new one. \param name (\c str) The name of an already assigned material \param newmat (\c Material) The new material """ for obj in getScene().walkWorld(): # Check all materials... for i in range(obj.getNumMaterials()): mat = obj.getMaterial(i) if mat == None: continue if mat.name == name: obj.setMaterial(newmat, i)
def __init__(self, name = "TargetCamera", fov = 45.0, target = vec3(0,0,0), roll = 0.0, up = None, fstop = 0, focallength = 0, **params): camerabase.CameraBase.__init__(self, name=name, **params) target = vec3(target) # FOV self.fov_slot = slots.DoubleSlot(fov) self.addSlot("fov", self.fov_slot) # Target self.target_slot = slots.Vec3Slot(target) self.addSlot("target", self.target_slot) # Roll self.roll_slot = slots.DoubleSlot(roll) self.addSlot("roll", self.roll_slot) # Up self.up_slot = slots.Vec3Slot() self.addSlot("up", self.up_slot) if up==None: self.up_slot.setValue(getScene().up) else: self.up_slot.setValue(vec3(up)) self._lookat = lookat.LookAt() self._lookat.name = "TargetCamera_LookAt" self._lookat.output_slot.connect(self.rot_slot) self.pos_slot.connect(self._lookat.pos_slot) self.target_slot.connect(self._lookat.target_slot) self.roll_slot.connect(self._lookat.roll_slot) self.up_slot.connect(self._lookat.up_slot) # fstop self.fstop_slot = slots.DoubleSlot(fstop) self.addSlot("fstop", self.fstop_slot) # focal length self.focallength_slot = slots.DoubleSlot(focallength) self.addSlot("focallength", self.focallength_slot)
def __init__(self, defaultoptionvar=None): """Constructor. defaultoptionvar is the name of an environment variable that contains the default options. """ # Create the option parser, ... self.optparser = self.createOptionParser() # set the options... self.setOptions(self.optparser) scene = getScene() timer = scene.timer() # Parse the default options defaultopts = None if defaultoptionvar != None: if defaultoptionvar in os.environ: optstring = os.environ[defaultoptionvar] args = optstring.split() defaultopts, dummy = self.optparser.parse_args(args) # ...and parse the command line. The options are in "options" self.options, self.args = self.optparser.parse_args(values=defaultopts) # Print default options if self.options.verbose: print("Python %s" % sys.version) if defaultoptionvar != None: if defaultoptionvar in os.environ: print("Default options in %s: %s" % (defaultoptionvar, os.environ[defaultoptionvar])) else: print("Environment variable %s not set." % defaultoptionvar) # Determine screen resolution... self._no_resolution_specified = False if self.options.width == None: self.options.width = 640 self._no_resolution_specified = True if self.options.height == None: self.options.height = int(self.options.width * 3.0 / 4) # Set the global application object to this tool class application._app = self
def exportFile(self, filename, root=None, mtlname=None, exportmtl=True): """Export an OBJ file. root is the root of the subtree that should be exported. If exportmtl is False, no MTL file is generated. mtlname determines the name of the MTL file (default: the same base name than filename). If exportmtl is False and no mtlname is given, then no material information will be written. """ self.fhandle = file(filename, "w") self.use_materials = (exportmtl or mtlname != None) self.root = cmds.worldObject(root) self.v_offset = 0 self.vt_offset = 0 self.vn_offset = 0 self.group_offset = 0 # This dictionary is used to find name clashes and store the materials # that have to be exported. # Key is the name of the material, value is the material object self.materials = {} # Determine the name of the MTL file (by changing the suffix) if mtlname == None: name, ext = os.path.splitext(filename) mtlname = name + ".mtl" if self.use_materials: print >> self.fhandle, "mtllib %s" % os.path.basename(mtlname) # Export objects... if root != None: self.group_offset = len(self.getGroups(self.root)) - 1 self.exportObject(self.root) for obj in getScene().walkWorld(self.root): self.exportObject(obj) self.fhandle.close() # Export the MTL file... if exportmtl: self.exportMTL(mtlname)
def setupObjectNames(): """Create a string that can be executed to 'import' all scene names. """ res = "" valid_chars = string.ascii_letters + "_" + string.digits for obj in getScene().item("WorldRoot").iterChilds(): varname = "" for c in obj.name: if c not in valid_chars: c = "_" varname += c if varname=="": continue if varname[0] in string.digits: varname = "_"+varname[1:] res += '%s = worldObject("%s")\n'%(varname, obj.name) return res
def setupObjectNames(): """Create a string that can be executed to 'import' all scene names. """ res = "" valid_chars = string.ascii_letters + "_" + string.digits for obj in getScene().item("WorldRoot").iterChilds(): varname = "" for c in obj.name: if c not in valid_chars: c = "_" varname += c if varname == "": continue if varname[0] in string.digits: varname = "_" + varname[1:] res += '%s = worldObject("%s")\n' % (varname, obj.name) return res
def exportFile(self, filename, root=None, mtlname=None, exportmtl=True): """Export an OBJ file. root is the root of the subtree that should be exported. If exportmtl is False, no MTL file is generated. mtlname determines the name of the MTL file (default: the same base name than filename). If exportmtl is False and no mtlname is given, then no material information will be written. """ self.fhandle = file(filename, "w") self.use_materials = (exportmtl or mtlname!=None) self.root = cmds.worldObject(root) self.v_offset = 0 self.vt_offset = 0 self.vn_offset = 0 self.group_offset = 0 # This dictionary is used to find name clashes and store the materials # that have to be exported. # Key is the name of the material, value is the material object self.materials = {} # Determine the name of the MTL file (by changing the suffix) if mtlname==None: name, ext = os.path.splitext(filename) mtlname = name+".mtl" if self.use_materials: print >>self.fhandle, "mtllib %s"%os.path.basename(mtlname) # Export objects... if root!=None: self.group_offset = len(self.getGroups(self.root))-1 self.exportObject(self.root) for obj in getScene().walkWorld(self.root): self.exportObject(obj) self.fhandle.close() # Export the MTL file... if exportmtl: self.exportMTL(mtlname)
def getNearFar(self): """Return the distances to the near and far clipping plane. If auto_nearfar is True, the near/far values are computed from the scene extent, otherwise the stored values are used. Compute near and far clipping plane distances from the bounding box of the scene. The scene bounding box is converted to a bounding sphere and the near and far clipping planes are set as tangent planes to the bounding sphere. """ if not self.autonearfar: return self.nearplane, self.farplane # Get the bounding box of the entire scene bbox = getScene().boundingBox() # Determine bounding sphere bmin,bmax = bbox.getBounds() if bmin!=None and bmin!=bmax: # Box center (resp. sphere center) c = 0.5*(bmin+bmax) # Radius of the bounding sphere r = (bmax-c).length() else: c = vec3(0,0,0) r = 10 # Transformation World->Camera VT = self.viewTransformation() # minnear = (bmax-bmin).length()/1000 minnear = self.nearplane minfar = minnear+1 # cz: Depth of the center point cz = (VT*c).z near = max(cz-r, minnear) far = max(cz+r, minfar) if (far-near)<0.01: far+=1 return (near,far)
def getNearFar(self): """Return the distances to the near and far clipping plane. If auto_nearfar is True, the near/far values are computed from the scene extent, otherwise the stored values are used. Compute near and far clipping plane distances from the bounding box of the scene. The scene bounding box is converted to a bounding sphere and the near and far clipping planes are set as tangent planes to the bounding sphere. """ if not self.autonearfar: return self.nearplane, self.farplane # Get the bounding box of the entire scene bbox = getScene().boundingBox() # Determine bounding sphere bmin, bmax = bbox.getBounds() if bmin != None and bmin != bmax: # Box center (resp. sphere center) c = 0.5 * (bmin + bmax) # Radius of the bounding sphere r = (bmax - c).length() else: c = vec3(0, 0, 0) r = 10 # Transformation World->Camera VT = self.viewTransformation() # minnear = (bmax-bmin).length()/1000 minnear = self.nearplane minfar = minnear + 1 # cz: Depth of the center point cz = (VT * c).z near = max(cz - r, minnear) far = max(cz + r, minfar) if (far - near) < 0.01: far += 1 return (near, far)
def __init__(self, defaultoptionvar=None): """Constructor. defaultoptionvar is the name of an environment variable that contains the default options. """ # Create the option parser, ... self.optparser = self.createOptionParser() # set the options... self.setOptions(self.optparser) scene = getScene() timer = scene.timer() # Parse the default options defaultopts = None if defaultoptionvar!=None: if defaultoptionvar in os.environ: optstring = os.environ[defaultoptionvar] args = optstring.split() defaultopts, dummy = self.optparser.parse_args(args) # ...and parse the command line. The options are in "options" self.options, self.args = self.optparser.parse_args(values=defaultopts) # Print default options if self.options.verbose: print ("Python %s"%sys.version) if defaultoptionvar!=None: if defaultoptionvar in os.environ: print ("Default options in %s: %s"%(defaultoptionvar, os.environ[defaultoptionvar])) else: print ("Environment variable %s not set."%defaultoptionvar) # Determine screen resolution... self._no_resolution_specified = False if self.options.width==None: self.options.width = 640 self._no_resolution_specified = True if self.options.height==None: self.options.height = int(self.options.width*3.0/4) # Set the global application object to this tool class application._app = self
def rotate(self, dx, dy): """Rotate around target.""" T = self.cam.transform if hasattr(self.cam, "target"): pivot = self.cam.target else: pivot = vec3(0) up = getScene().up R = mat4(1).rotation(-dx, up) dp = self.cam.pos - pivot self.cam.pos = pivot + R * dp T = self.cam.transform bx = vec3(tuple(T.getColumn(0))[:3]) R = mat4(1).rotation(dy, bx) dp = self.cam.pos - pivot self.cam.pos = pivot + R * dp
def rotate(self, dx, dy): """Rotate around target.""" T = self.cam.transform if hasattr(self.cam, "target"): pivot = self.cam.target else: pivot = vec3(0) up = getScene().up R = mat4(1).rotation(-dx, up) dp = self.cam.pos-pivot self.cam.pos = pivot + R*dp T = self.cam.transform bx = vec3(tuple(T.getColumn(0))[:3]) R = mat4(1).rotation(dy, bx) dp = self.cam.pos-pivot self.cam.pos = pivot + R*dp
def computeOutput(self): err = self.setpoint - self.input dt = getScene().timer().timestep I = self._integral D = (err - self._prev_err) / dt # print "D:",D res = self.Kp * err + self.Ki * I + self.Kd * D self._prev_err = err maxout = self.maxout minout = self.minout if res > maxout: res = maxout elif res < minout: res = minout return res
def computeOutput(self): err = self.setpoint-self.input dt = getScene().timer().timestep I = self._integral D = (err-self._prev_err)/dt # print "D:",D res = self.Kp*err + self.Ki*I + self.Kd*D self._prev_err = err maxout = self.maxout minout = self.minout if res>maxout: res = maxout elif res<minout: res = minout return res
def __init__(self, up = None, handedness = None, unit = None, unitscale = None, **keyargs): scene = getScene() if up!=None: scene.up = vec3(up) if handedness!=None: scene.handedness = handedness if unit!=None: scene.unit = unit if unitscale!=None: scene.unitscale = unitscale for opt in keyargs: scene._globals[opt] = keyargs[opt]
def __init__(self, up=None, handedness=None, unit=None, unitscale=None, **keyargs): scene = getScene() if up != None: scene.up = vec3(up) if handedness != None: scene.handedness = handedness if unit != None: scene.unit = unit if unitscale != None: scene.unitscale = unitscale for opt in keyargs: scene._globals[opt] = keyargs[opt]
def link(childs, parent=None, relative=False): """Link all childs to parent. The function modifies the name of a child object if there would be a clash with an existing object under the new parent. \param childs (\c list or WorldObject) A single WorldObject or a sequence of WorldObjects \param parent (\c WorldObject) Parent object or None (=unlink) \param relative (\c bool) If True the local child transform is not modified (i.e. it is interpreted as a relative position) """ # Check if childs is a sequence (other than a string)... try: len(childs) if isinstance(childs, types.StringTypes): is_sequence = False else: is_sequence = True except: is_sequence = False if not is_sequence: childs = [childs] # No parent given? Then use the world root (=unlink) if parent == None: parent = getScene().worldRoot() else: parent = worldObject(parent) # Relink all childs... for child in childs: child = worldObject(child) oldparent = child.parent if oldparent != None: oldparent.removeChild(child) if not relative: Lp1 = oldparent.worldtransform Lp2 = parent.worldtransform child.transform = Lp2.inverse() * Lp1 * child.transform child.name = parent.makeChildNameUnique(child.name) parent.addChild(child)
def link(childs, parent=None, relative=False): """Link all childs to parent. The function modifies the name of a child object if there would be a clash with an existing object under the new parent. \param childs (\c list or WorldObject) A single WorldObject or a sequence of WorldObjects \param parent (\c WorldObject) Parent object or None (=unlink) \param relative (\c bool) If True the local child transform is not modified (i.e. it is interpreted as a relative position) """ # Check if childs is a sequence (other than a string)... try: len(childs) if isinstance(childs, types.StringTypes): is_sequence = False else: is_sequence = True except: is_sequence = False if not is_sequence: childs = [childs] # No parent given? Then use the world root (=unlink) if parent==None: parent = getScene().worldRoot() else: parent = worldObject(parent) # Relink all childs... for child in childs: child = worldObject(child) oldparent = child.parent if oldparent!=None: oldparent.removeChild(child) if not relative: Lp1 = oldparent.worldtransform Lp2 = parent.worldtransform child.transform = Lp2.inverse()*Lp1*child.transform child.name = parent.makeChildNameUnique(child.name) parent.addChild(child)
def exportFile(self, filename, root=None): """Export an OFF file. root is the root of the subtree that should be exported. """ self.N_flag = False self.C_flag = False self.ST_flag = False # Create a list of objects that should be exported scene = getScene() self.objects = [] root = cmds.worldObject(root) if root != None: self.objects.append(root) self.objects += list(scene.walkWorld(root)) # Initialize variable flags and return number of verts and faces numverts, numfaces = self.getNumVertsNFaces() self.fhandle = file(filename, "w") # Write header line kw = "" if self.ST_flag: kw += "ST" if self.C_flag: kw += "C" if self.N_flag: kw += "N" kw += "OFF" print >> self.fhandle, kw # Write number of vertices and faces print >> self.fhandle, "%d %d 0" % (numverts, numfaces) # Write vertices... self.writeVertices() # Write faces self.writeFaces() self.fhandle.close()
def exportFile(self, filename, root=None): """Export an OFF file. root is the root of the subtree that should be exported. """ self.N_flag = False self.C_flag = False self.ST_flag = False # Create a list of objects that should be exported scene = getScene() self.objects = [] root = cmds.worldObject(root) if root!=None: self.objects.append(root) self.objects += list(scene.walkWorld(root)) # Initialize variable flags and return number of verts and faces numverts, numfaces = self.getNumVertsNFaces() self.fhandle = file(filename, "w") # Write header line kw = "" if self.ST_flag: kw += "ST" if self.C_flag: kw += "C" if self.N_flag: kw += "N" kw += "OFF" print >>self.fhandle, kw # Write number of vertices and faces print >>self.fhandle, "%d %d 0"%(numverts, numfaces) # Write vertices... self.writeVertices() # Write faces self.writeFaces() self.fhandle.close()
def getCamera(self): """Get or create a camera object. """ scene = getScene() cname = self.options.camera # Search for a camera... cam = None for obj in scene.walkWorld(): prots = obj.protocols() if ICamera in prots: if obj.name == cname or cname == None: cam = obj break if cname != None and cam == None: raise ValueError('Camera "%s" not found.' % cname) # No camera? Then create a default camera... if cam == None: if self.options.verbose: print("No camera set, using a default camera.") bbmin, bbmax = scene.boundingBox().getBounds() dif = bbmax - bbmin b1 = scene.up.ortho() b2 = scene.up.cross(b1) pos = dif.length() * (0.5 * b1 + b2) + (bbmax.z + 0.5 * dif.z) * scene.up if abs(dif.z) < 0.0001: pos += 0.8 * dif.length() * scene.up cam = TargetCamera(pos=pos, target=0.5 * (bbmin + bbmax) - 0.2 * (dif.z * scene.up), fov=50) else: if self.options.verbose: print("Camera: %s" % cam.name) return cam
def onStepFrame(self): timer = getScene().timer() ### State 0: Waiting for the transition if self.state==0: if timer.time>=self.transition_start: self.state = 1 ### State 1: Begin of transition if self.state==1: self.transition.preTransition(self) eventManager().event("SlidePreTransition", self.images[self.imageidx][0]) self.state = 2 ### State 2: Transition if self.state==2: if self.transition.duration>0: t = (timer.time-self.transition_start)/self.transition.duration else: t = 1.0 if t>1.0: t = 1.0 self.transition.doTransition(self, t) eventManager().event("SlideDoTransition", t) if t==1.0: self.state = 3 ### State 3: Transition is over elif self.state==3: eventManager().event("SlidePostTransition") self.transition.postTransition(self) self.switchSlide() self.frontplate.transform = mat4(1) self.backplate.transform = mat4(1) self.backplate.pos = vec3(0,0,-1) # self.transition_start += 5.0 self.transition_start = 999999.0 self.state = 0
def onStepFrame(self): timer = getScene().timer() ### State 0: Waiting for the transition if self.state == 0: if timer.time >= self.transition_start: self.state = 1 ### State 1: Begin of transition if self.state == 1: self.transition.preTransition(self) eventManager().event("SlidePreTransition", self.images[self.imageidx][0]) self.state = 2 ### State 2: Transition if self.state == 2: if self.transition.duration > 0: t = (timer.time - self.transition_start) / self.transition.duration else: t = 1.0 if t > 1.0: t = 1.0 self.transition.doTransition(self, t) eventManager().event("SlideDoTransition", t) if t == 1.0: self.state = 3 ### State 3: Transition is over elif self.state == 3: eventManager().event("SlidePostTransition") self.transition.postTransition(self) self.switchSlide() self.frontplate.transform = mat4(1) self.backplate.transform = mat4(1) self.backplate.pos = vec3(0, 0, -1) # self.transition_start += 5.0 self.transition_start = 999999.0 self.state = 0
def getCamera(self): """Get or create a camera object. """ scene = getScene() cname = self.options.camera # Search for a camera... cam = None for obj in scene.walkWorld(): prots = obj.protocols() if ICamera in prots: if obj.name==cname or cname==None : cam = obj break if cname!=None and cam==None: raise ValueError('Camera "%s" not found.'%cname) # No camera? Then create a default camera... if cam==None: if self.options.verbose: print ("No camera set, using a default camera.") bbmin, bbmax = scene.boundingBox().getBounds() dif = bbmax-bbmin b1 = scene.up.ortho() b2 = scene.up.cross(b1) pos = dif.length()*(0.5*b1+b2) + (bbmax.z+0.5*dif.z)*scene.up if abs(dif.z)<0.0001: pos += 0.8*dif.length()*scene.up cam = TargetCamera(pos = pos, target = 0.5*(bbmin+bbmax)-0.2*(dif.z*scene.up), fov = 50) else: if self.options.verbose: print ("Camera: %s"%cam.name) return cam
def importFile(self, filename, flags=GEOM_INIT_ALL, parent=None): """Import a 3DS file.""" self.filename = filename self.ddds = _core.File3ds() self.ddds.load(filename) # f = self.ddds.current_frame f = getScene().timer().frame if f<self.ddds.segment_from: f = self.ddds.segment_from if f>self.ddds.segment_to: f = self.ddds.segment_to self.ddds.eval(f) # Create a dictionary containing all available meshes. # Key is the mesh name. This is used to check if all meshes have # been processed (i.e. if there were corresponding nodes). self.meshes = {} m = self.ddds.meshes() while m!=None: if m.name in self.meshes: print("Warning: Duplicate mesh names in 3ds file") self.meshes[m.name] = m m = m.next() # Create objects... self.materials = {} self.createObject(self.ddds.nodes(), parent=parent, flags=flags) del self.materials # Create TriMeshes for all left over meshes... for n in self.meshes: mesh = self.meshes[n] tm = TriMeshGeom() mesh.initGeom(tm, flags) worldobj = TriMesh(name = mesh.name, parent=parent) worldobj.geom = tm self.ddds.free()
def importFile(self, filename, flags=GEOM_INIT_ALL, parent=None): """Import a 3DS file.""" self.filename = filename self.ddds = _core.File3ds() self.ddds.load(filename) # f = self.ddds.current_frame f = getScene().timer().frame if f < self.ddds.segment_from: f = self.ddds.segment_from if f > self.ddds.segment_to: f = self.ddds.segment_to self.ddds.eval(f) # Create a dictionary containing all available meshes. # Key is the mesh name. This is used to check if all meshes have # been processed (i.e. if there were corresponding nodes). self.meshes = {} m = self.ddds.meshes() while m != None: if m.name in self.meshes: print("Warning: Duplicate mesh names in 3ds file") self.meshes[m.name] = m m = m.next() # Create objects... self.materials = {} self.createObject(self.ddds.nodes(), parent=parent, flags=flags) del self.materials # Create TriMeshes for all left over meshes... for n in self.meshes: mesh = self.meshes[n] tm = TriMeshGeom() mesh.initGeom(tm, flags) worldobj = TriMesh(name=mesh.name, parent=parent) worldobj.geom = tm self.ddds.free()
def onSpaceMotion(self, e): """ this is still somewhat experimental (should distinguish between the camera types as it's meant to be used with a FreeCamera) """ scene = getScene() tr = 0.001*e.translation rot = e.rotation if scene.handedness=='r': tr.x = -tr.x rot.y = -rot.y rot.z = -rot.z M = mat4().translation(tr) if rot!=vec3(0): a = 0.0002*rot.length() M = M*mat4().rotation(a, rot) T = self.cam.transform*M # Align camera to up direction R = T.getMat3() bz = vec3(tuple(T.getColumn(2))[:3]) by = scene.up bx = by.cross(bz) by = bz.cross(bx) try: R = mat3(bx.normalize(), by.normalize(), bz.normalize()) except: R = mat3(1) T.setMat3(R) self.cam.transform = T
def onSpaceMotion(self, e): """ this is still somewhat experimental (should distinguish between the camera types as it's meant to be used with a FreeCamera) """ scene = getScene() tr = 0.001 * e.translation rot = e.rotation if scene.handedness == 'r': tr.x = -tr.x rot.y = -rot.y rot.z = -rot.z M = mat4().translation(tr) if rot != vec3(0): a = 0.0002 * rot.length() M = M * mat4().rotation(a, rot) T = self.cam.transform * M # Align camera to up direction R = T.getMat3() bz = vec3(tuple(T.getColumn(2))[:3]) by = scene.up bx = by.cross(bz) by = bz.cross(bx) try: R = mat3(bx.normalize(), by.normalize(), bz.normalize()) except: R = mat3(1) T.setMat3(R) self.cam.transform = T
def getResolution(self): """Read the global resolution setting. Returns a tuple (width, height, pixel aspect) """ res = getScene().getGlobal("resolution", (640,480)) # If the resolution is a string, try to evaluate it if isinstance(res, basestring): try: res = eval(res) except: pass try: if len(res)==2: w,h = res aspect = 1 elif len(res)==3: w,h,aspect = res else: raise Exception() except: print >>sys.stderr, "Error: Invalid resolution setting:",res w,h,aspect = 640,480,1 return w,h,aspect
def drawText(pos, txt, font=None, color=(1, 1, 1)): """Draw a text string. font can be one of the constants defined in GLUT: - GLUT_BITMAP_8_BY_13 - GLUT_BITMAP_9_BY_15 (default) - GLUT_BITMAP_TIMES_ROMAN_10 - GLUT_BITMAP_TIMES_ROMAN_24 - GLUT_BITMAP_HELVETICA_10 - GLUT_BITMAP_HELVETICA_12 - GLUT_BITMAP_HELVETICA_18 \param pos Text position (3D) \param txt The actual text \param font A GLUT font constant \param color Text color """ try: drw = getScene().worldObject("Global_DrawText") except KeyError: drw = worldobject.WorldObject(name="Global_DrawText") drw.geom = drawtextgeom.DrawTextGeom() drw.geom.addText(pos, txt, font, color)