Skip to content

Commit

Permalink
Narrow BufferAttribute's array to TypedArray (#515)
Browse files Browse the repository at this point in the history
* Narrow BufferAttribute's array to TypedArray

* Add example

* Update patch
  • Loading branch information
Methuselah96 authored Jul 4, 2023
1 parent 260c4df commit 77387e1
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 14 deletions.
37 changes: 37 additions & 0 deletions examples-testing/changes.patch
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
157 changes: 157 additions & 0 deletions examples-testing/examples/misc_exporter_ply.ts
Original file line number Diff line number Diff line change
@@ -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);
}
2 changes: 1 addition & 1 deletion examples-testing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
19 changes: 15 additions & 4 deletions types/three/src/core/BufferAttribute.d.ts
Original file line number Diff line number Diff line change
@@ -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 )
Expand Down Expand Up @@ -34,7 +45,7 @@ export class BufferAttribute {
* Default `false`.
* @throws `TypeError` When the {@link array} is not a `TypedArray`;
*/
constructor(array: ArrayLike<number>, itemSize: number, normalized?: boolean); // array parameter should be `TypedArray`.
constructor(array: TypedArray, itemSize: number, normalized?: boolean);

/**
* Optional name for this attribute instance.
Expand All @@ -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<number>;
array: TypedArray;

/**
* The length of vectors that are being stored in the {@link BufferAttribute.array | array}.
Expand Down
7 changes: 3 additions & 4 deletions types/three/src/core/InstancedBufferAttribute.d.ts
Original file line number Diff line number Diff line change
@@ -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}
*/
Expand All @@ -14,7 +13,7 @@ export class InstancedBufferAttribute extends BufferAttribute {
* @param normalized
* @param meshPerAttribute
*/
constructor(array: ArrayLike<number>, 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.
Expand Down
3 changes: 2 additions & 1 deletion types/three/src/core/InstancedInterleavedBuffer.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { InterleavedBuffer } from './InterleavedBuffer';
import { TypedArray } from './BufferAttribute';

/**
* An instanced version of {@link THREE.InterleavedBuffer | InterleavedBuffer}.
Expand All @@ -12,7 +13,7 @@ export class InstancedInterleavedBuffer extends InterleavedBuffer {
* @param itemSize
* @param meshPerAttribute
*/
constructor(array: ArrayLike<number>, stride: number, meshPerAttribute?: number);
constructor(array: TypedArray, stride: number, meshPerAttribute?: number);

/**
* @defaultValue `1`
Expand Down
5 changes: 3 additions & 2 deletions types/three/src/core/InterleavedBuffer.d.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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<number>, 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<number>;
array: TypedArray;

/**
* The number of {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray | TypedArray} elements per vertex.
Expand Down
4 changes: 2 additions & 2 deletions types/three/src/core/InterleavedBufferAttribute.d.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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<number>;
get array(): TypedArray;

/**
* Flag to indicate that the {@link data | .data} ({@link InterleavedBuffer}) attribute has changed and should be re-sent to the GPU.
Expand Down

0 comments on commit 77387e1

Please sign in to comment.