If you're new to Python
  and VPython: Introduction

  A VPython tutorial

  Introductory Videos

  Pictures of 3D objects




  VPython 7 web site
  VPython license


The compound object lets you group objects together and manage them as though they were one object, by specifying in the usual way pos, color, size (or length, width, height), axis, up, opacity, shininess, emissive, and texture. Moreover, the display of a complicated compound object is faster than displaying the individual objects one at a time. (In GlowScript version 2.1 the details were somewhat different.)

The object shown above is a compound of a cylinder and a box:

handle = cylinder( size=vector(1,.2,.2),                   color=vector(0.72,0.42,0) )

head = box( size=vector(.2,.6,.2), pos=vector(1.1,0,0),              color=color.gray(.6) )

hammer = compound([handle, head])
hammer.axis = vector(1,1,0)

The size of the object: After creating the compound named "hammer", hammer.size represents the size of the xyz bounding box of the object. The x, y, and z components of hammer.size can also be referred to as hammer.length, hammer.height, and hammer.width.

The position of the compound is hammer.pos: After creating the compound, hammer.pos is located at the center of the bounding box. Later changes to hammer.pos move the center of the compound object to a new location.

No linkage of axis and size: After creating the hammer as a compound object, changing the axis rotates the combined object. Changing the axis does not affect the size.

Invisible objects are included: All objects in the list become part of the compound, even if they have visible = False. It is as though all the objects have visible set to True.

The individual objects in a compound are "frozen". You can't change their attributes such as positions or orientations except as a group.

Color blending

Setting hammer.color to something other than white makes a multiplicative blend of the overall color with the colors of the individual objects. For example, if the color of the handle is cyan, vector(0,1,1), and the hammer color is yellow, vector(1,1,0), the blend results in vector(0*1, 1*1, 0*0) or vector(0,1,0), which is green. If you plan to vary the color after creating the compound object, start with the color being white, vector(1,1,1), which is the default.

Specifying an origin

As mentioned above, after creating a compound its position (pos) is at the center of the bounding box that encloses all the pieces of the compound. Sometimes it is convenient for pos to be somewhere else in the compound, such as at the left end or even outside the bounding box. When creating a compound you can optionally specify a different location by setting the "origin", as in "compound([....] origin=vec(x,y,z))". This sets the initial pos of the compound to the origin, and when you move the compound by changing pos, origin doesn't change, thereby preserving a record of the original choice of origin.

Setting parameters when creating a compound

You can optionally specify parameters to be applied to a compound after its creation. The following statement is equivalent to creating the hammer, then changing the position and axis, where the resulting center of the compound will be at vector(3,2,0):

hammer = compound( [handle, head], pos=vector(3,2,0),
                   axis=vector(1,1,0) )

If you specify an origin, that sets the default pos value, which is then changed if you also specify a value for pos when creating the compound.

All of the objects to be compounded must belong to the same canvas, and the compound itself must also be in this canvas. Also, it is currently not possible to clone a compound to a different canvas.

Compound and world coordinates

There are two functions for translating between compound and world coordinates, which may differ if the compound object has been moved or rotated or resized. Suppose when you created the compound c a location on one of the objects was the vector v, and that after moving, rotating, and resizing the compound you would like to know where that point is now. In the following, world_pos is the corresponding location in "world" coordinates, the actual location in the current 3D scene:

world_pos = c.compound_to_world(v)

You can go the other way, from world coordinates to the coordinates at the time you created the compound. The following will display the value of the vector v:

print( c.world_to_compound(world_pos) )

Current restrictions

Currently objects in a compound can have their own values of color, opacity, shininess, and emissive, but they cannot have individual textures or bumpmaps, which can only be specified for the combined object, and which affect all of the compounded objects.

Currently label objects, lights, and objects based on curve objects (curve, helix) cannot be compounded. However, triangles, quads, and even other compounds can be compounded. Also, a compound object can be cloned to make additional copies.

Limitation on the number of objects to compound: In the WebGL 3D graphics library that is used by VPython, a compound cannot have more than 65536 (2**16) vertexes (pos, normal, color), due to WebGL using 16-bit integers to reference the vertexes. For example, a box object has 8*3 = 24 vertex objects, because each corner requires three vertex objects, all with the same positions but with three different normals. That means that a list of boxes to compound must not contain more than int(65536/24) = 2730 boxes. A cylinder, in order to have smooth sides, requires 206 vertexes, so a list of cylinders to compound must not contain more than int(65536/206) = 318 cylinders. If you need to compound more than 2730 boxes, a way to deal with the limitation is to make several compounds, each with less than 2730 boxes (and it may be convenient to store these compounds in a list). You can compound a list of compound objects, but the total number of vertexes cannot exceed the limit.

Currently here are the number of vertexes in each of the basic objects: box 24, cylinder 206, sphere 961, simple_sphere 81, pyramid 16, cone 604, ring 1281. Consequently, at present the limits on the number of objects that can be compounded are these (if all the objects are boxes, or cylinders, etc.): box 2730, cylinder 318, sphere 68, simple_sphere 809, pyramid 4096, cone 108, ring 51.

An informative error message is given if the vertex limit is exceeded.