Ver código fonte

Refactor so each project does not need to recreate basic setup;

Lee Morgan 1 ano atrás
pai
commit
5f70e6b6f4

+ 3 - 2
app.js

@@ -8,15 +8,16 @@ const views = `${__dirname}/views/`;
 app.get("/", (req, res)=>res.sendFile(`${views}/index.html`));
 
 app.get("/workbench", (req, res)=>res.sendFile(`${views}/workbench/index.html`));
-
-app.get("/workbench.js", (req, res)=>res.sendFile(`${views}/workbench/index.js`));
+app.get("/workbench.js", (req, res)=>res.sendFile(`${views}/workbench/workbench.js`));
 
 app.get("/three.js", (req, res)=>res.sendFile(`${__dirname}/threejs/three.min.js`));
 app.get("/orbit-controls.js", (req, res)=>res.sendFile(`${__dirname}/threejs/orbitControls.min.js`));
+app.get("/css-2d-renderer.js", (req, res)=>res.sendFile(`${__dirname}/threejs/CSS2DRenderer.min.js`));
 
 app.get("/image/workbench.webp", (req, res)=>res.sendFile(`${views}/image/workbench.webp`));
 
 app.get("/objects/board.js", (req, res)=>res.sendFile(`${views}/objects/board.js`));
+app.get("/objects/setup.js", (req, res)=>res.sendFile(`${views}/objects/setup.js`));
 
 if(process.env.NODE_ENV === "production"){
     module.exports = app;

+ 235 - 0
threejs/CSS2DRenderer.js

@@ -0,0 +1,235 @@
+import {
+	Matrix4,
+	Object3D,
+	Vector2,
+	Vector3
+} from 'three';
+
+class CSS2DObject extends Object3D {
+
+	constructor( element = document.createElement( 'div' ) ) {
+
+		super();
+
+		this.isCSS2DObject = true;
+
+		this.element = element;
+
+		this.element.style.position = 'absolute';
+		this.element.style.userSelect = 'none';
+
+		this.element.setAttribute( 'draggable', false );
+
+		this.center = new Vector2( 0.5, 0.5 ); // ( 0, 0 ) is the lower left; ( 1, 1 ) is the top right
+
+		this.addEventListener( 'removed', function () {
+
+			this.traverse( function ( object ) {
+
+				if ( object.element instanceof Element && object.element.parentNode !== null ) {
+
+					object.element.parentNode.removeChild( object.element );
+
+				}
+
+			} );
+
+		} );
+
+	}
+
+	copy( source, recursive ) {
+
+		super.copy( source, recursive );
+
+		this.element = source.element.cloneNode( true );
+
+		this.center = source.center;
+
+		return this;
+
+	}
+
+}
+
+//
+
+const _vector = new Vector3();
+const _viewMatrix = new Matrix4();
+const _viewProjectionMatrix = new Matrix4();
+const _a = new Vector3();
+const _b = new Vector3();
+
+class CSS2DRenderer {
+
+	constructor( parameters = {} ) {
+
+		const _this = this;
+
+		let _width, _height;
+		let _widthHalf, _heightHalf;
+
+		const cache = {
+			objects: new WeakMap()
+		};
+
+		const domElement = parameters.element !== undefined ? parameters.element : document.createElement( 'div' );
+
+		domElement.style.overflow = 'hidden';
+
+		this.domElement = domElement;
+
+		this.getSize = function () {
+
+			return {
+				width: _width,
+				height: _height
+			};
+
+		};
+
+		this.render = function ( scene, camera ) {
+
+			if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
+			if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
+
+			_viewMatrix.copy( camera.matrixWorldInverse );
+			_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
+
+			renderObject( scene, scene, camera );
+			zOrder( scene );
+
+		};
+
+		this.setSize = function ( width, height ) {
+
+			_width = width;
+			_height = height;
+
+			_widthHalf = _width / 2;
+			_heightHalf = _height / 2;
+
+			domElement.style.width = width + 'px';
+			domElement.style.height = height + 'px';
+
+		};
+
+		function hideObject( object ) {
+
+			if ( object.isCSS2DObject ) object.element.style.display = 'none';
+
+			for ( let i = 0, l = object.children.length; i < l; i ++ ) {
+
+				hideObject( object.children[ i ] );
+
+			}
+
+		}
+
+		function renderObject( object, scene, camera ) {
+
+			if ( object.visible === false ) {
+
+				hideObject( object );
+
+				return;
+
+			}
+			
+			if ( object.isCSS2DObject ) {
+
+				_vector.setFromMatrixPosition( object.matrixWorld );
+				_vector.applyMatrix4( _viewProjectionMatrix );
+
+				const visible = ( _vector.z >= - 1 && _vector.z <= 1 ) && ( object.layers.test( camera.layers ) === true );
+
+				const element = object.element;
+				element.style.display = visible === true ? '' : 'none';
+
+				if ( visible === true ) {
+
+					object.onBeforeRender( _this, scene, camera );
+
+					element.style.transform = 'translate(' + ( - 100 * object.center.x ) + '%,' + ( - 100 * object.center.y ) + '%)' + 'translate(' + ( _vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - _vector.y * _heightHalf + _heightHalf ) + 'px)';
+
+					if ( element.parentNode !== domElement ) {
+
+						domElement.appendChild( element );
+
+					}
+
+					object.onAfterRender( _this, scene, camera );
+
+				}
+
+				const objectData = {
+					distanceToCameraSquared: getDistanceToSquared( camera, object )
+				};
+
+				cache.objects.set( object, objectData );
+
+			}
+
+			for ( let i = 0, l = object.children.length; i < l; i ++ ) {
+
+				renderObject( object.children[ i ], scene, camera );
+
+			}
+
+		}
+
+		function getDistanceToSquared( object1, object2 ) {
+
+			_a.setFromMatrixPosition( object1.matrixWorld );
+			_b.setFromMatrixPosition( object2.matrixWorld );
+
+			return _a.distanceToSquared( _b );
+
+		}
+
+		function filterAndFlatten( scene ) {
+
+			const result = [];
+
+			scene.traverseVisible( function ( object ) {
+
+				if ( object.isCSS2DObject ) result.push( object );
+
+			} );
+
+			return result;
+
+		}
+
+		function zOrder( scene ) {
+
+			const sorted = filterAndFlatten( scene ).sort( function ( a, b ) {
+
+				if ( a.renderOrder !== b.renderOrder ) {
+
+					return b.renderOrder - a.renderOrder;
+
+				}
+
+				const distanceA = cache.objects.get( a ).distanceToCameraSquared;
+				const distanceB = cache.objects.get( b ).distanceToCameraSquared;
+
+				return distanceA - distanceB;
+
+			} );
+
+			const zMax = sorted.length;
+
+			for ( let i = 0, l = sorted.length; i < l; i ++ ) {
+
+				sorted[ i ].element.style.zIndex = zMax - i;
+
+			}
+
+		}
+
+	}
+
+}
+
+export { CSS2DObject, CSS2DRenderer };

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
threejs/CSS2DRenderer.min.js


+ 18 - 0
views/objects/board.js

@@ -1,4 +1,5 @@
 import * as three from "three";
+import {CSS2DObject} from "2dRenderer";
 
 export default class Board{
     constructor(scene, width, height, length){
@@ -19,6 +20,8 @@ export default class Board{
         this.board.add(board);
         this.board.add(line);
 
+        this.label = this.createLabel(board);
+
         scene.add(this.board);
     }
 
@@ -44,4 +47,19 @@ export default class Board{
     toRadians(n){
         return n*(Math.PI/180);
     }
+
+    createLabel(board){
+        const labelElem = document.createElement("div");
+        labelElem.classList.add("label");
+        labelElem.textContent = `${this.type}x${this.length} in.`;
+        labelElem.style.backgroundColor = "transparent";
+
+        const label = new CSS2DObject(labelElem);
+        label.position.set(0, 0, 0);
+        label.center.set(0, 1);
+        board.add(label);
+        label.layers.set(0);
+
+        return label;
+    }
 }

+ 56 - 0
views/objects/setup.js

@@ -0,0 +1,56 @@
+import * as three from "three";
+import {OrbitControls} from "orbitControls";
+import {CSS2DRenderer} from "2dRenderer";
+
+import Board from "board";
+
+const canvas = document.getElementById("canvas");
+const renderer = new three.WebGLRenderer({antialias: true, canvas});
+
+const camera = new three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
+camera.position.z = 100;
+camera.position.y = 1.8;
+
+const labelRenderer = new CSS2DRenderer();
+labelRenderer.setSize(window.innerWidth, window.innerHeight);
+labelRenderer.domElement.style.position = "absolute";
+labelRenderer.domElement.style.top = "0px";
+labelRenderer.domElement.style.pointerEvents = "none";
+document.body.appendChild(labelRenderer.domElement);
+
+const controls = new OrbitControls(camera, renderer.domElement);
+
+export const scene = new three.Scene();
+
+const light = new three.DirectionalLight(0xffffff, 3);
+scene.add(light);
+
+function resizeRendererToDisplaySize(renderer){
+    const canvas = renderer.domElement;
+    const width = canvas.clientWidth;
+    const height = canvas.clientHeight;
+    const needResize = canvas.width !== width || canvas.height !== height;
+    if(needResize) renderer.setSize(width, height, false);
+    return needResize;
+}
+
+function render(time){
+    if(resizeRendererToDisplaySize(renderer)){
+        const canvas = renderer.domElement;
+        camera.aspect = canvas.clientWidth / canvas.clientHeight;
+        camera.updateProjectionMatrix();
+    }
+
+    renderer.render(scene, camera);
+    labelRenderer.render(scene, camera);
+    requestAnimationFrame(render);
+}
+
+renderer.render(scene, camera);
+requestAnimationFrame(render);
+
+export function compute(data){
+    console.log(data);
+}
+
+export const Group = three.Group;

+ 9 - 1
views/workbench/index.html

@@ -6,19 +6,27 @@
     <style>
         *{margin:0;padding:0;box-sizing:border-box;}
         #canvas{height:100vh;width:100vw;display:block;}
+        .label{color: #ffffff;font-family:sans-serif;padding:2px;background:rgba(0,0,0,0.6);font-size:10px;}
+        #specs{height:250px;width:250px;position:fixed;top:0;left:0;background:rgb(200,200,200);overflow:auto;}
+        h3{text-align:center;}
     </style>
     <script type="importmap">
         {
             "imports": {
                 "three": "/three.js",
                 "orbitControls": "/orbit-controls.js",
-                "board": "/objects/board.js"
+                "2dRenderer": "/css-2d-renderer.js",
+                "board": "/objects/board.js",
+                "setup": "/objects/setup.js"
             }
         }
     </script>
 </head>
 <body>
     <canvas id="canvas"></canvas>
+    <div id="specs">
+        <h3>Specs</h3> 
+    </div>
     <script type="module" src="/workbench.js"></script>
 </body>
 </html>

+ 22 - 4
views/workbench/index.js

@@ -1,5 +1,6 @@
 import * as three from "three";
 import {OrbitControls} from "orbitControls";
+import {CSS2DRenderer} from "2dRenderer";
 
 import Board from "board";
 
@@ -7,12 +8,20 @@ const canvas = document.getElementById("canvas");
 const renderer = new three.WebGLRenderer({antialias: true, canvas});
 
 const camera = new three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
-camera.position.z = 200;
+camera.position.z = 100;
 camera.position.y = 1.8;
 
+const labelRenderer = new CSS2DRenderer();
+labelRenderer.setSize(window.innerWidth, window.innerHeight);
+labelRenderer.domElement.style.position = "absolute";
+labelRenderer.domElement.style.top = "0px";
+labelRenderer.domElement.style.pointerEvents = "none";
+document.body.appendChild(labelRenderer.domElement);
+
 const controls = new OrbitControls(camera, renderer.domElement);
 
 const scene = new three.Scene();
+export scene;
 
 const light = new three.DirectionalLight(0xffffff, 3);
 scene.add(light);
@@ -38,6 +47,7 @@ function render(time){
     }
 
     renderer.render(scene, camera);
+    labelRenderer.render(scene, camera);
     requestAnimationFrame(render);
 }
 
@@ -110,6 +120,7 @@ function computeBoards(boards){
     let boardsObj = {
         totalSurfaceArea: 0
     };
+    const boardList = document.createElement("div");
     let allItems = "";
     for(let i = 0; i < boards.length; i++){
         if(boardsObj[boards[i].type]){
@@ -122,9 +133,16 @@ function computeBoards(boards){
             }
         }
         boardsObj.totalSurfaceArea += boards[i].surfaceArea();
-        allItems += `${boards[i].type}x${boards[i].length}\n`;
+
+        const p = document.createElement("p");
+        p.textContent = `${boards[i].type}x${boards[i].length}`;
+        boardList.appendChild(p);
     }
 
-    console.log(boardsObj);
-    console.log(allItems);
+    const specs = document.getElementById("specs");
+    specs.appendChild(boardList);
+
+    const thing = document.createElement("p");
+    thing.textContent = boardsObj;
+    specs.appendChild(thing);
 }

+ 65 - 0
views/workbench/workbench.js

@@ -0,0 +1,65 @@
+import {scene, Group, compute} from "setup";
+import Board from "board";
+
+const container = new Group();
+scene.add(container);
+
+const boards = [];
+
+createLegs(boards);
+let tableTop = new Board(scene, 2, 36, 72);
+tableTop.translate(0, 18 + (tableTop.width / 2), 0);
+tableTop.rotate(0, 90, 90);
+
+//Creating edge boards with 2x4
+let borderOne = new Board(scene, 2, 4, 72);
+borderOne.translate(0, 16, 17);
+borderOne.rotate(0, 90, 0);
+let borderTwo = new Board(scene, 2, 4, 72);
+borderTwo.translate(0, 16, -17);
+borderTwo.rotate(0, 90, 0);
+let borderThree = new Board(scene, 2, 4, 32);
+borderThree.translate(35, 16, 0);
+let borderFour = new Board(scene, 2, 4, 32);
+borderFour.translate(-35, 16, 0);
+
+//Add shelf
+let shelf = new Board(scene, 1, 24, 60);
+shelf.translate(0, -3.5, 0);
+shelf.rotate(0, 90, 90);
+let shelfSupportOne = new Board(scene, 2, 4, 32);
+shelfSupportOne.translate(-29, -6, 0);
+let shelfSupportTwo = new Board(scene, 2, 4, 32);
+shelfSupportTwo.translate(29, -6, 0);
+let shelfSupportThree = new Board(scene, 2, 4, 56);
+shelfSupportThree.translate(0, -6, 11);
+shelfSupportThree.rotate(0, 90, 0);
+let shelfSupportFour = new Board(scene, 2, 4, 56);
+shelfSupportFour.translate(0, -6, -11);
+shelfSupportFour.rotate(0, 90, 0);
+
+boards.push(
+    tableTop,
+    borderOne, borderTwo, borderThree, borderFour,
+    shelf,
+    shelfSupportOne, shelfSupportTwo, shelfSupportThree, shelfSupportFour
+);
+
+function createLegs(boards){
+    let legs = [];
+    for(let i = 0; i < 4; i++){
+        let leg = new Board(scene, 4, 4, 36);
+        leg.rotate(90, 0, 0);
+        legs.push(leg);
+        boards.push(leg);
+    }
+
+    let posX = 32;
+    let posZ = 14;
+    legs[0].translate(posX, 0, posZ);
+    legs[1].translate(posX, 0, -posZ);
+    legs[2].translate(-posX, 0, posZ);
+    legs[3].translate(-posX, 0, -posZ);
+
+    return legs;
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff