Sky Lantern the Wish is a 3D Interactive Web application. Our idea comes from the traditional Chinese culture of making "Kongming lantern" where people hand-writing their wishes on a small hot air balloon that made of paper and set it up to the sky at night. In Asia and elsewhere around the world, sky lanterns have been traditionally made for centuries, to be launched for play or as part of long-established festivities. 
The Sky Lantern represents the holding of beautiful wishes; we want to inherit the beautiful culture and make it into the digital world that people can assess and making sky lanterns, wishes on the internet. 
When people go inside our application, they will see an ocean and a sky full of lanterns. After clicking the "make a wish" button, users can type their wishes that will show on the "lantern", then they can release it up to the "sky" and restore it on the "sky". By moving the mouse and pressing the up, down, left, right keys, the user will be able to change their views and "fly" into the "sky", to see other's wishes as well.

Our user flow is: 
1. open the website and see the opening lines
2. click the make a wish button and type some wishes to the lantern
3. press the return(enter) key for releasing the lantern to the lanterns sky
4. move the mouse and press the up, down, left, right keys to change the view and "fly" to the sky to see other's wishes
5. make another wish   - then back to 2,3,4 flow

Here will be the full experience for having and releasing a wish lantern to the sky.​​​​​​​
Coding Stages
1 stage
building the environmen
we chose using the THREE.JS  for building 3D environment, so we tried planeGeometry for making an "ocean".
var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);
    var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
        color: meshColor,
        transparent: true ,
    }));


for making the still ocean wave, we are updating the numbers in the vertical function 
for (var i = 0; i < planeGeo.vertices.length; i++) {
                    var z = +planeGeo.vertices[i].z;
                    planeGeo.vertices[i].z = Math.sin(( i + count * 0.00002)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ* 0.6))
                    plane.geometry.verticesNeedUpdate = true;
                    count += 0.1
                }
also the background 
        background = "#002134",

Stage 2
building the lanterns
we are using load MTL and load OBJ files for adding 3D lanterns on the environment
function loadModelSky(){
    var onProgress = function ( xhr ) {
        if ( xhr.lengthComputable ) {
            var percentComplete = xhr.loaded / xhr.total * 100;
        }
    };
    var onError = function () { };
    new THREE.MTLLoader()
        .load( 'assets/lowpolygroup.mtl', function ( materials ) {
            materials.preload();
            new THREE.OBJLoader()
                .setMaterials( materials )
                .load( 'assets/lowpolygroup.obj', function ( object ) {
                    object.position.set(120000,60000,10000);
                    object.scale.set(50,50,50);
                    scene.add( object );
                }, onProgress, onError );
        } );
}

for the texture is a really hard one to code...
we want to not only make it a .jpg texture, but also make it can be applied text onto the texture...
function generateTexture(){
    wishCanvas.width = 4096;
    wishCanvas.height = 4096;
    wishContext.fillStyle = 'black';
    wishContext.font = "96px Amatic";
    wishContext.drawImage(baseTex,0,0);
    texture = new THREE.CanvasTexture(wishCanvas);
    texture.needsUpdate = true;
    wrapText(wishContext,inputText,2330,2050,maxWidth,lineHeight);
}
function wrapText(wishContext, text, x, y, maxWidth, lineHeight) {
    var words = text.split(' ');
    var line = '';
    for(var n = 0; n < words.length; n++) {
      var testLine = line + words[n] + ' ';
      var metrics = wishContext.measureText(testLine);
      var testWidth = metrics.width;
      if (testWidth > maxWidth && n > 0) {
        wishContext.fillText(line, x, y);
        line = words[n] + ' ';
        y += lineHeight;
      }
      else {
        line = testLine;
      }
    }
    wishContext.fillText(line, x, y);
  }

and put it into the animate() function, which is updating the text that the input of users.

Stage 3
set up controllers
We are using the perspective camera with THREE.JS, and setting up a FirstPersonControl controller for moving and changing the view perspective and positions.
We made changes in the FirstPersonControls library because it cannot be used as we want.
var controls = new THREE.FirstPersonControls( camera );
and a resetCamera function for resetting views when enter another wish. 
function resetCamera(){
      camera.position.x = -1633;
        camera.position.z = 17000;
        camera.position.y = 23300;
    //  camera.lookAt(-1533,23000,17000);
    //    controls.object.position =  new THREE.Vector3 (-1633,17000,23300);
      controls.target.x = 7000;
            controls.target.y = 23000;
            controls.target.z = 17000;
            controls.object.position.x = -1633;
            controls.object.position.y = 23300;
            controls.object.position.z = 17000;
                controls.lat = 0;
                controls.lon = 0;
                controls.phi = 0;
                controls.theta = 0;
            resetCameraTrue = true;
}
Stage 4 
adding css, html and js (with tween.js) animations.
something like that examples:
    //tween kongmingdeng fly animation
        var tween;
        function initTween() {
                var randomX = Math.floor((Math.random() * 700) + 60000);
                var randomY = Math.floor((Math.random() * 10000) + 70000);
                var randomZ = Math.floor((Math.random() * (-20000)) + 40000);
                tween = new TWEEN.Tween(objsize)
                .to( { x: randomX,y:randomY,z:randomZ}, 17000 );
                tween.start();
                tween.easing(TWEEN.Easing.Sinusoidal.InOut);
        }
    <div class="bottom" id="bottom-button">
            <div id="button-start" onclick="makeWish()" class="hvr-underline-from-left">
                <h2> Make A Wish</h2>
            </div>
.blkCanvas{
    display: none;
    width:100%;
    height:100%;
    position: absolute;
    transition: opacity 1s ease-in;
    z-index: 40;
    opacity: 1;
}



Stage 5
collecting and re-editing the functions and orders of the code. important and a lot of debugging....
 
And WE MADE IT!!!!!! (include 2 night of not sleeping at all...)


Questions:
Is that clear to make a wish?
How do you want to fly in the sky?
Does it matter to see others' wishes?
Is that comfortable for typing the wishes?



For the future:
1.Set up a server and restore the text(wishes) that the input of users, also load those inputs for automatically adding textures on the lantern.
2. We want to make it a Web VR movie, this will be our first scene (hopefully).
concept:
years and years, we make wishes
years and years after, where our wishes go?
scenes after scenes, we will see the unknow "AI" are transfering our wishes to something and some worlds...

3.also re-editing the style of visuals.


Back to Top