Client: BEGOC
Agency: UBGM (URBIS)
Developer: POSSIBLE
Producer: Charles-Henry Contamine
Creative Director: Steven Delcourt
Project Leads: Nazim Aliyev and Kanan Gafarov
What?
"The 2015 European Games, also known as Baku 2015 or Baku 2015 European Games"
Provide a platform for the flame country-wide tour throughout Azerbaijan visiting 59 cities.
Running for a month, leaving a flame in each city it visits.
How?
Sitecore
UID skeleton (BUD Possible)
1 account
1 GFX
1 BE lead, 3 BE
1 UID lead, 3 UID
(BE/UID/GFX HEADOF)
How?
Wireframes, webpage designs - Invision
JIRA
Scrum (Weekly Sprints + Daily standups)
GIT - JIRA based tickets
integration branch - testing
master - final branches
master -> deploy
Tools?
Threejs
TweenMax
Handlebars
Middleman
Grunt
SCSS,
etc..
Before design
Code site / Make 3D terrain without design / 3d rendered scenes
-> create/setup UID skeleton
-> create dummy html / css styles
-> social logins (fb, instagram)
-> prototyping 3d terrain / globe
-> shot screens from prototype to designs
3x
Desktop/Tablet
Full 3d experience
Fallback with google maps. (funnystory.)
Mobile
google maps
User agent detection - BE side
Basic threejs setup
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({antialias: true, clearColor: 0x000000});
renderer.setSize( window.innerWidth, window.innerHeight );
camera = new THREE.PerspectiveCamera(90, 640 / 480, 1, 10000);
document.body.appendChild( renderer.domElement );
//add Lights!
initLights();
//add 3d objects.
init3DThings();
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
Terrain
Terrain datasource
get elevation data by brightness
Terrain image
Terrain size
Elevation data
function calculateElevationArray(data) {
...
pixels = ctx.getImageData(0, 0, imgW, imgH).data;
for (var x = 0; x < imgW; x++) {
for (var y = 0; y < imgH; y++) {
r = pixels[index];
g = pixels[index + 1];
b = pixels[index + 2];
a = pixels[index + 3];
index = (x * 4) + y * (4 * imgW);
sum = r + g + b;
if (sum > 43) {
elevationArray[x].push({
x: x - imgW / 2,
y: y - imgH / 2,
scale: sum,
active: true
});
} else {
... active: false
}
}
...
}
Terrain
Terrain wireframe
Terrain (lines)
Terrain (lines2)
Terrain (lines2)
Terrain (particles)
Terrain (particles)
Terrain ~ final
Border
get border data from svg path
Border
var path = this, //svg path
length = path.getTotalLength(),
p = path.getPointAtLength(0),
diff = length / res,
size = 1.66;
for (var i = 1; i < res; i++) {
p = path.getPointAtLength(i * diff);
vertex.push(new THREE.Vector3(p.x * size, 0, p.y * size));
}
Border
closedSpline = new THREE.ClosedSplineCurve3(vertex);
extrudeSettings = {
extrudePath: closedSpline
};
shape = new THREE.Shape(pts);
geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
Border
Bonus, real 3d
Bonus, real 3d, oculus
Bonus, real 3d, oculus
Optimization
Render only if necessary!
function setRenderTimeout(timeout, callFrom) {
needRender = true;
clearTimeout(renderTimer);
if (timeout > 0) {
renderTimer = setTimeout(function () {
needRender = false;
}, timeout);
}
}
function render() {
if (needRender) {
renderer.render(scene, camera);
}
requestAnimationFrame(render);
}
Optimization
Don't use/call on every frame!!!
mesh.geometry.verticesNeedUpdate = true
mesh.computeFaceNormals()
mesh.material.needsUpdate = true
Optimization
Use shaders:)
//FIRE
var vShader = $('#vertexshader2'),
fShader = $('#fragmentshader2');
uniforms = {
iGlobalTime: {type: 'f', value: 0.1}
};
shaderMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vShader.text(),
fragmentShader: fShader.text()
});
mesh = new THREE.Mesh(new THREE.PlaneGeometry(50, 150, 1, 1), shaderMaterial);
scene.add(mesh);
Best comment
Thank you!
jozsef.szabadszallasi@possible.com
baku2015flame
By Szabadszállási József
baku2015flame
- 1,090