Last active
February 5, 2018 00:02
-
-
Save duhaime/890cbdd0b95052d36450aeee0ef110db to your computer and use it in GitHub Desktop.
Hokusai (Three.js)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<style> | |
html, body { width: 100%; height: 100%; } | |
body { margin: 0; overflow: hidden; } | |
canvas { width: 100%; height: 100%; } | |
</style> | |
</head> | |
<body> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js'></script> | |
<script src='https://threejs.org/examples/js/controls/TrackballControls.js'></script> | |
<script> | |
/** | |
* Globals | |
**/ | |
var xMin = Number.POSITIVE_INFINITY, | |
xMax = Number.NEGATIVE_INFINITY, | |
yMin = Number.POSITIVE_INFINITY, | |
yMax = Number.NEGATIVE_INFINITY, | |
group = new THREE.Group(); | |
/** | |
* Ajax helper | |
**/ | |
function get(url, handleSuccess, handleErr, handleProgress) { | |
var xmlhttp = new XMLHttpRequest(); | |
xmlhttp.onreadystatechange = function() { | |
if (xmlhttp.readyState == XMLHttpRequest.DONE) { | |
if (xmlhttp.status === 200) { | |
if (handleSuccess) handleSuccess(xmlhttp.responseText) | |
} else { | |
if (handleErr) handleErr(xmlhttp) | |
} | |
}; | |
}; | |
xmlhttp.onprogress = function(e) { | |
if (handleProgress) handleProgress(e); | |
}; | |
xmlhttp.open('GET', url, true); | |
xmlhttp.send(); | |
}; | |
/** | |
* Generate a scene object with a background color | |
**/ | |
function getScene() { | |
return new THREE.Scene(); | |
} | |
/** | |
* Generate the camera to be used in the scene. Camera args: | |
* [0] field of view: identifies the portion of the scene | |
* visible at any time (in degrees) | |
* [1] aspect ratio: identifies the aspect ratio of the | |
* scene in width/height | |
* [2] near clipping plane: objects closer than the near | |
* clipping plane are culled from the scene | |
* [3] far clipping plane: objects farther than the far | |
* clipping plane are culled from the scene | |
**/ | |
function getCamera() { | |
var aspectRatio = window.innerWidth / window.innerHeight; | |
var camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 1000); | |
camera.position.set(0, 0, -170); | |
return camera; | |
} | |
/** | |
* Generate the light to be used in the scene. Light args: | |
* [0]: Hexadecimal color of the light | |
* [1]: Numeric value of the light's strength/intensity | |
* [2]: The distance from the light where the intensity is 0 | |
* @param {obj} scene: the current scene object | |
**/ | |
function getLight(scene) { | |
var light = new THREE.PointLight(0xffffff, 1, 0); | |
light.position.set(1, 1, 1); | |
scene.add(light); | |
var ambientLight = new THREE.AmbientLight(0x111111); | |
scene.add(ambientLight); | |
return light; | |
} | |
/** | |
* Generate the renderer to be used in the scene | |
**/ | |
function getRenderer() { | |
// Create the canvas with a renderer | |
var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, }); | |
// Add support for retina displays | |
renderer.setPixelRatio(window.devicePixelRatio); | |
// Specify the size of the canvas | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
// Add the canvas to the DOM | |
document.body.appendChild(renderer.domElement); | |
return renderer; | |
} | |
/** | |
* Generate the controls to be used in the scene | |
* @param {obj} camera: the three.js camera for the scene | |
* @param {obj} renderer: the three.js renderer for the scene | |
**/ | |
function getControls(camera, renderer) { | |
var controls = new THREE.TrackballControls(camera, renderer.domElement); | |
controls.zoomSpeed = 0.4; | |
controls.panSpeed = 0.4; | |
return controls; | |
} | |
/** | |
* Load svg data | |
**/ | |
function loadData() { | |
var i, j, k, l, x, y, | |
triangles = [], | |
triangle = []; | |
get('output.svg', function(data) { | |
var background = data.split('fill="')[1].split('"')[0] | |
document.body.style.backgroundColor = background; | |
data.split('<polygon ').forEach(function(i, idx) { | |
triangle = []; | |
if (idx >= 1) { | |
j = i.split('points="')[1].split(' />')[0]; | |
j.split(' ').forEach(function(k) { | |
l = k.split(','); | |
x = parseFloat(l[0]); | |
y = parseFloat(l[1]); | |
triangle.push({ | |
x: x, | |
y: y, | |
fill: i.split('fill="')[1].split('"')[0], | |
}) | |
if (x < xMin) xMin = x; | |
if (x > xMax) xMax = x; | |
if (y < yMin) yMin = y; | |
if (y > yMax) yMax = y; | |
}) | |
triangles.push(triangle); | |
} | |
}) | |
drawTriangles(triangles); | |
}) | |
} | |
function drawTriangles(triangles) { | |
var z = 0, v1, v2, v3, geom, geometry, material, mesh, | |
xOffset = (xMax + xMin) / 2, | |
yOffset = (yMax + yMin) / 2; | |
triangles.map(function(t) { | |
z -= 0.05; | |
v1 = new THREE.Vector3( t[0].x - xOffset, t[0].y - yOffset, z ); | |
v2 = new THREE.Vector3( t[1].x - xOffset, t[1].y - yOffset, z ); | |
v3 = new THREE.Vector3( t[2].x - xOffset, t[2].y - yOffset, z ); | |
geometry = new THREE.Geometry(); | |
geometry.vertices.push(v1); | |
geometry.vertices.push(v2); | |
geometry.vertices.push(v3); | |
geometry.faces.push( new THREE.Face3(0, 1, 2) ); | |
geometry.computeFaceNormals(); | |
var material = new THREE.MeshBasicMaterial({ | |
color: t[0].fill, | |
opacity: 0.5, | |
}); | |
material.transparent = true; | |
var mesh = new THREE.Mesh(geometry, material); | |
group.add(mesh); | |
}) | |
group.rotation.z = Math.PI; | |
scene.add(group); | |
} | |
/** | |
* Render! | |
**/ | |
function render() { | |
requestAnimationFrame(render); | |
renderer.render(scene, camera); | |
controls.update(); | |
}; | |
var scene = getScene(); | |
var camera = getCamera(); | |
var light = getLight(scene); | |
var renderer = getRenderer(); | |
var controls = getControls(camera, renderer); | |
loadData(); | |
render(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment