## Summary of new features in the VPython version 4 beta release

Back to contents

### Beta release

This beta release is experimental in the sense that there are known bugs described below. Feel free to play with the exciting new features, but be aware that you may encounter problems.

There is a new example program texture_and_lighting.py that displays many of the new features: a swinging spotlight illuminates a translucent beach ball that rolls on a wood-texture table. Also see the example program boxlighttest.py.

### New toolbar with "pan" mode

At the top of a graphics window is a toolbar with an icon to change right-button dragging to "pan" rather than rotate (and another icon to switch back). There are also icons to exit the program, switch to or from full-screen mode, and reset to a standard camera position.

### Opacity

You can make most objects be partially 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, convex, faces, and helix objects do not allow transparency.

You can also specify opacity as a 4th component of a color:
box(color=(1, 0, 0, 0.8)) is the same as box(color=color.red, opacity=0.8).

In preparation for wider use of transparency, curve, faces, and points objects accept color arrays whose elements are either red-green-blue (rgb) such as (1, 1, 0) or red-green-blue-opacity (rgbo) such as (1, 1, 0, 0.8).

### Surface textures

You can create a texture object and then apply it to the surface of an object. This capability is currently limited to boxes and spheres. A surface texture is an M by N array of 1, 2, 3, or 4 numerical values (a list or tuple). M and N must be powers of 2 (1, 2, 4, 8, 16, 32, etc.). Here are the possible values for each slot in the array:

1 value: texture type must be "luminance" (how bright) or "opacity"

2 values (opacity,luminance): texture type must be "opacity_luminance"

3 values (red,green,blue): texture type must be "rgb"

4 values (red,green,blue,opacity): texture type must be "rgbo"

A VPython texture is basically a mask. For example, if you apply a texture to a box that is red, any cyan region of the texture will display as black, because the cyan (0,1,1) doesn't overlap at all with the red (1,0,0).

You can create a numeric array of zeros in various formats, then assign values:

zeros([...], ubyte) means an 8-bit unsigned integer 0-255
zeros([...], short) means a 16-bit iinteger plus or minus 0-32767
zeros([...], int) means a 32-bit integer plus or minus 0-2147483648
zeros([...], float) means a floating-point (fractional) number

Here is an example program in which a checkerboard texture is created and applied to a box:

from visual import *
M=4 # must be a power of 2 (1, 2, 4, 8, 16, 32, etc.)
N=4 # must be a power of 2 (1, 2, 4, 8, 16, 32, etc.)
checks = zeros([M,N], float) # create a numeric array of floating-point zeros (0.0)
for i in range(M):
for j in range(N):
if ((i&1) ^ (j&1)): # true for every alternate square of the checkerboard
checks[i][j] = 1.0
print checks
lum = texture(data=checks, type="luminance")
box(color=color.cyan, texture=lum)

If you wanted to create a texture containing "rgb" values, you would start with zeros([M,N,3], float), and entries into this array would be the usual (red,green,blue) triples, with values for each color in the range 0-1 inclusive.

See the contributed section of vpython.org for an example of a program to create, save, and use a wood-grain texture. Such a texture is included in the examples and used by the program texture_and_lighting.py.

### Lighting

Some objects now have a "shininess" attribute which by default is 0.5 (box, sphere, cylinder, cone, ring). A shininess of 0 means no specular highlights. A shininess of 1 means strong specular highlights. You can also for special purposes specify an attribute "lit" to False (or 0) in which case lights have no effect on it.

For compatibility with past programs, there is still a list of lights in scene.lights, and you can still manipulate those lights as before. However, those lights were restricted to being very far ("at infinity") from the scene. Now you can create lights that are nearby, and if you wish they can be spotlights with directed beams. The following statement creates a local blue light positioned at (x,y,z):

bl = light(pos=(x,y,z), color=color.blue, local=True)

Note that if you continually update bl.pos, the light will move.

By default, local is True. If you set local = False, the light is at infinity, in a direction given by pos.

Other attributes are spot_direction (a vector), spot_cutoff (half angle of the beam in degrees), diffuse_color, and specular_color. The attribute attentuation=(const, linear, quadratic) makes the light diminish with distance d according to the formula 1/(const + linear*d +quadratic*d). The default is (1,0,0). OpenGL guarantees to permit a minimum of seven lights.

If you want to disable all of the old lights, say scene.lights = [], making an empty list of old lights.

### New frame capabilities

You can now make a frame visible or invisible, and all objects in the frame will be affected. And you can set the vector "scale" attribute of a frame to change the size of the combined object. For example, someframe.scale = (2,.5,4) will make objects in the frame display as though you had doubled all the x components of objects in the frame (relative to the frame), halved the y components, and quadrupled the z components, with respect to their original values; initially a frame has scale = (1,1,1). As with other vector attributes, you can refer to the x component as someframe.scale.x.

### Points object

A new points object can be plotted in "screen" size as well as the usual "world" coordinates. Like curve, the pos attribute is a list of points, as is color. If you say shape = "round", the points are round, which is the default; shape = "square" makes square points. You can specify the size of the points, and the default is size = 5 (meaning a square 5 pixels by 5 pixels, or a circular disk bounded by a 5 by 5 square). The size attribute is in screen pixels if the type attribute is "screen" (the default), but if type is "world", the size is in the usual coordinates. A good use for the new object is for the gdots displayed using visual.graph. These used to be awkward labels using the letter "o" but have been replaced with screen-pixel points.

Technical caveats: If the "GL_ARB_point_parameters" property is shown in scene.info() then type = "world" will work. Otherwise the type is silently ignored and considered to be "screen". There is an implementation-defined size range for either round or square points, which is not easily visible to programs at this time. Specifying a size outside this range will cause it to be silently clamped internally to whatever range that the hardware supports.

### New aspects of curves

In older versions of VPython, no matter how many points were in a curve, only 1000 were displayed, selected evenly over the full set of points, in order that the display of a very long curve doesn't slow down unacceptably. In the new version this is still true but the number of points displayed is 10000.

The new option curve.retain = 500 means that only the 500 most recently added points of a curve will be displayed; the earlier ones are deleted. This is a nice option for having a moving object leave a tail behind itself.

### Nonuniform axes

The option scene.uniform = False now facilitates making graphs of functions and is used by the module visual.graph. The option is useful for making 2D displays whose x and y scale factors are different. The only objects supported are curve, faces, points, and label. Set the scale factors with scene.range.

### Fonts in labels

You can now specify font='times' or 'system' or 'symbol' etc. in a label object.

### Specifying a gray

For convenience you can now say color=0.7 to mean color=(0.7,0.7,0.7).

### Titlebar and toolbar heights

The height in pixels of the titlebar is given by display.get_titlebar_height(), and the height of the (to be optional) toolbar is given by display.get_toolbar_height(). These values are true for all windows, and these functions are associated with the display class of objects, not with individual displays such as the standard scene. So scene.get_titlebar_height() won't work..

### Render time

If you say scene.show_rendertime = True, in the lower left os the graphics window you will see the cycle time (time between renderings of the scene) and the render time (time taken to render the scene. This can be a useful diagnostic of performance issues. .

### Known bugs in this beta version

Here are known bugs:

> Can drag a window to be larger, but not smaller.

> Autoscaling is pretty good but occasionally positions the camera farther
> from the scene than one would prefer.

> Rendering of curves isn't quite right. This can be seen in the example program
> tictac.py, where one of the grid lines doesn't show until you rotate the view.

> Unicode text in labels works properly on Linux but not on Windows.
> As a temporary measure, Windows handles only simple English text.

> Spotlights created in a frame don't change with changes in the frame orientation.

> scene.cursor.visible is not implemented yet and gives an error.

Back to contents