Example #1
0
def surfacescan(scene, density):
    result = []
    for shape in scene:
        position = pgl.Vector3(0, 0, 0)
        heading = pgl.Vector3(0, 0, 1)
        geometry = shape.geometry
        while isinstance(geometry, pgl.Transformed):
            if isinstance(geometry, pgl.Translated):
                position = geometry.translation
            if isinstance(geometry, pgl.Oriented):
                heading = cross(geometry.primary, geometry.secondary)
            geometry = geometry.geometry
        if isinstance(geometry, pgl.Cylinder):
            for p in range(
                    int((pi * (geometry.radius**2) * geometry.height) //
                        density)):
                v = pgl.Vector3(random.rand() * 2 - 1,
                                random.rand() * 2 - 1,
                                random.rand() * 2 - 1)
                pos = position + \
                    pgl.Vector3(cross(heading, v)).normed() * (geometry.radius)
                point = pos + heading * random.rand() * geometry.height
                result.append(point)
        elif isinstance(geometry, pgl.Extrusion):
            result.append(geometry.axis)
    result = pgl.PointSet(result)
    return result
Example #2
0
def cones(obj, **kwds):
    X_attr = kwds.get('X_attr', 'X')
    Y_attr = kwds.get('Y_attr', 'Y')
    pos_dist = kwds.get('dist', 'Distance')
    pos_az = kwds.get('az', 'Azimuth')
    circ_attr = kwds.get('circ_attr', 'Circonference')
    height_attr = kwds.get('height_attr', 'Haut')
    botHoup_attr = kwds.get('botHoup', 'BaseHoup')
    radiusHoup_prefix = kwds.get('radiusHoup_prefix', 'r_houp')
    radiusHoup = kwds.get('radiusHoup', None)
    wood = kwds.get('wood', True)
    rgb = kwds.get('rgb', None)
    spec_name = kwds.get('spec_name', 'houppier_mat')

    if not obj.__dict__.has_key("posX") and not obj.__dict__.has_key("posY"):
        try:
            r = obj.__dict__[pos_dist]
            a = obj.__dict__[pos_az]
            obj.posX = r * cos(radians(forest2geomAZ(a)))
            obj.posY = r * sin(radians(forest2geomAZ(a)))
        except KeyError:
            obj.posX = obj.__dict__[X_attr]
            obj.posY = obj.__dict__[Y_attr]

    ht = 100 * (obj.__dict__[height_attr] - obj.__dict__[botHoup_attr])

    rd_kz = [k for k in obj.__dict__.keys() if radiusHoup_prefix in k]
    radii = [obj.__dict__[k] for k in rd_kz]

    if radiusHoup:
        if radiusHoup == 'Max':
            cone_radius = 1.0 * max(radii)
        else:
            cone_radius = obj.__dict__[radiusHoup]
    else:
        cone_radius = 1.0 * sum(radii) / len(radii)
        #cone_radius = ht/2.
    h = pgl.Translated(
        pgl.Vector3(obj.posX, obj.posY, obj.__dict__[botHoup_attr] * 100),
        pgl.Cone(cone_radius, ht, 1, 12))
    tr = pgl.Translated(
        pgl.Vector3(obj.posX, obj.posY, 0),
        pgl.Cylinder(obj.__dict__[circ_attr] / (2 * pi),
                     obj.__dict__[botHoup_attr] * 100 + ht * 0.1))

    if rgb == None:
        s_h = pgl.Shape(h, stand_material(spec_name=spec_name))
    else:
        r, g, b = rgb
        s_h = pgl.Shape(h, stand_material(r, g, b, spec_name))

    s_tr = pgl.Shape(
        tr,
        stand_material(spec_name="trunk_mat"),
    )  # s_h.id*10 )

    if wood:
        return (s_h, s_tr)
    else:
        return (s_h, )
Example #3
0
def tgl():
    return pgl.TriangleSet(
        pgl.Point3Array([
            pgl.Vector3(1, 0, 0),
            pgl.Vector3(-0.2, 1, 0),
            pgl.Vector3(-0.2, -1, 0)
        ]), pgl.Index3Array([pgl.Index3(0, 1, 2)]))
Example #4
0
def mangoLeaf(length = 1, alpha=0, color = __niceGreen):
  x = array(arange(0.1,length,0.1))
  y = (-3/(length*5.)) * (x**2/length - x)
  cos = math.cos(math.radians(alpha/2.0))
  sin = math.sin(math.radians(alpha/2.0))
  list = []
  idxList = []
  for i in range(len(x)):
    list.append(pgl.Vector3(x[i],0,0))
    list.append(pgl.Vector3(x[i],y[i]*cos,y[i]*sin))
    list.append(pgl.Vector3(x[i],-y[i]*cos,y[i]*sin))
  list.append(pgl.Vector3(0,0,0))
  list.append(pgl.Vector3(length,0,0))
  for i in range(len(x) -1):
    idxList.append(pgl.Index(3*(i+1), 3*(i+1)+1, 3*i+1, 3*i ))
    idxList.append(pgl.Index(3*i+2, 3*(i+1)+2, 3*(i+1), 3*i ))
    #idxList.append(pgl.Index(3*i,3*i+1,3*(i+1)+1, 3*(i+1)))
    #idxList.append(pgl.Index(3*i,3*(i+1),3*(i+1)+2,3*i+2))

  idxList.append(pgl.Index(0, 1, len(list)-2 ))
  idxList.append(pgl.Index(2, 0, len(list)-2 ))
  idxList.append(pgl.Index(3*(len(x)-1)+1, 3*(len(x)-1), len(list)-1 ))
  idxList.append(pgl.Index(3*(len(x)-1), 3*(len(x)-1)+2, len(list)-1 ))
  #idxList.append(pgl.Index(len(list)-2, 1, 0))
  #idxList.append(pgl.Index(len(list)-2, 0, 2))
  #idxList.append(pgl.Index(len(list)-1, 3*(len(x)-1), 3*(len(x)-1)+1))
  #idxList.append(pgl.Index(len(list)-1, 3*(len(x)-1)+2, 3*(len(x)-1)))
  #p3r = pgl.Point3Array(list)
  #ir = pgl.IndexArray(idxList)
  fs = pgl.FaceSet(list,idxList)
  return pgl.Shape(fs, color)
Example #5
0
def leaf(**kwds):
    global __myLeaf
    if __myLeaf is None:
        __myLeaf = mangoLeaf(alpha=20)

    rp = rdm_pos((1, 1, 1))
    rx, ry, rz = rp.x, rp.y, rp.z
    az, el, rl = rdm_orientation()
    x = kwds.get('x', rx)
    y = kwds.get('y', ry)
    z = kwds.get('z', rz)
    delta = kwds.get('rotz', az)
    phi = kwds.get('roty', el)
    psi = kwds.get('rotx', rl)
    size = kwds.get('len', 10.0)
    color = kwds.get('color', __niceGreen)
    if not size:
        size = 10.0
        print "length is None, using 10 instead : small leaf"
    v = pgl.Vector3(x, y, z)
    #print "leaf size : ", size
    #sx = pgl.Vector3(4,1,1) * size/40.
    #scaled_geometry = pgl.Scaled(sx, pgl.Translated(pgl.Vector3(0.5,0,0), pgl.Disc(0.5, 6)) )
    sx = pgl.Vector3(1, 1, 1) * size / 10.

    scaled_geometry = pgl.Scaled(sx, __myLeaf.geometry)
    rotated_geometry = pgl.EulerRotated(delta, phi, psi, scaled_geometry)
    tr = pgl.Translated(v, rotated_geometry)
    return pgl.Shape(tr, color)
Example #6
0
def genericLeaf(allo_length, allo_surf, **kwds):
  if kwds.has_key('surface'):
    surface = kwds['surface']
    length = math.sqrt(surface / (allo_length*allo_surf) )
  else:  
    length = kwds.get('length', 1)

  alpha = kwds.get('alpha', 0)
  color = kwds.get('color', __niceGreen)
  step = length/10.
  x = array(arange(step,length,step)) #begin and end are specific
  y = (-3.0*allo_length*allo_surf) * (x**2/length - x)
  cos = math.cos(math.radians(alpha/2.0))
  sin = math.sin(math.radians(alpha/2.0))
  list = []
  idxList = []
  for i in range(len(x)):
    list.append(pgl.Vector3(x[i],0,0))
    list.append(pgl.Vector3(x[i],y[i]*cos,y[i]*sin))
    list.append(pgl.Vector3(x[i],-y[i]*cos,y[i]*sin))
  list.append(pgl.Vector3(0,0,0))
  list.append(pgl.Vector3(length,0,0))
  for i in range(len(x) -1):
    idxList.append(pgl.Index(3*(i+1), 3*(i+1)+1, 3*i+1, 3*i ))
    idxList.append(pgl.Index(3*i+2, 3*(i+1)+2, 3*(i+1), 3*i ))

  idxList.append(pgl.Index(0, 1, len(list)-2 ))
  idxList.append(pgl.Index(2, 0, len(list)-2 ))
  idxList.append(pgl.Index(3*(len(x)-1)+1, 3*(len(x)-1), len(list)-1 ))
  idxList.append(pgl.Index(3*(len(x)-1), 3*(len(x)-1)+2, len(list)-1 ))
  p3r = pgl.Point3Array(list)
  ir = pgl.IndexArray(idxList)
  fs = pgl.FaceSet(p3r, ir)
  return pgl.Shape(fs, color)
Example #7
0
def generate_random_point(size=[1, 1, 1], distribution='uniform'):
    from random import uniform, gauss
    if distribution == 'uniform':
        return pgl.Vector3(uniform(-size[0], size[0]),
                           uniform(-size[1], size[1]),
                           uniform(-size[2], size[2]))
    elif distribution == 'gaussian':
        return pgl.Vector3(gauss(0, size[0] / 3.), gauss(0, size[1] / 3.),
                           gauss(0, size[1] / 3.))
Example #8
0
def arrow(x,y,z,length,az=0, el=0, radius=None, color=color(255,255,255),id=0):
  if radius==None:
    radius=length*0.05
  rad_az = math.radians(az)
  rad_el = math.pi/2 - math.radians(el)
  v = pgl.Vector3( x, y, z )
  c = pgl.Cylinder(radius, length*0.8, 10)
  con =pgl.Translated(pgl.Vector3(0,0,length*0.7), pgl.Cone(2*radius, length*0.3))
  arr = pgl.Group([c,con])
  dir_arr = pgl.EulerRotated(rad_az,rad_el,0,arr)
  tr_dir_arr = pgl.Translated(v,dir_arr)
  return pgl.Shape(tr_dir_arr, color, id)
Example #9
0
 def _common_init( self, **keys ):
     """
     """
     if "height" in keys:
         self._height = keys[ "height" ]
     else:
         self._height = pgl.norm( keys[ "axis" ] )
     self._radius = keys[ "radius" ]
     
     self.shaft = pgl.Scaled(pgl.Vector3(1, 1, AARROW_SHAFT_PROPORTION), ACYLINDER_PRIMITIVE )
     self.head = pgl.Translated(pgl.Vector3(0, 0, AARROW_SHAFT_PROPORTION), pgl.Scaled(pgl.Vector3(
         AARROW_HEAD_PROPORTION,AARROW_HEAD_PROPORTION,1-AARROW_SHAFT_PROPORTION), ACONE_PRIMITIVE) )
Example #10
0
 def _set_radius(self, radius=ACYLINDER_STANDARD_RADIUS):
     """Property helper method.
     """
     if radius != self._radius:
         self._radius = radius
         self.scale = pgl.Vector3(2 * self._radius, 2 * self._radius,
                                  self._height)
Example #11
0
def inflorescence(g, vid, turtle):
    """ HT: inflorescence
    Box (may change)
    
    parameters:
    -----------
    g: is a current MTG
    vid: vertex id in the mtg
    turtle: openalea.pltgl.turtle
    
    return:
    ----------
    for each HT in mtg return an object compose of cylender and a blue box. 
    Shape of the box is dependent of the number of total flower and number of open flowers.
    """

    t = colors_turtle(turtle)
    nid = g.node(vid)
    order = nid.order
    nb_flower = nid.FLWRNUMBER
    nb_flower_open = nid.FLWRNUMBER_OPEN

    t.setColor(2 + order)
    turtle.F(0.2)
    if nb_flower is None:
        nb_flower = 0.5
    if nb_flower_open is None or nb_flower_open == 0:
        nb_flower_open = 0.5

    cube = pgl.Box(0.05 * pgl.Vector3(1, 1, nb_flower_open / 4.))
    tap = pgl.Tapered(3. / 20 * nb_flower, 3. / 20 * nb_flower_open, cube)
    turtle.customGeometry(tap)
Example #12
0
def scene2grid(scene, gridSize):
    """
  Convert a scene into a matrix-grid where non-zero values are the coresponding surface included in the coresponding voxel
  """
    bbox = pgl.BoundingBox(scene)
    epsilon = pgl.Vector3(0.01, 0.01, 0.01)
    origin = bbox.lowerLeftCorner - epsilon
    step = (bbox.getSize() + epsilon) * 2 / (gridSize)
    """
  getSize is a radius vector whereas gridSize is the voxel number desired per dimension, hence the gridSize must be *2
  """
    print "Bbox size : ", bbox.getSize() * 2
    print "Step : ", step, "    gridSize : ", gridSize
    grid = {}
    tgl_list = surfPerTriangle(scene)
    for tgl in tgl_list:
        pos = gridIndex(tgl[0] - origin, step)
        if grid.has_key(pos):
            grid[pos] += tgl[1]
        else:
            grid[pos] = tgl[1]
    print "nbTgl : ", len(tgl_list), "  <--->   nbVoxel : ", len(grid)
    kize = grid.keys()
    kize.sort()
    pts = []
    mass = []
    for k in kize:
        pts.append(list(k))
        mass.append(grid[k])
    return (pts, mass, step)  #gridSize )
Example #13
0
def weber_penn_markov(parameters, seed, position, p0, p1):
    if not parameters:
        return

    random.seed(seed)

    scene = Scene()
    client = Markov_Laws(parameters, p0, p1)
    server = tree_server.TreeServer(client)
    server.run()
    if not position:
        position = pgl.Vector3(0., 0., 0.)
    Vector2 = pgl.Vector2
    p = [
        Vector2(0.5, 0),
        Vector2(0, 0.5),
        Vector2(-0.5, 0),
        Vector2(0, -0.5),
        Vector2(0.5, 0)
    ]
    section = pgl.Polyline2D(p)

    geom = tree_geom.GeomEngine(server, section, position)

    scene = geom.scene('axis', scene)

    return scene,
Example #14
0
 def _set_height( self, height=ACYLINDER_STANDARD_HEIGHT):
     """Property helper method.
     """
     #TODO think about norm(self._axis) height relation. Shouldn't it be updated? 
     if height != self._height:
         self._height = height
         self.scale = pgl.Vector3( 2*self.radius, 2*self.radius, self._height )
Example #15
0
def inflorescence(g, vid, turtle):
    """Generates the inflorescences

    HT: inflorescence
    Box (may change)
    for each HT in mtg return an object compose of cylender and a blue box. 
    Shape of the box is dependent of the number of total flower and number of open flowers.

    :param g: MTG
    :type g: MTG
    :param vid: vid selected
    :type vid: int
    :param turtle: Turtle
    :type turtle: Turtle
    :return: for each HT in mtg return an object compose of cylender and a blue box. 
    :rtype: [type]
    """    
    t = colors_turtle(turtle)
    nid = g.node(vid)
    order = nid.order
    nb_flower = nid.FLWRNUMBER
    nb_flower_open = nid.FLWRNUMBER_OPEN

    t.setColor(2+order)
    turtle.F(0.2)
    if nb_flower is None:
        nb_flower = 0.5
    if nb_flower_open is None or nb_flower_open == 0:
        nb_flower_open = 0.5

    cube = pgl.Box(0.05*pgl.Vector3(1,1,nb_flower_open/4.))
    tap = pgl.Tapered(3./20*nb_flower, 3./20*nb_flower_open, cube)
    turtle.customGeometry(tap)
Example #16
0
def transform4(matrix, shape):
    """
    Return a shape transformed by a Matrix4.
    """
    if matrix == None:
        matrix = pgl.Matrix4()
    scale, (a, e, r), translation = matrix.getTransformation2()

    if type(shape) is pgl.Cylinder and matrix != pgl.Matrix4():
        #print "scale for cylinder is :", scale
        #print "scale.xyz = ", scale.x, scale.y, scale.z
        if round(scale.x, 1) == 1.0 and round(scale.y, 1) == 1.0 and round(
                scale.z, 1) == 1.0:
            shape = pgl.Translated(translation,
                                   pgl.EulerRotated(a, e, r, shape))
        else:
            raise Exception, "Invalid transformation for cylinder!"

    elif type(shape) is pgl.Sphere:
        shape = pgl.Translated(
            translation, pgl.EulerRotated(a, e, r, pgl.Scaled(scale, shape)))
    elif type(shape) is pgl.BezierPatch:
        scale1 = pgl.Vector3(1, 1, 1)
        shape = pgl.Translated(
            translation,
            pgl.EulerRotated(a, e, r,
                             pgl.Scaled(scale, pgl.Scaled(scale1, shape))))
    else:
        shape = pgl.Translated(
            translation, pgl.EulerRotated(a, e, r, pgl.Scaled(scale, shape)))

    return shape
Example #17
0
def center(pointList):
  """centre d'une liste de points"""
  v= pgl.Vector3(0,0,0)
  for pt in pointList:
    v += pt
  v /= len(pointList)
  return v
Example #18
0
def disc( x,y,z, color=color( 30,10,140 ) ):
  v = pgl.Vector3( x, y, z )
  d = pgl.Disc( 0.4, 5 )
  azimuth, elevation, roll= rdm_orientation()
  rotated_geometry= pgl.EulerRotated(azimuth, elevation, roll, d)
  tr = pgl.Translated( v,rotated_geometry )
  return pgl.Shape( tr, color )
Example #19
0
    def NURBSCurve(self, ctrlpoints, dimension, **kwds):
        ctrlpoints = str(ctrlpoints)
        ctrlpoints = [float(num) for num in ctrlpoints.split(",")]
        dimension = int(dimension)
        items, chunk = ctrlpoints, dimension
        pointArray = zip(*[iter(items)] * chunk)

        if (dimension == 2):
            v4array = []
            for item in pointArray:
                v4array.append(pgl.Vector2(item))

            parray = pgl.Point3Array(0)
            for item in v4array:
                parray.append(Vector3(item,1))

            return (pgl.NurbsCurve2D(parray), None)
        elif (dimension == 3):
            v4array = []
            for item in pointArray:
                v4array.append(pgl.Vector3(item))

            parray = pgl.Point4Array(0)
            for item in v4array:
                parray.append(Vector4(item,1))
            return (pgl.NurbsCurve(parray), None)
Example #20
0
def getProjectionMatrix(forward, up = pgl.Vector3(0,0,1)):
    forward.normalize()
    up.normalize();
    side = pgl.cross(up, forward);
    side.normalize();
    up = pgl.cross(forward, side);
    up.normalize();
    return pgl.Matrix3(side, up, forward).inverse()
def plotSkyTurtle():
  pgl.Viewer.start()
  sc = pgl.Scene()
  for i in range(len(elevations)):
    pos = pgl.Vector3(pgl.Vector3.Spherical(30,radians(azimuths[i]),radians(90-elevations[i])))
    sc += pgl.Shape(pgl.Translated(pos,pgl.Sphere(0.5)),pgl.Material(),i+1)
  pgl.Viewer.display(sc)
  return sc
def simplify(leaf, nb_points):
    xn, yn, sn, rn = leaf

    points = [pgl.Vector3(*pt) for pt in izip(xn, rn, yn)]
    pts = filter(None, cost(points, nb_points))
    coords = ((pt.x, pt.y, pt.z) for pt in pts)
    x, r, y = map(array, izip(*coords))
    s = curvilinear_abscisse(x, y)
    return x, y, s, r
Example #23
0
def process_line(line):
    line = line.strip()
    if not line:
        return
    if line[0] == '#':
        return

    l = line.split()
    nb_polygon = int(l[-10])
    assert nb_polygon == 3
    coords = list(map(float, l[-9:]))
    label = l[2]
    if len(label) < 11:
        label = (12 - len(label)) * '0' + label

    triangle = (pgl.Vector3(*coords[:3]), pgl.Vector3(*coords[3:6]),
                pgl.Vector3(*coords[6:]))
    return label, triangle
Example #24
0
 def __init__(self, radius=absolute_shapes.ASPHERE_STANDARD_RADIUS, **keys):
     """Default constructior.        
     """
     keys.update({"radius": radius})
     self._common_init(**keys)
     AIShape3D.__init__(self,
                        scale=pgl.Vector3(2 * self.radius, 2 * self.radius,
                                          2 * self.radius),
                        geometry=absolute_shapes.ASPHERE_PRIMITIVE,
                        **keys)
def Inflo_Primordia(g, vid, turtle):
    """ ht: Primordia inflorescence
    """
    t = turtle
    #turtle.setColor(1)
    nid = g.node(vid)
    order = nid.order
    t.setColor(8 + order)
    turtle.F(0.1)
    cube = pgl.Box(0.02 * pgl.Vector3(1, 1, 1))
    turtle.customGeometry(cube)
    def to_geom_args(self,
                     conversion=1.0,
                     name=None,
                     _as_obj=False):  # pragma: lpy
        r"""Get arguments for creating a PlantGL geometry.

        Args:
            conversion (float, optional): Conversion factor that should be
                applied to the vertices. Defaults to 1.0.
            name (str, optional): Name that should be given to the created
                PlantGL symbol. Defaults to None and is ignored.

        Returns:
            tuple: Class, arguments and keyword arguments for PlantGL geometry.

        """
        import openalea.plantgl.all as pgl
        kwargs = dict()
        # Add vertices
        obj_points = []
        obj_colors = []
        for v in self['vertices']:
            xarr = conversion * np.array([v[k] for k in ['x', 'y', 'z']])
            obj_points.append(
                pgl.Vector3(np.float64(xarr[0]), np.float64(xarr[1]),
                            np.float64(xarr[2])))
            c = [v.get(k, None) for k in ['red', 'green', 'blue']]
            if None not in c:
                cast_type = int
                obj_colors.append(
                    pgl.Color4(cast_type(c[0]), cast_type(c[1]),
                               cast_type(c[2]), cast_type(1)))
        points = pgl.Point3Array(obj_points)
        if obj_colors:
            colors = pgl.Color4Array(obj_colors)
            kwargs['colorList'] = colors
            kwargs['colorPerVertex'] = True
        # Add indices
        obj_indices = []
        index_class = pgl.Index
        array_class = pgl.IndexArray
        smb_class = pgl.FaceSet
        # index_class = pgl.Index3
        # array_class = pgl.Index3Array
        # smb_class = pgl.TriangleSet
        for f in self['faces']:
            if _as_obj:
                f_int = [int(_f['vertex_index']) for _f in f]
            else:
                f_int = [int(_f) for _f in f['vertex_index']]
            obj_indices.append(index_class(*f_int))
        indices = array_class(obj_indices)
        args = (points, indices)
        return smb_class, args, kwargs
Example #27
0
def pgl_scene(g, flip=False):
    geometry = g.property('geometry')
    scene = pgl.Scene()
    for id in geometry:
        if not flip:
            sh = pgl.Shape(geometry[id])
        else:
            sh = pgl.Shape(pgl.AxisRotated(pgl.Vector3(1, 0, 0), pi, geometry[id]))
        sh.id = id
        scene.add(sh)
    return scene
Example #28
0
 def __init__( self,  radius=absolute_shapes.ACYLINDER_STANDARD_RADIUS, axis=absolute_shapes.ACYLINDER_STANDARD_AXIS, **keys ):
     """ Default constructor.
     """
     #if keys.has_key("height"):
     #    self._height = keys[ "height" ]
     #else:
     #    self._height = pgl.norm( axis )
     #self._radius = radius
     keys.update( {"radius": radius, "axis": axis} )
     absolute_shapes.ACylinder._common_init( self, **keys  )
     AIShape3D.__init__( self,  scale=pgl.Vector3(2*self.radius,2*self.radius,self.height), geometry=absolute_shapes.ACYLINDER_PRIMITIVE,  **keys )
Example #29
0
def add_sun(scene, sun, distance=5, radius=0.1):
    elevation, azimuth, luminance = sun
    colors = jet_colors(luminance)
    pgl_colors = [pgl.Material(pgl.Color3(r, g, b)) for r, g, b in colors]
    sph = pgl.Sphere(radius)
    #red = pgl.Material(pgl.Color3(150, 0, 0))
    pos = cartesian(elevation, azimuth, distance)
    pgl_pos = [pgl.Vector3(*p) for p in pos]
    for i, vect in enumerate(pgl_pos):
        shape = pgl.Translated(vect, sph)
        scene.add(pgl.Shape(shape, pgl_colors[i]))
    return scene
 def transform(self, mesh, face_up=False):
     x = self.getUp()
     if face_up:
         z = pgl.Vector3(0, 0, 1)
     else:
         z = self.getHeading()
     bo = pgl.BaseOrientation(x, z ^ x)
     matrix = pgl.Transform4(bo.getMatrix())
     matrix.translate(self.getPosition())
     # print 'Position ', turtle.getPosition()
     mesh = mesh.transform(matrix)
     return mesh