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" Source="http://content.vastpark.com/VastParkWS/get.vpws?publisher=craigomatic&name=VncPlugin&domain=vastpark&context=park"> <Element Name="TargetElement"/> <Element Name="OnPasswordRequired"/> <Parameter Key="Uri" Value="the-vnc-server-address.com"/> <Parameter Key="Port" Value="5900"/> <Parameter Key="PasswordRequired" Value="OnPasswordRequired"/> </Plugin> <Script Name="OnPasswordRequired"> function main(obj, args) vncplugin:setpassword('pass') --hardcoding password is bad, you should ask the user to enter one! end </Script> <Primitive Type="Box" Name="TargetElement" Size="1,1,1"/>
Here’s one I prepared earlier (well, Adrian did most of the work…):
Plugin Parameters
Uri
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://)
Port
Defaults to the VNC default of 5900
ConnectionFailed
Name of a Script/Timeline/other ITimelineExecutable element to execute when a VNC connection has failed
PasswordRequired
Name of a Script/Timeline/other ITimelineExecutable element to execute when a password is required to connect to the VNC server
UpdateFrequency
The number of milliseconds to wait before automatically refreshing the remote screen when ManualUpdate is false. Defaults to 500.
ManualUpdate
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: http://vastpark-svn.cvsdude.com/public/trunk/Plugins/Plugin.VNC/
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:
http://vastpark-svn.cvsdude.com/public/
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: http://theparkisvast.com/2010/02/17/updated-imml-for-stock-market-ticker/ | |
![]() |
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:
- Opening price
- Last trade
- Volume
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.
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:
http://finance.yahoo.com/d/quotes.csv?s=<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:
- A bar indicating the open price
- A bar indicating the last price
- Some text showing the name of the stock
- Some text showing the last trade price of the stock
- Some text showing the percentage change
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 end </Script>
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 scene:set('stocks', 'IPL.AX, CFE.AX,FMG.AX,RIO.AX,BHP.AX,BBI.AX,BBP.AX,BOQ.AX,BRM.AX,FGL.AX,NAB.AX,TAM.AX,TLS.AX,WOW.AX') --create the http request request = httprequest('http://finance.yahoo.com/d/quotes.csv?s='..scene:get('stocks')..'&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 scene.ui:writeline(value) stock = explode(',', value) --todo: generate the visual for this stock end end
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) scene:add(element) 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!') end --representation for the last trade lastTradePrim = primitive() lastTradePrim.type = primitivetype.cylinder lastTradePrim.complexity = primitivecomplexity.high lastTradePrim.name = 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 openPricePrim.name = 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() stockCodeText.name = 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() basePrim.name = code.."_parent" basePrim.material.emissive = rgb("#000000") basePrim.size = vector3(3,0.5,3) basePrim:add(lastTradePrim) basePrim:add(openPricePrim) basePrim:add(stockCodeText) return basePrim end
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" /> </Timeline>
My UpdateStocks script looks something like this:
<Script Name="UpdateStocks">function main(obj, args) request = httprequest('http://finance.yahoo.com/d/quotes.csv?s='..scene:get('stocks')..'&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) > 0) then stock = explode(',', value) _updateStock(string.sub(stock[0],2,-2), stock[1], stock[2], stock[3], stock[4], stock[5], stock[6]) end end end 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 end --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).."%" end function _round(num, idp) local mult = 10^(idp or 0) return math.floor(num * mult + 0.5) / mult end</Script>
Putting all of the above together does the trick and we now have a good basis to make something more advanced.
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 www.vastpark.com!
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.