Army of Craig

I’ve always wondered what it would be like to have an army of clones that I could send out to do my bidding…

VastPark OpenGL “Army of Craig” Demo from VastPark on Vimeo.

Yes. It is a little strange.

Dem bones, dem bones, dem…digital bones

The creative department have been craving bones for a very long time in VastPark and we’ve finally added support for them, both in scripting and via plugin.

Here’s a teaser:

Vastpark Facial Expressions Demo from VastPark on Vimeo.

Virtual FCVW

Generally when on the road with VastPark at conferences/expos, I’m deprived of the opportunity to see many of the speakers and round table sessions that occur as I’m usually run off my feet speaking to people at the stand.

As I sit here at the VastPark booth during the Federal Consortium for Virtual Worlds during one of the few quiet periods I’m able to do both!


If you’re at home and wanting to get in on the action as well, jump onto this link:

It’s nearing the end of the day here in Washington but the feed will be live again tomorrow and you can certainly follow the twitter feeds post conference.

VastPark VNC Plugin

After some recent improvements to the core VastPark framework and the way textures are made available to the plugin API, I decided to build a VNC plugin for VastPark, basing it upon VncSharp. For those of you know don’t know what VNC is, there’s a good overview of it available on Wikipedia.

In it’s simplest form the IMML for the VNC Plugin will look something like this:

<Plugin Name="VncPlugin" Enabled="True" 
	<Element Name="TargetElement"/>
	<Element Name="OnPasswordRequired"/>
	<Parameter Key="Uri" Value=""/>
	<Parameter Key="Port" Value="5900"/>
 	<Parameter Key="PasswordRequired" Value="OnPasswordRequired"/>
<Script Name="OnPasswordRequired">
    function main(obj, args)
        vncplugin:setpassword('pass') --hardcoding password is bad, you should ask the user to enter one!
<Primitive Type="Box" Name="TargetElement" Size="1,1,1"/>

Here’s one I prepared earlier (well, Adrian did most of the work…):


Plugin Parameters


The host address of the VNC server. You should avoid using the scheme at the start of this address (ie: don’t put the http://)


Defaults to the VNC default of 5900


Name of a Script/Timeline/other ITimelineExecutable element to execute when a VNC connection has failed


Name of a Script/Timeline/other ITimelineExecutable element to execute when a password is required to connect to the VNC server


The number of milliseconds to wait before automatically refreshing the remote screen when ManualUpdate is false. Defaults to 500.


True/False. When true, you need to call the vncplugin:requestupdate(true) for a fullscreen update. Defaults to False

You can download an example IMML document here: basic-vnc.imml and view the source code for the VNC Plugin over here:

A good free windows VNC Server is TightVNC

VastPark Masterclass 2

Some video from the second masterclass I spoke at. Adrian Shepherd also features first up with some info on the content pipeline. Was quite unprepared for this one, so definitely isn’t my best work 🙂

Virtual Worlds Down Under – Part 4 of 4 – Masterclass 2 from VastPark on Vimeo.

VastPark Source Code Online


Yesterday as part of the many happenings during the Virtual Worlds Down Under 09 event, we made the source code for the core VastPark libraries available to the public

The source is pure C# targeting .NET 3.0, licensed under GPL and is available for anonymous access at this address:

Be sure to check out Sample projects\read first.txt for information in acquiring and setting up 3rd party dependencies to avoid losing hair getting the code to compile 🙂

Many thanks to CVSDude for supporting us with hosting and you can find out more about VastPark’s open source philosophy here.

VastPark Masterclass 1

Here’s the video of a recent lecture I spoke at which was given in-world:

VastPark Masterclass1 from VastPark on Vimeo.

Building a stock market ticker in VastPark

Update: Revised IMML here:

As I’m sure you’ve probably noticed by now, the stock markets around the world have crashed and burned with lots of dollars drained off the portfolio’s of many an investor, myself included.

To avoid future surprises, I’ve decided to pay a little more attention to what’s happening with the stock market and what better way to do so than via VastPark 🙂

The first step was to work out a reliable data source for the stock prices that would let me retrieve at least the following info:

As an Aussie, I’m primarily interested in stocks from the asx – but to allow others to re-use the code, something that would work worldwide was desirable.

Yahoo Finance

After a search lead me to the blog of Mads Kristensen and this post I realised Yahoo Finance would work perfectly using the request csv method:<StockName>&f=sl1c1ohgv 

For the first version of the ticker, I wanted to keep things simple. It would provide the following visual for each stock:

I also wanted to avoid writing a plugin to do the work and instead make use of the scene.web:loadstring method in VastScript, which would return a string containing all of the data to process.

Step 1: A Loaded trigger and target script
Use a document level Trigger and an inline script, get things rolling:

<Trigger Event="Loaded" Target="GenerateStocks" />
<Script Name="GenerateStocks">
function main(obj, args)
  --todo: retrieve the data
  --todo: parse the response data
  --todo: generate the visuals

Step 2: Retrieve data from Yahoo!
To make life easier when changing stocks, I’m going to store a scene variable called stocks containing all of the stock codes I’m interested in.

--store a scene variable for the stocks to retrieve
  --create the http request
  request = httprequest(''..scene:get('stocks')..'&amp;f=sl1c1ohgv')
  --load the response 
  response = scene.web:loadstring(request)

Step 3: Parse the data into something useful
The response of the above turns out to be a large string containing all of the data for each stock separated by a comma and all stocks separated by a new line.

--reponse is returned as each stock on a new line, break into a table entry for each stock
  stocks = explode('\r\n', response)
  count = 1
  --stocks is a dictionary of all listed stocks, need to explode each listing to generate a representation
  --format: stock code, last trade,change, open, high, low, volume
  for key,value in pairs(stocks) do
    if(string.len(value) > 0) then
      stock = explode(',', value)
      --todo: generate the visual for this stock

Step 4: Generate the visual
We get a little tricky here, generating a red primitive if the stock is worth less than the open, green otherwise.

element = _generateStock(string.sub(stock[0],2,-2), stock[1], stock[2], stock[3], stock[4], stock[5], stock[6])
element.position = vector3(-20 + count*4.5, -9, 30)
function _generateStock(code, lastTrade, change, open, high, low, volume)
	scene.ui:writeline('generating representation for: '..code)
	emissive = rgb("#00ff00") --default to green
	changeFromOpen = string.sub(change, 1,1)
	if(changeFromOpen == "-") then
		emissive = rgb("#ff0000") --red
		scene.ui:writeline('stock trading lower than open!')
	--representation for the last trade
	lastTradePrim = primitive()
	lastTradePrim.type = primitivetype.cylinder
	lastTradePrim.complexity = primitivecomplexity.high = code.."_last"
	lastTradePrim.material.emissive = emissive
	lastTradePrim.size = vector3(0.5, tonumber(lastTrade), 0.5)
	lastTradePrim.position = vector3(0.5,0.5,0)
	--representation for the opening price
	openPricePrim = primitive()
	openPricePrim.type = primitivetype.cylinder
	openPricePrim.complexity = primitivecomplexity.high = code.."_open"
	openPricePrim.material.emissive = rgb("#ffffff")
	openPricePrim.size = vector3(0.5, tonumber(open), 0.5)
	openPricePrim.position = vector3(-0.5,0.5,0)
	--stock code text
	stockCodeText = text() = code.."_text"
	stockCodeText.value = code
	stockCodeText.billboard = true
	stockCodeText.position = vector3(0,-1,-3) --1 unit lower than the parent and 3 units fwd
	--parent prim for the platform the 2 colums will sit on
	basePrim = primitive() = code.."_parent"
	basePrim.material.emissive = rgb("#000000")
	basePrim.size = vector3(3,0.5,3)
	return basePrim

Once the stocks have been generated, they now need to be updated with the new values. Yahoo Finance appears to operate on a slight delay but the data changes real-time, offset by that delay, so we can query for new data quite often. The best way to do this is with a looping timeline that runs a script every n seconds. I’ve chosen to do this every 2 seconds:

<Timeline Name="Timeline" Enabled="True" Speed="1" Loop="True" AutoTween="False">
    <ExecuteEvent Time="00:00:02" Element="UpdateStocks" />

My UpdateStocks script looks something like this:

<Script Name="UpdateStocks">function main(obj, args)
	request = httprequest(''..scene:get('stocks')..'&amp;f=sl1c1ohgv')
	response = scene.web:loadstring(request)
	--reponse is returned as each stock on a new line, break into a table entry for each stock
	stocks = explode('\r\n', response)
	count = 1
	--stocks is a dictionary of all listed stocks, need to explode each listing to generate a representation
	--format: stock code, last trade,change, open, high, low, volume
	for key,value in pairs(stocks) do
		if(string.len(value) &gt; 0) then
			stock = explode(',', value)
			_updateStock(string.sub(stock[0],2,-2), stock[1], stock[2], stock[3], stock[4], stock[5], stock[6])
function _updateStock(code, lastTrade, change, open, high, low, volume)
	emissive = rgb("#00ff00") --default to green
	changeFromOpen = string.sub(change, 1,1)
	if(changeFromOpen == "-") then
		emissive = rgb("#ff0000") --red
	--update the last trade visual
	lastTradeVisual = scene:getelement(code..'_last')
	lastTradeVisual.material.emissive = emissive
	lastTradeVisual.size = vector3(0.5, tonumber(lastTrade), 0.5)
	--update the % change
	percentageChange = (tonumber(change) / tonumber(open)) * 100
	stockText = scene:getelement(code..'_text')
	stockText.value = code.."\r\n$"..lastTrade.."\r\n".._round(percentageChange,2).."%"
function _round(num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult

Putting all of the above together does the trick and we now have a good basis to make something more advanced.

The finished product

The stock ticker in action

Download the IMML document here (right-click, save as): Stock ticker.park

VastPark tools go public!

Very recently the entire toolset for VastPark went live over at!

Included in the current toolset:

Creator 0.9 Beta 3
– Like Dreamweaver is a WYSIWYG for HTML, the Creator is the WYSIWYG for IMML. Allows users to create virtual experiences very rapidly and deploy them in a variety of ways

Browser 0.9 Alpha
– Used to view the virtual experiences (parks) built in the Creator and hosted on VastServer

VastServer Alpha
– Hosts IMML for consumption by the Browser, manages multi-user interaction, uses very little resources and can be hosted on any Windows PC (XP SP2 and above)

Viewer Alpha
– Used to view ParkPak files, which are self-contained virtual experiences. Want to do a 3D presentation using VastPark? Use a ParkPak to remove the risk that internet access may be down where you are presenting 🙂

Asset Publisher Alpha
– Finally, those eagerly awaiting being able to use their own content can do so! The asset publisher allows content creators to publish content online quickly and easily.

Multi-User Stress Test #1

After our recent stress test (which stressed a number of things, including the devs!) we finally have the chat transcript available. Take a look at the official VastPark Team Blog for the full overview here and the pdf of the transcript here.


← Previous PageNext Page →