Editor's note: You can download an oar file for the klein bottle
example and a klein bottle generator from rexxed.com.
Most objects in Opensim and Second Life are made of
prims.
Indeed, if we exceptuate avies, wearables (i.e., non-attachable
clothes and body parts), Linden trees and particles,
everything you see is made of prims. Prims are
small, often uncomplicated geometrical shapes, like a cube, a
sphere or a cylinder. By combining ("linking") prims, builders
create more complex objects like houses, vehicles, shoes, hair,
jewellery, etc. When prims are linked, the resulting object
remembers the order in which they were linked (which is important,
for example when an object is scripted) and some other properties;
the set comprised of the linked prims and these additional
properties is called a link set
or linkset.
Linksets in Second Life have
several limitations: two prims can't be linked if they are too far
apart, and an object cannot contain more than 256
prims. This is the cause all kind of problems. For
example, if you buy a big house, i.e., a house that has more than
256 prims or that it is very large (and therefore its prims are
very far apart), the house can't be assembled into a single object,
because of the above rules. Then the house is normally packaged
with a rezzer, a scripted assistant that helps you
to position the house; once the house is positioned to your liking,
you normally ask the rezzer to freeze the house in place, and then
delete the rezzer.

Opensim (when used with an
appropriate viewer, like the Hippo viewer) supports large
linksets, i.e., objects comprising more than 256 prims. In
this post I'll describe some experiments I made with large and very
large linksets. In one of these experiments, I created a
single object consisting of 2889 prims. Such extremely
large linksets are difficult to manage and create, but once you get
them built they work wonderfully.
Klein bottles

In August 2008, I visited in the
Wales Springs region of Second Life a fantastic sculpture by Suzanne
Graves. The sculpture reminded me of a Klein bottle
[indeed, technically speaking Ms. Graves' surface is not
Klein-like, because it has an odd number of curls], and I decided
to try to write a script to generate Klein bottles (you can find
the script in the appendix at the end of this post).
After some attempts, I got the
scripts working, and I generated a nice bottle, which I placed on
top of my club, in the center of the Condensation Land region in
SL. I made a fun video of my friend Ludmilla
and myself dancing inside the bottle :-)
Since the bottle existed in Second
Life and consisted of thousands of prims, it could not be linked
into a single object. The bottle stayed there several months, and
when the
Openspace fiasco started we
had to concentrate in a single island and I had to delete it
because Condensation Land got cramped and Second Life has a 15,000
prim limitation.
When I migrated the Condensation
Land archipielago to Opensim, I was not able to migrate the bottle,
because it was not linked. I still had the
program, though. Some tests I made when testing the
brand-new Rezzable Private Grid Alpha indicated that the script
could not be run unchanged (I tried to run it and brought the sim
to its knees :-/). But now I was the owner of my own grid, and
could look at the Opensim console while working with the script, so
that I could see if something was going wrong, stop the server,
etc. And the Hippo Opensim
viewer, since version 0.5.0, allowed linksets
larger that 256 prims! I absolutely wanted to test this feature
and see what could I do with it.
The Opensim experience
I had to adapt my Klein
bottle generator for Opensim - the technical details are
in the Appendix at the end of the post. Once the generator had run
(which took around two hours), I had a collection of 2888 unlinked
prims, i.e., the bottle itself (2880 prims), and 8 prims that had
beed doubly generated because of a small bug in the program. I then
created a central transparent prim destined to serve as the root
prim, and started to link the vertices to the root prim.
Up to around 1000 prims
everything worked flawlessly. When I tried to link more
prims, the linking operation started to be progressively slower; in
some cases, I was thrown out of the grid and had to relog.
When I got over 2000 prims, further linking was simply
impossible: the client got so busy that it stopped
responding to pings from the client, and the regions started to
drop the scene; the client itself timed out, and threw me out
before the linking operation was complete…
What to do? I then realized that I
was always using the same linking approach, imported from my SL
experience: I was selecting a moderately big number of prims, say
150, and trying to link them to the previously linked large
linkset. Maybe if I separately linked the remaining prims into
another large linkset, I would be able later to link the two
linksets between them? Well, I tried this approach, and it worked!
:-) I had to create another, temporary root prim, link the
remaining prims to the secondary root prim, link then the two
linksets, enter "select linked prims", unlink the secondary root
prim, take the object, and re-rezz it. And that was it! The final
linking took some time, but I was not thrown out of Opensim :-),
and both taking the object and re-rezzing it took an inordinately
big amount of time, but apart from that (which is very
understandable if you think of what's really going on under the
hoods) everything worked fine. I was able to move the huge
2889-prims linkset, to rotate it, to copy it, to make it full
bright, to apply some glow, and even to set it rotating! :-)

What seems to be happening (this is
all inference, I have not looked at the code)? Well, it appears
that if you link "n" prims to an existing linkset, this is
equivalent to recreating the linkset "n" times, one for each newly
linked prim. This is not a problem when the existing linkset is
small and the number of prims is also small, but if you're
attempting to link, say, 300 new prims to an existing linkset of
2000 prims, this involves 300 recalculations of a linkset averaging
2150 prims, and this is too much for the client, which hangs
miserably.
To the contrary, if you've got two
large linksets and you try to link them, there's only one
recalculation operation for the new linkset. And this
operation, albeit slow, occurs in a lapse of time small enough so
that the client does not crash.
Here's a video of the new bottle,
rotating on top of my club in the Condensation Land grid:
Appendix: Program code
Here is the code for the scripts
(I'll post a link to a downloadable version of the code as soon as
I find some time) [Update:] including links to the downloadable
source. The main script goes inside a standard cube, and works in
the following way: a Klein bottle is a bidimensional surface
immersed into a 3D space; apart from an irrelevant twist, it can be
considered as the product of two circumferences, and therefore it
can be parameterized using two variables "u" and "v". Some formulas
I found at
Planetmath calculate the corresponding 3D points taking "u" and
"v" as an input.
We generate only the edges (each
edge will be a prim; the code for generating the vertices is
commented out; I didn't figure how to generate the sides). Since we
are parameterizing in "u" and "v" and we can only generate a finite
number of prims, we have to decide on how many partitions of 2*PI
we'll use for "u" and "v". These are the "m" and "n" variables of
our program. In our example, we generate 120 partitions of "u" (the
"slices") and 8 partitions of "v" (the "stripes").
The program calculates the
vertices, and then computes the positions of the edges; the edges
are generated by rezzing a small prim ("Cylinder"), which is then
rotated, resized and colored; part of this job is done by a small
script residing inside "Cylinder"; the script auto-deletes itself
on completion.
The drawLineSegment routine I cannibalized from
somewhere, but I didn't write the reference [ I know, I know! :-)
If someone knows the reference, I'll happily include it here]
[Update]
http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryBezierCurveDemo
(thanks, Trevor! :-)).
Please note that I had to insert a
llSleep call after each rezzing - otherwise XEngine
starts to choke, compilation starts to fail, and the bottle
generation aborts.

Download
source code
This is the small script that goes
inside "Cylinder".

Download source code