Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] WebGLRenderer #129

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,7 @@ Once a set of Three.js files (`.js`, `.d.ts`, and `.tests.js`) are ported, we
can run the unit tests (or run them as we go during porting).

You can read more about this on the [**Development**](DEVELOPMENT.md) page

## TODOs

There are random comments labeled with `TODO PORT` that denote areas that still need handling.
98 changes: 82 additions & 16 deletions src/as/core/BufferAttribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {Vector4} from '../math/Vector4'
import {Vector3} from '../math/Vector3'
import {Vector2} from '../math/Vector2'
import {Color} from '../math/Color'
import {fillUint32ArrayWithValues, fillFloat32ArrayWithValues} from './TypedArrayUtils'
import {fillUint32ArrayWithValues, fillFloat32ArrayWithValues, fillUint16ArrayWithValues} from './TypedArrayUtils'
import {thro} from '../utils'

class UpdateRange {
offset: f32
Expand Down Expand Up @@ -44,6 +45,9 @@ function getArrayTypeName(arrayType: ArrayType): string {
}

class TypedArrays {
// TODO PERFORMANCE: If we make these properties lazy getters (internally
// values are null at first, and constructed only when accessed), would
// that be better (less memory use)?
Int8: Int8Array = new Int8Array(0)
Uint8: Uint8Array = new Uint8Array(0)
Uint8Clamped: Uint8ClampedArray = new Uint8ClampedArray(0)
Expand All @@ -61,25 +65,32 @@ class TypedArrays {
export class BufferAttribute {
name: string = ''

arrays: TypedArrays = new TypedArrays()
readonly arrays: TypedArrays = new TypedArrays()
dynamic: boolean = false
updateRange: UpdateRange = {offset: 0, count: -1}
version: i32 = 0

isBufferAttribute: true = true
onUploadCallback: () => void = () => {}

private __length: i32 = 0

get length(): i32 {
return this.__length
}

constructor(
public arrayType: ArrayType,
public count: i32,
public itemSize: i32,
public normalized: boolean = true
) {
this.__length = this.count * this.itemSize
this.__makeInitialArray()
}

private __makeInitialArray(): void {
const size = this.count * this.itemSize
const size = this.length

// prettier-ignore
switch (this.arrayType) {
Expand Down Expand Up @@ -147,6 +158,11 @@ export class BufferAttribute {
// return this;
// }

copy(other: BufferAttribute): this {
// TODO, like copyArray, but from another BufferAttribute
return this
}

copyArray<A extends ArrayLike<number>>(array: A): this {
if (array instanceof Int8Array) this.copyInt8Array(array)
else if (array instanceof Uint8Array) this.copyUint8Array(array)
Expand All @@ -165,25 +181,23 @@ export class BufferAttribute {
copyInt8Array(array: Int8Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Int8)
const thisArray = this.arrays.Int8
if (array.length > thisArray.length)
throw new Error('copyInt8Array: Source array is bigger than the target array.')
if (array.length > this.length) throw new Error('copyInt8Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
}

copyUint8Array(array: Uint8Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Uint8)
const thisArray = this.arrays.Uint8
if (array.length > thisArray.length)
throw new Error('copyUint8Array: Source array is bigger than the target array.')
if (array.length > this.length) throw new Error('copyUint8Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
}

copyUint8ClampedArray(array: Uint8ClampedArray): this {
this.__checkArrayTypeMatch(array, ArrayType.Uint8Clamped)
const thisArray = this.arrays.Uint8Clamped
if (array.length > thisArray.length)
if (array.length > this.length)
throw new Error('copyUint8ClampedArray: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
Expand All @@ -192,16 +206,15 @@ export class BufferAttribute {
copyInt16Array(array: Int16Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Int16)
const thisArray = this.arrays.Int16
if (array.length > thisArray.length)
throw new Error('copyInt16Array: Source array is bigger than the target array.')
if (array.length > this.length) throw new Error('copyInt16Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
}

copyUint16Array(array: Uint16Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Uint16)
const thisArray = this.arrays.Uint16
if (array.length > thisArray.length)
if (array.length > this.length)
throw new Error('copyUint16Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
Expand All @@ -210,16 +223,15 @@ export class BufferAttribute {
copyInt32Array(array: Int32Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Int32)
const thisArray = this.arrays.Int32
if (array.length > thisArray.length)
throw new Error('copyInt32Array: Source array is bigger than the target array.')
if (array.length > this.length) throw new Error('copyInt32Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
}

copyUint32Array(array: Uint32Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Uint32)
const thisArray = this.arrays.Uint32
if (array.length > thisArray.length)
if (array.length > this.length)
throw new Error('copyUint32Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
Expand All @@ -228,7 +240,7 @@ export class BufferAttribute {
copyFloat32Array(array: Float32Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Float32)
const thisArray = this.arrays.Float32
if (array.length > thisArray.length)
if (array.length > this.length)
throw new Error('copyFloat32Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
Expand All @@ -237,7 +249,7 @@ export class BufferAttribute {
copyFloat64Array(array: Float64Array): this {
this.__checkArrayTypeMatch(array, ArrayType.Float64)
const thisArray = this.arrays.Float64
if (array.length > thisArray.length)
if (array.length > this.length)
throw new Error('copyFloat64Array: Source array is bigger than the target array.')
for (let i = 0, l = array.length; i < l; i++) thisArray[i] = array[i]
return this
Expand Down Expand Up @@ -487,6 +499,13 @@ export class BufferAttribute {

// TODO Make more of the following static from* methods as needed...

static fromArrayOfUint16(array: u16[], itemSize: i32, normalized: boolean = false): Uint16BufferAttribute {
if (array.length % itemSize != 0) throw new Error('itemSize does not fit into the array length')
const attr = new Uint16BufferAttribute(array.length / itemSize, itemSize, normalized)
attr.copyArray(fillUint16ArrayWithValues(array))
return attr
}

static fromArrayOfUint32(array: u32[], itemSize: i32, normalized: boolean = false): Uint32BufferAttribute {
if (array.length % itemSize != 0) throw new Error('itemSize does not fit into the array length')
const attr = new Uint32BufferAttribute(array.length / itemSize, itemSize, normalized)
Expand All @@ -500,6 +519,53 @@ export class BufferAttribute {
attr.copyArray(fillFloat32ArrayWithValues(array))
return attr
}

// TODO Make more of the following static to* methods as needed...

// Can we make this generic to specify which type to convert to, so we
// don't have to make many versions of this function for all the data
// types?
toUint16(targetAttribute: BufferAttribute | null = null): Uint16BufferAttribute {
const attr = targetAttribute || new Uint16BufferAttribute(this.count, this.itemSize, this.normalized)

if (attr.arrayType != ArrayType.Uint16)
throw new Error('Expected a BufferAttribute with arrayType Uint16 or a Uint16BufferAttribute.')

for (let i = 0, l = this.length; i < l; i++) {
this.arrayType === ArrayType.Int8
? (attr.arrays.Uint16[i] = u16(this.arrays.Int8[i]))
: this.arrayType === ArrayType.Uint8
? (attr.arrays.Uint16[i] = u16(this.arrays.Uint8[i]))
: this.arrayType === ArrayType.Uint8Clamped
? (attr.arrays.Uint16[i] = u16(this.arrays.Uint8Clamped[i]))
: this.arrayType === ArrayType.Int16
? (attr.arrays.Uint16[i] = u16(this.arrays.Int16[i]))
: this.arrayType === ArrayType.Uint16
? (attr.arrays.Uint16[i] = this.arrays.Uint16[i])
: this.arrayType === ArrayType.Int32
? (attr.arrays.Uint16[i] = u16(this.arrays.Int32[i]))
: this.arrayType === ArrayType.Uint32
? (attr.arrays.Uint16[i] = u16(this.arrays.Uint32[i]))
: this.arrayType === ArrayType.Float32
? (attr.arrays.Uint16[i] = u16(this.arrays.Float32[i]))
: this.arrayType === ArrayType.Float64
? (attr.arrays.Uint16[i] = u16(this.arrays.Float64[i]))
: thro(new Error('This is impossible!'))
}

return attr
}

// TODO is is possible to make a convert<T> method that is more DRY than toUint16/etc?
convert<T>(): BufferAttribute {
// if (T is u16) {
const attr = new Uint16BufferAttribute(this.count, this.itemSize, this.normalized)
// } else if (T is i32) {
// etc
// }

return attr
}
}

export class Int8BufferAttribute extends BufferAttribute {
Expand Down
14 changes: 5 additions & 9 deletions src/as/core/BufferGeometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ export class BufferGeometry extends EventDispatcher {
name: string = ''
type: string = 'BufferGeometry'

// Index must have data type u16 or u32.
index: BufferAttribute | null = null

attributes: Map<string, BufferAttribute> /* | InterleavedBufferAttribute> */ = new Map()

morphAttributes: Map<string, BufferAttribute[]> = new Map()
Expand Down Expand Up @@ -102,6 +104,7 @@ export class BufferGeometry extends EventDispatcher {
this.setIndexFromBufferAttribute(array)
}

// TODO PORT
// setIndexFromArray<A extends Array<number>>(index: A): void {
// if (arrayMax(index) > 65535) {
// this.index = new Uint32BufferAttribute(index.length, 1)
Expand All @@ -110,7 +113,6 @@ export class BufferGeometry extends EventDispatcher {
// this.index = new Uint16BufferAttribute(index.length, 1)
// fillUint16ArrayWithValues(index, this.index.arrays.Uint16)
// }
// // CONTINUE
// }

setIndexFromBufferAttribute(index: BufferAttribute): void {
Expand All @@ -131,13 +133,7 @@ export class BufferGeometry extends EventDispatcher {
}

addAttribute(name: string, attribute: BufferAttribute /*| InterleavedBufferAttribute*/): BufferGeometry {
//type system requires us to be sent BufferAttribute
// if (!(attribute && attribute.isBufferAttribute) && !(attribute && attribute.isInterleavedBufferAttribute)) {
// console.warn('THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).')

// return this.addAttribute(name, new BufferAttribute(arguments[1], arguments[2]))
// }

// TODO PORT
// if (name === 'index') {
// //console.warn('THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.')

Expand All @@ -151,7 +147,7 @@ export class BufferGeometry extends EventDispatcher {
return this
}

//TODO: uncomment when needed
//TODO PORT: uncomment when needed
// getAttribute(name: string): BufferAttribute | InterleavedBufferAttribute {
// return this.attributes[name]
// }
Expand Down
12 changes: 8 additions & 4 deletions src/as/core/EventDispatcher.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ class CountListener extends Listener {
}
}

class NoopListener extends Listener {
onEvent(event: Event): void {}
}

describe('EventDispatcher', (): void => {
test('.constructor', (): void => {
// expect(a.x).toBe(0)
})

test('.addEventListener', (): void => {
const eventDispatcher = new EventDispatcher()
const listener: Listener = new Listener()
const listener: Listener = new NoopListener()

eventDispatcher.addEventListener('anyType', listener)

Expand All @@ -45,7 +49,7 @@ describe('EventDispatcher', (): void => {
.get('anyType')
).toStrictEqual([listener])

const listener2: Listener = new Listener()
const listener2: Listener = new NoopListener()

eventDispatcher.addEventListener('anyType', listener2)

Expand All @@ -60,15 +64,15 @@ describe('EventDispatcher', (): void => {

test('.hasEventListener', (): void => {
const eventDispatcher = new EventDispatcher()
const listener: Listener = new Listener()
const listener: Listener = new NoopListener()
eventDispatcher.addEventListener('anyType', listener)
expect(eventDispatcher.hasEventListener('anyType', listener)).toBeTruthy()
expect(eventDispatcher.hasEventListener('anotherType', listener)).toBeFalsy()
})

test('.removeEventListener', (): void => {
const eventDispatcher = new EventDispatcher()
const listener: Listener = new Listener()
const listener: Listener = new NoopListener()

eventDispatcher.addEventListener('anyType', listener)

Expand Down
6 changes: 2 additions & 4 deletions src/as/core/EventDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
import {Event} from './Event'
import {EventTargetable} from './EventTargetable'

export class Listener {
onEvent(event: Event): void {
// subclasses should implement this
}
export abstract class Listener {
abstract onEvent(event: Event): void
}

export type ListenerArray = Array<Listener>
Expand Down
3 changes: 3 additions & 0 deletions src/as/core/InstancedBufferGeometry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class InstancedBufferGeometry {
// TODO
}
Loading