Solution
3D-Visualization and gaming has come a long way since just two decades ago, when
implementations required a lot of overwork, including third-party plug-ins, and in some cases also
required capturing of motion graphics for commercial 3D gaming,
The results we found had always been awe-inspiring, but they often incurred huge costs and
required countless hours of work behind the scenes. However, the options that is and Babylon.js -
that use WebGl to provide cross- browser solutions for 3D visualization and gaming.
WHAT IS WEBGL?
WebGl is a JavaScript-based API that provides a medium to render interactive 3D and 2D graphics
on any compatible web browser. The advantage here lies in the fact that there is no dependency on
plug-ins. webgl does this with the help of control logic implemented with JavaScript and shader
logic that is executed on a Graphics Processing Unit (GPU), Code implementations for 30 graphics
can be written directly in WebGL but it comes with some caveats, like a very high learning curve
and the absence of graceful fall back in case of incompatibility. This is where two of the most
flexible open source libraries, Three,js and Babylon.js, come to the rescue,
WHAT ARE THREE.JS AND BABYLON.JS?
These are JavaScript-based frameworks that handle the complexities of webGL with ease and
provide a user-friendly way of implementing 3D graphics. While Three.js was designed as a tool
for general purpose web animations, babylon.js was designed to take a more targeted approach for
web-based game development and uses an extensive physics engine for collision detection and
other intricacies involved for 3D graphics
As a brief introduction. Let us take a look at the interiors of Three,js, For any 3D visualization, we
would require the following objects
• Camera
• Scene-represents a list of objects that is displayed on- screen, like 3D models and lights.
• Geometry-the shape of objects, like cube, sphere, cylinder
• Material-color, image, or texture that defines how a geometrical shape would he displayed.
• Mesh-composed of the geometry and material
To begin, we would implement an animated cube. The declaration of objects that we would need
comes first:
var camera, scene, renderer;
var geometry, material, mesh;
We require two functions–init( ) and animate( ).
The init() function creates and sets the position of the camera, creates a cubic geometrical shape,
defines the material of the mesh that the shape would be composed of, adds the shape and the mesh
onto the scene, and renders the entire scene on a canvas element.
The code for the entire init() function is listed below;
var init = function() {
Camera = new Three.PerspectiveCamera(75, window.innerwidth / window, innerHeight, 1,
10000);
Camera.position.2 = 500;
Scene = new THREE.Scene();
//geometry = new THREE.IcosahedronGeometry( 200, 1 );
Geometry = new THREE.CubeGeometry(210, 210, 210, 1, 1, 1);
Material = new THREE.MeshnormalMaterial ({
Wireframe: false,
WireframeLinewidth: 1
)};
Mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.CanvasRenderer();
renderer.setsize(window.innerwidth, window.innerHeight);
document.body.appendChild(renderer, docelement);
}
There are multiple types of camera classes provided by Three.js, out of which
THREE.PerspectivCamera is used for a perspective view of the scene. The scene can be added
with a mesh (where mesh is composed of a geometrical shape and the color, or texture, or image
that defines how the shape would look), which is implemented by using the
THREE.meshBasicMaterial class. Again, Three.js provides a vast collection of classes of material
that can be applied to different geometrical shapes.
The most important aspect is the rendering of the objects that makes WebGL with Three.js or
Babylon.js easy to work with. Three.js provides a class THREE.CanvasRenderer that renders the
objects automatically on the HTML5 canvas element. This provides a very graceful fallback in
case WebGL (which is dependent on the compatibility of the latest browsers) is not compatible
with the browser being used at client end.
The animate () function makes use of the requestAnimationFrame() function to perform a call back
of the animate() function itself, which updates the animation before the next repaint takes place in
the browser. For this example, the rotation vector is updated for the mesh in the scene in any
subsequent repaints. The code for the animate() function is listed below:
var animate = function () {
requestAnimationFrame(animate);
mesh.rotation.x = Date. (now). = 0.00005;
mesh.rotation.y = Date. (now). = 0.001;
renderer.render(scent, camera);
}
init(); animate();
Code
// Get the canvas element from our HTML above
var canvas = document.getElementById(“mesh_id”);
// Load the BABYLON 3D engine
var engine = new BABYLON.Engine(canvas);
// Now create a basic Babylon Scene object
var scene = new BABYLON.Scene(engine);
var gravityVector = new BABYLON.Vector3(0,-9.81, 0);
var physicsPlugin = new BABYLON.CannonJSPlugin();
scene.enablePhysics();
scene.enablePhysics(gravityVector, physicsPlugin);
scene.setGravity(new BABYLON.Vector3(0, -9.81, 0));
scene.clearColor = new BABYLON.Color3(0.8, 0.8, 0.8);
var light = new BABYLON.HemisphericLight(“hemi”, new BABYLON.Vector3(0, 1, 0), scene);
light.groundColor = new BABYLON.Color3(0.2, 0.2, 0.5);
light.intensity = 0.6;
var light2 = new BABYLON.PointLight(“light2”, new BABYLON.Vector3(-20, 0, -20), scene);
light2.diffuse = BABYLON.Color3.White();
light2.specular = BABYLON.Color3.Black();
light2.intensity = 0.6;
var camera = new BABYLON.ArcRotateCamera(“Camera”, 3 * Math.PI / 2, Math.PI / 2, 50,
BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
camera.setPosition(new BABYLON.Vector3(0, 15, 150));
camera.checkCollisions = true;
camera.applyGravity = true;
var subdivisions = 96;
var groundWidth = 0;
var garment = new BABYLON.Mesh(“mesh”, scene);
var myMaterial = new BABYLON.StandardMaterial(“myMaterial”, scene);
// garment.setPhysicsState({ impostor: BABYLON.PhysicsEngine.BoxImpostor, mass: 1,
friction: 0.5, restitution: 0.7 });
garment.checkCollisions = true;
myMaterial.diffuseTexture = new BABYLON.Texture(“textures/flowers.jpg”, scene);
myMaterial.specularTexture = new BABYLON.Texture(“textures/flowers.jpg”, scene);
myMaterial.emissiveTexture = new BABYLON.Texture(“textures/flowers.jpg”, scene);
myMaterial.ambientTexture = new BABYLON.Texture(“textures/flowers.jpg”, scene);
myMaterial.backFaceCulling = true;
garment.position.y = 60;
garment.material = myMaterial;
myMaterial.wireframe = true;
// Garment(T-Shirt)
coordinates_list = [-5.000000,0.000000,5.000000,-2.500000,0.000000,…..]
var indices = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,……]
var uvs = [0.000000,0.000000,0.250000,0.000000,0.250000,0.250000,…..]
var normals = [];
var vertexData = new BABYLON.VertexData();
BABYLON.VertexData.ComputeNormals(coordinates_list, indices, normals);
vertexData.positions = coordinates_list;
vertexData.indices = indices;
vertexData.normals = normals;
vertexData.uvs = uvs;
vertexData.applyToMesh(garment);
garment.physicsImpostor = new BABYLON.PhysicsImpostor(garment,
BABYLON.PhysicsImpostor.MeshImpostor, { mass: 1, restitution: 0.9 }, scene);
var position_vertices_data = garment.getVerticesData(BABYLON.VertexBuffer.PositionKind);
var spheres = [];
for (var i = 0; i = subdivisions) {
createJoint(point.physicsImpostor, spheres[idx – subdivisions].physicsImpostor);
if (idx % subdivisions) {
createJoint(point.physicsImpostor, spheres[idx – 1].physicsImpostor);
}
}
});
garment.registerBeforeRender(function () {
var positions = [];
spheres.forEach(function (s) {
positions.push(s.position.x, s.position.y, s.position.z);
});
garment.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions);
garment.refreshBoundingInfo();
});
// BASE MODEL STARTS
var basemodel = new BABYLON.Mesh(“basemodel”, scene);
var basemodelmaterial = new BABYLON.StandardMaterial(“basemodelmaterial”, scene);
basemodel.setPhysicsState({ impostor: BABYLON.PhysicsEngine.SphereImpostor, mass:
0,friction: 0.9 }, scene, true);
basemodel.checkCollisions = false;
basemodelmaterial.backFaceCulling = false;
basemodel.material = basemodelmaterial;
var coordinates_list = [-4.679900,39.907700,1.244800,-4.377600,40.614700,1.138200,…….]
var indices = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,………]
var normals = [];
var vertexData = new BABYLON.VertexData();
BABYLON.VertexData.ComputeNormals(coordinates_list, indices, normals);
vertexData.positions = coordinates_list;
vertexData.indices = indices;
vertexData.normals = normals;
vertexData.applyToMesh(basemodel);
basemodel.physicsImpostor = new BABYLON.PhysicsImpostor(basemodel,
BABYLON.PhysicsImpostor.MeshImpostor, { mass: 0 }, scene,true);
// BASE MODEL ENDS
// Collision
scene.collisionsEnabled = true;
scene.applyGravity = true;
ground.checkCollisions = true;
spheres.checkCollisions = true;
// Register a render loop to repeatedly render the scene
engine.runRenderLoop(function () {
scene.render();
});
// Watch for browser/canvas resize events
window.addEventListener(“resize”, function () {
engine.resize();
});
Animation Results
References
https://www.3pillarglobal.com/