Other Websites

  • SeaCloud9 Interactive
  • SeaCloud9 Commercial Development
  • i-os
  • stArcade9

Brendon Smith Social Networks

  • On Linkedin
  • Bookmarks
  • On Twitter
  • On Facebook
Open ↓ Close ↑
  • Home
  • Subscribe
Browse: Home / 3d, i-create, JavaScript / WebGL TweetTank Built with C3DL Part 1
i-create | therefore-i am
i-create | therefore i-am | a blog about opensource technology and rich internet applications
 

WebGL TweetTank Built with C3DL Part 1

By Brendon Smith on April 18, 2010

 

First of all let me mention you will not be able to run this demo unless your browser is WebGL ready. So that means if you want to see this then you have to download a nightly build of FireFox, Chrome, or Safari. You can read how to do this here.

My first impressions of WebGL is it is awesome and easy to do. I believe WebGL will make it easy for any developer to rapidly create a game on the web. It is fast appears to have decent support meaning that it works awesome on my Apple computers and on one of my Windows7 computers but then fails for me on one of my workstations that has a souped up ATI graphics card humm.. go figure. It is hard to say how well the graphics rendering will perform on the majority of computers out their but it probably won’t be that bad and after all these are nightly builds that are pre-alpha for the most part. It also makes me wonder if the next iPhones will have this feature built into their webkit. Hard to say. It is known that out of all the new browsers coming out that ie9 will not support graphics rendering shocking (Not really). It might be because Microsoft believes that WebGL will be an epic failure or maybe they simply don’t have the resources to devote to it at this time.

I believe graphic card support in these new browsers will speed up canvas rendering a little but I when looking at the flash benchmarks that are currently out their it definitely shows you how fast the flash player is in comparison. In short canvas tag is not even remotely as fast. In the news their has been lots of discussion about flash being dead but this simply isn’t true. Here is why forthcoming HDTV/3DTV will support flash, google phones will support flash, blackberry, and windows phones will all support flash. So as a mobile platform it will be the easiest way to build and deploy to all platforms. It is too bad Apple doesn’t see it but oh well. I guess I will just have to get better at Objective-C to be on that platform.

This is the first part of a two part example. I created a simple mashup. To create this example I used C3DL and jQuery. C3DL is an awesome opensouce library put together by the wonderful people at Seneca College. This example pulls a search results from twitter with the search query subject being fishing. Yes, I know that twitter is all about birds and tweets but after scouring the Google 3D warehouse, I decided that most of the models for birds that are freely available suck. So I made a virtual fish tank instead. The tank has bubbles rendered with the C3DL particle library and it also has a school of fish that swim slowly though the tank. It’s not really ground shaking stuff pretty simple. I will work on a future version where it pulls results with ajax. I noticed the C3DL library attaches an event listener in the init.js that listens for the document to be loaded :( . This of course makes my search function of twitter fail. I have looked at overriding this feature a number of ways not limited to jQuery getScript, etc.. I could also put the query on the query string for the window location and then re-load the page but I think that would be kind of wonky so whatever I will do this in the next version of the experiment. So whatever I will save it for next time.

Check out the experiment here but before you do download a nightly build of Firefox.

TweetTank WebGL example Created with C3DL

Here is the code for the experiment:

var CANVAS_WIDTH = $(window).width();
var CANVAS_HEIGHT = $(window).height()*2;
$('#tweetTank').width(CANVAS_WIDTH);
$('#tweetTank').height(CANVAS_HEIGHT);
$('#tweetTank').css('display','block');
 
		var arrayTwit;
        var schooloffish;
        var fishArray = [];
        var bubblesArray = [];
        var bubbles;
		var objectsHit = "";
		var objectSelected;
        function mRandom(r) {
            var randomInt = Math.floor(Math.random() * r + 1);
            return randomInt;
        }
 
        c3dl.addModel("fish.dae");
        c3dl.addModel("OceanSphere.dae"); 
        // The program main
        function canvasMain(canvasName) {
 
            // Create new c3dl.Scene object
            scn = new c3dl.Scene();
            scn.setCanvasTag(canvasName);
 
            // Create GL context
            renderer = new c3dl.WebGL();
            renderer.addTexture("bubble.jpg");
            renderer.createRenderer(this);
 
            // Attach renderer to the scene
            scn.setRenderer(renderer);
            scn.init(canvasName);
 
            //the isReady() function tests whether or not a renderer
            //is attached to a scene.  If the renderer failed to
            //initialize this will return false but only after you
            //try to attach it to a scene.
            if (renderer.isReady()) {
                // Create a Collado object that
                // will contain a imported
                // model of something to put
                // in the scene.
 
                //fish.setAngularVel(new Array(0.0, 0.0001, 0.0));
 
                var schooloffish = mRandom(100);
                var ocean = new c3dl.Collada();
                ocean.init("OceanSphere.dae");
                ocean.setAngularVel(new Array(0, .00005, 0));
                ocean.scale([20.0, 20.0, 20.0]);
                ocean.setPickable(false);
                scn.addObjectToScene(ocean); 
				//console.log(arrayTwit.length);
                for (var i = 0; i < arrayTwit.length; i++) {
					//console.log(arrayTwit[i]);
                    fishArray[i] = new c3dl.Collada();
                    fishArray[i].init("fish.dae");
                    fishArray[i].yaw(45.0);
					fishArray[i].ID = "Fish" + i;
                    //fish.roll(25.0);
                    fishArray[i].pitch(-86.4);
					fishArray[i].setLinearVel([0,0,-2]);
                    fishArray[i].url = "http://twitter.com/" + arrayTwit[i].from_user;
                    //fish.setPosition([1200, 100, 700]);
                    fishArray[i].setPosition([mRandom(1200), mRandom(900), mRandom(1500)]);
                    scn.addObjectToScene(fishArray[i]);
                }
                for (var i = 0; i < 7; i++) {
                    bubblesArray[i] = new c3dl.ParticleSystem();
                    bubblesArray[i].setMinVelocity([-2, 0, -2]);
                    bubblesArray[i].setMaxVelocity([2, 25, 2]);
                    bubblesArray[i].setMinLifetime(5.3);
                    bubblesArray[i].setMaxLifetime(10.7);
                    bubblesArray[i].setMinColor([0, 0, 0.3, 0]);
                    bubblesArray[i].setMaxColor([0, 0.3, 0.5, 1]);
                    bubblesArray[i].setSrcBlend(c3dl.ONE);
                    bubblesArray[i].setDstBlend(c3dl.ONE);
                    bubblesArray[i].setMinSize(0.5);
                    bubblesArray[i].setMaxSize(5.0);
                    bubblesArray[i].setTexture("bubble.gif");
                    bubblesArray[i].setAcceleration([0, 9, 0]);
                    bubblesArray[i].setEmitRate(40);
                    bubblesArray[i].init(150);
                    bubblesArray[i].setPosition([mRandom(1200), mRandom(100), mRandom(700)]);
                    scn.addObjectToScene(bubblesArray[i]);
                }
                // Create a camera
                //var cam = new c3dl.FreeCamera();
 
 
 
               // scn.setCamera(cam);
                cam = new c3dl.OrbitCamera();
                cam.setFarthestDistance(2000);
                //cam.pitch(90);
                cam.setPosition(new Array(3000.0, 300.0, 200.0));
                //cam.setLookAtPoint(new Array(0.0, 0.0, 0.0));
                cam.setOrbitPoint(new Array(800.0, 100.0, 200.0));
                cam.setClosestDistance(200);
                cam.setDistance(900);
                //cam.pitch(1);
                scn.setCamera(cam);
                // Start the scene
                scn.startScene();
                scn.setPickingCallback(goLink);
                scn.setKeyboardCallback(onKeyUp, onKeyDown);
                scn.setMouseCallback(mouseMove, mouseWheel);
 
            }
        }
 
		function goLink(pickingObj)
		{
 			var objectsHit = pickingObj.getObjects();
 
 			if( objectsHit.length > 0 )
			 {
 				var sepiaEffect = new c3dl.Effect();
				sepiaEffect.init(c3dl.effects.SEPIA);
 				window.open(objectsHit[0].url, '_blank');
				objectsHit[0].setEffect(sepiaEffect);
 					for(var i = 0; i < arrayTwit.length; i++){
 						if(objectsHit[0].url == scn.getObj(i).url)
 					scn.getObject(i).setEffect(sepiaEffect);
 					}
 				}
		} 
 
 
        function onKeyUp(event) {
            if (event.keyCode == 89) { keyD = false; }
        }
 
 
        function mouseWheel(event) {
            var delta = 0;
 
            // Chromium
            if (event.wheelDelta) {
                delta = -event.wheelDelta / 20;
            }
            // Minefield
            else if (event.detail) {
                delta = event.detail * 4;
            }
 
            else {
                if (keyD) {
                    cam.yaw(delta * ZOOM_SENSITIVITY / 100);
                }
                else {
 
                    // towards user
                    if (-delta * ZOOM_SENSITIVITY < 0) {
                        cam.goFarther(-1 * -delta * ZOOM_SENSITIVITY);
                    }
 
                    // towards screen
                    else {
                        cam.goCloser(-delta * ZOOM_SENSITIVITY);
                    }
                }
            }
        }
 
 
        function onKeyDown(event) {
            if (event.keyCode == 65) {
                cam.setOrbitPoint([0, 0, 0]);
            }
            if (event.keyCode == 89) {
                keyD = true;
            }
        }
        function mouseMove(event) {
            // get mouse coords relative to window
            var mmx = event.pageX - 1;
            var mmy = event.pageY - 1;
 
 
 
            if (mmx != null && mmy != null) {
                // NDC
                var normalizedDeviceCoords = [
        (2 * mmx / CANVAS_WIDTH) - 1,
       -((2 * mmy / CANVAS_HEIGHT) - 1),
        1, 1];
 
                // Sometimes this is called before the perspective transform
                // is setup which causes warnings. This check prevents that.
                if (c3dl.isValidMatrix(scn.getProjectionMatrix())) {
                    var iproj = c3dl.inverseMatrix(scn.getProjectionMatrix());
 
                    // To get the clip coords, we multiply the viewspace coordinates by
                    // the projection matrix.
                    // Working backwards across the pipeline, we have to take the normalized
                    // device coordinates and multiply by the inverse projection matrix to get
                    // the clip coordinates.
                    var clipCoords = c3dl.multiplyMatrixByVector(iproj, normalizedDeviceCoords);
 
                    // perspective divide
                    clipCoords[0] /= clipCoords[3];
                    clipCoords[1] /= clipCoords[3];
                    clipCoords[2] /= clipCoords[3];
                    clipCoords[2] = -clipCoords[2];
 
                    var rayInitialPoint = cam.getPosition();
 
                    var x = clipCoords[0];
                    var y = clipCoords[1];
                    var z = clipCoords[2];
 
                    var kludge = c3dl.multiplyVector(cam.getLeft(), -1);
                    var viewMatrix = c3dl.makePoseMatrix(kludge, cam.getUp(), cam.getDir(), cam.getPosition());
 
                    var rayTerminalPoint = c3dl.multiplyMatrixByVector(viewMatrix, [x, y, z, 0]);
                    var rayDir = c3dl.normalizeVector(rayTerminalPoint);
 
                    // get angle
                    var angle = Math.acos(-1 * rayDir[1]);
                    var camHeight = rayInitialPoint[1];
 
                    var hyp = camHeight / Math.cos(angle);
 
                    mx = hyp * rayDir[0] + rayInitialPoint[0];
                    my = hyp * rayDir[1];
                    mz = hyp * rayDir[2] + rayInitialPoint[2];
                }
            }
        }
function twitterSearch(searchTag) {
	//console.log(searchTag);
	arrayTwit = "";
	arrayTwit = new Array();
                $.getJSON("http://search.twitter.com/search.json?q=" + searchTag + "&callback=?",
        function(data) {
            $.each(data.results, function(i, item) {
                twitSeach = item;
                arrayTwit.push(twitSeach);
            });
			//c3dl.init();
			c3dl.addMainCallBack(canvasMain, "tweetTank");
        });
 
        }
$(document).ready(function() {
            twitterSearch("fishing");
        });

Launch Experiment / Download Code

I mentioned possibly creating a spider with silverlight. I still would like to do that in the near future. I found this cool silverlight examples and would like to study it! I have installed Visual Studio 2010 on my Windows boxes and it is awesome!

I have also been eying a new tutorial on the Hype Framework in ComputerArts latest issue(174). Has a really cool example that teaches you how to use Hype to make music drawings created by Stewart Hamilton-Arrandale. I will learn from this code. I could add this type of functionality into my KulerSplash.

I also found this resource recently on Objective-C really cool web site it was nice of them to share so much Fabien also has some cool JAVA examples as well.

WebGL libraries:
C3DL
CopperLicht
SceneJS

  • Share/Bookmark

Related posts:

  1. WebGL TweetTank Built with C3DL Part 2
  2. WebGL Rendering of BSP Maps
  3. Away3D with Hype Fish Tank
  4. Tweet Tank in Away3D and Hype
  5. Tweet Tank in Away3D and Hype pt. 2

Posted in 3d, i-create, JavaScript | Tagged 3d, C3DL, Experiment, JavaScript, JQuery, MashUp, webGL

Brendon Smith

GUI Development, Action Script, Java Script, .NET, AJAX, Java, PHP, CakePHP, Mashup Development, Flash, Silverlight, C#, XML, SQL, Apache, IIS, Photoshop, Fireworks,etc.. Oh, and Biking and Camping

  • mattoby2010
    Great article, loved the fish ;-)

    PS: checkout http://glge.org if you haven't already

blog comments powered by Disqus
« Previous Next »
 
 

3d ActionScript Adobe Air Android Apollo Apple art as3 Away3D C# CakePHP CSS Experiment Flash Flash Develop Flex Games Generative Design Google HTML5 hype JavaScript Joshua Davis JQuery JSON Life Linux MashUp OpenSource Open Source PaperVision3D PC History Processing quick tip RIA Silverlight Technology/Internet travel twitter Web webGL Webware XML Yahoo Pipes

WP Cumulus Flash tag cloud by Roy Tanck and Luke Morton requires Flash Player 9 or better.

  • Monthly
  • Yearly
  • Links
  • August 2010
  • June 2010
  • May 2010
  • April 2010
  • March 2010
  • February 2010
  • January 2010
  • December 2009
  • November 2009
  • October 2009
  • 2010
  • 2009
  • 2008
  • 2007
  • 2006
  • 2005
  • agit8
  • Away3D
  • Ben Nadel
  • Bit-101
  • Bruce Jawn
  • Causecast
  • D.I.Y.
  • Dr Woohoo
  • draw.logic
  • Flight404
  • Flong
  • generatorX
  • gSkinner
  • haXe
  • Jonathan Snook
  • Joshua Davis
  • Jot
  • Kirupa
  • LifeHacker
  • Make
  • Minor White
  • Mr Doob
  • NihiLogic
  • NurseOnTheRun
  • octane42
  • OpenFrameWorks
  • Processing
  • PV3D
  • Senocular
  • Sephiroth
  • ShineDraw
  • Stroep
  • SWX
  • Tech News
  • Toxi
  • UnitZeroOne
  • World We Live In
  • ZeusLabs

Photos

stream.JPG

Recent Comments

  • seacloud9 on Tweet Tank in Away3D and Hype pt. 2
  • Brendon Smith on Tweet Tank in Away3D and Hype pt. 2

RSS LifeStream

  • Elysium
  • Giles Bowkett: Archaeopteryx: A Ruby MIDI Generator
  • Grant Nestor » Blog Archive » Generative music, huh?

Copyright © 2010 i-create | therefore-i am.