Last active
December 14, 2015 11:59
-
-
Save artzub/5083200 to your computer and use it in GitHub Desktop.
Test
This file contains hidden or 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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>three.js webgl - interactive - voxel painter</title> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | |
<style> | |
body { | |
font-family: Monospace; | |
background-color: #f0f0f0; | |
margin: 0px; | |
overflow: hidden; | |
} | |
#oldie { background-color: #ddd !important } | |
</style> | |
</head> | |
<body> | |
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r55/three.min.js"></script> | |
<script type="text/javascript" src="https://raw.github.com/mrdoob/three.js/master/examples/js/Detector.js"></script> | |
<script type="text/javascript" src="https://raw.github.com/mrdoob/three.js/master/examples/js/libs/stats.min.js"></script> | |
<script type="text/javascript" src='https://raw.github.com/mrdoob/three.js/master/examples/js/libs/dat.gui.min.js'></script> | |
<script> | |
if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); | |
var container, stats; | |
var camera, scene, renderer; | |
var projector, plane, cube; | |
var mouse2D, mouse3D, raycaster, | |
rollOveredFace, isShiftDown = false, | |
theta = 45 * 0.5, isCtrlDown = false; | |
var rollOverMesh, rollOverMaterial, voxelPosition = new THREE.Vector3(), tmpVec = new THREE.Vector3(); | |
var cubeGeo, cubeMaterial; | |
var i, intersector; | |
var gui, voxelConfig = { | |
orthographicProjection: false | |
}; | |
init(); | |
animate(); | |
function init() { | |
container = document.createElement( 'div' ); | |
document.body.appendChild( container ); | |
var info = document.createElement( 'div' ); | |
info.style.position = 'absolute'; | |
info.style.top = '10px'; | |
info.style.width = '100%'; | |
info.style.textAlign = 'center'; | |
info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js</a> - voxel painter - webgl<br><strong>click</strong>: add voxel, <strong>control + click</strong>: remove voxel, <strong>shift + click</strong>: rotate, <a href="javascript:save();return false;">save .png</a>'; | |
container.appendChild( info ); | |
camera = new THREE.CombinedCamera( window.innerWidth, window.innerHeight, 45, 1, 10000, -2000, 10000 ); | |
camera.position.y = 800; | |
scene = new THREE.Scene(); | |
// roll-over helpers | |
rollOverGeo = new THREE.CubeGeometry( 50, 50, 50 ); | |
rollOverMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000, opacity: 0.5, transparent: true } ); | |
rollOverMesh = new THREE.Mesh( rollOverGeo, rollOverMaterial ); | |
scene.add( rollOverMesh ); | |
// cubes | |
cubeGeo = new THREE.CubeGeometry( 50, 50, 50 ); | |
cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80, ambient: 0x00ff80, shading: THREE.FlatShading, map: THREE.ImageUtils.loadTexture( "textures/square-outline-textured.png" ) } ); | |
cubeMaterial.color.setHSV( 0.1, 0.7, 1.0 ); | |
cubeMaterial.ambient = cubeMaterial.color; | |
// picking | |
projector = new THREE.Projector(); | |
// grid | |
plane = new THREE.Mesh( new THREE.PlaneGeometry( 1000, 1000, 20, 20 ), new THREE.MeshBasicMaterial( { color: 0x555555, wireframe: true } ) ); | |
plane.rotation.x = - Math.PI / 2; | |
scene.add( plane ); | |
mouse2D = new THREE.Vector3( 0, 10000, 0.5 ); | |
// Lights | |
var ambientLight = new THREE.AmbientLight( 0x606060 ); | |
scene.add( ambientLight ); | |
var directionalLight = new THREE.DirectionalLight( 0xffffff ); | |
directionalLight.position.set( 1, 0.75, 0.5 ).normalize(); | |
scene.add( directionalLight ); | |
renderer = new THREE.CanvasRenderer(); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
container.appendChild( renderer.domElement ); | |
stats = new Stats(); | |
stats.domElement.style.position = 'absolute'; | |
stats.domElement.style.top = '0px'; | |
container.appendChild( stats.domElement ); | |
document.addEventListener( 'mousemove', onDocumentMouseMove, false ); | |
document.addEventListener( 'mousedown', onDocumentMouseDown, false ); | |
document.addEventListener( 'keydown', onDocumentKeyDown, false ); | |
document.addEventListener( 'keyup', onDocumentKeyUp, false ); | |
// | |
window.addEventListener( 'resize', onWindowResize, false ); | |
// add GUI | |
gui = new dat.GUI(); | |
gui.add( voxelConfig, 'orthographicProjection' ).onChange( function(){ | |
if ( voxelConfig.orthographicProjection ) { | |
camera.toOrthographic(); | |
camera.position.x = 1000; | |
camera.position.y = 707.106; | |
camera.position.z = 1000; | |
theta = 90; | |
} else { | |
camera.toPerspective(); | |
camera.position.y = 800; | |
} | |
} ); | |
gui.close(); | |
} | |
function onWindowResize() { | |
camera.setSize( window.innerWidth, window.innerHeight ); | |
camera.updateProjectionMatrix(); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
} | |
function getRealIntersector( intersects ) { | |
for( i = 0; i < intersects.length; i++ ) { | |
intersector = intersects[ i ]; | |
if ( intersector.object != rollOverMesh ) { | |
return intersector; | |
} | |
} | |
return null; | |
} | |
function setVoxelPosition( intersector ) { | |
tmpVec.copy( intersector.face.normal ); | |
tmpVec.applyMatrix4( intersector.object.matrixRotationWorld ); | |
voxelPosition.addVectors( intersector.point, tmpVec ); | |
voxelPosition.x = Math.floor( voxelPosition.x / 50 ) * 50 + 25; | |
voxelPosition.y = Math.floor( voxelPosition.y / 50 ) * 50 + 25; | |
voxelPosition.z = Math.floor( voxelPosition.z / 50 ) * 50 + 25; | |
} | |
function onDocumentMouseMove( event ) { | |
event.preventDefault(); | |
mouse2D.x = ( event.clientX / window.innerWidth ) * 2 - 1; | |
mouse2D.y = - ( event.clientY / window.innerHeight ) * 2 + 1; | |
} | |
function onDocumentMouseDown( event ) { | |
event.preventDefault(); | |
var intersects = raycaster.intersectObjects( scene.children ); | |
if ( intersects.length > 0 ) { | |
intersector = getRealIntersector( intersects ); | |
// delete cube | |
if ( isCtrlDown ) { | |
if ( intersector.object != plane ) { | |
scene.remove( intersector.object ); | |
} | |
// create cube | |
} else { | |
intersector = getRealIntersector( intersects ); | |
setVoxelPosition( intersector ); | |
var voxel = new THREE.Mesh( cubeGeo, cubeMaterial ); | |
voxel.position.copy( voxelPosition ); | |
voxel.matrixAutoUpdate = false; | |
voxel.updateMatrix(); | |
scene.add( voxel ); | |
} | |
} | |
} | |
function onDocumentKeyDown( event ) { | |
switch( event.keyCode ) { | |
case 16: isShiftDown = true; break; | |
case 17: isCtrlDown = true; break; | |
} | |
} | |
function onDocumentKeyUp( event ) { | |
switch( event.keyCode ) { | |
case 16: isShiftDown = false; break; | |
case 17: isCtrlDown = false; break; | |
} | |
} | |
function save() { | |
window.open( renderer.domElement.toDataURL('image/png'), 'mywindow' ); | |
} | |
// | |
function animate() { | |
requestAnimationFrame( animate ); | |
render(); | |
stats.update(); | |
} | |
function render() { | |
if ( isShiftDown ) { | |
theta += mouse2D.x * 1.5; | |
} | |
raycaster = projector.pickingRay( mouse2D.clone(), camera ); | |
var intersects = raycaster.intersectObjects( scene.children ); | |
if ( intersects.length > 0 ) { | |
intersector = getRealIntersector( intersects ); | |
if ( intersector ) { | |
setVoxelPosition( intersector ); | |
rollOverMesh.position = voxelPosition; | |
} | |
} | |
camera.position.x = 1400 * Math.sin( THREE.Math.degToRad( theta ) ); | |
camera.position.z = 1400 * Math.cos( THREE.Math.degToRad( theta ) ); | |
camera.lookAt( scene.position ); | |
renderer.render( scene, camera ); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment