diff --git a/examples-testing/changes.patch b/examples-testing/changes.patch index bc1f3e4a5..ca62c4b54 100644 --- a/examples-testing/changes.patch +++ b/examples-testing/changes.patch @@ -1384,6 +1384,43 @@ index 02ad9072..efb71b1d 100644 save(new Blob([text], { type: 'text/plain' }), filename); } +diff --git a/examples-testing/examples/misc_exporter_ply.ts b/examples-testing/examples/misc_exporter_ply.ts +index b6a334dd..a0e6691a 100644 +--- a/examples-testing/examples/misc_exporter_ply.ts ++++ b/examples-testing/examples/misc_exporter_ply.ts +@@ -4,7 +4,11 @@ import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; + import { PLYExporter } from 'three/addons/exporters/PLYExporter.js'; + import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + +-let scene, camera, renderer, exporter, mesh; ++let scene: THREE.Scene, ++ camera: THREE.PerspectiveCamera, ++ renderer: THREE.WebGLRenderer, ++ exporter: PLYExporter, ++ mesh: THREE.Mesh; + + const params = { + exportASCII: exportASCII, +@@ -142,16 +146,16 @@ const link = document.createElement('a'); + link.style.display = 'none'; + document.body.appendChild(link); + +-function save(blob, filename) { ++function save(blob: Blob, filename: string) { + link.href = URL.createObjectURL(blob); + link.download = filename; + link.click(); + } + +-function saveString(text, filename) { ++function saveString(text: string, filename: string) { + save(new Blob([text], { type: 'text/plain' }), filename); + } + +-function saveArrayBuffer(buffer, filename) { ++function saveArrayBuffer(buffer: BufferSource, filename: string) { + save(new Blob([buffer], { type: 'application/octet-stream' }), filename); + } diff --git a/examples-testing/examples/misc_exporter_stl.ts b/examples-testing/examples/misc_exporter_stl.ts index 673bad13..71e65414 100644 --- a/examples-testing/examples/misc_exporter_stl.ts diff --git a/examples-testing/examples/misc_exporter_ply.ts b/examples-testing/examples/misc_exporter_ply.ts new file mode 100644 index 000000000..b6a334ddc --- /dev/null +++ b/examples-testing/examples/misc_exporter_ply.ts @@ -0,0 +1,157 @@ +import * as THREE from 'three'; + +import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; +import { PLYExporter } from 'three/addons/exporters/PLYExporter.js'; +import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + +let scene, camera, renderer, exporter, mesh; + +const params = { + exportASCII: exportASCII, + exportBinaryBigEndian: exportBinaryBigEndian, + exportBinaryLittleEndian: exportBinaryLittleEndian, +}; + +init(); +animate(); + +function init() { + camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000); + camera.position.set(200, 100, 200); + + scene = new THREE.Scene(); + scene.background = new THREE.Color(0xa0a0a0); + scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000); + + exporter = new PLYExporter(); + + // + + const hemiLight = new THREE.HemisphereLight(0xffffff, 0x8d8d8d); + hemiLight.position.set(0, 200, 0); + scene.add(hemiLight); + + const directionalLight = new THREE.DirectionalLight(0xffffff); + directionalLight.position.set(0, 200, 100); + directionalLight.castShadow = true; + directionalLight.shadow.camera.top = 180; + directionalLight.shadow.camera.bottom = -100; + directionalLight.shadow.camera.left = -120; + directionalLight.shadow.camera.right = 120; + scene.add(directionalLight); + + // ground + + const ground = new THREE.Mesh( + new THREE.PlaneGeometry(2000, 2000), + new THREE.MeshPhongMaterial({ color: 0xcbcbcb, depthWrite: false }), + ); + ground.rotation.x = -Math.PI / 2; + ground.receiveShadow = true; + scene.add(ground); + + const grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000); + grid.material.opacity = 0.2; + grid.material.transparent = true; + scene.add(grid); + + // export mesh + + const geometry = new THREE.BoxGeometry(50, 50, 50); + const material = new THREE.MeshPhongMaterial({ vertexColors: true }); + + // color vertices based on vertex positions + const colors = geometry.getAttribute('position').array.slice(); + for (let i = 0, l = colors.length; i < l; i++) { + if (colors[i] > 0) colors[i] = 0.5; + else colors[i] = 0; + } + + geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3, false)); + + mesh = new THREE.Mesh(geometry, material); + mesh.castShadow = true; + mesh.position.y = 25; + scene.add(mesh); + + // + + renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setPixelRatio(window.devicePixelRatio); + renderer.setSize(window.innerWidth, window.innerHeight); + renderer.shadowMap.enabled = true; + document.body.appendChild(renderer.domElement); + + // + + const controls = new OrbitControls(camera, renderer.domElement); + controls.target.set(0, 25, 0); + controls.update(); + + // + + window.addEventListener('resize', onWindowResize); + + const gui = new GUI(); + + gui.add(params, 'exportASCII').name('Export PLY (ASCII)'); + gui.add(params, 'exportBinaryBigEndian').name('Export PLY (Binary BE)'); + gui.add(params, 'exportBinaryLittleEndian').name('Export PLY (Binary LE)'); + gui.open(); +} + +function onWindowResize() { + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize(window.innerWidth, window.innerHeight); +} + +function animate() { + requestAnimationFrame(animate); + renderer.render(scene, camera); +} + +function exportASCII() { + exporter.parse(mesh, function (result) { + saveString(result, 'box.ply'); + }); +} + +function exportBinaryBigEndian() { + exporter.parse( + mesh, + function (result) { + saveArrayBuffer(result, 'box.ply'); + }, + { binary: true }, + ); +} + +function exportBinaryLittleEndian() { + exporter.parse( + mesh, + function (result) { + saveArrayBuffer(result, 'box.ply'); + }, + { binary: true, littleEndian: true }, + ); +} + +const link = document.createElement('a'); +link.style.display = 'none'; +document.body.appendChild(link); + +function save(blob, filename) { + link.href = URL.createObjectURL(blob); + link.download = filename; + link.click(); +} + +function saveString(text, filename) { + save(new Blob([text], { type: 'text/plain' }), filename); +} + +function saveArrayBuffer(buffer, filename) { + save(new Blob([buffer], { type: 'application/octet-stream' }), filename); +} diff --git a/examples-testing/index.js b/examples-testing/index.js index 501a029ad..2eb5758dc 100644 --- a/examples-testing/index.js +++ b/examples-testing/index.js @@ -393,7 +393,7 @@ const files = { 'misc_exporter_draco', // 'misc_exporter_gltf', 'misc_exporter_obj', - // 'misc_exporter_ply', + 'misc_exporter_ply', 'misc_exporter_stl', 'misc_exporter_usdz', 'misc_lookat', diff --git a/types/three/src/core/BufferAttribute.d.ts b/types/three/src/core/BufferAttribute.d.ts index 24e9a4e51..1061dcec1 100644 --- a/types/three/src/core/BufferAttribute.d.ts +++ b/types/three/src/core/BufferAttribute.d.ts @@ -1,6 +1,17 @@ import { Usage, AttributeGPUType } from '../constants'; -import { Matrix3 } from './../math/Matrix3'; -import { Matrix4 } from './../math/Matrix4'; +import { Matrix3 } from '../math/Matrix3'; +import { Matrix4 } from '../math/Matrix4'; + +export type TypedArray = + | Int8Array + | Uint8Array + | Uint8ClampedArray + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Float32Array + | Float64Array; /** * This class stores data for an attribute (such as vertex positions, face indices, normals, colors, UVs, and any custom attributes ) @@ -34,7 +45,7 @@ export class BufferAttribute { * Default `false`. * @throws `TypeError` When the {@link array} is not a `TypedArray`; */ - constructor(array: ArrayLike, itemSize: number, normalized?: boolean); // array parameter should be `TypedArray`. + constructor(array: TypedArray, itemSize: number, normalized?: boolean); /** * Optional name for this attribute instance. @@ -46,7 +57,7 @@ export class BufferAttribute { * The {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray} holding data stored in the buffer. * @returns `TypedArray` */ - array: ArrayLike; + array: TypedArray; /** * The length of vectors that are being stored in the {@link BufferAttribute.array | array}. diff --git a/types/three/src/core/InstancedBufferAttribute.d.ts b/types/three/src/core/InstancedBufferAttribute.d.ts index a3bca9d5c..80308e08d 100644 --- a/types/three/src/core/InstancedBufferAttribute.d.ts +++ b/types/three/src/core/InstancedBufferAttribute.d.ts @@ -1,8 +1,7 @@ -import { BufferGeometry } from './BufferGeometry'; -import { BufferAttribute } from './BufferAttribute'; +import { BufferAttribute, TypedArray } from './BufferAttribute'; /** - * An instanced version of {@link THREE.InstancedBufferAttributeBufferAttribute | BufferAttribute}. + * An instanced version of {@link THREE.BufferAttribute | BufferAttribute}. * @see {@link https://threejs.org/docs/index.html#api/en/core/InstancedBufferAttribute | Official Documentation} * @see {@link https://github.com/mrdoob/three.js/blob/master/src/core/InstancedBufferAttribute.js | Source} */ @@ -14,7 +13,7 @@ export class InstancedBufferAttribute extends BufferAttribute { * @param normalized * @param meshPerAttribute */ - constructor(array: ArrayLike, itemSize: number, normalized?: boolean, meshPerAttribute?: number); + constructor(array: TypedArray, itemSize: number, normalized?: boolean, meshPerAttribute?: number); /** * Defines how often a value of this buffer attribute should be repeated. diff --git a/types/three/src/core/InstancedInterleavedBuffer.d.ts b/types/three/src/core/InstancedInterleavedBuffer.d.ts index 165ccfc20..b9660fc38 100644 --- a/types/three/src/core/InstancedInterleavedBuffer.d.ts +++ b/types/three/src/core/InstancedInterleavedBuffer.d.ts @@ -1,4 +1,5 @@ import { InterleavedBuffer } from './InterleavedBuffer'; +import { TypedArray } from './BufferAttribute'; /** * An instanced version of {@link THREE.InterleavedBuffer | InterleavedBuffer}. @@ -12,7 +13,7 @@ export class InstancedInterleavedBuffer extends InterleavedBuffer { * @param itemSize * @param meshPerAttribute */ - constructor(array: ArrayLike, stride: number, meshPerAttribute?: number); + constructor(array: TypedArray, stride: number, meshPerAttribute?: number); /** * @defaultValue `1` diff --git a/types/three/src/core/InterleavedBuffer.d.ts b/types/three/src/core/InterleavedBuffer.d.ts index 478cddc2b..f0e96397f 100644 --- a/types/three/src/core/InterleavedBuffer.d.ts +++ b/types/three/src/core/InterleavedBuffer.d.ts @@ -1,5 +1,6 @@ import { InterleavedBufferAttribute } from './InterleavedBufferAttribute'; import { Usage } from '../constants'; +import { TypedArray } from './BufferAttribute'; /** * **"Interleaved"** means that multiple attributes, possibly of different types, (e.g., _position, normal, uv, color_) are packed into a single array buffer. @@ -14,12 +15,12 @@ export class InterleavedBuffer { * @param array A {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray} with a shared buffer. Stores the geometry data. * @param stride The number of typed-array elements per vertex. Expects a `Integer` */ - constructor(array: ArrayLike, stride: number); + constructor(array: TypedArray, stride: number); /** * A {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray} with a shared buffer. Stores the geometry data. */ - array: ArrayLike; + array: TypedArray; /** * The number of {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray} elements per vertex. diff --git a/types/three/src/core/InterleavedBufferAttribute.d.ts b/types/three/src/core/InterleavedBufferAttribute.d.ts index 82be3b1d4..74095a33b 100644 --- a/types/three/src/core/InterleavedBufferAttribute.d.ts +++ b/types/three/src/core/InterleavedBufferAttribute.d.ts @@ -1,4 +1,4 @@ -import { BufferAttribute } from './BufferAttribute'; +import { BufferAttribute, TypedArray } from './BufferAttribute'; import { InterleavedBuffer } from './InterleavedBuffer'; import { Matrix4 } from './../math/Matrix4'; import { Matrix } from './../math/Matrix3'; @@ -57,7 +57,7 @@ export class InterleavedBufferAttribute { * The value of {@link InterleavedBufferAttribute.data | data}.{@link InterleavedBuffer.array | array}. * @remarks _get-only property_. */ - get array(): ArrayLike; + get array(): TypedArray; /** * Flag to indicate that the {@link data | .data} ({@link InterleavedBuffer}) attribute has changed and should be re-sent to the GPU.