Various Scripted 3D Projects

When: 2006-present
Technologies: CG, VR, LSL, SecondLife, 3D modeling, animation, Gimp, Photoshop, linear algebra, simulation, emulation

I created many projects on SecondLife — a very flexible, community-driven 3D virtual world. One of the things which attracted me to that environment was the ability to freely script 3D models and bring them to “life,” making them interact with each other and the other people (“avatars”) within SL. The added challenge is working within the limitations of the small CPU and memory footprint available to LSL scripts, as well as the limited API, pushing the boundaries of what is possible.

Some of these projects are functional tools, while others are more of an artistic exploration.

Intel 8080 emulator

This was a particular opportunity to push LSL to its limits. I have a nostalgia for retro computing, and the Intel 8080 holds a special place in history: the first “personal computer,” the Altair 8800 used it (Paul Allen and Bill Gates’ first big success was implementing BASIC on the 8080), and Nintendo’s GameBoy was based on it. Zilog’s Z80 became immensely popular, ending up in Tandy’s TRS-80, and even graphing calculators like the TI-83 and 86.

The 8080 instruction set should have a “familiar” feel to it, for anyone who has used the x86 family, and that’s no coincidence. When Intel designed the 8085 and 8086, they wanted 8080 assembly code to run smoothly, as well. This was before higher-level compiled languages were widely used, and people still wrote their applications in CPU-specific assembly.

The nice thing from a modern perspective is that it’s fairly easy to wrap one’s head around the processor architecture, its various states, and its full instruction set. Thus, we still learn about and use microcontrollers based on this family, decades later.

There are naturally many 8080 emulators in the world, but to my knowledge, this was the first time anyone created one in SL. The primary technical challenges of this project were as follows:

  • Limited memory per script: LSL Mono scripts are limited to 64KB per script, which includes the compiled byte code and all data generated by the script. However, 8080-based systems like the Altair 8800 typically included 4-8KB RAM and could address up to 64KB. The CPU logic, registers, and flags, combined with comm routines can easily approach 64KB.
  • Inefficient data structures: LSL has only two dynamic data structures: strings and lists. There is no pointer-based memory access, and list operations are rather inefficient. The most efficient way I could devise of implementing “RAM” was to pack the byte data into LSL’s 32-bit signed integers, and store those into a list. Accessing the list involves some overhead, so that in practice, I could only store about 4KB data per script.
  • Inter-script communication: Due to the script size limits, the project requires at least two scripts (one for the CPU and one for 4KB memory). This means the scripts will need to synchronize signals and data transfers, much like an actual 8080 system, in fact!
  • Optimal state machine structure: LSL scripts are modeled as finite state machines, with event handlers in each state handling the logic. I tried to follow the 8800 CPU’s internal states as closely as possible, but of course, a few auxiliary and helper states were also needed.
  • Run real software: I fully intended this emulator to be a working 8080 simulator, indistinguishable from the real thing, as far as software is concerned. Every instruction should have the same side-effects as a real 8080 (e.g. CPU flag and register states). That means a good test suite, aka CPU exerciser, is mandatory. There is also the practical concern of loading assembled code in a format like Intel HEX. Fortunately, people have been writing 8080 emulators for roughly 40 years, so there are significant resources available.
  • Emulate real hardware: To run actual software like Microsoft 4K BASIC means I had to emulate I/O devices like the tape loader, display, and keyboard. This required a good bit of digging around in old documentation for e.g. the Altair 8800.
  • Implement text display: OK, this wasn’t necessary strictly speaking, but for the true “retro” experience, I wanted that classic green-text look (Matrix-style, you know?). That comes with its own peculiar set of challenges in LSL: ASCII symbols are packed into textures, applied to faces of “prims,” which have been shaped to have a large number of aligned, rectangular faces that can be arranged into interlinked rows and columns.

The physical design is something like the Altair 8800: a panel of mysterious switches and lights, with a text monitor sitting on top. Unfortunately, due to network latency (≈20ms RTT) in script communication, the emulator can’t function at anything like full speed. Still, there is something magical about watching the lights flicker, and watching the patterns as various subroutines are called, a “feel” which is mostly lost in the modern computing experience. And I enjoyed resurrecting Microsoft Altair BASIC 🙂

Working orrery (model of the solar system)

This was an idea inspired by steampunk culture, a growing fascination with astronomy, and the mechanical devices crafted to show the motions of the planets of our solar system. The movie Men in Black may have been some influence as well 😉

I thought it would be really neat to have a working, pocket-sized orrery. While there are a few such devices made today, they are either non-functional gimmicks or prohibitively expensive. Mechanically, I can’t imagine constructing something so tiny and complex, but programming… that I can do!

After reading numerous papers and articles on e.g. orbital mechanics, I realized this is actually a very complex topic. However, I don’t need the accuracy of NASA simulations, only something that looks good. I found a 1970s paper on integer-based formulas for calculating the positions of the planets to reasonable accuracy (“Low-precision formulae for planetary positions”), which combined with some more modern guides, I was able to script a functional orrery in LSL.

Designed in typical steampunk fashion (polished brass, gold, etc.), with added dials for moon phase, time, date, velocity, and altitude, because honestly, who doesn’t need all of that information at a glance?!

Animated 3D sculptures

I really like visualizing data in new ways. Adding randomness and interpolation means you can discover previously unexplored things.

Fractal trees

Random idea I had: How about animated 3D fractal trees?! In SL, there is a limit of 255 primitives per object. I want fractal trees with far more than 255 nodes. So, I used a master-slave approach, where a single master script controls unlimited slave scripts, each of which is responsible for up to 255 prims. There is still a limit at the simulator level, but we can nonetheless generate some nice-looking and fun fractals! Trees have a configurable number of branches per node, angle constraints, etc.

Splines

A spline is a parametric curve. Anyone who had a Windows computer back in the 90s-early 00s will remember the screensavers that had color-changing, transforming shapes on the screen — some of those were splines! Why not bring the fun of splines to SL?

By connecting primitive cylinders end-on-end using 3D vector and quaternion math, it’s possible to construct a spline. With some creativity and animation, the effect can be quite mesmerizing.

Random trees and tubes

Similar to splines, only instead of parametric curves, we can form constrained piece-wise solids out of toruses, boxes and cylinders. Large prim sets update more slowly, and smooth animation becomes more difficult, but the visuals are fascinating.

Chaotic spheres

Tiny spheres that randomly “jump” around a center point, changing size and color, but in a visually pleasing manner. Most aspects are configurable such as: size and distance constraints, and speed.

Random shapes

SL shapes are referred to as primitives (“prims”). Most primitives are parametric, meaning they are defined by a set of parameters. For example, the standard “box” shape has a 3-dimensional size up to 10m in each direction, as well as a 3D position, quaternion rotation, per-face textures, optional hole shape, and many others. One of the challenges of building or modelling in SL is recognizing the best parameters to minimize the number of prims needed.

By exploring the full set of parameters, it’s possible to discover many strange and interesting shapes. With random parameters and interpolation, I found that it’s possible to create nice-looking animated sculptures.

A variation on this idea is “prim memory,” a game which I created to test memory skills, while admiring the vast permutations of prims. An n x n grid of random prims is created, which begin hidden under blank wooden cubes, but are revealed when you touch one. The goal is to find its match somewhere else in the grid, using the minimum number of guesses. A wrong guess means both are hidden again, and you have to try again. (To make it a little easier with similar shapes, each pair is also colored).

Animated particle systems

Particles are a CG concept, involving systems with potentially large numbers of camera-facing 2D sprites. You see them all the time for simulating fluids like smoke and water. They can also be used as art. The tricky thing about particle systems is discovering the optimal set of parameters to achieve the desired effect. SL particle systems have something like two dozen different parameters, all of which can take on a range of values, e.g. starting color, burst radius, burst rate.

Similarly to random prims, it is possible to create random particle systems and animate them using interpolation.