You are on page 1of 31

The arrow object has a straight box-shaped shaft with an

arrowhead at one end. The following statement will display an


arrow pointing parallel to the x axis:
pointer = arrow (pos=vector (0,2,1),
axis=vector (5,0,0), shaftwidth=1)
The arrow object has the following attributes and default values,
like those for cylinders: pos (0,0,0), axis (1,0,0), length (1), color
(1,1,1) which is color.white, red (1), green (1), blue (1), opacity (1),
shininess (0.6), emissive (False), texture, and up (0,1,0). As with
box, the up attribute is significant for arrow because the shaft and
head have square cross sections, and setting the up attribute
rotates the arrow about its axis. Additional arrow attributes:
shaftwidth By default, shaftwidth = 0.1*(length of arrow)
headwidth By default, headwidth = 2*shaftwidth
headlength By default, headlength = 3*shaftwidth
Assigning shaftwidth = 0 makes it be the default (0.1 times the length of the arrow). If you don't
explicitly set headwidth or headlength, its length is based as shown above on shaftwidth (either
the default or whatever value you specify for shaftwidth). If headlength becomes larger than half
the length of the arrow, or the shaft becomes thinner than 1/50 the length, the entire arrow is
scaled accordingly.
This default behavior makes the widths of very short arrows shrink, and the widths of very long
arrows grow (while displaying the correct total length). If you prefer that shaftwidth and headwidth
not change as the arrow gets very short or very long, specify the desired shaftwidth. In this case
the only adjustment that is made is that headlength is adjusted so that it never gets longer than
half the total length, so that the total length of the arrow is correct. This means that very short,
thick arrows look similar to a thumbtack, with a nearly flat head.
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the
object, whereas for a box, sphere, or ring it corresponds to the center of the object.
If you include make_trail=True when you create the object, a trail will be left behind the object as
you move it. For related options, see Leaving a Trail.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

Page | 1
Here is how to create a box object:
mybox = box(pos=vector(x0,y0,z0), length=L, height=H,
width=W)
The given position is in the center of the box, at (x0, y0, z0).
This is different from cylinder, whose pos attribute is at one end of the cylinder.
Just as with a cylinder, we can refer to the individual vector components of the
box as mybox.x, mybox.y, and mybox.z. The length (along the x axis) is L , the height (along the y axis) is H, and
the width is W (along the z axis).
For this box, we have mybox.axis = vector(L, 0, 0) . Note that the axis of a box is just like the axis of a cylinder.
For a box that isn't aligned with the coordinate axes, additional issues come into play. The orientation of the
length of the box is given by the axis (see the diagram):
mybox = box(pos=vector(x0,y0,z0), axis=vector(a,b,c), size=vector(L,H,W) )
The axis attribute gives a direction for the length of the box, and here the length, height, and width of the box
are given in terms of "size" (if the length or size is not specified when creating a box, the length is set to the
magnitude of the axis vector).
You can rotate the box around its own axis by changing which way is "up" for the box, by specifying an up
attribute for the box that is different from the up vector of the coordinate system:
mybox = box(pos=vector(x0,y0,z0), axis=vector(a,b,c), length=L, height=H,
width=W, up=vector(q,r,s))
With this statement, the width of the box will lie in a plane perpendicular to the (q,r,s) vector, and the height of
the box will be perpendicular to the width and to the (a,b,c) vector.
The box object has the following attributes and default values, like those for cylinders:
pos vector(0,0,0), axis vector(1,0,0), up vector(0,1,0), length (1), color (1,1,1) which is color.white, red
(1), green (1), blue (1), opacity (1), shininess (0.6), emissive (False), and texture. Additional box attributes and
details:
- height In the y direction in the simple case, default is 1
- width In the z direction in the simple case, default is 1
- size (length, height, width), default is vector(1,1,1) mybox.size=vector(20,10,12) sets leng th=20,
height=10, width=12
- axis Setting the axis makes the length of the box be equal to the magnitude of the axis vector.
An object's axis and up attributes are always perpendicular to each other.
Changing the direction of axis also changes the direction of up so that the two directions always remain at
right angles to each other. Similarly, changing the direction of up changes the direction of axis so that the two
directions always remain at right angles to each other.

Page | 2
- canvas By default, an object such as a box will be displayed in the most recently created 3D canvas, which
will be the default canvas named "scene" unless you create a canvas yourself (see the related discussion at
the start of the canvas documentation).
Order of operations: If when you create an object you specify values for axis and size and up, the operations are
executed in that order. That is, first axis is set (which sets the x component of size and may change up if
necessary to ensure that axis and up are perpendicular to each other), then size is set (which sets the
magnitude of the axis), and then up is set (which may change axis if necessary to ensure that axis and up are
perpendicular to each other).
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the object,
whereas for a box, sphere, or ring it corresponds to the center of the object.
If you include make_trail=True when you create the object, a trail will be left behind the object as you move it.
For related options, see Leaving a Trail.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

The cone object has a circular cross section and tapers to a point.
The following statement will display a cone with the center of its circular base at (5,2,0), pointing parallel to the
x axis with length 12; the wide end of the cone has radius 1:
cone(pos=vector(5,2,0), axis=vector(12,0,0), radius=1)
The cone object has the following attributes and default values, like
those for cylinders: pos vector(0,0,0), axis vector(1,0,0), length (1),
color (1,1,1) which is color.white, red (1), green (1), blue (1), opacity
(1), shininess (0.6), emissive (False), texture, and up vector(0,1,0).
As with cylinders, up has only a subtle effect on the 3D appearance
of a cone unless a non-smooth texture is specified or the cross
section is oval. Additional cone attributes:
radius Radius of the wide end of the cone, default = 1
size Instead of specifying length and radius, you can set size=vector(length, height, width), which means that
the cross section of the cone can be elliptical, which is not currently possible in classic VPython
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the object,
whereas for a box, sphere, or ring it corresponds to the center of the object.
If you include make_trail=True when you create the object, a trail will be left behind the object as
you move it. For related options, see Leaving a Trail.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

Page | 3
The curve object displays straight lines between points, and if the points are sufficiently close together you get
the appearance of a smooth curve.
Details of the curve object
The simplest example of a curve is the following statement, which draws a white straight line of length 2,
between the positions < -1,-1,0 > and < 1,--1,0 >:
c = curve(vector(-1,-1,0), vector(1,-1,0))
You can add additional points to this curve like this, completing a square of width 2 whose center is at location
< 0,0,0 >:
c.append(vector(1,1,0), vector(-1,1,0), vector(-1,-1,0))
Suppose you have two vectors named v1 and v2. Any of the following schemes will draw a white straight line
from position v1 to position v2:
1) c = curve(v1,v2)
2) c = curve([v1,v2])
3) c = curve(pos=[v1,v2])
4) c = curve(v1) c.append(v2)
5) c = curve() c.append(v1,v2)
Specifying overall color and radius
By default a curve is white, with a radius of the cross-section of only a few pixels. You can change the default
color and radius for all points, using either of the following schemes:
1) c = curve(pos=[v1,v2], color=color.cyan, radius=0.3)
2) c = curve(color=color.cyan, radius=0.3)
c.append(v1,v2)
Specifying the color and radius of individual points
You can specify the color and radius of individual points that override the color and radius specified for the
curve as a whole. The following sequence will create two dictionaries to use as individual points, then will use
them to draw a line whose color shades from red to blue and whose radius increases from 0.1 to 0.3:
p1 = dict(pos=v1, color=color.red, radius=0.1) p2 = dict(pos=v2,
color=color.blue, radius=.3) curve(p1,p2)
If you prefer, you can create the dictionaries like this:
p1 = {'pos':v1, 'color':color.red, 'radius':0.1} p2 = {'pos':v2,
'color':color.blue, 'radius':0.3} curve(p1,p2)
In addition to the attributes pos, color, radius, and emissive, each point has a visible attribute, which makes that
particular point visible or invisible. One cannot make a curve transparent (opacity < 1).
Retaining a limited number of points
When creating a curve, or when appending a point to a curve, you can specify how many points
Page | 4
should be retained. The following statement specifies that only the most recent 150 points should be retained
as you add points to the curve:
c = curve(retain=150)
The following statement specifies that if there are already 30 points in the curve, the oldest one should be
deleted and the new point added.
c.append( pos=vector(2,-1,0), retain=30)
The curve attributes
Here is a summary of the attributes for individual points or for the curve as a whole:
pos A vector position or list of positions used in creating a curve. After the curve is created, one must use curve
methods such as c.point(N) to read position data.
radius Radius of the cross-section of this segment of the curve; if specified for the curve as a whole, it specifies
the radius of any points for which no specific radius was given.
The default radius is 0, which makes a thin curve.
color Color of a point; if specified for the curve as a whole, it specifies the color of any points for which no
specific color was given.
emissive If True, local and distant lights are ignored, and the brightness is governed by the object's own color.
The effect is that the object looks as though it is glowing. The default for emissive is False.
visible If False, point is not displayed; if False for the curve as a whole, no points are displayed.
retain Specify how many points to retain.
A curve also has the standard attributes size, axis, up, shininess, and emissive.
No texture, opacity, or compounding: Currently curves cannot be transparent, it is not possible to apply a
texture, and a curve cannot be part of a compound object.
Moving, reorienting, and resizing a curve
Point positions are relative; the use of origin: A point whose pos is vector(2, 1, 0) is of course normally displayed
at location vector(2, 1, 0). However, the position of a point is relative to a curve's own origin value, which by
default is vector(0, 0, 0). If you change the curve's origin value to vector(10, 6, 5), the point is displayed at the
location vector(12, 7, 5); that is, the point is displayed 2 to the right, 6 above, and 0 in front of the curve's
position vector(10, 6, 5). Another way of saying this is that the display location is the vector sum vector(10, 6,
5) + vector(2, 1, 0).
This means that you can quickly and efficiently move the entire curve just by changing the curve's origin value.
The pos value of an individual point does not change; it's just that the point is displayed in a shifted position. As
a result, moving an entire curve is very fast.
Similarly, changes to size, axis, up, shininess, and emissive immediately and quickly change the size of the
curve, its orientation in space, and the appearance of its surface. When you specify the position of a point, it is
relative to an origin at vector(0,0,0) and with the standard axis vector(1,0,0). Changing the size does not
change the radius; it just moves the points closer or farther apart.
Rotating a curve As with other objects, the way to change the orientation of the entire curve is to change the
curve's axis. You can also rotate the entire curve about a specified axis. If you don't specify an origin, rotation
will occur around the origin of the curve:

Page | 5
c.rotate( angle=ang, axis=a, origin=o )
c.rotate( angle=ang, axis=a )
Curve methods
The basic aspects of the curve object are the same as the Classic VPython curve object. You create a curve and
append points to it. However, modifying existing points is not done directly but instead by using a powerful set
of functions, and this change makes it possible to display curves much more rapidly. In Classic VPython, the
possibility of direct modification of the positions meant that the entire curve had to be reprocessed every time
it was rendered, on the chance that some undetected change had occurred.
The following are useful for modifying a curve named "c" (full documentation below):
c.npoints The total number of points currently in the curve.
c.append(...) Add a point or several points to the end.
c.unshift(...) Insert a point or several points at the start.
c.splice(...) Insert a point or several points anywhere.
c.modify(...) Modify the Nth point.
c.clear() Remove all points.
data = c.pop(n) Get the data for point number n and remove it. Can use negative values, where -1 is the last
point, -2 the next to the last, etc.
data = c.shift() Get the data for the first point and remove it.
data = c.point(N) Get the data for the Nth point.
data = c.slice(start, end) Get the data for a list of points.
Appending points
Suppose you have created a curve named c. You can add points to the curve one at a time, like this:
c.append(pos=vector(-1,0,0), color=color.red, radius=0.05)
c.append(pos=vector(0,1,0), color=color.cyan, radius=0.15)
c.append(pos=vector(1,0,0), color=color.red, radius=0.05)
This creates the following image:

If you don't need to specify color or radius you can just give a list of positions, either as individual positions or
in a list of positions:
c.append( vector(-1,0,0), vector(0,1,0), vector(1,0,0) )
c.append([vector(-1,0,0), vector(0,1,0), vector(1,0,0)])
Suppose you have created a curve named c, and p represents either just a position vector (as just shown above)
or a full description of a point:
p = dict(pos=a vector, color=a vector, radius=a number, visible=True or False)

Page | 6
This can also be written in the form of a Python dictionary:
p = {'pos':vector, 'color':a vector, 'radius':a number, 'visible':t=True or
False}
c.append( p1, p2, p3 ) # add several points
c.append([p1, p2, p3]) # add several points
pts = [p1, p2, p3] c.append(pts) # add several points
You can also add several points that all have the same color, radius, etc.:
c.append(pos=[p1, p2, p3], color=color.green)
Manipulating points
Here are details on getting data about points in a curve named "c", or modifying them.
npoints
c.npoints # the number of points in the curve
append
c.append(...) # add points at the end (see above)
unshift
c.unshift(p1, p2, p3) # insert points at start
pts = [p1, p2, p3] c.unshift(pts) # insert points at start
The splice method inserts new points starting at location "start" (where 0 is the first point of the curve),
deleting "howmany" points before doing the insertion:
c.splice(start,howmany,p1,p2,p3) # insert
pts = [p1, p2, p3] c.splice(start,howmany,pts) # insert
The modify method lets you change specified attributes of a point:
c.modify(N, # modify point number N pos=p, color=c, radius=r, visible=v)
c.modify(N, x=3, y=5) # changing x and y but not z c.modify(N, vector(x,y,z)) #
change only pos
clear
c.clear() # remove all points from curve
pop
data = c.pop() # get & remove last point data = c.pop(3) # get & remove point
number 3
shift This is the same as c.pop(0):
data = c.shift() # get & remove first point
point
P = c.point(N) # get a point in the form # {'pos':p, 'color':c, 'radius':r,
'visible':v} # P['pos'] is p, P['color'] is c, etc.
slice
data = c.slice(2,4) # get a list of # points from point no. 2 through point no.
3, # each in the form # {'pos':p, 'color':c, 'radius':r, 'visible':v} # The
first point is 0, the last point is -1

Page | 7
Interpolation of colors
The curve machinery interpolates colors from one point to the next. If you want an abrupt change in color, add
another point at the same location. In the following example, adding a cyan point at the same location as the
orange point makes the first segment be purely cyan.
c = curve(color=color.cyan, radius=0.2) c.append( vector(-1,0.5,0) ) # add an
extra cyan point: c.append( vector(0,0,0) ) # repeat the same point: c.append(
pos=vector(0,0,0), color=color.orange ) # add another orange point: c.append(
pos=vector(1,0.5,0), color=color.orange )
In the image shown here, the upper thick curve, made without the second cyan point, has three
pos and color points, cyan, orange, orange, left to right, so the blue fades into the orange. The
lower curve includes the extra cyan point and has four pos and color points, cyan, cyan, orange,
orange, so there is a sharp break between blue and orange.

Studying this description of the cylinder object provides an overview of important aspects common to all of the
VPython 3D objects, box, sphere, pyramid, etc. Additional details about how to orient an object using "axis" and
"up" are found in the description of the box object.
Here is an example of how to make a cylinder, naming it "rod" for future reference:
rod = cylinder(pos=vector(0,2,1),
axis=vector(5,0,0), radius=1)
The center of one end of this cylinder is at x=0, y=2, and z=1. Its axis lies along the
x axis, with length 5, so that the other end of the cylinder is at (5,2,1), as shown in
the accompanying diagram.
You can modify the position of the cylinder after it has been created, which has the
effect of moving it immediately to the new position:
rod.pos = vector(15,11,9)
rod.pos.x = 15 # only change pos.x
If you create an object such as a cylinder but without giving it a name such as rod, you can't refer to it later. This
doesn't matter if you never intend to modify the object.

Page | 8
Since we didn't specify a color, the cylinder will be the current "foreground" color (see Controlling One or More
VPython Canvases). The default foreground color is white. After creating the cylinder, you can change its color:
rod.color = vector(0,0,1) # make rod be blue
This will make the cylinder suddenly turn blue, using the so-called RGB system for specifying colors in terms of
fractions of red, green, and blue. (For details on choosing colors, see Specifying Colors.) You can set individual
amounts of red, green, and blue like this:
rod.red = 0.4 rod.green = 0.7 rod.blue = 0.8
The cylinder object can be created with other, optional attributes, which can be listed in any order.
Here is a full list of attributes, most of which also apply to other objects:
pos Position: the center of one end of the cylinder; default = vector(0,0,0)
axis The axis points from pos to the other end of the cylinder, default = vector(1,0,0). Setting the axis makes
length equal to the magnitude of the axis. An object's axis and up attributes are always perpendicular to each
other. Changing the direction of axis also changes the direction of up so that the two directions always remain
at right angles to each other.
up Which side of the cylinder is "up"; this has only a subtle effect on the 3D appearance of the cylinder unless a
non-smooth texture is specified or the cross section is oval; the default is vector(0,1,0). An object's axis and up
attributes are always perpendicular to each other. Changing the direction of up also changes the direction of
axis so that the two directions always remain at right angles to each other.
length Length of axis and x component of size; default is 1. Setting the length makes the magnitude of the axis
equal to the length.
radius The radius of the cylinder, default = 1
size Instead of specifying length and radius, you can set size=vector(length,height,width), which means that
the cross section of the cylinder can be elliptical, which is not currently possible in classic VPython. Setting size
makes the magnitude of axis be equal to the x component of the size (the length).
color Color of object, as a red-green-blue (RGB) triple: vector(1,0,0) is pure red, default = vector(1,1,1), which
is color.white
red, green, blue (can set these color attributes individually), defaults are all 1
opacity Opacity of object, default = 1; 0 is completely transparent
shininess 0 to 1, default 0.6; governs the amount of specular reflections.
emissive If True, local and distant lights are ignored, and the brightness is governed by the
object's own color. An example of its use is to put an emissive sphere at the location of a local_light, which looks
like a glowing lamp. The default for emissive is False.
texture Texture of object; see Textures for currently available options (there are no materials in as there were
in Classic VPython, but textures are similar)
canvas By default, an object such as a cylinder will be displayed in the most recently created 3D canvas, which
will be the default canvas named "scene" unless you create a canvas yourself (see the related discussion at the
start of the canvas documentation).
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the object,
whereas for a box, sphere, or ring it corresponds to the center of the object. If you include make_trail=True

Page | 9
when you create the object, a trail will be left behind the object as you move it. For related options, see Leaving
a Trail.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.
When you start a VPython program, for convenience VPython creates a canvas and names it scene. By default,
objects that you create go into that canvas. See Controlling One or More VPython Display Windows later in this
reference for how you can create additional canvases and place objects in them.

A long ellipsoid object looks like a cigar; a short one looks like somewhat like a pill. Its cross sections are circles
or ellipses. The elllipsoid object has the same attributes as the box object and it can be thought of as fitting
inside a box of the same dimensions:
myell = ellipsoid(pos=vector(x0,y0,z0), length=L, height=H, width=W)
You can also make an ellipsoid simply by specifying the size of a sphere as vector(length, height, width), where
length, height, and width aren't all the same.
The given position is in the center of the ellipsoid, at (x0, y0, z0). This is different from cylinder, whose pos
attribute is at one end of the cylinder. Just as with a cylinder, we can refer to the individual vector components
of the ellipsoid as myell.pos.x, myell.pos.y, and myell.pos.z. The length from end to end (along the x axis) is L ,
the height (along the y axis) is H , and the width is W (along the z axis). For this ellipsoid, we have myell.axis =
vector(L, 0, 0) . Note that the axis of an ellipsoid is just like the axis of a cylinder.
For an ellipsoid that isn't aligned with the coordinate axes, additional issues come into play. The orientation of
the length of the ellipsoid is given by the axis (see diagrams shown with the documentation on the box object):
myell = ellipsoid(pos=vector(x0,y0,z0), axis=vector(a,b,c), length=L, height=H,
width=W)
The axis attribute gives a direction for the length of the ellipsoid, and the length, height, and width of the
ellipsoid are given as before (if a length attribute is not given, the length is set to the
magnitude of the axis vector).
The ellipsoid object has the following attributes and default values, like those for cylinders:
Pos vector(0,0,0), axis vector(1,0,0), length (1), color (1,1,1) which is color.white, red (1), green (1),
blue (1), opacity (1), shininess (0.6), emissive (False), texture, and up (0,1,0).
Additional attributes, similar to those for a box:
height In the y direction in the simple case, default is 1
width In the z direction in the simple case, default is 1
size vector(length, height, width), default is vector(1,1,1)
myell.size=vector(20,10,12) sets length=20, height=10, width=12
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the object,
whereas for an ellipsoid, box, sphere, or ring it corresponds to the center of the object.
Page | 10
If you include make_trail=True when you create the object, a trail will be left behind the object as you move it.
For related options, see Leaving a Trail.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

The extrusion object extrudes a 2D shape along a path. Here is an example, and here is the minimal syntax:
ex = extrusion(path=..., shape=...)
The path attribute is a list of points defining a path along which a 2D shape is extruded. The shape attribute is a
list of x-y pairs describing the perimeter of a 2D surface, such as[ [2,0], [0,4], [-2,0], [2,0] ]. This 2D shape is
extruded along the points specified by the pos list. (In GlowScript version 2.1 the details were somewhat
different.)
The size of the extrusion: After creating an extrusion named "ex", ex.size represents the size of the bounding box
of the extrusion. The x, y, and z components of ex.size can also be referred to as ex.length, ex.height, and
ex.width.
The position of the extrusion is ex.pos: After creating an extrusion named "ex", ex.pos is located at the center of
the bounding box. Later changes to ex.pos move the center of the extrusion to a new location. If you specify pos
when creating the extrusion, the center of the extrusion will be moved to that location, just as if you changed
ex.pos after creating the extrusion.
After creating an extrusion, changing the axis rotates the combined object. As with some other objects such as
sphere or compound, changing the axis does not affect the size.
Other attributes
An extrusion is made out of quads and triangles which are then made into a compound object for speed of
display. You can make additional copies of an extrusion by cloning it. You can move an extrusion by specifying a
new pos, and you can change its size, axis, up, color, opacity, shininess, and emissive, as with other objects, but
note that color is "multiplicative"; see compound.
Here are additional attributes that can be specified when creating an extrusion but cannot be changed later:
show_start_face and show_end_face By default, these attributes are True and the start and end faces are
displayed. If you set one of these to False, that face is left open.
These attributes have no effect if the path is closed.
start_face_color and end_face_color By default,the starting and ending faces are given the same color as the rest
of the extrusion, as specified by color, but you can specify that other colors be used for the starting or ending
face.
These attributes have no effect if the path is closed.

Page | 11
smooth By default, adjacent normals for which the cosine of the angle between them is greater than 0.95
(corresponding to an angle of 18 degrees) are averaged so as to smooth the adjacent surfaces. You can set
smooth to a looser criterion for more smoothing. For example, setting smooth=0.9 will smooth adjoining
surfaces whose orientation differs by 53 degrees, a much looser criterion.
The three steps to making an extrusion
1) Create a 2D shape, either by giving a list of points or by choosing a shape from a supplied library of common
shapes. Here are three examples. The first creates a triangle by listing 2D points. The second example creates a
circular shape from the shapes and paths library, and the third creates a rectangular shape, using the shapes
library.
tri = [ [2,0], [0,4], [-2,0], [2,0] ]
circ = shapes.circle(radius=3)
rect = shapes.rectangle(width=0.2, height=0.4)
A shape must be closed. That is, the last point must be the same as the first point.
2) Create a 2D or 3D path along which to extrude your shape, either by giving a list of points or by choosing a
path from the shapes and paths library. Here are two examples (2D for simplicity).
The first is a triangular path. The second chooses a circular path in the xz plane, and the third chooses a
rectangular path in the xz plane. (Recall that "vec" is shorthand for "vector".)
tripath = [ vec(1,0,0), vec(0,0,-2), vec(-1,0,0), vec(1,0,0) ]
circpath = paths.circle(radius=3)
rectpath = paths.rectangle(width=4, height=2)
A path need not be closed, in which case there will be end caps. For example, the following path is a portion of a
circle:
arcpath = paths.arc(angle1=pi/4, angle2=pi)
3) Create an extrusion object to extrude your shape along your path. For example, using paths and shapes
defined above, plus a color specification,
extrusion(path=circpath, shape=rect, color=color.red)
In this example a color (red) will be applied to the extrusion. You can include attributes such as
pos, color, size, axis, up, opacity, shininess, and emissive when creating the extrusion, and these specifications
will be applied to the compound object after it is created.
Path direction
The 2D paths in the shapes and paths library go counterclockwise in the xz plane, as seen from above. That is, if
starting from a position on the x axis, they head in the -z direction and bend toward the left. If your shape has
something sticking out on the right, it will be on the outer side of the extrusion, whereas something sticking out
on the left will be on the inner side of the extrusion.
However, when specifying a path from the shapes and paths library, you can specify a pos and up, to tip the
path out of the x-z plane. The path of the following extrusion will have a center at the location vec(1,2,0),
oriented perpendicular to the vec(1,0,0):
extrusion(path=paths.circle(pos=vec(1,2,0), shape=shapes.rectangle(width=0.4,
height=0.2),
up=vec(1,0,0), radius=2), color=color.cyan)
Page | 12
How the extrusion machinery works
At every point along the path this point plus the preceding and following points define a plane.
A 2D plane is established perpendicular to the plane at this point.
The 2D shape is drawn in this 2D plane.
A shape should be positioned so that its center is approximately at the location of the path locations.
If you offset the shape far from the path, you may get odd results, because there is enhanced danger of two
adjacent drawing planes intersecting each other.
Also, making sharp turns of wide extrusions may lead to one segment overlapping another.
If the bending angle from one point to the next is large, a mitered joint is produced.
The bending angle is considered to be large if its cosine is greater than 0.95 (an angle of less than about 18
degrees).
Holes in the 2D shape
You can create a 2D shape with holes in it, in which case the extrusion has hollow sections.
The statement below creates an extrusion of a circular disk that contains a triangular hole and a
trapezoidal hole:

extrusion(path=[vec(0,0,0), vec(0,0,-5)], color=color.orange,


shape=[ shapes.circle(radius=3), shapes.triangle(length=2),
shapes.trapezoid(pos=[0,2], width=4, height=1, top=2) ])
Here the shape is described by a list of shapes. The first shape in the list is always the
outer contour, and the remaining shapes represent holes. Holes must not overlap each other, which gives an
error.
It is even possible to have several (non-overlapping) outer contours, each with holes.
Suppose "O" represents an outer contour and "I" represents an inner contour (a hole). The following shape
has three pieces, two of them with holes:
s =[ [O, I, I], [O], [O, I] ]
As an example of this, the statement below creates an extrusion of a triangle and a rectangle,
and the triangle contains two holes:

extrusion(path=paths.arc(radius=2, angle1=-pi/3,
angle2=pi+pi/3), color=color.cyan, shape=[
[shapes.triangle(length=2),
shapes.circle(pos=[0,.5], radius=0.2),
shapes.trapezoid(pos=[0,-0.2], width=0.6,
height=0.4)], [shapes.rectangle(pos=[0,1.8],
width=1,height=0.3)] ])

Page | 13
The following statement will display a helix that is parallel to the x axis:
spring = helix(pos=vector(0,2,1), axis=vector(5,0,0), radius=0.5)
The helix object has the following attributes and default values: pos vector(0,0,0), axis vector(1,0,0), length (1),
radius (1), coils (5), thickness (radius/20), color vector(1,1,1) which is color.white, red (1), green (1), blue (1),
and up vector(0,1,0). More details:
length Length of axis; if not specified, axis determines the length, default = 1
If length is specified, it overrides the length given by axis radius The radius of the helix, default = 1
thickness is the diameter of the cross section of the curve used to draw the helix; default is radius/20.
size Instead of specifying length and radius, you can set size=vector(length,height,width), which means that
the cross section of the helix can be elliptical.
Note that the pos attribute for cylinder, arrow, cone, pyramid, and helix corresponds to one end of the object,
whereas for a box, sphere, or ring it corresponds to the center of the object.
Currently it is not possible to specify the opacity of a helix object, which is based on the curve object.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

With the label object you can display text in a box, and the label always faces forward,
even if you rotate the scene (for 3D text, see the text object). Here is a simple example:
label( pos=vec(0,0.25,0), text='Hello!' )
There are many additional label options. In the diagram to the right, an object located at
"obj.pos" has an associated label with the text "Early" in a box, connected to the object.
L = label(pos=obj.pos, text='Early', xoffset=20, yoffset=50,
space=30, height=16, border=4, font='sans')
A unique feature of the label object is that several attributes are given in terms of screen
pixels instead of the usual "world-space" coordinates. For example, the height of the text
is given in pixels, with the result that the text remains readable even when the sphere object is moved far away.
Other pixel-oriented attributes include xoffset, yoffset, and border. Here are the label attributes:
pos The point in world space being labeled.
pixel_pos If True, pos is the position in terms of pixels, with vec(0,0,0) in the lower left corner.

Page | 14
align Specify 'left', 'right', or 'center'. When you specify 'center', which is the default, the center of the topmost
line of text is at the location given by pos. When you specify 'left', the start of the topmost line of text is at the
location given by pos. When you specify 'right', the right end of the topmost line of text is at the location given
by pos.
xoffset, yoffset The x and y components of the line, in pixels (see diagram). Unless you specify a value for align,
text above or below pos is centered, text to the left of pos is right-adjusted, and text to the right of pos is left-
adjusted.
text The text to be displayed, such as 'Earth'. You can give a number or numerical expression; it will be
converted to a string.You can include the HTML styles for italic (<i> or
<em>), bold (<b> or <strong>), superscript (<sup>), or subscript (<sub>). For
example, the string
'The <b>mass < i>M</i></b><sub>sys</sub> = 10<sup>3</sup> kg.
displays as
'The mas s Msys = 103 kg.
Multiple lines can be displayed by inserting line breaks (\n), as in
"Three\nlines\nof text" and you can insert <br> or <br/> instead of \n. You can
also create multiple lines by using triple quotes:
L = label() L.text = """The quick brown fox jumps over the lazy dog."""
font Name of the desired font; 'sans' or 'serif'' or 'monospace' (fixed-width), or a specific font name; the default
is "sans"
height Height of the font in pixels; default is 15 pixels
color Color of the text; default is scene.foreground
background Color of the background of the box; default is scene.background
opacity Opacity of the background of the box, default 0.66 (0 transparent, 1 opaque, for objects behind th e box)
border Distance in pixels from the text to the surrounding box; default is 5 pixels
box True if the box should be drawn (default), else False
line True if a line from the pos to the box should be drawn (default), else False
linecolor Color of the line and box
linewidth Thickness of the line drawn from the pos to the box, and the edges of the box (default is 1 pixel)
space Radius in pixels of a sphere surrounding pos, into which the connecting line does not go
visible Label is not displayed if False
See description of Additional Attributes available for all 3D display objects.

Page | 15
You can light a scene with distant lights (which act like point-like lamps far from the scene) and/or local lights
(point-like lamps near the scene, like the yellow light shown above).
For a distant light you specify its direction from the origin. For a local light you specify its location in the scene.
There is a list of all distant and local light objects, scene.lights. By default, scene.lights is this list:
[distant_light(direction=vector( 0.22, 0.44, 0.88),
color=color.gray(0.8)), distant_light(direction=vector(-0.88, -0.22, -0.44),
color=color.gray(0.3))]
You can get rid of these default lights by setting the list to empty with scene.lights = [].
You can turn a light on or off by setting visible to True or False.
In addition to these default distant lights, there is default ambient lighting in the form of
scene.ambient=color.gray(0.2). The color of light objects and the amount of scene.ambient must be specified
with some care, because if the total lighting intensity exceeds 1 anywhere in the scene the results are
unpredictable.
The following statement creates a local yellow light whose position is at (x,y,z), and if you continually update
lamp.pos, the light will move. You may wish to place a sphere or box with emissive=True at the same location
so that the lamp looks like a glowing lamp.
lamp = local_light(pos=vector(x,y,z), color=color.yellow)
A distant red light located in the direction (x,y,z) from the origin is created like this:
distant_light(direction=vector(x,y,z), color=color.red)

The points object is essentially the same as the curve object except that it displays individual points at the
specified positions instead of connecting them with lines, and it does not have origin, size, axis, or up attributes,
nor does it have a rotate method. The points are rendered as simple_sphere objects, for maximum display
speed.
The points object takes a list of points for pos, like the curve object. The following statement will display two
points, each of radius 50 pixels:
points(pos=[vector(-1,0,0), vector(1,0,0)], radius=50, color=color.red)
Page | 16
The points object is similar to a curve, but with disconnected points. As with curve, the pos attribute is an array
of points. The size of the points is specified by radius and the default radius is 2.5, meaning a sphere whose
radius is 2.5 pixels (a diameter of 5 pixels). The radius attribute is in screen pixels if size_units="pixels" (the
default), but if size_units="world", the radius is in the same terms as other objects. Setting the radius to 0 is the
same as not specifying a size, in which case the radius will be 2.5 pixels, just as a curve is thin if its radius is
specified as 0.
If size_units="world", the default radius is 0.5.
With size_units="pixels" in effect (the default), a point in the z = 0 plane will have the specified radius, but it
will be larger or smaller than the specified radius if it is nearer or farther from the camera.
Unlike a curve object, a points object can be transparent (opacity < 1).
The options for manipulating a curve can also be used with the points object, but currently the points object
doesn't handle changes in axis or size, does not have an origin nor a rotate method, nor can it be made into a
compound.

The pyramid object has a rectangular cross section and tapers to a point. The following statement
will display a pyramid with the center of the rectangular base at (5,2,0), pointing parallel to the x
axis with a base that is 6 high (in y), 4 wide (in z), and with a length 12 from base to tip:
pyramid(pos=vector(5,2,0), size=vector(12,6,4))
The pyramid object has the following attributes and default values, like those for cylinders:
Pos which is the center of the rectangular base vector(0,0,0), axis vector(1,0,0), length (1), color (1,1,1) which
is color.white, red (1), green (1), blue (1), opacity (1), shininess (0.6), emissive (False), texture, and up (0,1,0).
Additional pyramid attributes:
height In the y direction in the simple case, default is 1
width In the z direction in the simple case, default is 1
size (length, height, width), default is vector(1,1,1)
mypyramid.size=vector(20,10,12) sets length=20, height=10, width=12
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the object,
whereas for a box, sphere, or ring it corresponds to the center of the object.
If you include make_trail=True when you create the object, a trail will be left behind the object as you move it.
For related options, see Leaving a Trail.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

Page | 17
The ring object is by default circular, with a specified radius and thickness and with its
center given by the pos attribute:
ring(pos=vector(1,1,1), axis=vector(0,1,0), radius=0.5,
thickness=0.1)
The ring object has the following attributes and default values, similar to those for
cylinders: pos vector(0,0,0), axis vector(1,0,0), length (0.2), color vector(1,1,1) which
is color.white, red (1), green (1), blue (1),
opacity (1), shininess (0.6), emissive (False), texture, and up (0,1,0).
As with cylinders, up has a subtle effect on the 3D appearance of a ring unless a non-
smooth texture is specified or the ring is oval.
The axis attribute only affects the orientation of the ring; the magnitude of the axis attribute is irrelevant.
Additional ring attributes:
radius Radius of the central part of the ring, default = 1, so
outer radius = radius+thickness
inner radius = radius-thickness
thickness The radius of the cross section of the ring (1/10th of radius if not specified), not the full diameter as
you might expect.
size Instead of specifying radius and thickness, you can make the ring be oval by specifying its size as
size=vector(length,height,width), with different height and width..
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the object,
whereas for a ring, sphere, and box it corresponds to the center of the object.
If you include make_trail=True when you create the object, a trail will be left behind the object as you move it.
For related options, see Leaving a Trail.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

Page | 18
Here is an example of how to make a sphere:
ball = sphere(pos=vector(1,2,1), radius=0.5)
This produces a sphere centered at location (1,2,1) with radius = 0.5, with the current
foreground color.
The sphere object has the following attributes and default values, similar to cylinder:
pos vector(0,0,0), axis vector(1,0,0), color vector(1,1,1) which is color.white, red (1),
green (1), blue (1), opacity (1), shininess (0.6), emissive (False), texture, and up
vector(0,1,0).
As with cylinders, up and axis attributes affect the orientation of the sphere but have
only a subtle effect on appearance unless a non-smooth texture is specified or the cross section is oval. The
magnitude of the axis attribute is irrelevant. Additional sphere attributes:
radius The radius of the sphere, default = 1
size Default is vector(2,2,2). Instead of specifying the radius, you can set size=vector(length,height,width),
which means that the cross section of the sphere can be elliptical, making it like the ellipsoid object. Unlike
other objects, changing size doesn't change axis, changing axis doesn't change size.
canvas By default, an object such as a sphere will be displayed in the most recently created 3D canvas, which
will be the default canvas named "scene" unless you create a canvas yourself (see the related discussion at the
start of the canvas documentation).
Note that the pos attribute for cylinder, arrow, cone, and pyramid corresponds to one end of the object,
whereas for a sphere it corresponds to the center of the object.
If you include make_trail=True when you create the object, a trail will be left behind the object as you move it.
For related options, see Leaving a Trail.
A fast sphere object: simple_sphere
In order to look smooth, a sphere is made of a very large number of triangles. Sometimes speed is more
important than ultimate beauty. The simple_sphere object can be used just like a sphere, but a large number of
simple_sphere objects is displayed very much faster than the same number of regular spheres. For speed, the
simple_sphere object is used in the points object and in trails that use points.
See Rotating an Object for an easy way to change the orientation of an object.
See description of Additional Attributes available for all 3D display objects.

Page | 19
See the Text Output discussion for additional ways to output text in the GlowScript environment.
With the text object you can display 3D text. The green 3D text shown above was created with the following
statement:
T = text(text='My text is\ngreen', align='center', color=color.green)
Labels were added to the display above to illustrate some of the main attributes of the text object.
Whether you extrude into or out of the screen, the text is created so that it is readable left to right from the
normal viewing position, in the +z direction.
Limitations: It is important to know that this 3D text object is very complex and expensive to display, nor can
you modify the letters displayed once the object has been created.
If for example you want to display rapidly changing text, use the label object (displayed in front of the canvas)
or the wtext object (displayed above the canvas as part of the title or below the canvas as part of the caption).
Also see the section "Displaying text" of the canvas documentation.
Currently this 3D text object does not handle HTML options, such as bold, italic, subscript, or superscript. The
label and wtext objects do however support these options.
3D text is made out of quads and triangles which are then made into a compound object for
speed of display. You can make additional copies of a text object by cloning it. You can move the text by
specifying a new pos, and you can change its axis, up, color, opacity, shininess, and emissive, as with other
objects, but note that color and size are "multiplicative"; see compound.
The 3D text object does not have a size attribute. Instead, the size of the display is specified by height, length and
depth as discussed below.
Here is a list of text attributes, in addition to the usual attributes of canvas, color, shininess, and opacity (but
not texture or bumpmap, currently):
pos The location of the baseline of the text, to the left, to the right, or at the center of the text, as per align.
align Specify 'left' (default), 'right', or 'center'.
text The text to be displayed, such as "My text is\ngreen" in the example above ('\n' is a newline character).
Unicode strings are supported. After creating the object, the text is read-only -- it cannot be changed.
The reason for this is that it takes a significant portion of a second to create a 3D text object. If you need to
change the text, make the current object invisible (visible=False) and create a new object. The text
need not be a string; it can be anything that you could print.

Page | 20
height Height of an uppercase letter (see above); default is 1. Specifying the height when creating the text
object sets the scale for the entire text display. After creating the 3D text, you can change the height of the
object.
For example, if you say T.height = 0.5*T.height, the letters become shorter but the length stays the same.
Changing the height also changes descent and vertical_spacing.
length length of the displayed text. You cannot specify a length when creating the 3D text, but you can change
this later. For example, if you say T.length = 0.5*T.length, the letters become narrower but the height stays the
same.
depth Depth of the text; the default is 0.2 times the height when creating the 3D text.
A positive number means extrude toward you, out of the screen; negative means
extrude away from you, into the screen. After creating the 3D text, you can change this. For example, if you say
T.depth = 2*T.depth, the letters become twice as thick. If the depth is zero, the thickness is made to be 0.01
times the height, and the text looks like a thin sheet.
font Name of the desired font, either "sans" (sans serif, the default) or "serif". This is read-only.
billboard In computer graphics "billboard" behavior means that the object always faces you, no matter how you
reorient the camera. Specifying billboard = True when creating the text turns this on, and then is read-only.
Because lighting changes as you rotate the camera, you may wish to specify emissive = True, so that the text is
always bright.
color The color of the text.
start_face_color and end_face_color By default,the starting and ending faces are given the same color as the rest
of the text, as specified by color, but you can specify that other colors be used for the starting or ending face of
the extruded text.
show_start_face and show_end_face By default, these attributes are True and the start and end faces of the
extruded text are displayed. If you set one of these to False, that face is left open.
descender Height of the descender on lower-case letters such as y (whether or not there is such a letter in the
text). This is typically about 0.3 times the height.
This is readonly but is affected by changes in height.
upper_left, upper_right, lower_right, lower_left The bounding box of the displayed text; all of these are read-
only. For example, if you create title = text(text="My Text"), you
can place a sphere at the upper left corner with the statement
sphere(pos=title.upper_left).
See the screen display above.
start, end The left-most and right-most locations on the baseline. These are read-only. If align is 'left', pos is the
same as start. If align is 'right', pos is the same as end.
vertical_spacing Vertical distance from one baseline to the next in a multiline text. This is readonly.

Page | 21
There is a set of built-in 3D objects (box, sphere, etc.). You can also create your own 3D objects, and even
change their shapes dynamically, as in the case of the example program shown above, in which a pulse moves
up along a rug.
The surface of an object consists of a mesh of triangles, and a triangle consists of 3 vertices.
We can create a triangle by first creating three vertex objects, then using them to form a triangle:
a = vertex( pos=vec(0,0,0) )
b = vertex( pos=vec(1,0,0) )
c = vertex( pos=vec(1,1,0) )
T = triangle( v0=a, v1=b, v2=c )
Equivalently, one could write this:
T = triangle( v0=vertex( pos=vec(0,0,0) ), v1=vertex( pos=vec(1,0,0) ),
v2=vertex( pos=vec(1,1,0) ) )
Another option is to give a list of vertex objects:
T = triangle( vs=[a,b,c] )
Often it is convenient to divide a surface into rectangles instead of triangles, which is done with a quad object.
The following statements are equivalent to creating two triangles with vertices (a, b, c) and (a, c, d):
a = vertex( pos=vec(0,0,0) )
b = vertex( pos=vec(1,0,0) )
c = vertex( pos=vec(1,1,0) )
d = vertex( pos=vec(0,1,0) )
Q = quad( v0=a, v1=b, v2=c, v3=d )
You could also write this:
Q = quad( vs=[a,b,c,d] )
The vertices of a triangle or quad can have their own colors, which are blended between vertices:

Page | 22
The role of the "normals", shown here as arrows perpendicular to the plane of the triangle, is discussed in detail
below. If you point the thumb of your right hand in the direction of the normal, and curl the fingers of your right
hand, your fingers should go from v0 to v1 to v2. To put it another way, looking down the normals from above,
going from v0 to v1 to v2 should go counterclockwise.
The power of triangles and quads
There are two powerful capabilities of triangles and/or quads: First, any surface can be approximated by a
mesh of triangles, so you can make any shape you like. Second, by changing the attributes of vertex objects, you
can change the shape of a surface dynamically.
A vertex object can be shared by several adjacent triangles, and changing that vertex object simultaneously
affects all of the triangles that include that vertex object.
In the rug example pictured above, the rug is divided into a rectangular mesh of vertex objects, and quad objects
are created from these vertex objects. The same vertex may be shared by as
many as four adjacent quad objects. Changing the z position of a shared vertex object affects all those quads
that refer to that vertex, which makes it easy to create a moving pulse simply by modifying the vertex positions.
In the rug program the quad objects are needed to display the rug,
but once the quads have been created all further calculations refer just to the underlying vertex objects.
For a triangle or quad, in addition to specifying vertex objects you can specify texture and/or visible, but the
usual attributes for other objects such as pos or color don't apply; this information is specified in the vertex
objects. (It is not possible to specify place, flipx, flipy, or turn for a triangle or quad texture. These effects can be
achieved by the way texpos is specified in the vertex objects.)
If you wish to specify a bumpmap to go with a texture, use the same scheme used with other objects.
This example assumes that you have specified texpos values in the vertex objects
(see below):
quad(vs=[a,b,c,d],texture=dict(file=textures.stones,bumpmap=bumpmaps.stones))
If you prefer, you can create the dictionary like this:
quad(vs=[a, b, c, d], texture={'file':textures.stones,
'bumpmap':bumpmaps.stones))
Display speedup: Typically you will use many triangles to create a complex object. For clarity you
might wish to keep them all in a list: tris = [ triangle1, triangle2, ....]. If the object's internal shape
need not change (unlike the case of the rug), you can say "s = compound(tris)" in which case you
can move and resize and rotate the object "s" very rapidly, just as though it were a built-in object
such as a sphere.
Vertex attributes
The attributes of a vertex object are pos, normal, color, opacity, texpos, bumpaxis, shininess, and
emissive. The pos attribute represents the location of the vertex in 3D space.
The attributes color, opacity, shininess, and emissive are the same as those for other objects such
as box or sphere, but within a triangle they are averaged among the three vertex objects. For
example, at locations between a red vertex and a green vertex there is a fade from red to green. A
striking effect occurs if two of the three vertex objects have opacity = 0, because as you approach
the edge of the triangle bounded by those two vertices the triangle fades to nothing.
Page | 23
The vertex attributes normal, texpos, and bumpaxis require additional explanation..
normal: The lighting of a triangle, based on its own color and the lights provided, is calculated
based on the "normals" to the triangle, vectors pointing away from the surface of the triangle. In
the simplest case, the normal at each vertex is perpendicular to the surface of the triangle, as
shown in the figure above.
Each triangle has three normals, at each of the three vertices. The normal at each interior point of
the triangle is an average of the three specified normals.
Where two triangles meet, you will see a sharp break if the two triangles have different normals. If
you want to smooth the transition, you should average the neighboring normals (n1+n2)/2 and
apply them to both triangles; this will smooth out the joint.
If you don't explicitly specify a normal for a vertex, the normal is given the default value vec(0,0,1),
pointing out of the screen. If the vertex is to be used in a triangle that does not lie in the xy plane,
you need to specify a normal yourself. If the three vertices are a, b, and c (in counter-clockwise
order), and you want normals that are perpendicular to the triangle, you can calculate the normal
like this:
(b-a).cross(c-b).norm()
The "vector cross product" produces a vector that is perpendicular to the plane defined by the two
vectors b-a and c-b, the first two edges as you go around the triangle. If the fingers of your
relaxed right hand curl in the direction a to b to c, your outstretched thumb points in the direction
of the vector cross product.
texpos: If you intend to apply a texture or bumpmap to a mesh object, you must specify in the
mesh how you want the texture to be mapped onto your object. You might want the texture to
occupy only a portion of the object, or be stretched or distorted in some way. This is done by
specifying "texel" coordinates, given as texpos vectors in the vertex objects.
Texel coordinates for a surface texture are specified by an "x" and a "y", both ranging from 0 to 1 if
the entire texture is to be displayed, left to right and bottom to top. (In many discussions texel
coordinates are referred to as "u" and "v", or as "s" and "t".) In anticipation that WebGL will
eventually enable 3D textures, which permit filling a textured volume, GlowScript requires that in
texpos elements the third component must be zero.
For example, to fill a quad with a texture, the texpos vectors in the vertex objects v0, v1, v2, and
v3 would be vec(0,0,0), vec(1,0,0), vec(1,1,0), vec(0,1,0), no matter what the 3D pos attributes
are. If you want only the lower quarter of the texture to fill the quad, the texpos vectors would be
vec(0,0,0), vec(0.5,0,0), vec(0.5,0.5,0), vec(0,0.5,0). Note that <0,0,0> is at the lower left, and
<1,1,0> is at the upper right.
bumpaxis: If you will use a bumpmap, you need to specify a vector bumpaxis direction for each
vertex, specifying the direction of the "x" axis of the texture at that location. The default bumpaxis
is vector(1,0,0).
Important limitation: WebGL currently supports no more than 65536 vertex objects. However,
when you compound an object involving vertex objects, any vertex objects that are not used in

Page | 24
other objects are are freed up to be re-used.
Mouse picking of triangles/quads
The operation scene.mouse.pick() gives the object lying under the mouse. It may be convenient to
specify my_id='car' as your own attribute for each triangle or quad in the object, so that you can
tell whether the triangle or quad is part of the 'car' group:
t1 = triangle(... my_id='car')
t2 = triangle(... my_id='car')
...
obj = scene.mouse.pick()
if (obj != null and
obj.my_id != un defined and
obj.my_id == 'car') hitcar = True

Color
In the RGB color system, you specify a color in terms of fractions of red, green, and blue, corresponding to how
strongly glowing are the tiny red, green, and blue dots of the computer screen.
In the RGB scheme, white is the color with a maximum of red, blue, and green (1, 1, 1).
Black has minimum amounts (0, 0, 0). The brightest red is represented by (1, 0, 0); that is, it has the full amount
of red, no green, and no blue.
Here are some examples of RGB colors, with names you can use in VPython:
vec(1,0,0) color.red vec(1,1,0) color.yellow vec(0,0,0) color.black
vec (0,1,0) color.green vec(1,0.6,0) color.orange vec(1,1,1) color.white
vec(0,0,1) color.blue vec(0,1,1) color.cyan
vec(0.4,0.2,0.6) color.purple vec(1,0,1) color.magenta
You can also create your own colors, such as these:
vector(0.5, 0.5, 0.5) a rather dark gray; or you can say color=color.gray(0.5) to mean (0.5,0.5,0.5)
vector(1,0.7,0.2) a coppery color
Colors may appear differently on different computers, and under different 3D lighting conditions.
The named colors above are most likely to display appropriately, because RGB values of 0 or 1 are unaffected
by differing color corrections ("gamma" corrections).
There is a VPython demo program that lets you adjust RGB sliders to visualize colors and print color triples that
you copy into your program. It also provides HSV sliders to adjust hue, saturation (how much white is added to
dilute the hue), and value (brightness), which is an alternative way to describe colors.
VPython only accepts RGB color descriptions, but there are functions for converting color triples between RGB
and HSV:
c = vector(1,1,0) c2 = color.rgb_to_hsv(c) # convert RGB to HSV print(hsv) #
vector(0.16667, 1, 1) c3 = color.hsv_to_rgb(c2) # convert back to RGB print(c3)
# vector(1, 1, 0)
Another example: sphere(radius=2, color=color.hsv_to_rgb(vector (0.5,1,0.8) )

Page | 25
Opacity
You can make most objects be transparent by specifying a value from 0-1 inclusive for the
attribute "opacity". For example, box(color=color.red, opacity=0.8) is slightly transparent. An
opacity value of 0 means totally transparent, and 1 means totally opaque. Currently curve and
helix objects do not allow transparency.

The print functions


The print function places text in a scrolling text region at the bottom of the window. Consider the following
statements:
v = vec(1,2,3) print("This is a test.") print("The vector v =", v, ".")
These statements produce this output:
This is a test. The vector v = < 1, 2, 3>.
The first print statement creates the scrolling text region. Later print statements add to the existing text, with
end-of-line breaks after each print, and with spaces between items listed in a print statement.
You can print multiline text like the following:
print('''This is a test of multiline text which displays as shown.''')
You can change the end of line ('\n" by default) and the item separator (" " by default). Consider the following
print statements:
v = vec(1,2,3) print("Look:", end="---") print("v =", v, ".", sep="_",
end="!!")
These statements produce this output:
Look:---v =_< 1, 2, 3 >_.!!
The elements "sep=..., end=..." must be the last arguments in the print statement.
String formatting
Python has a powerful mechanism for formatting a string. This has now been implemented in GlowScript (for
VPython, RapydScript, and JavaScript). Here is an example (in VPython):
V = 13.47 s = "There are {:.1f} {}." p = s.format(V, 'liters') print(p) #
"There are 13.5 liters."
Or more compactly,
print( "There are {:.1f} {}.".format(V, 'liters') )
The element "{:.1f}" indicates "fixed format" with ".1" indicating that one digit should be shown after the
decimal point. The value 13.47 is rounded to 13.5. If you specify "{:12.3f}", what will be displayed is " 13.470",
with 6 spaces before the number, plus the 6 digits of "13.470" (3 after the decimal point), for a total of 12
characters.
The element "{}" indicates that the default method for representing an argument should be used.
In this case "bucket" is displayed.
There are many formats available: b for binary (base 2), o for octal (base 8), x for hexadecimal (base 16; 28
displays as 1c), d for decimal integer, e for exponential (e.g. 5.32e-7), c for character

Page | 26
code (e.g. converts "b" to 97), % for percent (displays 0.34 as 34%). The E exponential format gives 5.32E-7
and the X hexidecimal format gives 1C.
The g format (g for general) is particularly useful because it flips between fixed and exponential formats
depending on the size of the number.
The following statement
print("The {} {} {}.".format("quick","brown","fox"))
produces "The quick brown fox". You can specify a different order of the arguments. The following statement
print("The {2} {0} {1}.".format("quick","brown","fox")) produces "The fox quick brown."
In other words, {N} refers to the Nth argument, counting from zero.
Moreover, you can combine specifying which argument to display with the format to use:
s = "Here are fixed format ({0:.3f}) and exponential
format ({0:.3e}) versions.".format(127.73)
Print options (not currently available in VPython 7)
With print_options you can change the default size of the print region, allow the user to edit the text, clear the
text from the region, destroy the region, or obtain the current contents of the print region.
The following statement changes both the width (default 640) and height (default 100) of the print region.
If you execute this before your first print statement, the initial size will be 500 by 300. If you execute this after
executing print statements, the size of the region will change (but will retain its contents).
print_options(width=500, height=300)
By default, the text in the print region is read-only; the user cannot edit the text. If you want the user to be able
to edit the text, do this:
print_options(readonly=False)
In any case, the user can select text and copy the text with ctrl-c.
By default, numbers are displayed with six digits, such as 123.456 or 1.23456e+8. You can specify the number
of digits to display:
print_options(digits=4)
You can clear out all the text from the region like this:
print_options(clear=True)
You can delete the region from the screen with this statement:
print_options(delete=True)
After deleting the region, another print statement will recreate it, with the previously specified width and
height.
By default the print area appears underneath the canvas (pos = 'bottom') but you can make it appear to the
right of the canvas with the following statement (you may have to include something like width=100, because
if the window is too narrow to fit the canvas and the text area side by side, the text area goes below the canvas):
print_options(pos='right')
You can also place the print area at a specifiable place on the page:
print_options(place=scene.title_anchor)
print_options(place=scene.caption_ancho r)
You can obtain the current contents of the print region as a character string:
Page | 27
text = print_options(contents=True)
The text is extracted before processing clear or destroy requests. If you don't request the contents,
print_options returns the empty character string ""'.
You can of course combine any options in one statement:
print_options(width=150, readonly=False)
Additional text output methods
The canvas documentation explains how to add text above a canvas (scene.title) or below a canvas
(scene.caption). The wtext object lets you place dynamically modifiable text in the middle of the caption or title
of a canvas.
The Example program ScrollingText shows how to create a scrolling text object that you can send output to and
type into, using the HTML element "textarea". This is the mechanism used by
print.
alert('The mass is '+m+' kg.')
This pauses execution and dis plays the string in a dialog box. Numeric values are converted to strings.
$('body').append('This is a test.<br>')
...
$( 'body').append('This is only a test.<br>')
These statements add text to the bottom of th e web page. The <br> element makes a line break,
console.log('A scalar', a+10, 'and a vector', v.toString())
The output in the console is the following:
A scalar 15 and a vector < 10, 20, 30 >
Successive console.log outputs appear as new lines.
Using console.log requires opening the browser's "console". To enable the console, in Chrome press shift-ctrl-j
on Windows or Ubuntu, or option-cmd-j on Mac. In Firefox on Windows choose Firefox > Web Developer >
Web Console, and on Ubuntu choose Tools > Web Developer > Web Console.
The output will be found at the end of the console output In some of these output options, to display the value
of a vector v you have to write v.toString(), but this is done automatically by the print statement.

Page | 28
The stucco-textured box shown above was made with this statement:
box( texture=textures.stucco )
A collection of ready-to-use textures is provided; "textures.stucco" actually represents a character string giving
the name of the image file. For the complete set of existing built-in textures, see the example program Textures.
You can optionally specify that only portions of the object should be textured. The following statement places
the texture only on the right face of the box, leaving the rest of the box untextured:
box( color=color.green, texture={'file':textures.stucco, 'place':'right'} )
Using images from other web sites:
You can use an image from another web site as a texture by specifying its URL, if that web site is "CORS
enabled" (CORS = Cross-Origin Resource Sharing). For example,
texture="https://s3.amazonaws.com/glowscript/textures/flower_texture.jpg"
will fetch an image consisting of a cactus flower. For technical reasons, if the image has a width or height that is
not a power of 2 (that is, not 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, etc.), the image is stretched to the next
larger width or height that is a power of 2.
There is a CORS-enabled site, http://i.imgur.com, that has extensive galleries of freely usable images. When you
see an image you want, right-click the image (Mac Ctrl-click), choose "Copy image address", and paste the
address into your texture specification, bracketed by quotation marks. You can upload an image to i.imgur.com
by clicking the "+" icon.
VPython 7 and textures: If you are using VPython 7 you can use a texture on your own computer.
The texture file must be in the same directory as your program file (in which case you would specify
texture='T.jpg'), or in a subdirectory of that directory (for example, texture='images/T.jpg').
If you want your texture to be available to programs stored in different places, look at ...../ Lib/site
packages/vpython/vpython_data
There you will find the standard textures that are installed with VPython. Place a copy of your texture in this
folder.
In your VPython program, the following statements will display a box with your texture on it, depending on
whether you use a Jupyter notebook or not:
Jupyter notebook: box(texture='/nbextensions/vpython_data/T.jpg')
No notebook: box(texture='T.jpg')
There should be a change to VPython 7 to accept 'T.jpg" in either environment. It should first look for the file
where your program is located, and then in the vpython_data folder.
If you use "Share this program" in the GlowScript editor and copy code to a page on your own

Page | 29
web site, you can fetch an image to use as a texture from the same web site, even if your web site isn't CORS-
enabled.
Placing a texture on portions of the object: Placement options are 'left', 'right', 'sides' (all but the left and right
ends), 'ends' (both left and right), and 'all' (the default). The meaning of left and right is that by default
GlowScript objects have their axis in the (1,0,0) direction (+x), and the right end is on the right initially, before
possible later changes of axis. In the case of a cylinder, 'sides' specifies the curving surface.
You can combine these options: 'place' : ['left', 'sides'] will place the texture on the left end and the sides.
Flipping and rotating: You can change the orientation of a texture on an object by specifying
'flipx' : True (reflect left <-> right),'flipy' : True(reflect up <-> down), 'turn' : N (rotate counterclockwise N 90-
degree angles; if N is negative, the turning is clockwise).
These transformations are applied in the order flipx, flipy, turn.
All the parameters for a texture are seen in the following example.
b = box( pos=vec(-1,2,0), texture={'file':textures.stucco,
'bumpmap':bumpmaps.stucco, 'place':['right', 'sides'], 'flipx':True,
'flipy':True, 'turn':-3} )
Currently you have to give all the information in one package, as in the example above, rather than specifing an
individual parameter such as texture.turn. You can retrieve this information as T = b.texture, which gives you
the information in the form of a Python dictionary.
Color: Textures have their own colors, but if you specify a non-white color for a fully textured object, that color
is mixed into the texture color, so that you can have for example green stucco.
If only portions of the object are textured, the object color is not mixed with the texture color, and non-textured
portions are shown with the specified object color.
Textures loaded: It takes time to load a texture from the specified file, so it may be important in your program
to wait for all textures to be loaded before displaying the scene.
The following sequence will achieve this effect:
scene.visible = False # show nothing yet ...create the objects
scene.waitfor("textur es") scene.visible = True # s how everything
First, make the scene invisible, create the objects (which won't be visible), then wait for all textures to have
been loaded. Then make the scene visible, and you'll see the objects with their textures.
This is the technique used in the example program Textures.
You can also check the status of an individual object B: the quantity B.ready is true if the texture has been
loaded (or if B has no texture).
Textured objects are not displayed until the texture has been loaded. If you don't wait with
scene.waitfor("textures"), you may see objects become visible in a random sequence, depending on when the
various textures have been loaded.
Removing a texture: If you set texture=None, no texture is displayed.

Bump maps:Another option is to specify a "bump map". Bump maps make small distortions in a surface to
give the illusion of a non-smooth surface.

Page | 30
There are several kinds of bump maps, but the type of bump map currently supported in GlowScript is a
"normals map", in which the normals (perpendiculars) to the surface, which affect the lighting of the surface,
are varied across a surface in such a way that the surface no longer seems smooth. When you move the surface
or the lights you will see an enhanced 3D effect. Bump maps can be produced from images by using computer
tools made for this purpose, and a few bumpmaps have been provided in GlowScript. For example,
bumpmaps.stucco is a normals map that enhances the 3D appearance of textures.stucco. Here is the statement
that adds the built-in bump map to the built-in texture:
box(texture={'file':textures.stucco, 'bumpmap':bumpmaps.stucco)
The example program Bumpmaps lets you move the lighting around as well as rotate the object so that you can
see the effects of adding a bumpmap.
The bump maps currently available are bumpmaps.gravel (to accompany textures.gravel), bumpmaps.rock (to
accompany textures.rock), bumpmaps.stones (to accompany textures.stones), bumpmaps.stucco (to
accompany textures.stucco), and bumpmaps.wood_old (to accompany textures.wood_old).

Page | 31

You might also like