Saturday, March 5, 2011

Minecraft procedural texturing success

Followup to the Temple of Rule 30:  I made another attempt at mapping the output of a 2D cellular automaton to 3D objects in Minecraft and had better luck with a different ruleset.  It can work, provided you choose the rules carefully and work only with large objects.

Here's a sampling of various block mappings used with the same algorithm on a 125 block diameter sphere.

Subtle & mossy
Nested bands of ore
Not-even-remotely-subtle edition
Pig approves.


With a little more work, I might be able to recreate Planet Bitmap from STNG...

Hmm, there's an idea:  Glowing planets in the night sky.  Pity the world is 30 million blocks wide but only 128 blocks tall.

Wednesday, March 2, 2011

Minecraft, Python, and the Temple of Rule 30

I've noticed in my recent job search that Python is a commonly requested scripting language.  I haven't really had much interest in learning it; several years of Ruby (on Rails), a long stretch of Perl, and various other languages at various levels of abstraction ranging all the way down to assembler have made it quite clear that there are only so many ways to express a control flow statement.  I feel that a computer language, as with any tool, should include staying out of your way as a central part of its design philosophy.  Ruby is very good about that.

So why learn Python?  Because it's frequently used as an embedded interpreter.  It's used to control and extend other software.  But what does this have to do with Minecraft?  MCEdit includes a Python interpreter, and I've been using MCEdit quite a bit.

I decided one day that I'd try to clear a large ziggurat-shaped space underground using more or less the same techniques used for TNT drift mining, only without leaving any of the intervening walls standing.  I'd clear the whole space and make the walls nice and tidy.

Right.

As amusing as it is to blast the hell out of stuff in Minecraft, clearing layers of 5x5x5 chunks became mighty tedious by the 5th layer down, at which point the floor was roughly 45x45.  Roughly, because some very large dirt and gravel inclusions were making a mess of things.  There was still a long way to go to bedrock.  I have my kinks, but holding down a mouse button long enough to remove or replace c. 73,000 blocks and calling that "fun" isn't one of them.  It was time to bring the power tools into the sandbox.

A long editing session brought the the pattern down to bedrock, exposing an existing railway and a bunch of deep caves I'd explored earlier.  I cleared out the lava and cleaned up the walls.  Here's the result.  The floor is 125 x 125, with torches in the middle of each visible 5x5 face.


Great!  All done.  The simple repeating patterns of light and dark and the hundreds of pinpoint torches looked quite nice.  But after riding through it and viewing the room from many angles, I thought it was missing a little something.  How about some texture?

This is where Python comes in.  Why not script a volumetric texture generator and use it to "paint" the world?  I had a vague idea that cellular automata might be up to the task, rather than using discrete samples of continuous functions.  Water and lava already appear to follow CA rules, and Minecraft is basically a voxel space you can walk around in.  This seemed a perfect match.  Elegant, even.

It's been a long time since I played with CA.  It's a topic I revisit every few years as a sort of touchstone for how insanely fast microprocessors have become,  like watching real-time fractal renders on a GPU while still having a memory of waiting for a single low-res Mandelbrot render to fill in one scan line at a time on workstation-class hardware.  Well, it's 2011, and now we have Golly and people simulating Conway's Life inside Conway's Life (sort of) just because they can.  I love it.

I experimented with Golly for a while and decided to implement a Generations algorithm with NumPy.  Generations is Life-like, but cells which are marked for death are not zeroed out immediately; instead they age for a certain number of iterations before they are removed from the grid.  This spreads out the active growth regions and tends to make the patterns flow rather than shimmer.

After a lot of trial-and-error, I was able to fill a 3D selection within MCEdit using two dimensions for the CA grid and one for time.  It worked, and I learned a bit of Python and NumPy in the process.

There was only one problem:  The results looked awful.

Within Golly, iterations of the Generations rule are expressed as video, with subtle changes in color indicating the changing age of each cell.  The result is a gnarly, mesmerizing wash of color.

Generations rule S2/B13/15 starting with only 5 living cells,
at 20, 100, 500, and 1000 iterations



But regardless of how I mapped the CA into the world, the subtlety was lost.  It always looked either streaky or random.  Part of the difficulty was the deliberate lo-fi look of Minecraft itself -- a smooth color palette isn't really possible -- but it was mostly due to the translation of time into depth.

Back to the drawing board.  I could continue to tweak the 2D CA and mapping rules to look for a pleasing translation, but a different approach might be more appropriate for this particular application.

How about a 1D CA instead?  I could run a 1D rule to create a 2D array and then project that into the 3D world.  This simpler approach actually looked much nicer in tests.  The most complex part turned out to be the projection of the texture onto the "front" of an MCEdit selection volume which has no knowledge of where the camera is located.  I handled this by requiring that the center of one side of the selection contain nothing but air; it's assumed that the camera isn't inside a solid object.

Here's the final appearance.  All the torches have been eliminated and the walls "textured" with glowstone and obsidian based on Rule 30.


Sort of a cross between TRON and the Luxor Las Vegas.  :)

Sunday, February 13, 2011

Large Constructions in Minecraft

I've been goofing around with Minecraft single player since alpha-something-or-other.  Legitimate spelunking can still be fun, but I also enjoy building improbably large things.  This is really only made practical by the wonderful MCEdit.

Here's a 144x144x128 mob trap.


Outside view showing the scale of the building. (v.2, different world)


The top half is made of pitch-black spawning trays and short canals ending in 2x2 holes.  The bottom is mostly empty space, partly filled by a large number of falling / drowning traps.  The key to the design is the observation that the potential spawning zone is (currently, as of beta) a subset of a 17x17 chunk volume, which contains many millions of blocks, but the active mob cap is quite small.  The goal here is to both control most of the spawn volume and to kill everything in it as quickly as possible in order to allow new mobs to spawn.  None of the canals in the spawning zone is more than 15 blocks long.  Each one ends in a very long fall into shallow moving water, which then leads to a drowning trap for the mobs not killed by the fall.  The very bottom of the structure is just a network of collection canals.

The distant wall appears to be made of floating blobs because I converted all the rock in the surrounding areas into glass; the sky blue color is actually distance fogging and the blobs are everything that isn't rock.



I liked the "visible Minecraft" effect so much that I built a 10 km railway with all the surrounding rock, dirt, and gravel converted to glass.  Gold ore was converted to lightstone for additional underground illumination. 


The effect is visible at night through the bottom of the ocean.


Sunrise seen through a hillside.




And now for something completely different:  A forested crater which extends all the way to the rendering horizon.


Night view.


The original site was mostly ocean.  The crater was constructed in MCEdit by creating a very large sphere of dirt using the brush tool, then creating a slightly smaller sphere of air centered within the dirt, also using the brush tool.  Technically this was only a section of a sphere, as it was made much larger than the 128-block maximum height in order to keep the steepest part of the bowl shallow enough to hold trees.  The portion of the bowl above sea level was then deleted, and the crater rim integrated with the surrounding landscape in-game using pick, shovel, and dynamite.

But this just left a big bowl of dirt.  I wanted the area to be heavily forested.  How do you generate thousands of trees?

MCEdit filters to the rescue!  I learned enough Python to write a filter which picked random x,z coordinates within a selection block, located ground level, added a sapling there, and changed a nearby empty block to lightstone to help the sapling grow.  Then I entered the game and waited.

Once the forest was fairly dense, I dynamited several points on the rim and cleared out some of the foliage in order to create a network of waterfalls and rivers leading to pond in the center.  Next I added a rail terminus leading to my spawn point.  The last few steps were cleanup:  Removal of ungrown saplings and redundant lightstone blocks, both of which were performed with Python filters, along with a lot of detail tweaking in-game.

I'd originally planned to remove the lightstone after the trees were grown, but I found I really liked the effect at night.

Monday, September 27, 2010

Fascinate

The new phone—a Verizon-branded Samsung Galaxy S, AKA Fascinate—is a blast. I've set up ssh, tethering via both wifi and usb, apps to stream media to and from the device, a direct interface to the XDA forums, an alternate app store, a barcode/QR code reader, and Google Goggles, which is just freakin' cool. There's an app which makes light saber noises when you wave the phone around and another which emulates an electric shaver. All of this stuff, ranging from highly productive to delightfully stupid, was free.

I've already started some simple development.  All the development tools are free. Samsung even gives you the source code used to build the kernel.  Most of it, anyway.

Oh! And unlike our AT&T phones, it lets me make phone calls.  To other people!  AT&T was never able to get that bit sorted.  It didn't matter if I was literally standing next to a tower in the middle of an open field at 2 AM; they'd still drop calls.

On the down side, there's still a bit of Microsoft lurking in the system due to their alleged half-billion-dollar deal with Verizon. This is unfortunate, as the true power of such a device comes from the integration of different services. The mandatory Bing search integration only gets in the way. But that, after all, is what Microsoft does best. :p

I expect all traces of Bing to be fully removed after the Froyo update (Danielle explained that this is short for "frozen yogurt", something which is apparently known by everyone but myself).  It's sort of difficult to enforce the use of crapware if the end user has the source code.

UPDATE 3/8/2011

Over five months later, people are still speculating about Android 2.2 on the Fascinate.  The Galaxy Tabs in the Verizon store have had it loaded from day one.  Android 2.3, Gingerbread, has been available for a while now.  A 2.3 ROM for the Galaxy S was leaked about a week ago.  There's already a tablet on the market running Android 3.0.  I hope Android can reach relative stability soon; this has got to be a pain for both developers and carriers.

The bad news is, Verizon still doesn't have their act together.  Perhaps they're pulling a Creative Labs:  Why should we give you the software updates you've already paid for when we can charge you for new hardware?  The good news is, the leaked Froyo ROM works fine, it uses Google as the default search instead of Bing, and it still lets me make phone calls.

Thursday, August 19, 2010

Oracle on OpenSolaris, part 2

If this is going to be a sandbox, it needs more toys. Oracle requires certain packages. The installer still uses Motif. I'm ambivalent about installing a full Gnome desktop, but I'll want X and VNC. And compilers and GNU make.

All actions are performed in the oracle zone as root, until the point where I su to the newly created oracle user. I'll omit the command prompts and responses this time.

Packages

pkg install SUNWxorg-server
pkg install SUNWxorg-client-programs
pkg install SUNWxwopt
pkg install SUNWxwfsw
pkg install SUNWxvfb
pkg install SUNWxorg-graphics-ddx
pkg install SUNWxorg-headers
pkg install FSWxorg-fonts
pkg install SUNWmfrun
pkg install SUNWxvnc

pkg install SUNWman
pkg install SUNWgmake
pkg install SUNWbinutils
pkg install SUNWgcc
pkg install SUNWgzip
pkg install SUNWunzip
pkg install SUNWwget
pkg install SUNWbtool
pkg install SUNWzfs-auto-snapshot
pkg install pkg:/sunstudioexpress

Where's my manpage index? Grrr. This ought to be a post-install action for SUNWman.

catman -w

Oracle user and group

I suppose these will become reserved IDs when Oracle Corp gets around to releasing Solaris 11. I'm going to skip the oinstall and oper groups.
mkdir -c /export/home

groupadd -g 300 dba
useradd -m -d /export/home/oracle -g dba -u 300 -s /usr/bin/bash oracle
passwd oracle

mkdir /db/oracle
mkdir /db/oraInventory
chown oracle:dba /db/oracle
chown oracle:dba /db/oraInventory
chmod 755 /db/oracle
chmod 755 /db/oraInventory

System Parameter(s)

Prior to Solaris 10, there was some /etc/system tweaking to be done. Each version of Unix has it's own set of required system-level tweaks and accompanying reboots for Oracle.

In Solaris 10+, there's only one key parameter to change, and it's handled through projects, a more fine-grained approach to resource management.

The box has 8GB of memory. The default max shared memory is 25% or 2GB.  Starting a database with 2GB of memory configured will cause a ORA-27102: out of memory error.  I'll up the limit to 4GB.

Get our current project ID
oracle@oracle:~$ id -p
uid=300(oracle) gid=300(dba) projid=100(user.oracle)

We'll need be root to make these changes to the oracle user. Confirm the current shared memory limit
root@oracle:~$ prctl -n project.max-shm-memory -i project 100
project: 100: user.oracle
NAME PRIVILEGE VALUE FLAG ACTION RECIPIENT
project.max-shm-memory
privileged 2.00GB - deny -
system 16.0EB max deny -

Set it to 4GB now. I believe this only affects the current shell.
root@oracle:~$ prctl -n project.max-shm-memory -r -v 4gb -i project 100

Set it to 4GB for next reboot
root@oracle:~$ projadd -U oracle -K "project.max-shm-memory=(priv,4GB,deny)" user.oracle

Confirm the changes
root@oracle:~$ prctl -n project.max-shm-memory -i project 100
project: 100: user.oracle
NAME PRIVILEGE VALUE FLAG ACTION RECIPIENT
project.max-shm-memory
privileged 4.00GB - deny -
system 16.0EB max deny -

root@oracle:~$ projects -l user.oracle
user.oracle
projid : 100
comment: ""
users : oracle
groups : (none)
attribs: project.max-shm-memory=(priv,4294967296,deny)

I've got a note here that a hack is needed to link libcrypto.so on OpenSolaris during the install, but I'm not sure if it applies here.
ln -s /lib/amd64/libcrypto.so /usr/sfw/lib/amd64

Installation

At this point I set up a VNC session as root so I can use the default Oracle installer. Now the oracle user needs permission to use the display. It's been a very long time since I needed to know this, so I spent a while staring at cryptic error messages before realizing the problem had nothing to do with the Oracle installer. A page of Java stack dump and complaints about permissions on /tmp/.X11-pipe actually mean "run xhost, dummy".
vncserver :1
xhost +local:oracle

Holy cats, that default window manager is ugly!

But it takes me back...late nights on Sun pizzabox workstations in a frigid computer room...spamming full-screen xeyes onto other students' monitors...hey, it's a lot more amusing when nobody in the room has slept in two days.


Away we go.
su - oracle
export DISPLAY=oracle:1.0
cd /junk/database
./runInstaller

The installer will complain because it does not recognize OpenSolaris and can't run any pre-flight checks. That's ok. Say yes. If you're missing a package, it'll probably become apparent later, when the installer invokes make.

I won't screenshot all of the installation screens, but here's a brief summary:

  • I skipped entering an email address. This won't be a supported installation, and in any case, we already have a problem if I have to hear about "critical security issues in my configuration" via email.
  • Unless I'm performing an upgrade, I always choose to install the database software only. I prefer to make sure I have basic functionality - in the past, this was by no means assured and often required a support call to Oracle to work around installation bugs - and run dbca later.
  • The system isn't prepped for RAC so this will be a single instance installation.  Perhaps that will be a different writeup.
  • I chose to install Enterprise, minus OLAP, which I never use. (Table partitioning is still an option with a separate price tag? Seriously?)
  • The Oracle Base directory is going to be /db/oracle and the software location /db/oracle/product/11.2.0.
  • The software will be owned by user oracle, group dba.

Post-Installation

Setup the oracle user's environment in ~/.profile.

export ORACLE_HOME=/db/oracle/product/11.2.0
export ORACLE_OWNER=oracle
export ORACLE_SID=toybox
export ORACLE_UNQNAME=toybox
export NLS_LANG=AMERICAN_AMERICA.UTF8

export PATH=/usr/gnu/bin:/usr/bin:/usr/X11/bin:/usr/sbin:/sbin:/${ORACLE_HOME}/bin

export DISPLAY=oracle:1.0