A demostration of the Getting Started guide from the Three.js documentation. The wireframe around the cube is from an answer to a StackOverflow question.
Last active
June 14, 2018 22:58
-
-
Save HarryStevens/e159afb21b227ed42e250013c385115c to your computer and use it in GitHub Desktop.
Rotating Cube
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
license: gpl-3.0 |
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> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<style> | |
body { | |
margin: 0; | |
} | |
canvas { | |
width: 100%; | |
height: 100%; | |
} | |
#controls { | |
position: absolute; | |
padding: 10px; | |
color: #fff; | |
font-family: "Helvetica Neue", sans-serif; | |
background: rgba(255, 255, 255, .1); | |
} | |
#controls .input-wrapper { | |
display: inline-block; | |
text-align: center; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="controls"> | |
<div class="input-wrapper"> | |
<div>Vertical rotation</div> | |
<input id="x" type="range" value="0" min="0" max="1000"> | |
</div> | |
<div class="input-wrapper"> | |
<div>Horizontal rotation</div> | |
<input id="y" type="range" value="1000" min="0" max="1000"> | |
</div> | |
</div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script> | |
<script> | |
var scene = new THREE.Scene(); | |
// There are a few different cameras in three.js. For now, let's use a PerspectiveCamera. | |
// The first attribute is the field of view. | |
// FOV is the extent of the scene that is seen on the display at any given moment. | |
// The value is in degrees. | |
// The second one is the aspect ratio. | |
// You almost always want to use the width of the element divided by the height, | |
// or you'll get the same result as when you play old movies on a widescreen TV - | |
// the image looks squished. | |
// The next two attributes are the near and far clipping plane. | |
// What that means, is that objects further away from the camera than the value of far | |
// or closer than near won't be rendered. | |
// You don't have to worry about this now, but you may want to use other values in your apps | |
// to get better performance. | |
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
// Next up is the renderer. This is where the magic happens. | |
// In addition to the WebGLRenderer we use here, three.js comes with a few others, | |
// often used as fallbacks for users with older browsers | |
// or for those who don't have WebGL support for some reason. | |
// In addition to creating the renderer instance, | |
// we also need to set the size at which we want it to render our app. | |
// It's a good idea to use the width and height of the area we want to fill with our app - | |
// in this case, the width and height of the browser window. For performance intensive apps, | |
// you can also give setSize smaller values, like window.innerWidth/2 and window.innerHeight/2, | |
// which will make the app render at half size. | |
// If you wish to keep the size of your app but render it at a lower resolution, | |
// you can do so by calling setSize with false as updateStyle (the third argument). | |
// For example, setSize(window.innerWidth/2, window.innerHeight/2, false) will render your app | |
// at half resolution, given that your <canvas> has 100% width and height. | |
var renderer = new THREE.WebGLRenderer(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
// Last but not least, we add the renderer element to our HTML document. | |
// This is a <canvas> element the renderer uses to display the scene to us. | |
document.body.appendChild(renderer.domElement); | |
// To create a cube, we need a BoxGeometry. | |
// This is an object that contains all the points (vertices) and fill (faces) of the cube. | |
// We'll explore this more in the future. | |
var geometry = new THREE.BoxGeometry(2, 2, 2); | |
// In addition to the geometry, we need a material to color it. | |
// Three.js comes with several materials, but we'll stick to the MeshBasicMaterial for now. | |
// All materials take an object of properties which will be applied to them. | |
// To keep things very simple, we only supply a color attribute of 0x00ff00, which is green. | |
// This works the same way that colors work in CSS or Photoshop (hex colors). | |
var material = new THREE.MeshBasicMaterial({ color: "steelblue" }); | |
// The third thing we need is a Mesh. | |
// A mesh is an object that takes a geometry, and applies a material to it, | |
// which we then can insert to our scene, and move freely around. | |
var cube = new THREE.Mesh(geometry, material); | |
// By default, when we call scene.add(), the thing we add will be added to the coordinates (0,0,0). | |
// This would cause both the camera and the cube to be inside each other. | |
// To avoid this, we simply move the camera out a bit. | |
scene.add(cube); | |
camera.position.z = 5; | |
// From https://stackoverflow.com/questions/20153705/three-js-wireframe-material-all-polygons-vs-just-edges/ | |
// If you want to render a wireframe of a given geometry, you can now use this pattern: | |
// WireframeGeometry will render all edges. EdgesGeometry will render the hard edges only. | |
var geo = new THREE.EdgesGeometry(geometry); // or WireframeGeometry(geometry) | |
var mat = new THREE.LineBasicMaterial({ color: "white", linewidth: 1 }); | |
var wireframe = new THREE.LineSegments(geo, mat); | |
scene.add(wireframe); | |
// This will create a loop that causes the renderer to draw the scene 60 times per second. | |
// This will be run every frame (60 times per second), | |
// and give the cube (and wireframe) a nice rotation animation. | |
// Basically, anything you want to move or change while the app is running | |
// has to go through the animate loop. | |
// You can of course call other functions from there, | |
// so that you don't end up with a animate function that's hundreds of lines. | |
function animate() { | |
// If you're new to writing games in the browser, | |
// you might say "why don't we just create a setInterval?" | |
// The thing is - we could, but requestAnimationFrame has a number of advantages. | |
// Perhaps the most important one is that it pauses | |
// hen the user navigates to another browser tab, | |
// hence not wasting their precious processing power and battery life. | |
requestAnimationFrame(animate); | |
var x = Math.sqrt(document.getElementById("x").value) / 1000; | |
var y = Math.sqrt(document.getElementById("y").value) / 1000; | |
cube.rotation.x += x; | |
cube.rotation.y += y; | |
wireframe.rotation.x += x; | |
wireframe.rotation.y += y; | |
renderer.render(scene, camera); | |
} | |
animate(); | |
window.onmousemove = () => { | |
var mouse_x = event.clientX, | |
mouse_y = event.clientY, | |
controls_bounds = document.getElementById("controls").getBoundingClientRect(); | |
if (mouse_x > controls_bounds.width || mouse_y > controls_bounds.height){ | |
document.getElementById("x").value = mouse_y / window.innerHeight * 1000; | |
document.getElementById("y").value = mouse_x / window.innerWidth * 1000; | |
} | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment