UNPKG

aframe-environment-component

Version:

Infinite environments for your A-Frame VR scene in just one file.

364 lines (333 loc) 8.07 kB
<!DOCTYPE html> <html lang="en"> <head> <title>LatheGeometry Editor for ThreeJS</title> <meta charset="utf-8"> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script> <style> body { font: 11px verdana, sans-serif; line-height: 1.1rem; } a { color: black; text-decoration: none; border-bottom: 1px solid black; } a:hover { color: #888; border-bottom: 1px solid #888; } p { margin: 0; } h1 { margin: 0; margin-bottom: 1rem; font-weight: normal; } b { font-weight: normal; background: #e0e0e0; padding: 0 2px; border-radius: 3px; } canvas { width: 500px; height: 500px; background: #555; cursor: default; } #c { grid-column: 2; -moz-user-select : none; -khtml-user-select : none; -webkit-user-select : none; -o-user-select : none; user-select : none; } #o { grid-column: 3; } footer { text-align: right; } .info { grid-column-start: 2; grid-column-end: 4; } #log { grid-column-start: 2; grid-column-end: 4; font-family: monospace; padding: 4px; } #all { margin-top: 30px; display: grid; grid-template-columns: auto 500px 500px auto; grid-template-rows: auto 500px auto ; grid-column-gap: 30px; grid-row-gap: 30px; } </style> </head> <body> <div id="all"> <div class="info"> <h1>Lathe editor for three.js</h1> <p> Place points on left canvas with <b>Left Click</b><br> Finish contour with <b>Double Click</b>, <b>ENTER</b> or <b>ESC</b><br> Delete / Add points by hovering on them and pressing <b>DEL</b> / <b>INS</b><br> Clear canvas with <b>c</b> key </p> </div> <canvas id="c"></canvas> <canvas id="o"></canvas> <div id="log"></div> <footer class="info"> <a href="http://github.com/feiss">GitHub</a> </footer> </div> <script> var editor = document.getElementById('c') var three = document.getElementById('o') editor.width = 500; editor.height = 500; var points = []; // list of control points var m = {x: 0, y: 0}; // mouse position var drawing = false; var editing = false; var hovering = false; var finished = false; var F = Math.floor; var c = editor.getContext('2d'); var W = editor.width; var H = editor.height; var W2 = F(W / 2); var H2 = F(H / 2); editor.addEventListener('dblclick', dblclick); editor.addEventListener('mousedown', mousedown); editor.addEventListener('mouseup', mouseup); editor.addEventListener('mousemove', mousemove); window.addEventListener('keydown', keydown); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 40, 1, 0.1, 1000 ); camera.position.z = 25; camera.position.y = -5; camera.lookAt(new THREE.Vector3(0, -5, 0)); var renderer = new THREE.WebGLRenderer({canvas: three, antialias: true}); renderer.setSize(W, H); var light = new THREE.PointLight(0xffffff, 1); light.position.set(10, 0, 30); scene.add(light); var obj = null; var material = new THREE.MeshPhongMaterial({color: 0xcccccc, side: THREE.DoubleSide}); function renderThree() { if (obj) { obj.rotation.y += 0.02; obj.rotation.x = -Math.PI + Math.sin(performance.now()/1000) * 0.5; } requestAnimationFrame( renderThree ); renderer.render(scene, camera); } renderThree(); paint(); function dblclick(evt) { if (finished) return; // remove last points.splice(points.length - 1, 1); drawing = false; m = null; finished = true; } function mousedown(evt) { if (hovering === false && !finished) { m = {x: Math.max(W2 + 0.1, evt.offsetX), y: evt.offsetY}; points.push(m) drawing = true; updateObj(); } else { editing = hovering; } paint(); } function mouseup(evt) { if (editing !== false) { updateObj(); editor.style.cursor = 'default'; } editing = false; paint(); } function mousemove(evt) { if (drawing || editing !== false) { m = {x: Math.max(W2 + 0.1, evt.offsetX), y: evt.offsetY}; if (editing !== false) { points[editing].x = m.x; points[editing].y = m.y; } } else { hovering = getControlPoint(evt.offsetX, evt.offsetY); editor.style.cursor = hovering !== false? 'pointer': 'default'; } paint(); } function keydown(evt) { if (evt.shiftKey || evt.metaKey || evt.ctrlKey || evt.altKey) return; if (evt.keyCode == 27 || evt.keyCode == 13) { // escape or enter if (!finished) { finished = true; drawing = false; m = null; paint(); } } else if (evt.keyCode == 67) { // c finished = false; drawing = false; editing = false; m = null; points = []; paint(); updateObj(); } else if (evt.keyCode == 45) { // insert var idx = 0; if (hovering !== false) { idx = hovering; } if (idx == points.length - 1) idx = Math.max(0, points.length - 2); var p = { x: (points[idx].x + points[idx + 1].x) / 2, y: (points[idx].y + points[idx + 1].y) / 2 }; points.splice(idx + 1, 0, p); paint(); updateObj(); } else if (evt.keyCode == 46) { // delete if (hovering !== false) { points.splice(hovering, 1); updateObj(); paint(); } } } function getControlPoint(x, y) { for (var i = 0; i < points.length; i++) { var dx = points[i].x - x; var dy = points[i].y - y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 20) { return i; } } return false; } function paint() { drawBG(); drawPoints(); } function drawPoints() { if (points.length == 0) return; // lines c.strokeStyle = '#f7f'; c.lineWidth = 2; c.beginPath(); c.moveTo(points[0].x, points[0].y) for (var i = 1; i < points.length; i++) { c.lineTo(points[i].x, points[i].y); } c.stroke(); // mirror c.strokeStyle = '#666'; c.lineWidth = 1; c.beginPath(); c.moveTo(W - points[0].x , points[0].y) for (var i = 1; i < points.length; i++) { c.lineTo(W - points[i].x, points[i].y); } c.stroke(); // to current mouse point if (m && drawing) { c.strokeStyle = '#bbb'; c.beginPath(); c.moveTo(points[points.length - 1].x, points[ points.length - 1].y) c.lineTo(m.x, m.y); c.stroke(); } // points c.lineWidth = 2; c.strokeStyle = '#f3a'; for (var i = 0; i < points.length; i++) { c.beginPath(); c.arc(points[i].x, points[i].y, hovering === i ? 8 : 2, 0, 2 * Math.PI, false); c.stroke(); } } function drawBG() { // background c.fillStyle = '#ddd'; c.fillRect(0, 0, W, H); // secondary axis c.lineWidth = 1; c.strokeStyle = '#ccc'; c.beginPath(); for (var i = 0; i < 10; i++) { c.moveTo(0, F(W / 10 * i)) ; c.lineTo(W, F(W / 10 * i)); c.moveTo(F(H / 10 * i), 0); c.lineTo(F(H / 10 * i), H); } c.stroke(); // primary axis c.setLineDash([]); c.strokeStyle = '#888'; c.beginPath(); c.moveTo(W2, 0); c.lineTo(W2, H); c.moveTo(0, H2); c.lineTo(W, H2); c.stroke(); } function getThreeCoords() { var coords = []; for (var i = 0; i < points.length; i ++ ) { coords.push(new THREE.Vector2( points[i].x / W - 0.5, points[i].y / H )); } return coords; } function updateObj() { var verts = getThreeCoords(); if (obj) { scene.remove(obj); } var geo = new THREE.LatheGeometry(verts); obj = new THREE.Mesh(geo, material); obj.scale.set(10,10,10); scene.add(obj); // dump ThreeJS code to <div> var log = document.getElementById('log'); var list = []; var dec3 = (v) => Math.floor(v * 1000) / 1000; // trim number to 3 decimals for (var i = 0; i < verts.length; i++) { list.push(dec3(verts[i].x), dec3(verts[i].y)); } html = 'var plist = [' + list.join(', ') + '];<br>'; html += 'var points = [];<br>'; html += 'for (var i = 0; i < plist.length; i += 2) {<br>'; html += '&nbsp;&nbsp;points.push(new THREE.Vector2(plist[i], plist[i + 1]);<br>'; html += '}<br>'; html += 'var geometry = new THREE.LatheGeometry(points);<br>var material = new THREE.MeshPhongMaterial();<br>var lathe = new THREE.Mesh(geometry, material);<br>scene.add(lathe);'; log.innerHTML = html; } </script> </body> </html>