Quantcast
Channel: Learning Three.js
Viewing all 89 articles
Browse latest View live

Tunnel Effect for your Demo

$
0
0

This post presents a tunnel effect. This is a classic in 3D demo. They are visually efficient and easy to code. In fact, tunnels are so trendy that evendoctor who andstargate havefunin them :)

Try the demo. It has been built using theboilerplate for three.js seen in aprevious post. The code is simple and small. Less than 20lines has been added on top of the boilerplate. We will create aTHREE.Geometry to get the shape of tunnel. Then we will use atexture trick to create thevisual illusion of moving.

Let's build the walls

The first step is to build the walls of the tunnel. It is easier that one would expect. A tunnel may be seen as a cylinder with the camera inside. Once you realized that, most of the work is done. Luckily for us,three.js got an easy way to build cylinders, calledCylinderGeometry. Nevertheless our tunnel / cylinder got 2 special points.

First, it is open-ended. So we must not build its top and bottom. We need this to see thru its extremities. This is handled by a parameter inCylinderGeometry. We just set openended parameter to true and the rest is done for us :)

Second, the camera is usually located outside of objects. But our tunnel/cylinder has the camera inside it. To make our object visible from the inside, we need to turn it inside out. For that, just use mesh.flipSided = true

Let's go forward

Now we need to go forward in this tunnel For that we will use an old trick. We won't move the tunnel walls themselves, only their appearance. It gives the visual illusion that we are moving. Remember what they say in matrix ?"there is no spoon". It is all the same, we are moving while staying still :)

A Texture isn't a spoon

First we want to move the appearance of the cylinder, thus the player got the illusion to go forward. We will use THREE.Texture for that. We wont move the actual pixels of the textures, only its coordinates. Additionnaly we want the texture to repeat on the cylinder, thus it appears as continuous. WebGL texture is a powerfull and flexible tool. You can tweak so many features.

First let's make this texture move. Suppose we want the texture to loop once every 10 seconds. So the coordinate .offset.y needs to go from 0 to 1 in 10 seconds. This line is enougth to make the tunnel move forward. You can change your speed within the tunnel by changing this number.

```javascript

texture.offset.y    += 0.1 * seconds;

```

Now the texture repetition. For that we will use a texture parameter called wrap. It indicates how the gpu repeat the texture on a face. Here is a goodtutorial on opengl wrap. By default, wrapS / wrapT are set to THREE.ClampToEdgeWrapping. So the texture is scaled to match exactly the size of the face. In our case, we want to repeat the texture and not scale it. So we use THREE.RepeatWrapping.

```javascript

texture.wrapT   = THREE.RepeatWrapping;

```

Conclusion

We have seen how to do a tunnel withthree.js. This is very simple to code and awesome on the screen. It is less than 20 lines added to the boilerplate. The cylinder geometry was already provided. We usedTHREE.Texture offsets to provide the optical illusion of moving.

Later, we may add a blue phonebooth and play doctor who :) The code is available ongithub under MIT license. Feel free to fork and modify. That's all folks, have fun.


Dom Events in 3D Space

$
0
0

Ever dreamed of a object3d.on('click', function(){ ... });?

I have :) This post presents a little experiment. What about implementing the concept ofdom events in 3D Space. In a web page, aclick event is trigger when a user click on aelement. This is common knowledge in web development. What about having that but in a three.js scene ? Maybe people will start do 3D user interface with that, who knows. How great would that be ?!? So let's do that.

Try it out. The demo contains 3 teapots. Each bind a different type of events. When the events are triggered, teapots are animated. Animations are made by tween.js, a nice js tweening engine seen in a previous post. Play with it to get a feel of it, maybe think about the type of UI you could do in 3D.

Let's Get Started

First let's include the source. You download threex.domevent.js. and copy this line in your page.

```html

<script src='threex.domevent.js'></script>

```

Let's Use It

Let's say we want do to an action when the user is clicking on a object. We just do the following.

```javascript

mesh.on('click', function(){
    mesh.scale.x *= 2;
});

```

This short line means "if the user click on this mesh, make it twice wider". Eloquent meaning, short syntax ... pretty sweet in my book. If you wish to stop listening just do as usual.

```javascript

mesh.off('click', callback)

```

In fact, there is 2 naming for those functions: one isaddEventListener /removeEventListener fromHTMLElement The other is copied onjQuery api:on /off Pick the one you like. They are doing the same thing.

Always in a effort to stay close to usual pratices, the events name are the same as in DOM. The semantic is the same too. Currently, the available events areclick, dblclick, mouseup, mousedown,mouseover and mouse out.

Some Internals

three.js already has the ability to interact with the mouse. You can see it in actionhere andhere. Internally they use 2 three.js classes:THREE.Projector andTHREE.Ray.threex.domevent.js is an higher level api on top of those functions, an interface which mimic dom events, something closer to the usual web developper.

It is a nice api. clean, short, object oriented and feels familiar to web developpers. A little hichup tho, it modifies THREE.Object3D class. It is a global class, so it may be legitimatly considered unclean by some people. If this bother you, simply do THREEx.DomEvent.noConflict() and use the standalone API. It is documented in theannoted source. In fact, the object oriented API is just a thin wrapper on top of the standalone API.

Conclusion

We all know the click event when the user click on a webpage. This experiment wishes to provide to web developpers the same experience in 3D. I hope people will do crazy innovations by using 3D in user interfaces. This is a first version. Maybe we will implementbubbling in the future, even events like'change'.

As usual, threex.domevent.js source is available ongithub. There is anannoted source for implementation details. That's all folks. Have fun.

Boilerplate Builder for Three.js

$
0
0

We recently introduced aboilerplate for three.js in aprevious post. It aims to ease your first contact withthree.js. It contains a template for a simple project, a sample on which we already applied good practices. You download it and run it in a matter of minutes. Thus you can immediatly focus on your own things. In short, it aims for Fast bootstrap + Good Practices.

It seems nice, hey ? Well there is a glitch. Theboilerplate for three.js needs more flexibily. In a way, it acts as a ground on top of which you start your own thing. We do our best to provide good defaults, but they are only defaults. What if you got specific requirements ? How to start your project then ? Theboilerplate builder has been written for you :)

Try it out. Go ahead, play with the options, discover what they do and customize your own boilerplate. Thescreencast below is short introduction where i describe theboilerplate builder.

Making-Of the Builder

Thebuilder itself was interesting to build. It uses various nice features from the current web. It is a pure-browser webapp with a file download, a preview of a webgl project and a nice looking visual appearance.

Pure Browser Download

I like to write pure-browser application. They dont require a server to run, only static files. It makes it much easier to host your application. Soboilerplate builder has been written as a pure-browser application :) It usesjszip , a library which create .zip files with Javascript. Its creates the boilerplater.zip that you download. Additionally, it usesdownloadify , a small library to create and download files without server.

Together,jszip anddownloadify makes it easy to pack several files together, and allow the user to download it. All that in pure-browser, neat no? I love what the web is becoming!

Boilerplate Preview

The preview is a bit different. We start to load the index.html template for the boilerplate. We apply all the options you configured and produce the final version. To actually preview this file, we encode it inbase64 to build adata url with it. Only then, we create an iframe with this data uri and you can see the webgl preview :)

Data url is an old thing from 1998 which is back in spotlight due to HTML5. It allows to encode data directly in the URL. It may be used to include image directly in css for examples. Very usefull but not for human consumption. To give you an idea, here isindex.html as a data url inbase64. You could encode it as text if youescape itproperly. It looks like long ugly random string.

```

data:text/html;base64,PCFkb2N0eXBlIGh0....

```

Visual Appearance

It includestwitter bootstrap for css. I am quite grateful for this framework. Without it, thebuilder page will be so ugly, that people run away without even trying the application itself.twitter bootstrap makes it so easy to write a webapp which looks good on the screen. I think all the css-impaired of the world should thanks twitter for this framework :)

Conclusion

It has been quite fun to write it. I learned some web skills, discovered new part of three.js, and on top of that, it looks good on screen. I could not ask for more. The goal ofboilerplate builder for three.js is to add more flexibility to the fast bootstrap + good practices from theboilerplate. I hope it will help people starting lots of newthree.js projects :)

That's all folks. Have fun.

Casting Shadows

$
0
0

This post is aboutshadow casting, a technique which approximates the effect you see in real life everyday. They may be tricky to tune but they looks so good, it worths it. Shadows are an efficient tool when you to make your scene more realistic. We will see how they can be used insidethree.js and see more about lights while we are at it.

As usual, there is a demo. It is kept it real simple thus you can read the code more easily. The scene is a simple object in the middle, a spotlight moving around and a plane to receive the object shadow. The light frustum is left visible in orange.

Let's Code Shadows

Casting shadows inthree.js involves 3 parts: therenderer which does the computation, thelights which cast shadows, andobjects which receives lights and shadows.

Set up the Renderer

The renderer is the one which will compute the shadows positions for your 3D scene. Shadow casting is quite expensive. It is only supported byWebGLRenderer. It usesShadow mapping, a technique specific to WebGL, performed directly on the GPU.

```javascript

renderer.shadowMapEnabled = true;

```

You can smooth produced shadows with shadowMapSoft. It default to false. On the left, the shadow is crisp, on the right it is soft.

```javascript

// to antialias the shadow
renderer.shadowMapSoft = true;

```

Configure your objects

ForObject3D, two parameters controls how they interact with lights and shadows. Set .castShadow to true if the object occludes light, so to cast a shadow. Set .receiveShadow to true if the object is supposed to receive shadows. Both default to false

```javascript

object3d.castShadow = true;
object3d.receiveShadow  = false;

```

This is the configuration for the central object in the demo. It will occlude lights but won't be able to receive shadow. So you wont see anyself shadow.

Tune your Lights

THREE.DirectionalLight orTHREE.SpotLight are able to cast shadows. Let's details them. A directional light is when light rays are parallel. A bit like when you look at the sun rays on the left. It mostly behaves like a light source very far from us. A spot light is when light rays seems to originate from a single point, and spreads outward in a coned direction, like in the dance club on the right (Images are from wikipedia). To enable the shadow casting on a light, just use this line.

```javascript

light.castShadow = true;

```

You can tune the shadowDarkness. It is the opacity of the shadow. 0 means no shadow, 1 means pure back shadow.

```javascript

light.shadowDarkness = 0.5;

```

In the same vibe, it possible to show the shadow camera on the screen with shadowCameraVisible. A very usefull feature during tuning or debugging.

```javascript

light.shadowCameraVisible = true;

```

More of Directional Lights

Additionally, when casting shadow with aTHREE.DirectionalLight, you need to setup an orthographic camera. What is that ? it is a different form of3D projection.Perspective is the way we see things in real life. So it seems more natural to us thanorthographic projection. On the left, an illustration shows a perspective projection. You can see what is inside the orange shape. On the right, the same for a orthographic one.

Recentthree.js r47 release includes avery didactic example fromalteredq. Play with it, it may understand the difference betweenorthographic andperspective cameras. Here is a possible configuration of the frustum for the orthographic camera of our light.

```javascript

light.shadowCameraRight     =  5;
light.shadowCameraLeft      = -5;
light.shadowCameraTop       =  5;
light.shadowCameraBottom    = -5;

```

Conclusion

This is it, you can code shadow casting in three.js now :) Go ahead and play with them. They are hard to master but very efficient visually. Keep in mind that those shadows aren't real. They only uses'some tricks' to make them appears as real. And they do so in real time !! To achieve this result, they take significant shortcuts which produce artifacts. To avoid those require tuning and experience.

That's all for today folks. Have fun.

Fun With Live Video in WebGL

$
0
0

This post is about live video in webgl. It is possible in today browsers to read the webcam using a new feature from html5, called WebRTC. This standard is about real-time communications such video conferences. It is an open source project supported by Google, Mozilla and Opera. Quite neat hey!

I think live video has a lot of potential usages in 3D. It is so cool for interactivity. The player sees himself on the screen. It becomes part of the actions. Quite immersive effect. We can imagine something like second life, where people wander around and interact live with each other in a virtual world. Our demo is about TV... Another obvious use may bereflections likemirror orwater. What about your face from the webcam reflecting in water with animated waves ? Would be nice!

It is surely nice but WebRTC is still quite on the edge. To enable webrtc on your computer, see how torun webrtc demos. It is currently available only inCanari. Mozilla people are working hard to make it happen as soon as possible. So it may be too early to use it for 'serious' things. But way enougth to do cool experiments like the one we gonna do today :)

Try it out!! The first step will be to create a video element. We gonna start to make it play either a normal video file then to play video from the webcam usingmediastream API. After that, we gonna map this video to a normal texture. And we will be done ! It is that simple, now let's get started.

Let's create the video element

Thevideo element is the DOM way to handle video in webpage. Let's create the video element. Later we will use it as texture and display it in WebGL.

```javascript

video       = document.createElement('video');
video.width = 320;
video.height    = 240;
video.autoplay  = true;

```

It you wish to create a video from a file webm, mp4 or ogv, just set its .src property.

```javascript

video.src = "http://example.com/supercatvideo.webm";

```

It wasn't too hard, hey :) So now we know how to get a video from a file. Let's see if we can use the webcam and get this nice immersive effect for our users.

Let's Use the Webcam if Available

Our first step is to detect if the media stream API is available. The following line will do the job nicely.hasUserMedia will be true if it is available, false otherwise.

```javascript

var hasUserMedia = navigator.webkitGetUserMedia ? true : false;

```

If it isn't, you may point the users tothis doc on how to get it and/or using a normal video file. Now we need to check if we can read the webcam. For that, we use the following lines.

```javascript

navigator.webkitGetUserMedia('video', function(stream){
    video.src   = webkitURL.createObjectURL(stream);
}, function(error){
    console.log("Failed to get a stream due to", error);
});

```

A pseudo URL will be created by .createObjectURL. It would allows the video element to automagically read the webcam. It looks a bit like that.

```

blob:http%3A//learningthreejs.com/e33eb278-08a8-4052-9dca-3c7663c88bc0

```

Handle the textures

Now we got the video element ready. Let's create a texture using it as source. The last step before seeing the video moving on screen :) Use this simple line. It is enougth.

```javascript

var videoTexture = new THREE.Texture( video );

```

This texture is a normal texture and can be used as usual in materials. For example, in a lambert material.

```javascript

var material    = new THREE.MeshLambertMaterial({
    map : videoTexture
});

```

But this texture is special, it is a video. So it need to be constantly updated. In your render loop, add those lines. They monitor the state of your video. Every time the video got enougth data to be display, the texture is updated and sent to the GPU.

```javascript

if( video.readyState === video.HAVE_ENOUGH_DATA ){
    videoTexture.needsUpdate = true;
}

```

Conclusion

Now you can display your webcam inside your webgl !! This is simple and cool. Browser support will increase with time. Live video is a very powerfull tool. The image from the webcam is a normal one. On it, you can performpost processing,edge detection, and many other crazy things. Up to you to experiment. Let's all for today folks, have fun :)

An Extension System for three.js

$
0
0

This post an overview of a work-in-progress. It is about an extension system on top of three.js which mimics jQuery API. I came up with the idea while thinking about how to trim three.js and make it easier to maintain. I have always been impressed with jQuery plugin ecosystem. It is lively, varied, and contains impressive specimens. I would love to have such a rich ecosystem for three.js's plugins.

Let's call this experiment tQuery as in "three.js + jQuery". It makes it easier to understand if you already known this library. This is a v0 in the"publish early, publish often" vibe. The goal of this little project is to see if we can mix to mix three.js power with jquery API usability... How far this concept can fly ? We will see.

So what do we want ? The code must make three.js easy to extend and should mimics jQuery whenever possible. In order to see if the system hold under load, i wrote several extensions already. It is very early. The architecture of it all is far from stable. Code is advancing at fast pace tho :) The screencast below is short live coding session. Just to give an idea of the current status.

DOM

With jQuery and theDOM, you get a tree ofelements from the page. In fact, three.js got this tree as well. Surprising hey ? We just name it ascene instead of a tree. And our element are calledObject3D. But all that is just a matter of vocabulary.

One one hand, jquery one, you got the dom and its tree of element. on the other hand, three.js one, you got the scene and its tree of object3D. Same Thing!

Chained API

jQuery got a chained API, so tQuery got a chained API. When we saidcopy jQuery whenever possible, we were not kidding :)

```javascript

tQuery('.fooKlass').scale(2).translate(1,0,0);

```

IDs and classes

They gotIds andclasses , or more recentlydata. So we did all the same with tQuery.

```javascript

var cube    = tQuery().createCube();
cube.id("myId");    // set the id of this element
cube.addClass('fooKlass');  // add 'fooKlass' class to this cube
cube.data('goom', 'baa');

```

Selector

jQuery got selectors so tQuery got selectors too. Here are the selector based on geometry, they are similar to the [element selector] in jQuery, e.g. jQuery('span').

```javascript

tQuery('sphere');   // select all objects with a sphere gemotry
tQuery('cube'); // smae with a cube gemotry
// and so on

```

Here are the one for classes and id. Note how the syntax is similar to css selector.

```javascript

tQuery('#myId') // to get the object with the 'myId' id
tQuery('.fooklass') // to get objects with the class 'fooklass'

```

obvious we got compose them like with jQuery

```javascript

tQuery('.bar.foo')  // objets with the class 'bar' and 'foo'
tQuery('.bar cube') // objets with the class 'bar' with a cube as descandant

```

Events

Obviously jQuery got events, so we got events in tQuery. we use domEvents we saw a few week back in'dom events in 3D space' post

```javascript

tQuery('cube').on('mouseover', function(){
    console.log("somebody put the mouse over a cube");
});

```

A Basic Page

This is a minimal page. the code is below, the preview on the right. Quite short.

```html

<!doctype html><title>tQuery Basic Page</title><script src="tquery-bundle.js"></script><body><script>

    var world = tQuery.createWorld().fullpage().start();
    var object = tQuery.createTorus().addTo(world);

    </script></body>

```

Conclusion

This was early presentation of tQuery. I like the idea, we will see how it goes. The purpose of this experiement is to help those who know jQuery to use three.js. So they reuse jquery syntax but inside a webgl context. This is a very early project. How far is it possible to push this concept of "three.js power + jQuery API usuability". It seems all very cute at first sight but only time will tell.

That's all folks. More on tQuery soon. Have fun :)

a Valentine card in tQuery

$
0
0

The tQuery experimentation is going on. It is a lot of fun to code :) This post is just a short presentation of two plugins currently in incubation: tquery.text and tquery.shape. Yesterday wasvalentine day, so i thought it would be cool to stay in topic. Thescreencast is a live coding of avalentine card in tQuery :)

Let's Write Text in 3D

tQuery.text plugin writes text in 3D. It is based onTextGeometry. Here is a simple example.

```javascript

tQuery.createText("tQuery is Fun!").addTo(world);

```

Let's Easily Create Shape

tQuery shape is made to easily build andextrude shapes in javascript. It is based onTHREE.Shape. tquery.shape is cool because it uses a API very similar tocanvas 2Dpath. This line will build a triangle.

```javascript

tQuery.createShape().moveTo(0,0).lineTo(1,1).lineTo(-1,1).lineTo(0,0);

```

Some shapes are already available, like the triangle above, or a fish, smiley and a heart. Here is a smiley.

```javascript

var shape = tQuery.createSmileyShape();

```

The valentince card

Last but not least, the valentine card!Try it out! It uses the plugins above to build an animated valentine card. It is done with less than 20lines... tQuery seems to produce short code.

Conclusion

Today we saw 2 plugins still in progress. tQuery experiment seems to go well for now. The code is moving at fast pace. I am currently experimenting with require.js to automatically resolve dependancies between plugins. What's next ? likely a series with a step by step on how to build a tunnel game.

That's all folks! have fun :)

Linkify, a tQuery Extension

$
0
0

This post is an update ontquery progress. It is about linkify, a first experimental extension. Thanks to it, any 3D object may become a link. So 3D objects act as a <a> tag, i.e. the object becomes clickable and clicking on it open a new url. It is built on top of domEvents. It is used to incoporatedom kindof events in 3D world. We saw them a few week back in'dom events in 3D space' post. Previous posts on tquery may be found here.

Building extensions on top of others is kinda the point of an extension system. My dream scenario is : (1) People do plugins for three.js, like they do in jQuery). (2) They share their work. (3) They build on top of each other. (4) Loop to 1. All in opensource spirit. All good in my book. Ok enougth talk, let's code.

Dom Events in 3D Space

domEvents have been ported to tQuery. It is an important part because jQuery developpers use this a lot, thru.on()/.off().

```javascript

tQuery('cube').on('mouseover', function(event){
    console.log("somebody put the mouse over a cube");
});

```

The supported events are click obviously,dblclick, mouseup, mousedown , mouseover and mouseout. It has been improved to better matchactual dom events. The callback now receives a event object. It contains .type and .target as described in dom specification.

```javascript

tQuery('.myClass').on('click', function(event){
    console.log("An event of type", event.type, "has been trigger on ", event.target);
    // If you wish to stop propagation, just do 
    event.stopPropagation();
});

```

Event bubbling is now supported. So events are dispatched to thetarget and follow its parent chain upward. It is possible to cancel propagation with an usual.stopPropagation().

Linkify or How Any 3D Object May Become a Link

Linkify is an experimental plugins built on top of tquery.domevent. It is shown in the screencast. It makes any 3D objects object act as a <a> tag, i.e. the object becomes clickable and clicking on it open a new url. When the mouse is over it, an underline is added to make it even more webpage like. Code is rather short.

```javascript

tQuery('text').linkify('http://example.com')

```

Conclusion

It has been quite time consuming to set up the basis for the project: tests, bechmarks, docs, or plugins interdependancy resolution. For each of those field, i had to review the various alternatives, pick one and setting it up as properly as possible.

Here are the current choises, they may change in the future.require.js will be used for the dependancies between plugins. Tests are done with mocha, a javascript test framework for javascript which run in node.js and browser. Later, we may improve that by testing the rendering output usingpixastic to dostatisticalimagescomparison. Benchmarks are done withbenchmarks.js, a robust benchmarking library for javascript, usingbenchrunner as runner. It is the engine behind the wellknownjsperf site. Inline documentation is written in jsdoc format usingcodeview template.

That's all folks. Have fun :)


tQuery v0 - Let's get started

$
0
0

This post is an update ontquery progress.Our previous posts were previews, for examplevalentine card in tQuery orlinkify, a tQuery extension. This post is the release of version 0. It will walk you thru the website and shows how to run your first tQuery project with the boilerplate. You should be able to play with tQuery after that :)

Ok It is still experimental. I have been paddling hard to make it usable by other people tho. The playground is the easiest way to start experimenting. It is all online. no install, no download, simple and understandable. tQuery code is all on github repository. Thescreencast below will walk you thru thewebsite.

Solid Ground to Build On

I would like tQuery to be a solid ground. Thus people can easily build their three.js extensions on top of it. So the code is documented, tested and performance is monitored. Here is some principles that i consider important for tQuery. Note that those principles are the theory. It doesnt imply i implement them well in practice :)

Code must be tested. It helps detect bugs earlier. Our tests are done withmocha.API must be documented. It helps new users to use the library.API documentation is done withjsdoc.Performance must be monitored. Thus developpers are immediatly aware of performance change when the code is modified. Ourbenchmarks are done withbenchmark.js and displayed bybenchrunner.

How to Get Started

or how to get the boilerplate :) tQuery Boilerplate is a template to get you started. You download it and modify it until it fits your needs. It is a fast way to start a clean project with tquery. The running boilerplate looks like that. Thescreencast below shows how to use it.

Running tQuery Boilerplate

You can try the boilerplate online with the playground. Want to run it on your computer ? First you get boilerplate's fileshere. Then you launch the http server to serve them. Here is a little shell script which does it all for you.

```bash

curl -OL https://github.com/downloads/jeromeetienne/tquery/tqueryboilerplate.zip
unzip tqueryboilerplate.zip
cd tqueryboilerplate
make server

```

Then you open a browser on http://127.0.0.1:8000/ to see it running. Up to you to modify index.html until it fits your needs. index.html looks like the code below... Quite short.

```html

<!doctype html><title>Minimal tQuery Page</title><script src="./tquery-all.js"></script><body><script>
    var world   = tQuery.createWorld().boilerplate().start();
    var object  = tQuery.createTorus().addTo(world);</script></body>

```

Conclusion

This is the initial release of tQuery. I like how it looks. API is documented, code is tested, and performance measured. The code produced by the API seems short and quite understandable. Nice foundations especially for a version 0.

The next step is about stabilizing tquery.js itself, cleaning it up. I am currently quite busy doing just that. So please dont hammer me with feature requests at the moment, i won't have time to handle them. Pull requests are welcomed tho. Things will change when tQuery core become more stable.

That's all folks, have fun :)

Augmented Reality in the Browser

$
0
0

This post is about augmented reality in the browser. In a recent post, we saw that it is now possible tohave live video in webgl withWebRTC. Due to this,augmented reality is under the spotlight. Recentlyhtml5rock published a tutorial byilmari heikkinen about "writting augmented reality application using jsartoolkit". Ilmari isgoogle devrel for webgl and the author ofJSARToolKit too. So we are in good hands :) The tutorial even include a part about binding it withthree.js. I took this nice tutorial and packaged the code even easier to reuse.

Try this demo. If you got WebRTC is available in your browser, takethis marker, and put it in front on your webcam. It is the same you see on the right. It is best to print it on paper. If you can't, point your phone tothis page instead. Phone screens tend to reflect lights from your environment tho. They may reduce the accuracy of the marker detection.

Now let's see how you can to use all this to build your own demos :)

You Include it

First you include it as usual in your page. The code is availablehere. Note thatJSARToolKit is released under GPL, so some restrictions apply. The threex is under MIT license as usual.

```html

<script src="JSARToolKit.js"></script><script src="threex.jsartoolkit.js"></script>

```

You Initialize It

Once you get the code, you instanciate the object like this.

```javascript

var threexAR    = new THREEx.JSARToolKit({
    srcElement  : srcElement,
    threshold   : threshold,
    callback    : function(event){}
});

```

The srcElement may be avideo, animage or acanvas. When the video is shoot in a uncontrolled environement, the marker detection may be less reliable, due to variations of lighting.threshold is a value between 0 and 255 to adapt your detection to those variations. To detect the augmented reality markers in the srcElement, just use this line in your rendering loop.

```javascript

threexAR.update();

```

No rocket science here.

You Use It

During .update(), the callback is notified with events. They describe the markers present on the srcElement. Each event got various fields: A .markerId which tell you which marker has been recognized. Theone used above is the 64. You can find the whole listin JSARToolKit repository.

The .type field describe what is happening to this marker. It may be create, update or delete.create if the marker has just been detected,update if the marker was present before. and delete if the marker is no more present. Rather obvious :) The .matrix field is aTHREE.Matrix4. It is a transform which matches the position of the marker in space.

Conclusion

So now we can do augmented reality in a browser. The code of the demo is here. Up to us to find actual application of this technology. Currently most browsers with webcam are running on desktop/laptop tho. As most their webcam is directly attached to screens, It limits the flexibility of what you could put on front of the camera. As for mobile, only opera 12 is currently the only mobile browser able to read the webcam.

That's all folks. Have fun :)

tQuery WebAudio for More Realistic 3D

$
0
0

This post is aboutWeb Audio API. It is a new HTML5 api which provide great controls on the audio layer. It is much better than theaudio tag. It is more suitable for games or music software. As 3D lovers, the one feature that we care about isaudio spacialization. This makes Web Audio a complement to webgl. It implements positional sounds, so you getpanning,dopler and all. It makes the scene so much more realistic.

The user tends to associate 3D to reality, so efficient 3D is a lot about realism. The brain identifies 2D as artificial while 3D seems immediatly more natural. Anything which appears close to reality increase this effect. Feeding this illusion creates a more immersive experience to the user. Realistic physics is one (stay tuned :). Web Audio audio spacialization is another.

Thescreencast below is a live coding session using tQuery.WebAudio. If you want, you can experiment with this code in our playground. Just clickhere and start coding :)

Background on WebAudio API

To learn about WebAudio API is a large subject. It is out of the scope of this introduction. You can refere to many dedicated tutorials tho. The specification itself is clear and very readable.

You can find more comprehensive documentation at html5rocks. It contains several very usefull tutorials to learn Web Audio API. They go from"Getting started with the web audio API" to"mixing positional audio and webgl" or"developing game audio". If you want, you can find demos inchromium samples.

Now let's start coding :)

Let's get Started

First you need to enable WebAudio into your world. Thus you will be able to play sound in it.

```javascript

world.enableWebAudio();

```

Now that the world is able to do sound, let's create one

```javascript

var sound = tQuery.createSound();

```

Now we need to load a sound file and to start playing it. The callback is notified when the file is downloaded. At this point, the sound it ready to play.

```javascript

sound.load('techno.mp3', function(sound){
    sound.play();
});

```

If you want to know more, the full API is documentedhere andhere thanks to jsdoc.

Spacialization and Animation

Now that we can play a sound, what else can we do ? One definitively interesting part forwebaudio API is the ability to spacialize the sound. The easiest way to do that is to use .follow() function.

```javascript

sound.follow(object3d);

```

If you want more controls, you can check.updateWithObject3d() or .updateWithMatrix4(). You may want to animate your 3D object based on the sound you hear. For that, a simple function .amplitude() has been written. It is likely a naive implementation but it does the trick, i think.

```javascript

var amplitude = sound.amplitude();

```

It returns an average of low frequencies of the sound. Note that i dunno if it is the proper term in audio world. Most likely not :) If you know the proper term, please leave a comment.

Want more info ?

You get two examples inthe source. Theminimal one simply play a sound. The other is more interactive. It is theplayground. It allows to play with various parameters. tQuery API documentation is provided viajsdoc. You can find the whole APIhere. The plan is to do the same for the plugins.

So for tQuery WebAudio plugin, you get API documentation of each class: the main classtQuery.WebAudio and theSound class. You can even check theNode chain builder doc if you want to go deep and configure your own audio nodes chain :)

Conclusion

Ok so now you can play sounds in your 3D scene. You can make the sound follows a given object3d with realistic sound spatialization. All that in just a few lines. Rather cool if you ask me :)Winamp effects are back !! Later i will likely implement click detection as seenhere and environmental effect like 'cathedral', 'telephone' etc... as seenhere.

I love how sound make our 3D scene more realistic. That's all for today, have fun :)

Video Conference on Top of WebGL

$
0
0

This post presentsWebGL Meeting, a very simple WebGL application to do webrtc call. It is a follow up of "Fun with live video on webgl". It was presenting how to use the WebCam usingWebRTC getUserMedia(). This one goes one step further and make an actualWebRTC call displayed in a WebGL scene.

In fact, it has already been done a month ago! As you can seehere :) The video from the first post, 'being on tv, watching tv' has been answered by Ethan Hugg from cisco. My very first video reponse btw! Heshows a SIP video call using an version of Chromium hacked bySuhas Nandakumar. Definitly cool stuff!WebGL Meeting is similar but run on unmodified browsers. Thescreencast below is short demo of it.

WebRTC progress

Using a modified browser is cool for make nice demo likethis one. Nevertheless it reduces how widely the technology can spread. It is now possible to do it using opensource and mainstream browsers. This field advances so fast!

Mozilla team isworking hard to make it happen as soon as possible. It is even available on mobile withOpera Mobile 12. Some "protothon" are happening about it.WebRTC is on the edge but it is definitly coming hard. The picture on the right is Chrome WebRTC team doing thumb up onWebGLMeeting at an WebRTC event forIETF 83 :)

What about the code ?

WebGLMeeting source is available on Github under MIT license. It uses three.js to handle the WebGL. It is the AppRTC app mostly unmodified, with a simple WebGL skin on top.

A post from Chrome WebRTC team recently announced"Source code to apprtc.appspot.com example app available". The post releases thesource on google code. The apprtc demo is a very simple, one-to-one, webrtc call. Go look at the source, dont be shy :) It is very small, the whole code client+server, is less than 15kbyte. It is easy to understand and deploy thanks too google App Engine.

Face tracker seeking love ?

Surprising hey ? Well the source contains a face tracker,face.html. It works rather well but it is slow. If somebody could give it more love... It is a rather naive implementation which works well but got many rooms for speed improvement. It could make face tracking, less clumsy than wearing augmented reality marker on top of your head likei did a while back :)

Conclusion

I got the feeling WebRTC gonna change a lot of things soon. The peer-to-peer aspect makes it super cheap to integrate live video conferences to your own sites.

That's all folks, have fun!

Augmented Reality 3D Pong

$
0
0

This post presents a livecoding screencast of Augmented Reality 3D Pong. This is an experiment to use augmented gestures as a way to interact with game. So i picked a game classic "pong". We gonna learn how to code a pong in augmented reality with webgl. The result code is only100lines!! Nice for augmented reality + webgl + a game :)

But First... What is augmented gestures ? I made augmentedgesture.js. This is a library which use getUserMedia and WebRTC to grab the webcam. It analizes the image with imageprocessing.js and extract the location of flashy balls. I presented it first at Web-5 conference with me punching Doom characters in augmented reality :)'Doom: a new workout for geek?' on youtube is preview of it. For the webgl, we obviously gonna usethree.js andtQuery.

Controllers for the Wii orPS3 did good as game controllers.kinect is super cool obviously. They all requires to buy specific hardware tho... So the money is a barrier. Some even require specific installation on your computer, with code to compile. This is another barrier. With augmented gestures, you dont need specific devices. I like to use objects which are cheap and readily available in our everyday life. Thus people got easily access to the content, in a pure web vibe. I use children toys that i paid 3euro per ball. Another possibility is to use post it. They work well thanks to their flashy colors as you can see in this video. They are available in most offices. Another is to use dish gloves. They are readily available and cheap.

Try it! This screencast is a presentation on how to codeaugmented reality pong 3D. The code is on github under MIT license. The slides of the presentation arehere. Im not sure about the format of this video... the mix live coding + slides + screencast is usual. Anyway publishing it in "publish early, publish often" mood :)

Enjoy

tQuery plugin for Doom Characters

$
0
0

This post is abouttQuery.md2Character plugin: a cool plugin which allow you to easily play with doom characters. You can see a live demohere. I will walk you thru its example. It include a checkerboard for the ground, a fog for the depth, keyboard to move your player and obviously plugins for the MD2 characters (doom formats). We gonna learn how to move doom characters in webgl in only 50lines of javascript!

Background knowledge

First what means MD2 ?MD2 is the file format used in the famousQuake II. Many of the monster you love to hate can be found in this format :) You can find md2 models at sitters-electronics or at planet quake.

You can use it easily in three.js thanks to oosmoxiecode He wrote a nice converter fromMD2 tothree.js json format. He wrote a post about it with plenty of usefull info on the subject.alteredq wrote several cooldemos using it.

Let's Get Started

We gonna walk you thru the 50lines of javascript needed make this demo. It is rather simple. It implies tQuery obviously, and various plugins: One for the fog, one for the checkerboard used as ground, one to bind the keyboard and obviously plugins for the MD2 Character itself.

Nice demo no ? You can try ithere. Let's code it!

The 3D World

First we initialize the world in 3D. With tQuery.createWorld(), we create a tQuery.World. With .boilerplate(), we setup a boilerplate on this world. A boilerplate is a fast way to get you started on the right foot. It is thelearningthreejs boilerplate for three.js With .start(), we start the rendering loop. So from now on, the world scene gonna be rendered periodically, typically 60time per seconds.

```js

var world   = tQuery.createWorld().boilerplate().start();

```

Change the background color. This confusing line ensure the background of the 3D scene will be rendered as 0x000000 color, aka black. We set a black background to give an impression of night.

```js

world.renderer().setClearColorHex( 0x000000, world.renderer().getClearAlpha() );

```

The Lights

Here we setup the lights of our scene. This is important as it determine how your scene looks. We add a ambient light and 2 directional lights. The ambient light is a dark grey, to simulate the lack of light during the night. We setup a directional light in front colored redish.... This is like a setting sun. In the opposite direction, we put another direction light, bluish. This is like the moon. Well this was my rational :)

```js

tQuery.createAmbientLight().addTo(world).color(0x444444);
tQuery.createDirectionalLight().addTo(world).position(-1,1,1).color(0xFF88BB).intensity(3);
tQuery.createDirectionalLight().addTo(world).position( 1,1,-1).color(0x4444FF).intensity(2);

```

The fog

We had a fog to the scene. For that, we use tquery.world.createfog.js plugins. It allows to create the 2 types of fog from three.js : fogexp2 andfog.density is the density of the fog. 0.01 is very light, 0.9 is almost opaque. In general, fogs are a nice visual trick. It is rather cheap to compute and limits the depth of what you see. It is a nice trick to hide the "end of the world" :)

```js

world.addFogExp2({density : 0.1});

```

The Columns

initialize a material

We will apply it to all the columns. It is lambert lighting the ambient is the color which gonna be combined with be combined with the ambient light we initialized on top. color will be combined with the directional lights. and map gives the texture to use.

```js

var material    = new THREE.MeshLambertMaterial({
    ambient : 0xFFFFFF,
    color   : 0xFFAAAA,
    map : THREE.ImageUtils.loadTexture('../../assets/images/water.jpg')
});

```

Build 15 Columns

loop over each column

```js

for(var i = 0; i < 15; i++ ){

```

Create the cylinder. We pass some parameters to the contructor to setup the size we see fit, and we add the material we want to apply on the cylinder. Then we use .addTo() to add our object to our tQuery.World.

```js

    var column  = tQuery.createCylinder(0.2,0.2,2, material).addTo(world);

```

Change the position of the column. We translate the column to build a kind of alley. Thus the character will be able to run inside it :)

```js

    column.translateX(i%2 ? +1 : -1).translateY(1).translateZ(15/2 + -1*i);
}

```

The Ground

We create a large checkerboard with tquery.checkerboard.js plugin. We scale the checkerboard to 100 per 100 units in the 3D world. Thus it is quite large and disappears into the fog. It gives the cheap impression of an infinite checkerboard.

```js

tQuery.createCheckerboard({
    segmentsW   : 100,  // number of segment in width
    segmentsH   : 100   // number of segment in Height
}).addTo(world).scaleBy(100);

```

The Character

We use tQuery.RatamahattaMD2Character plugin. Its inherits fromtQuery.MD2Character plugin. All the configuration for this particular character ratamahatta is already done for you. We attach it to tQuery world. Additionnaly we use .hookKeyboard() which bind arrow key to character moving. This function is part ofkeyboard plugins for ratamahatta

```js

var character   = new tQuery.RatamahattaMD2Character().attach(world).hookKeyboard();

```

Here we show an example of binding the "loaded" event. It is notified once the whole characters data are loaded (texture, mesh for animations of body and weapons). It just display the name of the available animations.

```js

character.bind("loaded", function(){
    console.log("list animmation", Object.keys(character._meshBody.geometry.animations))
});

```

We setup the user camera controls. It will determine how the user camera will move in the world scene. We use tQuery.MD2Character.CameraControls plugin made specially for this case. With it, the camera will follow the MD2 character looking at it from above. world.setCameraControls(new tQuery.MD2Character.CameraControls(character));

Change the Skin by Keyboard

hook a function in the rendering loop. This function will be executed everytime the scene is rendered. Within this function, we will use tQuery.Keyboard plugins to test the keyboard. if the key s is pressed, then use character.setSkin() to change the skin of the character.

```js

world.loop().hook(function(){
    var keyboard    = tQuery.keyboard();    // get keyboard instance
    if( keyboard.pressed("s") ){        // if the key 's' is pressed, change the skin
        character.setSkin(Math.floor(Math.random()*5));
    }
});

```

Conclusion

So we have seen what is possible to do with tquery.md2character and 50lines of javascript. It is a rather short code for what you got on the screen, if you ask me. Btw all that released under MIT license. I think i like the code walkthru format. I find it efficient to describe tQuery examples and fast for me to generate. It is directly derived from annoted doc format as you can see here. I will likely do more in the future.

That's all folks. Have fun :)

Sound Visualisation: a Vuemeter in WebGL

$
0
0

This post is about producing a 3D Vuemeter for real time sound. We gonna walk thru the code of awebaudio.js example. This example will show you how to create a WebGL vuemetter withwebaudio.js. It should be simple to understand, only 40-lines of javascript.webaudio.js is a web audio library for game. We gonna use it to reach Web Audio API. We gonna use tQuery to reach three.js 3D engine.

webaudio.js has been first coded as a tQuery plugin. You can find a post about it on learningthreejs blog. But this technology is so nice, it deserved its own repository. The library gained in flexibility in the process: It is now possible to display histogram in canvas2D of simply play sound, with no 3D at all :) see here for a list of webaudio.js examples.

Try the demo. This is the result that we gonna build together. Below is a small screencast of me presenting the code.

Background Knowledge

Web Audio API is aimed for games and based on openAL. Its API is real nice tho. It is Efficient and flexible. It is efficient because most processing happen in native code, still you configure it in js, your favorite language :) It is flexible as it is based on a routing concept which give you great controls on the sounds you play.

You can findmany good tutorials on the matter onhtml5rocks. I recently did a presentation at musichackparis on Web Audio API. If you want to know more, slides are here. This API is available on WebKit based browser, so safari and chrome and its derivative. Unfortunatly this API isn't compatible with major webgl browsers e.g. firefox and opera. The Web Audio API is real nice tho. Efficient flexible Sound is still the poor lone child of the web :( Well let's have fun with what we have.

Let's get started

Ok the very begining is real simple. We init a basic html page. Then we include the dependancies in javascript. We include webaudio.js to handle the sound playing and analysis. Then we just have to include tquery. tquery-bundle.js is tquery bundled withthree.js in a single file for convenience.

```

<!doctype html><title>webaudio example: histo3d</title><script src="../build/webaudio.js"></script><script src="vendor/tquery/tquery-bundle.js"></script><body><script>

```

Let's Code in JS

First we gonna intenciate WebAudio. This will initialize the layer. It will create the AudioNode`s for the end of the chain. By default it contains againNode and acompressorNode. The gainNode is used to tune the volume. and the compressNode to smooth the peaks we could hit in the sound.

```

var webaudio    = new WebAudio();

```

Now that we go webaudio available, let's use it to create the sound we gonna play..createSound() will create a WebAudio.Sound. Then we .load() it from this url 'sounds/perfume.mp3'. The callback will be notified as soon as the sound is loaded. Then we simply start to play it. Don't forget to get .loop(true) thus the sound will loop forever.

```

var sound   = webaudio.createSound().load('sounds/perfume.mp3', function(sound){
    sound.loop(true).play();
});

```

Initialize the 3D World

First we initialize the world in 3D. With tQuery.createWorld(), we create a tQuery.World. With .boilerplate(), we setup a boilerplate on this world. A boilerplate is a fast way to get you started on the right foot. It is thelearningthreejs boilerplate for three.js With .start(), we start the rendering loop. So from now on, the world scene gonna be rendered periodically, typically 60time per seconds.

```

var world   = tQuery.createWorld().boilerplate().start();

```

We Change the background color. This confusing line ensure the background of the 3D scene will be rendered as 0x000000 color, aka black.

```

world.renderer().setClearColorHex( 0x000000, world.renderer().getClearAlpha() );

```

Here we setup the lights of our scene. This is a key factor for the look and feel of your scene. We add a ambient light and 2 directional lights.

```

tQuery.createAmbientLight().addTo(world).color(0x888888);
tQuery.createDirectionalLight().addTo(world).position(+1,+1,1).color(0x88FF88);
tQuery.createDirectionalLight().addTo(world).position(-1,-1, 1).color(0x8888FF);

```

Some constants

First we initialize nBar to store number of bars in our 3D vuemeter. This number MUST be odd, thus the vuemeter is symteric with the middle

```

var nBar    = 41;
console.assert(nBar%2, "nBar MUST be a odd number.")

```

Now we need to compute the width of each 3D bar. The whole vuemeter is 80 wide. So each bar is 80/nBar wide.

```

var barW    = 80/nBar;

```

We create an array bars3d. We will use it to store the object3D for all bars of the histogram.

```

var bars3d  = [];

```

Build the 3D VueMeter

First we create the container group3D which gonna regroup all the bar3D. It is the container of the whole 3D Vuemeter

```

var group3d = tQuery.createObject3D().scale(1/20).addTo(world);

```

We gonna build each bar and add it to group3d. We loop to create nBar with tQuery.createCube(). In fact a bar is a rectangular box, so like a cube with different dimensions. a bar got a width of barW, an height of 10 and a depth of 5. The material is a simple lambert. Once the bar is create, we add it to group3d and set it to the correct position in space. We push every bar3d into bars3d for future reference.

```

for(var i = 0; i < nBar; i++){
    var bar3d   = tQuery.createCube(barW, 10, 5, new THREE.MeshLambertMaterial({
        ambient : 0x888888,
        color   : 0xFFFFFF
    }));
    bar3d.addTo(group3d).position((i-nBar/2)*barW, 0, 0);
    bars3d.push(bar3d);
}

```

Update Vuemeter From Sound Analyser

Here we hook a function to tQuery rendering loop, tQuery.Loop. Thus this function gonna be executed everytime our 3D scene is rendered. if the sound isnt yet loaded, do nothing.

```

world.loop().hook(function(){
    if( sound.isPlayable() === false )  return;

```

build the histogram of the sound based onRealtimeAnalyserNode.getByteFrequencyData()

```

var nBarHalf    = Math.ceil(nBar/2)
var histo   = sound.makeHistogram(nBarHalf);

```

We gonna loop over each bar3D of our vuemeter. We gonna update each of them based on the sound histogram we just computed.

```

bars3d.forEach(function(bar3d, barIdx){

```

We need to determine which value in the histogram match this vuemeter bar. As our vuemeter is symetric, the vuemeter bar on the far left got the same histogram value as the one on the far right. This make this computation a bit confusing.

```

        var histoIdx        = barIdx < nBarHalf ? nBarHalf-1-barIdx : barIdx - nBarHalf;

```

Now we need to compute the height of the vuemeter bar based on histogram value. This is simple scaling from one to the other: vuemeter height === histo height / 256

```

        var height      = histo[histoIdx] / 256;

```

Now that we computed all that, we update the bar3d. We update .scale.y to change its size and .material.color to change its color. The formulas i used "worked for me". Up to you to be creative and find the one that fit your own needs

```

        bar3d.get(0).scale.y    = height*3;
        bar3d.get(0).material.color.setHSV(0.3+height*0.7,1,1)
    });
});

```

Conclusion

So we usedwebaudio.js to play a sound and analyses in real time. We used this information to change 3D objects based on this analysis. We leveraged tQuery to reach three.js 3D engine. Now you can imagine any visual effect based on sound analysis. The road to winamp effects is open to you :) We got a rather nice looking WebGL output of a 3D Vuemeter in Real Time for only 40 lines of javascript. I love how short code reduces developement time.

That's all folks. Have fun :)


Punch A Doom Character in Augmented Reality

$
0
0

Did you ever dreamed of punching a doom character ? They look evil and killed you so many time while you were playing the game. It is revenge time! This post will help you realize your dream :) It is about a minigame called "Punch A Doom Character in Augmented Reality" because in this game, the player can punch Doom Character in augmented reality :)

The character is displayed in 3D with WebGL with three.js. The player gestures are recognized thru the webcam by augmentedgesture.js library. It uses WebRTCgetUserMedia to get the webcam using open standards. You can play this minigame here. In fact, it is an example of augmentedgesture.js library. We will walk you thru the code. Only 60 lines of Javascript.

We have seen augmented gesture in "Augmented Reality 3D Pong" post and MD2 Characters in "tQuery Plugin for Doom Characters" post. Now we gonna associate them together in our mini game :) I presented it at Web-5 conference in april. At the time, i recorded a preview "Doom: a new workout for geek?". Now let's get started!

The 3D World

First we initialize the world in 3D. With tQuery.createWorld(), we create a tQuery.World. With .boilerplate(), we setup a boilerplate on this world. A boilerplate is a fast way to get you started on the right foot. It is thelearningthreejs boilerplate for three.js. With .start(), we start the rendering loop. So from now on, the world scene gonna be rendered periodically, typically 60time per seconds.

```

var world   = tQuery.createWorld().boilerplate().start();

```

We setup the camera now. We remove the default camera controls from the boilerplate. Then we put the camera at (0,1.5,5) and looking toward (0,1,-1)

```

world.removeCameraControls()
world.camera().position.set(0,1.5, 4);
world.camera().lookAt(new THREE.Vector3(0,1,-1));

```

Now we change the background color. This confusing line ensure the background of the 3D scene will be rendered as 0x000000 color, aka black. We set a black background to give an impression of night.

```

world.renderer().setClearColorHex( 0x000000, world.renderer().getClearAlpha() );

```

We had a fog to the scene. For that, we use tquery.world.createfog.js plugins.

```

world.addFogExp2({density : 0.15});

```

The Lights

Here we setup the lights of our scene. This is important as it determine how your scene looks. We add a ambient light and a directional light.

```

tQuery.createAmbientLight().addTo(world).color(0x444444);
tQuery.createDirectionalLight().addTo(world).position(-1,1,1).color(0xFFFFFF).intensity(3);

```

The Ground

We create a large checkerboard with tquery.checkerboard.js plugin. We scale the checkerboard to 100 per 100 units in the 3D world. Thus it is quite large and disappears into the fog. It gives the cheap impression of an infinite checkerboard.

```

tQuery.createCheckerboard({
    segmentsW   : 100,  // number of segment in width
    segmentsH   : 100   // number of segment in Height
}).addTo(world).scaleBy(100);

```

The Character

We use tQuery.RatamahattaMD2Character plugin. Its inherits fromtQuery.MD2Character plugin. All the configuration for this particular character ratamahatta is already done for you. We attach it to tQuery world.

```

var character   = new tQuery.RatamahattaMD2Character().attach(world);

```

When an animation is completed, switch to animation 'stand'.

```

character.bind('animationCompleted', function(character, animationName){
    console.log("anim completed", animationName);
    this.animation('stand');
});

```

Recognize Augmented Gestures

First we instanciate an object of AugmentedGesture class..enableDatGui() will add a Dat.GUI. This is a nice library to tune parameters. We use it to tune augmentedgesture pointers. You can read more about it in "Dat-gui - Simple UI for Demos" post..start() asks it to begin monitoring the webcam and see if it finds markers..domElementThumbnail() put the webcam view as a thumbnail on the screen. This is what you see on top-left. This is usefull for the user, it is used as feedback to know what is happening

```

var aGesture    = new AugmentedGesture().enableDatGui().start().domElementThumbnail();

```

The Pointers

Now that we got our AugmentedGesture instance, we gonna configure the pointers. One for the right hand, one for the left hand. For each, we setup the options to adapt each hand colors. In my case, the right hand is containing a green ball and the left hand contains a red ball.

```

var pointerOpts = new AugmentedGesture.OptionPointer();
pointerOpts.pointer.crossColor  = {r:    0, g: 255, b:   0};
pointerOpts.colorFilter.r   = {min:   0, max:  95};
pointerOpts.colorFilter.g   = {min: 115, max: 255};
pointerOpts.colorFilter.b   = {min:  25, max: 150};
aGesture.addPointer("right", pointerOpts);

```

Now we do the same for the left pointer.

```

var pointerOpts = new AugmentedGesture.OptionPointer();
pointerOpts.pointer.crossColor  = {r:    255, g:   0, b: 128};
pointerOpts.colorFilter.r   = {min: 190, max: 255};
pointerOpts.colorFilter.g   = {min:  30, max: 255};
pointerOpts.colorFilter.b   = {min:   0, max: 100};
aGesture.addPointer("left", pointerOpts);

```

Gesture Analysis

Now that augmentedgesture.js is giving us the position of each hand, we gonna convert that into events. punchingRight when the user gives a punch with the right hand and punchingLeft for the left hand. We establish a variable to store the user moves. It is quite simple.punchingRight is true when the use is punching with his right hand..punchingLeft is the same for the left hand. and .changed is true when values change.

```

var userMove    = {
    punchingRight   : false,
    punchingLeft    : false,
    changed     : false
};

```

we bind the event mousemove.left thus we are notified when the user moves his left hand. The algo we use is very simple: if the left hand is on the right part of the screen, then the user is considered "punchingLeft". Dont forget to .changed to true

```

aGesture.bind("mousemove.left", function(event){
    var state   = event.x > 1 - 1/3;
    if( state === userMove.punchingLeft )   return;
    userMove.punchingLeft   = state;
    userMove.changed    = true;
});

```

Now we need the same thing for the other hand. all the the same.

```

aGesture.bind("mousemove.right", function(event){
    var state   = event.x < 1/3;
    if( state === userMove.punchingRight )  return;
    userMove.punchingRight  = state;
    userMove.changed    = true;
});

```

Bind Character and Augmented Gestures

Now we hook a function to the rendering loop. This function will be executed every time the scene is renderered. The first thing we do in this function is to check that userMove has .changed. If not, we do nothing.

```

world.loop().hook(function(){
    if( userMove.changed === false )    return;
    userMove.changed = false;

```

Now we process each move of the user. If the user is punchingRight, play the animation crdeath of the character. If he is punchingLeft, play crplain.

```

    if( userMove.punchingRight )        character.animation('crdeath');
    else if( userMove.punchingLeft )    character.animation('crpain');
});

```

And you are DONE! Pretty nice no ? :)

Conclusion

In this post we built a mini-game where users can punch doom character in augmented reality. All that in 60 lines of javascript. The Character is displayed in WebGL withthree.js and the augmented reality is handled by augmentedgesture.js. I like how those libraries makes the code so small, and the developement time so short.

That's all folks, have fun :)

Sport Car in WebGL

$
0
0

This post is about sport cars and how cool they can be! Once again, we gonna expose gems from three.js examples. It contains several sport cars which are fun to play with. You can drive them around and all. This is a good base for a game. We made tQuery plugins on top to make them easily reusable. Our scene will be a nice sport car, a grass ground, a sunset sky with shadow casting. All that in 40-lines of javascript.

What We Gonna Build ?

What you see below is what we gonna build. Pretty nice no ?Try it out.

It shows what is possible with tquery.car.js. It is a plugin provides rendering and controls of sport cars. It is heavily based on some examples by alteredq inthree.js. You can find themhere andhere. The car is a Bugatti Veyron model byTroyano. Now let's get started.

Let's start coding

We start to create our world as usual. We enable theboilerplate for three.js. It is a fast way start, avoids repetitive tasks, following DRY principles and includes all those good practices which are so easy to forget. Then we just have to .start() the rendering loop on this world.

```

var world   = tQuery.createWorld().boilerplate().start();

```

Now we setup the renderer. In this scene, we want to cast shadows as if it cames from the sun. This is a nice way to improve the realism in our 3D scene We already talked about it in "Casting Shadow" The renderer needs to be notified so we set .shadowMapEnabled and .shadowMapSoft to true.

```

world.renderer().shadowMapEnabled   = true;
world.renderer().shadowMapSoft      = true;

```

The Sky

Now we add a sky to the 3D scene. It will fill the space and make the scene more realistic. We use a skymap for that. It is WebGL trick which take a cube, make it so large that it seems infinite. On it, we map a 360degeree texture shaped as a cube, and use a special shader to display it. All is in this shader, it makes the cube appear as if we were in a gigantic sphere. Exactly like we would feel with a sky above our head. We already saw skymaps in "let's do a sky" post. We just added a new plugins tquery.skymap.js. It avoids repeative code when you do skymap or environement map.

```

tQuery.createSkymap('skybox').addTo(world);

```

The Lights

Here we setup the lights. We put one ambient and 2 directional lights.

```

tQuery.createAmbientLight().addTo(world).color(0xFFFFFF);
tQuery.createDirectionalLight().addTo(world).position(1,1,-1).color(0xffffff).intensity(2);

```

It is rather simple so lets focus on the last one, the one casting shadow. We want it to appear as coming from the sun. So we look at the skymap and approximatly localized the sun at (-10, 20, 30). Then we tune shadow parameters to fit our tastes. You can find more details in "Casting Shadow" post. Those parameters can be tricky to tune. It helps if you make the shaddow camera visible. You can do so with .shadowCameraVisible(true).

```

tQuery.createDirectionalLight().addTo(world).position(-10, 20, 30).color(0xffffff).intensity(4)
    .castShadow(true).shadowDarkness(0.8)
    .shadowMap(512*2,512*2)
    .shadowCamera(10, -10, 20, -20, 0.1, 50);

```

The Ground

Now we add the ground. A car needs a ground to stand on :) For that, we got a little helper tquery.grassground.js. This is just building a THREE.Plane and mapping a grass texture into it. It does the job for a simple and fast ground. We have seen something similar with tquery.checkerboard.js in"tQuery Plugin for Doom Characters" post.

```

var ground  = tQuery.createGrassGround({
    textureUrl  : '../../grassground/images/grasslight-big.jpg',
    textureRepeatX  : 30,
    textureRepeatY  : 30,       
}).addTo(world).receiveShadow(true).scaleBy(100);

```

The Car

First we instanciate a tQuery.Car object with tQuery.createCar(). It will load the models, then material will be setup.tQuery.Car handles the displacement of the car too. You can make the car turn, go forward and backward, using car.controls(). you can even switch on/off the lights with .flareVisible()

```

var car = tQuery.createCar();

```

Then we had the car model in our world scene. Important if you want to see it :)

```

world.add(car.model())

```

Now we got the car on the scene, this is all good. But we need the camera to follow this car. We create a camera controls specific to mimic the usual camera in car game. The camera is placed a bit behind the car and looks forward. The faster you go, the further you look. This is always nice to see what is coming at you :)

```

tQuery.Car.createCameraControls(car, world);

```

Car Controls

Now we hook the controls to the car. This determines how the player will control the car. It can be controlled by the keyboard, so users press arrows on keyboard and the car moves. It can be controlled by the device orientation. We already talked device orientation in game inthis post.

```

var hasTouchEvent   = "ontouchstart" in window;
if( hasTouchEvent ) car.hookDeviceOrientation();
else            car.hookKeyboard();

```

Now maybe you wonder "why this devices orientation" ? I ported tQuery to IOS. So since tQuery r49.1, it is possible to run tquery on your iphones or ipads. It is possible to render with canvas 2D in the regular browser. Even possible to render WebGL usingWebGL Browser by Ben Vanik.

The Road

In a scene, it is cool to create a goal, something for the user to do. A road seems like a perfect goal for a car :) First we create the material we gonna use. This is a lambert with a reflection. You put a cube texture in theenvMap parameter and you got your reflection :) Here again, we use tquery.skymap.js to create the cube texture.

```

var material    = new THREE.MeshLambertMaterial({
    ambient : 0x444444,
    color   : 0x666666,
    envMap  : tQuery.createCubeTexture('skybox')
});

```

Now we add the arches. In fact, they are torus which are half in the ground, so the visible part looks like an arche. We put 5 of them along the Z axis. They are all aligned to give a kindof road..castShadow(true) make the 3D object as casting shadow. Always a nice trick to enhance realism.

```

for(var i = 0; i < 5; i++){
    tQuery.createTorus(1.25-0.25, 0.25, 8, 6*4, material).addTo(world)
        .castShadow(true).translateZ( 2 + i * 5 );      
}

```

And we are DONE! We got a nice looking car, driving on grass with a sun set. It is controlled by keyboard and the camera controls is suitable for a game. Not bad for 40 lines of javascript.

Conclusion

In this post, i walked you thru a example of tQuery.car.js. It builds a rather cool scene in 40lines of js. It seems a nice base for a game. Like thetwoprevious walk through, we got very short code. I like this, it makes it easier to understand and learn. WebGL for All!! :)

That's all folks! have fun.

Three.js Sport Car on iOS at 40fps

$
0
0

This post is about iOS and three.js. It may seem surprising, but iOS supports WebGL since version 4.2. There is a tough limitation tho, it is available only in their advertisment plateform,iAds, not in safari browser. I got a ipad2 so i experimented a bit with three.js on iOS to see what is going on. Most WebGL examples fromthree.js andtQuery are working nicely on iOS.

Thescreencast below shows an ipad2 running the car demo we did last week in"Sport Car in WebGL" post. It runs at 40fps on the video. Rather good! Especially when you know the demo isn't optimized. This car is way too detailed. One could reduce the size of this model by half without loosing much. So on mobile, the Good part is that fps are good. The Bad part is that speed is slower and balanced differently. This unbalanced part worries me a bit i admit. We need to better understand the mobile plateform. But hey, 40fps is quite good, way enougth to make a game!

Experimenting with WebGL on iOS

Yesterday,daeken published aWebGL Enabler for iOS. It enables WebGL in the browser for jailbroken iOS devices. Or if you prefere a less invasive solution, not requiring to jailbreak your devices. You can useWebGL Browser made byBen Vanik , aka @benvanik on twitter. He is wellknow for WebGL Inspector.

By the way,WebGL Browser andWebGL Enabler, are both based on a similar trick. It has been discovered byNathan de Vries who told about it in thisexcelent post. A very good read to understand the underlying details! Unfortuntly this is using an unofficial API... so it is impossible to get it for the apps store unfortunatly.

WebGL Status on Mobile

WebGL is starting to be hot on mobile.blackberry playbook2 got itby default.boot on gecko got it too with firefox mobile. It isn't enabled on android and iOS tho, the 2 majors. Maybe we will have more info in june withgoogle.io andapple event. google got chrome on android. iOS already got support, this is more a matter of policy. So lets hope google will announce WebGL support for chrome mobile. and apple will announce they accepts WebGL on apps store applications. I am an optimist personn, i hope :)

Conclusion

WebGL is coming hard on mobile.three.js andtQuery already work on it. We need the 2 majors mobile OS to support it tho. It think having it on android and ios would significantly change WebGL landscape. Meanwhile you can already play with it, and do minigames with it, thus be ready when needed :)

That's all to today folks. Have fun :)

3D Physics With Three.js and Physijs

$
0
0

This is yet another post about physics. This one is aboutphysijs byChandler Prall. It easily bindammo.js andthree.js. We will walk thru an example using it. Physics is always important in 3D graphics. It makes scenes more realistic. Additionally, if you simple put your object into the scene, it will move nicely and realisticly. So you spend less time tuning each moves. I am quite lazy so it matters :) The screencast presents the demo we gonna code and various examples of what is possible withammo.js.

What About Physics Engines ?

We already did physics with three.js. It was with microphysics.js for marblesoccer minigame. It is a micro library implementing 3D physics. We talked quite a bit about it in"Lets Make a 3D Game: microphysics.js" and"Lets Make a 3D Game: microphysics.js, Even Easier". It is only 500lines! Unfortunatly, this tiny size comes limitations.

Today we gonna use physijs by Chandler Prall. This is a nice library which make it easy to useammo.js withthree.js. ammo.js is "Direct port of the Bullet physics engine to JavaScript usingEmscripten. The source code is translated directly to JavaScript, without human rewriting, so functionality should be identical to the original Bullet."

bullet is a full-blown physics engine well-known in the 3D community. It can do a lot as you can see in its docs.ammo.js supports all the features you can expect from a mature 3D physics engine. Charles J. Cliffe, aka @ccliffe, did several demos using ammo.js. This one is a heighfield And look at this stunt track! Both are on top of cubicvr, @ccliffe own library.

physijs has been written with performance in mind.ammo.js is running in awebworker. So it most likely run on a second CPU. This is twice more cpu power for your javascript! Coordinates are exchanged withtransferable objects when available. Transferable objects is a special type of object which can be transfered between the main thread and the worker without copying the data. Thus no matter how large the data are, it will be very low latency.

Lets Get Started

The code of today is a copy of thecollision example fromphysijs using it thru tQuery API. It may usefull to reimplement the same thing, just to be sure they both perform the same way. :)Try it out. So we got object falling on the ground and slightly bouncing on it. Let's do just that.

First a classic. We create a tQuery.World. So you immediatly got a scene, a renderer, camera and its controls. All that already setup according to reasonable default..boilerplate() adds the "three.js boilerplate" we did last year. We disable the camera controls as it will stay still in this scene. Then we .start() to launch the render loop.

```

var world   = tQuery.createWorld().boilerplate({cameraControls: false}).start();

```

Now we setup the camera to be a bit far from the scene center. Thus we got room to display larger objects

```

world.tCamera().position.set( 70, 40, 70 );
world.tCamera().lookAt( world.tScene().position );

```

Now we need to tell the renderer that shadow has to be casted. This is done by the simple lines below. We saw the details in "Casting Shadows" post.

```

world.tRenderer().shadowMapEnabled  = true;
world.tRenderer().shadowMapSoft     = true;
world.tRenderer().setClearColorHex( 0xffffff, 1 );

```

Now we enable the physics into the world. this is important. From now on, all the physics-enabled object of this world will move according to realistic physics rules.

```

world.enablePhysics();

```

Enlight your world

Here we setup the lights. For simplicity sake, we will use only one directional light. First we tune the position and color to fit our tastes. Dont be shy, play with those parameters to get a feel of it. Then we tune shadow parameters. Those can be tricky to tune. You can find more details in "Casting Shadow" post. It helps if you make the shaddow camera visible. You can do so with .shadowCameraVisible(true).

```

tQuery.createDirectionalLight().addTo(world)
    .position(20, 40, -15).color(0xffffff)
    .castShadow(true).shadowMap(512*2,512*2)
    .shadowCamera(60, -60, 60, -60, 20, 200)
    .shadowDarkness(0.7).shadowBias(.002)

```

Let's create a ground to stand on

First we create the texture for our ground. We use rocks.jpg to have like a rock effect. We use .RepeatWrapping to repeat the texture on the faces and get a proper scale.

```

var texture = THREE.ImageUtils.loadTexture( "images/rocks.jpg" );
texture.wrapS   = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 3, 3 );

```

In fact, the ground is only a cube which is wide and flat, a bit like the old-vision of earth :) It is usual now, we setup the position, material and shadow.

```

var ground  = tQuery.createCube(100, 1, 100).addTo(world)
    .position(0, -10, 0)
    .setLambertMaterial().map(texture).back()
    .receiveShadow(true)

```

Now we just have to setup the physics for the ground. This is done by .enablePhysics(). The mass parameter define the mass of the object in the physics. By default, it is automatically computed depending on the volume of the object. Here zeroing the mass is a special case, which say "the mass is infinite, dont move, ever" :)

```

ground.enablePhysics({
    mass    : 0
});

```

Spawning object in a 3D world

Spawning is always a delicate matter in our world. But first let's load the texture for the spawned objects. It is done outside of the loop thus it get reused. Aka it is sent only once to the GPU for all the objects. This is an important point from performance point of view. Last year,"Performance: Caching Material" post was about this very topic.

```

var cTexture    = THREE.ImageUtils.loadTexture( "images/plywood.jpg" );

```

Now we declare spawnObject() which gonna take care of spawning one object. So we create a cube, setup its position, rotation and material. This is all good. Oh dont forget to use .castShadow() as got shadow mapping going on :)

```

var spawnObject = function(){
    var object  = tQuery.createCube(4,4,4).addTo(world)
        .rotation(Math.random()*Math.PI*2, Math.random()*Math.PI*2, Math.random()*Math.PI*2)
        .position(Math.random()*15-7.5, 25, Math.random()*15-7.5)
        .setLambertMaterial().map(cTexture).back()
        .castShadow(true)

```

Here we enable the physics on this object. So the world will handle all its move from now on. It will object to physics laws according to the parameters you setup.friction is the force resisting when 2 objects slides against each other.resititution is how bouncy the object is. For scientific definition, go read a book :)

```

    object.enablePhysics({
        friction    : 0.4,
        restitution : 0.6
    });

```

Now we gonna play with the 'collision' event. Physijs is able to notify you when an object collide with another. Just use .addEventListener() on 'collision'. Here we gonna change the color of the object depending on the number of collisions they got.

```

    var nCollisions = 0;
    object.physics().addEventListener('collision', function(){
        var colliColors = [0xcc8855, 0xbb9955, 0xaaaa55, 0x99bb55, 0x88cc55, 0x77dd55];
        if( ++nCollisions < colliColors.length ){
            var color   = colliColors[nCollisions];
            object.get(0).material.color.setHex( color );
        }
    })
}

```

Now we simply use setInterval() to spawn an object every seconds.

```

setInterval(spawnObject, 1000);

```

And we are DONE! We got a realistic physics in our 3D world! not bad hey :)

Conclusion

So, thanks to physijs, it is now possible to get full blown realistic physics usingthree.js andtQuery. It is a simple way to make scene more realistic. It is nice to experiment with. I will do more on this very soon!

Thanks all folks! have fun :)

Minecraft Character in WebGL

$
0
0

This post is about Minecraft Character. We will play with the minecraft character, learn how to do your own and make it move. I recently saw this excelent minecraft items demo by @daniel_hede. It triggered a switch in my head :) I felt in love with minecraft style of 3d. It makes modeling so simple. You don't need to learn how to use 3d modeling software likeblender,maya and such. It is easy to create new model based on this style.

Try the minecraft plugin demo. This is the one we gonna build. I used @daniel_hede's code and did many plugins to make it all simple and fun :) In this demo, i introducethree.js post processing for the first time. This is theVignetting andsepia color that you see. Additionnaly, you can easily change the skins with the UI within the demo. Now let's get started!

Let's start coding

We start to create our world as usual. This initialize the renderer, the camera, its controls and a rendering loop. We setup theboilerplate for three.js and add a page title with some info on our little 3D demo. We just put the camera a little closer to scene center. Thus the character will be bigger on screen. We just can't get enougth of it, can we ;)

```

var world   = tQuery.createWorld().boilerplate().pageTitle('#info').start();
world.tCamera().position.z  = 1.8;

```

Now we add a bit of post processing. It is the first time we talk about this, so let's details it a bit. What is post processing (in a 3d context) ? Post processing is performed after rendering the 3D, hence the name. It applies on the screen as a whole. So the effects are in 2D. What's it not ? It isn't for 3d effect on specific objects in your world.

tquery.effectcomposer.js plugin provides a simple api to add postprocessing to our world. It is a chained API on top ofthree.js effect composer. In our case, we first apply .sepia() to change the colors towardsepia color. Then we apply .vignette() forVignetting and mark the effects list as finished.

```

world.addEffectComposer().sepia().vignette().finish();

```

Not too hard hey ;)

Hello Steve!

Now that we go a world. We will create a minecraft character. In fact, minecraft main character is called 'steve'.tQuery.MinecraftChar is the main class. It will create a character model and expose all its limbs too e.g right legs or right arms. More on that later. As you can see, we specify skinUrl parameter. It should point to the image of the skin texture. You can change it anytime with character.loadSkin(skinUrl)

```

var character   = new tQuery.MinecraftChar({
    skinUrl : 'images/3djesus.png'
}); 

```

Now that we got our character setup, we just need to include it in our 3D world.

```

character.model.addTo(world);

```

Make this model move

So we talked about exposed limbs... kinda gross, almost disturbing :) In fact it just means each part of our model is exposed for you to play with. It has the head, legs right and left, and the same for the arms. It is all in character.parts.

So the first step is to hook a function in the world rendering loop. two parameters are passed delta and now. delta is the number of seconds since the last iteration of the rendering loop. now is the absolute time in seconds. We use those values to tune the animation. Thus it will be animated at the same speed no matter the fps rate of your computer. Here is simple animation of the head. So we hook the function and change the headGroup rotation to fit our taste. We will make it do aneight orinfinite synbol

```

world.loop().hook(function(delta, now){
    character.parts.headGroup.rotation.x    = Math.sin(now*1.5)/3;
    character.parts.headGroup.rotation.y    = Math.sin(now)/3;
}); 

```

This is nice but the body would appear rather static if we move only the head. Let's make see how to make it walk. When people walks or run, they swing theirs arm and legs. So we need to change the rotation X of each of those limbs. First we get an angle relative to current time. It will determine the position of the arms/legs. The amplitude of the move has been tuned to 1.4, play with it and find the value you like. Then you move the legs and arms by setting the rotation. Just take care of balancing legs and arms thus his can keep his balance :)

```

world.loop().hook(function(delta, now){
    var angle   = 1/2 * now*Math.PI*2;
    // move the arms
    character.parts.armR.rotation.x = 1.4 * Math.cos(angle + Math.PI);
    character.parts.armL.rotation.x = 1.4 * Math.cos(angle);
    // move the legs
    character.parts.legR.rotation.x = 1.4 * Math.cos(angle);
    character.parts.legL.rotation.x = 1.4 * Math.cos(angle + Math.PI);
});

```

And we are done! Pretty cool no ? :)

Conclusion

So we did a little character ala minecraft. We got a basic animations of it. Nevertheless it would be neat to make animations more robusts and generic. A new post will likely focus on this. I so love this field and how it make things easier.

That's all folks. Have fun :)

Viewing all 89 articles
Browse latest View live