浏览代码

Added TiltLoader

Mr.doob 4 年之前
父节点
当前提交
c59328b4ee
共有 3 个文件被更改,包括 229 次插入0 次删除
  1. 145 0
      examples/jsm/loaders/TiltLoader.js
  2. 二进制
      examples/models/tilt/BRUSH_DOME.tilt
  3. 84 0
      examples/webgl_loader_tilt.html

+ 145 - 0
examples/jsm/loaders/TiltLoader.js

@@ -0,0 +1,145 @@
+import {
+	BufferAttribute,
+	BufferGeometry,
+	Color,
+	FileLoader,
+	Group,
+	Loader,
+	Points,
+	PointsMaterial
+} from "../../../build/three.module.js";
+import { JSZip } from "../libs/jszip.module.min.js";
+
+class TiltLoader extends Loader {
+
+	load( url, onLoad, onProgress, onError ) {
+
+		const scope = this;
+
+		const loader = new FileLoader( this.manager );
+		loader.setPath( this.path );
+		loader.setResponseType( 'arraybuffer' );
+		loader.setWithCredentials( this.withCredentials );
+
+		loader.load( url, function ( buffer ) {
+
+			try {
+
+				onLoad( scope.parse( buffer ) );
+
+			} catch ( e ) {
+
+				if ( onError ) {
+
+					onError( e );
+
+				} else {
+
+					console.error( e );
+
+				}
+
+				scope.manager.itemError( url );
+
+			}
+
+		}, onProgress, onError );
+
+	}
+
+	parse( buffer ) {
+
+		const group = new Group();
+		// https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/edit#
+
+		const zip = new JSZip( buffer.slice( 16 ) ); // eslint-disable-line no-undef
+
+		/*
+		const thumbnail = zip.files[ 'thumbnail.png' ].asArrayBuffer();
+		const img = document.createElement( 'img' );
+		img.src = URL.createObjectURL( new Blob( [ thumbnail ] ) );
+		document.body.appendChild( img );
+
+		const metadata = JSON.parse( zip.files[ 'metadata.json' ].asText() );
+		*/
+
+		/*
+		const blob = new Blob( [ zip.files[ 'data.sketch' ].asArrayBuffer() ], { type: 'application/octet-stream' } );
+		window.open( URL.createObjectURL( blob ) );
+		*/
+
+		const data = new DataView( zip.files[ 'data.sketch' ].asArrayBuffer() );
+
+		const num_strokes = data.getInt32( 16, true );
+
+		let offset = 20;
+
+		for ( let i = 0; i < num_strokes; i ++ ) {
+
+			const brush_index = data.getInt32( offset, true );
+			const brush_color = [
+				data.getFloat32( offset + 4, true ),
+				data.getFloat32( offset + 8, true ),
+				data.getFloat32( offset + 12, true ),
+				data.getFloat32( offset + 16, true )
+			];
+			const brush_size = data.getFloat32( offset + 20, true );
+			const stroke_mask = data.getUint32( offset + 24, true );
+			const controlpoint_mask = data.getUint32( offset + 28, true );
+
+			let offset_stroke_mask = 0;
+			let offset_controlpoint_mask = 0;
+
+			for ( let j = 0; j < 4; j ++ ) {
+
+				const byte = 1 << j;
+				if ( ( stroke_mask & byte ) > 0 ) offset_stroke_mask += 4;
+				if ( ( controlpoint_mask & byte ) > 0 ) offset_controlpoint_mask += 4;
+
+			}
+
+			// console.log( { brush_index, brush_color, brush_size, stroke_mask, controlpoint_mask } );
+			// console.log( offset_stroke_mask, offset_controlpoint_mask );
+
+			offset = offset + 28 + offset_stroke_mask + 4; // TOFIX
+
+			const num_control_points = data.getInt32( offset, true );
+
+			// console.log( { num_control_points } );
+
+			const positions = new Float32Array( num_control_points * 3 );
+			const quaternions = new Float32Array( num_control_points * 4 );
+
+			offset = offset + 4;
+
+			for ( let j = 0, k = 0; j < positions.length; j += 3, k += 4 ) {
+
+				positions[ j + 0 ] = data.getFloat32( offset + 0, true );
+				positions[ j + 1 ] = data.getFloat32( offset + 4, true );
+				positions[ j + 2 ] = data.getFloat32( offset + 8, true );
+
+				quaternions[ k + 0 ] = data.getFloat32( offset + 12, true );
+				quaternions[ k + 1 ] = data.getFloat32( offset + 16, true );
+				quaternions[ k + 2 ] = data.getFloat32( offset + 20, true );
+				quaternions[ k + 3 ] = data.getFloat32( offset + 24, true );
+
+				offset = offset + 28 + offset_controlpoint_mask;
+
+			}
+
+			// console.log( positions, quaternions );
+
+			const geometry = new BufferGeometry();
+			geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
+			const material = new PointsMaterial( { color: new Color().fromArray( brush_color ), size: brush_size } );
+			group.add( new Points( geometry, material ) );
+
+		}
+
+		return group;
+
+	}
+
+}
+
+export { TiltLoader };

二进制
examples/models/tilt/BRUSH_DOME.tilt


+ 84 - 0
examples/webgl_loader_tilt.html

@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - tilt loader</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="main.css">
+	</head>
+	<body>
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - tilt loader
+		</div>
+
+		<script type="module">
+
+			import * as THREE from '../build/three.module.js';
+
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+			import { TiltLoader } from './jsm/loaders/TiltLoader.js';
+
+			let camera, scene, renderer;
+
+			init();
+
+			function init() {
+
+				scene = new THREE.Scene();
+
+				const light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( 0.5, 1.0, 0.5 ).normalize();
+
+				scene.add( light );
+
+				camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );
+
+				camera.position.y = 5;
+				camera.position.z = 10;
+
+				scene.add( camera );
+
+				const grid = new THREE.GridHelper( 50, 50, 0xffffff, 0x555555 );
+				scene.add( grid );
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( renderer.domElement );
+
+				const loader = new TiltLoader();
+				loader.load( './models/tilt/BRUSH_DOME.tilt', function ( object ) {
+
+					scene.add( object );
+					render();
+
+				} );
+
+				const controls = new OrbitControls( camera, renderer.domElement );
+				controls.addEventListener( 'change', render );
+				controls.update();
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				render();
+
+			}
+
+			function render() {
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>