diff --git a/types/three/OTHER_FILES.txt b/types/three/OTHER_FILES.txt index eed338234..1e6bb7de9 100644 --- a/types/three/OTHER_FILES.txt +++ b/types/three/OTHER_FILES.txt @@ -36,7 +36,6 @@ examples/jsm/helpers/VertexNormalsHelper.d.ts examples/jsm/helpers/VertexTangentsHelper.d.ts examples/jsm/interactive/HTMLMesh.d.ts examples/jsm/interactive/InteractiveGroup.d.ts -examples/jsm/libs/stats.module.d.ts examples/jsm/lights/LightProbeGenerator.d.ts examples/jsm/lines/Wireframe.d.ts examples/jsm/lines/WireframeGeometry2.d.ts @@ -170,6 +169,7 @@ examples/jsm/shaders/VerticalTiltShiftShader.d.ts examples/jsm/shaders/VignetteShader.d.ts examples/jsm/shaders/VolumeShader.d.ts examples/jsm/shaders/WaterRefractionShader.d.ts +examples/jsm/utils/BufferGeometryUtils.d.ts examples/jsm/utils/GeometryCompressionUtils.d.ts examples/jsm/utils/PackedPhongMaterial.d.ts examples/jsm/utils/SceneUtils.d.ts diff --git a/types/three/src/constants.d.ts b/types/three/src/constants.d.ts index a8d0d3362..4977a8870 100644 --- a/types/three/src/constants.d.ts +++ b/types/three/src/constants.d.ts @@ -901,26 +901,3 @@ export type PixelFormatGPU = | 'DEPTH_COMPONENT32F' | 'DEPTH24_STENCIL8' | 'DEPTH32F_STENCIL8'; - -/////////////////////////////////////////////////////////////////////////////// - -export type BuiltinShaderAttributeName = - | 'position' - | 'normal' - | 'uv' - | 'color' - | 'skinIndex' - | 'skinWeight' - | 'instanceMatrix' - | 'morphTarget0' - | 'morphTarget1' - | 'morphTarget2' - | 'morphTarget3' - | 'morphTarget4' - | 'morphTarget5' - | 'morphTarget6' - | 'morphTarget7' - | 'morphNormal0' - | 'morphNormal1' - | 'morphNormal2' - | 'morphNormal3'; diff --git a/types/three/src/core/BufferGeometry.d.ts b/types/three/src/core/BufferGeometry.d.ts index 5d61bb588..426739b18 100644 --- a/types/three/src/core/BufferGeometry.d.ts +++ b/types/three/src/core/BufferGeometry.d.ts @@ -1,15 +1,19 @@ import { BufferAttribute } from './BufferAttribute'; import { InterleavedBufferAttribute } from './InterleavedBufferAttribute'; -import { GLBufferAttribute } from './GLBufferAttribute'; -import { Box3 } from './../math/Box3'; -import { Sphere } from './../math/Sphere'; -import { Matrix4 } from './../math/Matrix4'; -import { Quaternion } from './../math/Quaternion'; -import { Vector2 } from './../math/Vector2'; -import { Vector3 } from './../math/Vector3'; +import { Box3 } from '../math/Box3'; +import { Sphere } from '../math/Sphere'; +import { Matrix4 } from '../math/Matrix4'; +import { Quaternion } from '../math/Quaternion'; +import { Vector2 } from '../math/Vector2'; +import { Vector3 } from '../math/Vector3'; import { EventDispatcher } from './EventDispatcher'; -import { BuiltinShaderAttributeName } from '../constants'; -import * as BufferGeometryUtils from '../../examples/jsm/utils/BufferGeometryUtils'; +import { GLBufferAttribute } from './GLBufferAttribute'; + +export type NormalBufferAttributes = Record; +export type NormalOrGLBufferAttributes = Record< + string, + BufferAttribute | InterleavedBufferAttribute | GLBufferAttribute +>; /** * A representation of mesh, line, or point geometry @@ -43,7 +47,9 @@ import * as BufferGeometryUtils from '../../examples/jsm/utils/BufferGeometryUti * @see {@link https://threejs.org/docs/index.html#api/en/core/BufferGeometry | Official Documentation} * @see {@link https://github.com/mrdoob/three.js/blob/master/src/core/BufferGeometry.js | Source} */ -export class BufferGeometry extends EventDispatcher { +export class BufferGeometry< + Attributes extends NormalOrGLBufferAttributes = NormalBufferAttributes, +> extends EventDispatcher { /** * This creates a new {@link THREE.BufferGeometry | BufferGeometry} object. */ @@ -87,9 +93,7 @@ export class BufferGeometry extends EventDispatcher { * use {@link setAttribute | .setAttribute} and {@link getAttribute | .getAttribute} to access attributes of this geometry. * @defaultValue `{}` */ - attributes: { - [name: string]: BufferAttribute | InterleavedBufferAttribute | GLBufferAttribute; // TODO Replace for 'Record<>' - }; + attributes: Attributes; /** * Hashmap of {@link THREE.BufferAttribute | BufferAttributes} holding details of the geometry's morph targets. @@ -185,30 +189,25 @@ export class BufferGeometry extends EventDispatcher { * @param name * @param attribute */ - setAttribute( - name: BuiltinShaderAttributeName | (string & {}), - attribute: BufferAttribute | InterleavedBufferAttribute | GLBufferAttribute, - ): this; + setAttribute(name: K, attribute: Attributes[K]): this; /** * Returns the {@link attributes | attribute} with the specified name. * @param name */ - getAttribute( - name: BuiltinShaderAttributeName | (string & {}), - ): BufferAttribute | InterleavedBufferAttribute | GLBufferAttribute; + getAttribute(name: K): Attributes[K]; /** * Deletes the {@link attributes | attribute} with the specified name. * @param name */ - deleteAttribute(name: BuiltinShaderAttributeName | (string & {})): BufferGeometry; + deleteAttribute(name: keyof Attributes): this; /** * Returns true if the {@link attributes | attribute} with the specified name exists. * @param name */ - hasAttribute(name: BuiltinShaderAttributeName | (string & {})): boolean; + hasAttribute(name: keyof Attributes): boolean; /** * Adds a group to this geometry diff --git a/types/three/src/objects/Points.d.ts b/types/three/src/objects/Points.d.ts index a3aff8dc9..3abdb51ad 100644 --- a/types/three/src/objects/Points.d.ts +++ b/types/three/src/objects/Points.d.ts @@ -1,8 +1,9 @@ -import { Material } from './../materials/Material'; -import { Raycaster } from './../core/Raycaster'; -import { Object3D } from './../core/Object3D'; -import { BufferGeometry } from '../core/BufferGeometry'; -import { Intersection } from '../core/Raycaster'; +import { Material } from '../materials/Material'; +import { Object3D } from '../core/Object3D'; +import { BufferGeometry, NormalOrGLBufferAttributes } from '../core/BufferGeometry'; +import { BufferAttribute } from '../core/BufferAttribute'; +import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute'; +import { GLBufferAttribute } from '../core/GLBufferAttribute'; /** * A class for displaying {@link Points} @@ -12,7 +13,7 @@ import { Intersection } from '../core/Raycaster'; * @see {@link https://github.com/mrdoob/three.js/blob/master/src/objects/Points.js | Source} */ export class Points< - TGeometry extends BufferGeometry = BufferGeometry, + TGeometry extends BufferGeometry = BufferGeometry, TMaterial extends Material | Material[] = Material | Material[], > extends Object3D { /** diff --git a/types/three/test/integration/three-examples/misc_controls_pointerlock.ts b/types/three/test/integration/three-examples/misc_controls_pointerlock.ts index f14f41c45..f72b3c3c3 100644 --- a/types/three/test/integration/three-examples/misc_controls_pointerlock.ts +++ b/types/three/test/integration/three-examples/misc_controls_pointerlock.ts @@ -126,16 +126,14 @@ function init() { let position = floorGeometry.attributes.position; - if (!(position instanceof THREE.GLBufferAttribute)) { - for (let i = 0, l = position.count; i < l; i++) { - vertex.fromBufferAttribute(position, i); + for (let i = 0, l = position.count; i < l; i++) { + vertex.fromBufferAttribute(position, i); - vertex.x += Math.random() * 20 - 10; - vertex.y += Math.random() * 2; - vertex.z += Math.random() * 20 - 10; + vertex.x += Math.random() * 20 - 10; + vertex.y += Math.random() * 2; + vertex.z += Math.random() * 20 - 10; - position.setXYZ(i, vertex.x, vertex.y, vertex.z); - } + position.setXYZ(i, vertex.x, vertex.y, vertex.z); } const indexedGeometry = floorGeometry.toNonIndexed(); // ensure each face has unique vertices diff --git a/types/three/test/integration/three-examples/webgl_buffergeometry_glbufferattribute.ts b/types/three/test/integration/three-examples/webgl_buffergeometry_glbufferattribute.ts new file mode 100644 index 000000000..29addcf8a --- /dev/null +++ b/types/three/test/integration/three-examples/webgl_buffergeometry_glbufferattribute.ts @@ -0,0 +1,148 @@ +import * as THREE from 'three'; + +import * as Stats from 'three/examples/jsm/libs/stats.module.js'; + +let container: HTMLElement; +let stats: Stats; + +let camera: THREE.PerspectiveCamera; +let scene: THREE.Scene; +let renderer: THREE.WebGLRenderer; + +let points: THREE.Points>; + +const particles = 300000; +let drawCount = 10000; + +init(); +animate(); + +function init() { + container = document.getElementById('container')!; + + // + + renderer = new THREE.WebGLRenderer({ antialias: false }); + renderer.setPixelRatio(window.devicePixelRatio); + renderer.setSize(window.innerWidth, window.innerHeight); + + container.appendChild(renderer.domElement); + + // + + camera = new THREE.PerspectiveCamera(27, window.innerWidth / window.innerHeight, 5, 3500); + camera.position.z = 2750; + + scene = new THREE.Scene(); + scene.background = new THREE.Color(0x050505); + scene.fog = new THREE.Fog(0x050505, 2000, 3500); + + // + + const geometry = new THREE.BufferGeometry(); + + const positions = []; + const positions2 = []; + const colors = []; + + const color = new THREE.Color(); + + const n = 1000; + const n2 = n / 2; // particles spread in the cube + + for (let i = 0; i < particles; i++) { + // positions + + const x = Math.random() * n - n2; + const y = Math.random() * n - n2; + const z = Math.random() * n - n2; + + positions.push(x, y, z); + positions2.push(z * 0.3, x * 0.3, y * 0.3); + + // colors + + const vx = x / n + 0.5; + const vy = y / n + 0.5; + const vz = z / n + 0.5; + + color.setRGB(vx, vy, vz); + + colors.push(color.r, color.g, color.b); + } + + const gl = renderer.getContext(); + + const pos = gl.createBuffer()!; + gl.bindBuffer(gl.ARRAY_BUFFER, pos); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); + + const pos2 = gl.createBuffer()!; + gl.bindBuffer(gl.ARRAY_BUFFER, pos2); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions2), gl.STATIC_DRAW); + + const rgb = gl.createBuffer()!; + gl.bindBuffer(gl.ARRAY_BUFFER, rgb); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); + + const posAttr1 = new THREE.GLBufferAttribute(pos, gl.FLOAT, 3, 4, particles); + const posAttr2 = new THREE.GLBufferAttribute(pos2, gl.FLOAT, 3, 4, particles); + geometry.setAttribute('position', posAttr1); + + setInterval(() => { + const attr = geometry.getAttribute('position'); + + geometry.setAttribute('position', attr === posAttr1 ? posAttr2 : posAttr1); + }, 2000); + + geometry.setAttribute('color', new THREE.GLBufferAttribute(rgb, gl.FLOAT, 3, 4, particles)); + + // + + const material = new THREE.PointsMaterial({ size: 15, vertexColors: true }); + + points = new THREE.Points(geometry, material); + + // Choose one: + // geometry.boundingSphere = ( new THREE.Sphere() ).set( new THREE.Vector3(), Infinity ); + points.frustumCulled = false; + + scene.add(points); + + // + + stats = new Stats(); + container.appendChild(stats.dom); + + // + + window.addEventListener('resize', onWindowResize); +} + +function onWindowResize() { + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize(window.innerWidth, window.innerHeight); +} + +// + +function animate() { + requestAnimationFrame(animate); + + render(); + stats.update(); +} + +function render() { + drawCount = (Math.max(5000, drawCount) + Math.floor(500 * Math.random())) % particles; + points.geometry.setDrawRange(0, drawCount); + + const time = Date.now() * 0.001; + + points.rotation.x = time * 0.1; + points.rotation.y = time * 0.2; + + renderer.render(scene, camera); +} diff --git a/types/three/tsconfig.json b/types/three/tsconfig.json index dfec90b5d..0ac2c498e 100644 --- a/types/three/tsconfig.json +++ b/types/three/tsconfig.json @@ -32,6 +32,7 @@ "test/integration/three-examples/webgl2_multiple_rendertargets.ts", "test/integration/three-examples/webgl2_rendertarget_texture2darray.ts", "test/integration/three-examples/webgl2_volume_instancing.ts", + "test/integration/three-examples/webgl_buffergeometry_glbufferattribute.ts", "test/integration/three-examples/webgl_buffergeometry_instancing_interleaved.ts", "test/integration/three-examples/webgl_camera.ts", "test/integration/three-examples/webgl_camera_array.ts",