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 Web VPython 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), c
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.