mercoledì 19 marzo 2014

WebGL con ThreeJS


Sempre per un uso didattico, per visualizzare gli assi e i piani di simmetria dei minerali, stavo cercando un sistema semplice ed interattivo. Ero rimasto a VRML ma i tempi sono cambiati e la soluzione piu' semplice e' caduta su WebGL e la libreria ThreeJS


questo link c'e' una fonte inesauriibile di esempi ed idee. Io ho preso e modificato l'esempio HelloWorld per creare un cubo con indicato un asse di rotazione di ordine 4, un asse di rotazione di ordine 3 e 3 piani di simmetria.
Il modello e' navigabile (rotazione, spostamento) con il solo mouse ed e' compatibile sia con Chrome che con Firefox alle versioni piu' recenti

Il progetto completo e' scaricabile da qui

---------------------------------------------------------
<!doctype html>
<html lang="en">
<head>
<title>Solido</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link rel=stylesheet href="css/base.css"/>
</head>
<body>

<script src="js/Three.js"></script>
<script src="js/Detector.js"></script>
<script src="js/Stats.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/THREEx.KeyboardState.js"></script>
<script src="js/THREEx.FullScreen.js"></script>
<script src="js/THREEx.WindowResize.js"></script>


<!-- ------------------------------------------------------------ -->

<div id="ThreeJS" style="z-index: 1; position: absolute; left:0px; top:0px"></div>
<script>

// standard global variables
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();

var cube;

init();
animate();


function init() 
{
scene = new THREE.Scene();
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,50,40);
camera.lookAt(scene.position);


if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer(); 

renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);

// attach div element to variable to contain the renderer
container = document.getElementById( 'ThreeJS' );
// alternatively: to create the div at runtime, use:
//   container = document.createElement( 'div' );
//    document.body.appendChild( container );

// attach renderer to the container div
container.appendChild( renderer.domElement );

////////////
// EVENTS //
////////////

// automatically resize renderer
THREEx.WindowResize(renderer, camera);
THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });

//////////////
// CONTROLS //
//////////////

// move mouse and: left   click to rotate, 
//                 middle click to zoom, 
//                 right  click to pan
controls = new THREE.OrbitControls( camera, renderer.domElement );



//////////////
// GEOMETRY //
//////////////


var cubeMaterialArray = [];
// order to add materials: x+,x-,y+,y-,z+,z-
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff3333 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xff8800 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0xffff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x33ff33 } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x3333ff } ) );
cubeMaterialArray.push( new THREE.MeshBasicMaterial( { color: 0x8833ff } ) );
var cubeMaterials = new THREE.MeshFaceMaterial( cubeMaterialArray );
// Cube parameters: width (x), height (y), depth (z), 
//        (optional) segments along x, segments along y, segments along z
var cubeGeometry = new THREE.CubeGeometry( 10, 10, 10, 0, 0, 0 );
// using THREE.MeshFaceMaterial() in the constructor below
//   causes the mesh to use the materials stored in the geometry
cube = new THREE.Mesh( cubeGeometry, cubeMaterials );
cube.position.set(0, 0, 0);
scene.add( cube );

material = new THREE.LineBasicMaterial({
        color: 0x0000ff
    });

var geometry = new THREE.Geometry();
    geometry.vertices.push(new THREE.Vector3(0, 0, 10));
    geometry.vertices.push(new THREE.Vector3(0, 0, -10));
var line = new THREE.Line(geometry, material);
scene.add(line);

var plane = new THREE.Mesh(new THREE.PlaneGeometry(30, 30), new THREE.MeshNormalMaterial({ color: 0x888888, transparent: true, opacity: 0.5  }));
plane.material.side = THREE.DoubleSide;
    plane.overdraw = true;
    scene.add(plane);

    
    var plane2 = new THREE.Mesh(new THREE.PlaneGeometry(1,1,5, 5), new THREE.MeshNormalMaterial({ color: 0xff0000, transparent: true, opacity: 0.5  }));
plane2.material.side = THREE.DoubleSide;
    plane2.overdraw = true;
    scene.add(plane2);


}

function animate() 
{
    requestAnimationFrame( animate );
render();
update();
}

function update()
{
// delta = change in time since last call (in seconds)
var delta = clock.getDelta(); 

controls.update();
stats.update();
}

function render() 
{
renderer.render( scene, camera );
}

</script>

</body>
</html>