From a5231d59192c3ad42c21c2e06fa4bce22898f53d Mon Sep 17 00:00:00 2001 From: ZoeDreams Date: Wed, 18 Nov 2020 23:18:32 -0500 Subject: [PATCH 01/10] update comments on this. --- src/as/renderers/webgl/WebGLShader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/as/renderers/webgl/WebGLShader.ts b/src/as/renderers/webgl/WebGLShader.ts index cc9b2ee..7f4b6a6 100644 --- a/src/as/renderers/webgl/WebGLShader.ts +++ b/src/as/renderers/webgl/WebGLShader.ts @@ -1,6 +1,6 @@ /// THREE.js.r105 /// /** - * @version 0.0.1 + * @author mrdoob / http://mrdoob.com/ * @author Kara Rawson / https://github.com/ZoeDreams */ From fef28c4b661d25d85de25d7e49b8ec573366a5d0 Mon Sep 17 00:00:00 2001 From: ZoeDreams Date: Tue, 1 Dec 2020 19:08:31 -0500 Subject: [PATCH 02/10] Implemented .setContext of WebGLAnimation class and created two placeholder classes for `WebGLRenderingContext` & `WebGL2RenderingContext` which will become the wrappers for our native WebGLContext that is part of the native `window` class. --- src/as/index.spec.ts | 18 +++--- .../renderers/WebGL2RenderingContext_.spec.ts | 17 ++++++ src/as/renderers/WebGL2RenderingContext_.ts | 17 ++++++ .../renderers/WebGLRenderingContext_.spec.ts | 17 ++++++ src/as/renderers/WebGLRenderingContext_.ts | 17 ++++++ src/as/renderers/index.spec.ts | 2 + src/as/renderers/webgl/WebGLAnimation.d.ts | 11 ---- src/as/renderers/webgl/WebGLAnimation.spec.ts | 34 +++++++++++ src/as/renderers/webgl/WebGLAnimation.ts | 58 +++++++++++++++++++ src/as/renderers/webgl/WebGLShader.spec.ts | 2 +- src/as/renderers/webgl/WebGLShader.ts | 9 ++- src/as/renderers/webgl/index.spec.ts | 1 + 12 files changed, 180 insertions(+), 23 deletions(-) create mode 100644 src/as/renderers/WebGL2RenderingContext_.spec.ts create mode 100644 src/as/renderers/WebGL2RenderingContext_.ts create mode 100644 src/as/renderers/WebGLRenderingContext_.spec.ts create mode 100644 src/as/renderers/WebGLRenderingContext_.ts delete mode 100644 src/as/renderers/webgl/WebGLAnimation.d.ts create mode 100644 src/as/renderers/webgl/WebGLAnimation.spec.ts create mode 100644 src/as/renderers/webgl/WebGLAnimation.ts diff --git a/src/as/index.spec.ts b/src/as/index.spec.ts index 99e5325..8170266 100644 --- a/src/as/index.spec.ts +++ b/src/as/index.spec.ts @@ -1,11 +1,11 @@ -import './cameras/index.spec' -import './core/index.spec' -import './lights/index.spec' -import './materials/index.spec' -import './math/index.spec' -import './objects/index.spec' +// import './cameras/index.spec' +// import './core/index.spec' +// import './lights/index.spec' +// import './materials/index.spec' +// import './math/index.spec' +// import './objects/index.spec' import './renderers/index.spec' -import './scenes/index.spec' +// import './scenes/index.spec' -import './constants.spec' -import './utils.spec' +// import './constants.spec' +// import './utils.spec' diff --git a/src/as/renderers/WebGL2RenderingContext_.spec.ts b/src/as/renderers/WebGL2RenderingContext_.spec.ts new file mode 100644 index 0000000..57205a0 --- /dev/null +++ b/src/as/renderers/WebGL2RenderingContext_.spec.ts @@ -0,0 +1,17 @@ +/** + * @author Kara Rawson / rawsonkara@gmail.com + */ + +import { WebGL2RenderingContext_ } from "./WebGL2RenderingContext_"; + +/** + * Test class used to verify that we have the WebGL2RenderingContext placeholder + * within GLAS. This will be replaced with the real WebGLRenderingContext class. + */ +describe('Renderers', () => { + test('WebGL2RenderingContext_', (): void => { + var context: WebGL2RenderingContext_ = new WebGL2RenderingContext_() + expect(context.context).toBe(2, + "Make sure we are using version 2.x of WebGL in the 'WebGL2RenderingContext' class") + }) +}) diff --git a/src/as/renderers/WebGL2RenderingContext_.ts b/src/as/renderers/WebGL2RenderingContext_.ts new file mode 100644 index 0000000..f9a04d7 --- /dev/null +++ b/src/as/renderers/WebGL2RenderingContext_.ts @@ -0,0 +1,17 @@ + /** + * @author Kara Rawson / rawsonkara@gmail.com + */ + + /** + * simple placeholder class until we get support with AS web glue which is meant + * to provide access to the underlying context canvas element that exposes the + * GL layer of the browser. + */ + export class WebGL2RenderingContext_ { + context: i8 = 2 // version placeholder + + //// TODO needs ASGLue module to access native context canvas of GL in the browser + + // functions or properties required for testing + // ... + } \ No newline at end of file diff --git a/src/as/renderers/WebGLRenderingContext_.spec.ts b/src/as/renderers/WebGLRenderingContext_.spec.ts new file mode 100644 index 0000000..0a76864 --- /dev/null +++ b/src/as/renderers/WebGLRenderingContext_.spec.ts @@ -0,0 +1,17 @@ +/** + * @author Kara Rawson / rawsonkara@gmail.com + */ + +import { WebGLRenderingContext_ } from "./WebGLRenderingContext_"; + +/** + * Test class used to verify that we have the WebGLRenderingContext placeholder + * within GLAS. This will be replaced with the real WebGLRenderingContext class. + */ +describe('Renderers', () => { + test('WebGLRenderingContext_', (): void => { + var context: WebGLRenderingContext_ = new WebGLRenderingContext_() + expect(context.context).toBe(1, + "Make sure we are using version 1.x of WebGL in the 'WebGLRenderingContext' class") + }) +}) diff --git a/src/as/renderers/WebGLRenderingContext_.ts b/src/as/renderers/WebGLRenderingContext_.ts new file mode 100644 index 0000000..f648999 --- /dev/null +++ b/src/as/renderers/WebGLRenderingContext_.ts @@ -0,0 +1,17 @@ + /** + * @author Kara Rawson / rawsonkara@gmail.com + */ + + /** + * simple placeholder class until we get support with AS web glue which is meant + * to provide access to the underlying context canvas element that exposes the + * GL layer of the browser. + */ + export class WebGLRenderingContext_ { + context: i8 = 1 // version placeholder + + //// TODO needs ASGLue module to access native context canvas of GL in the browser + + // functions or properties required for testing + // ... + } \ No newline at end of file diff --git a/src/as/renderers/index.spec.ts b/src/as/renderers/index.spec.ts index 6878b24..50a1384 100644 --- a/src/as/renderers/index.spec.ts +++ b/src/as/renderers/index.spec.ts @@ -1 +1,3 @@ import './webgl/index.spec' +import './WebGLRenderingContext_.spec' +import './WebGL2RenderingContext_.spec' \ No newline at end of file diff --git a/src/as/renderers/webgl/WebGLAnimation.d.ts b/src/as/renderers/webgl/WebGLAnimation.d.ts deleted file mode 100644 index 0ffe0fd..0000000 --- a/src/as/renderers/webgl/WebGLAnimation.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export class WebGLAnimation { - - start(): void; - - stop(): void; - - setAnimationLoop( callback: Function ): void; - - setContext( value: WebGLRenderingContext | WebGL2RenderingContext ): void; - -} diff --git a/src/as/renderers/webgl/WebGLAnimation.spec.ts b/src/as/renderers/webgl/WebGLAnimation.spec.ts new file mode 100644 index 0000000..9fd3a80 --- /dev/null +++ b/src/as/renderers/webgl/WebGLAnimation.spec.ts @@ -0,0 +1,34 @@ + /** + * @author Kara Rawson / rawsonkara@gmail.com + */ + +import {WebGLAnimation} from './WebGLAnimation' +import {WebGLRenderingContext_} from "../WebGLRenderingContext_"; +import {WebGL2RenderingContext_} from "../WebGL2RenderingContext_"; + +describe('Renderers', () => { + describe('WebGL', () => { + describe('WebGLAnimation', () => { + todo('start') + todo('stop') + todo('setAnimationLoop') + test('setContext', (): void => { + var animation = new WebGLAnimation() + var gl: WebGLRenderingContext_ = new WebGLRenderingContext_() + var gl2: WebGL2RenderingContext_ = new WebGL2RenderingContext_() + + animation.setContext(gl, null) + + expect(animation.context).not.toBeNull("WebGLRenderingContext should not be null") + expect(animation.context2).toBeNull("WebGL2RenderingContext should be null") + expect(animation.context).toStrictEqual(gl, "WebGLRenderingContext should be type gl") + + animation.setContext(null, gl2) + + expect(animation.context).toBeNull("WebGLRenderingContext should be null") + expect(animation.context2).not.toBeNull("WebGL2RenderingContext should not be null") + expect(animation.context2).toStrictEqual(gl2, "WebGLRenderingContext should be type gl2") + }) + }) + }) +}) diff --git a/src/as/renderers/webgl/WebGLAnimation.ts b/src/as/renderers/webgl/WebGLAnimation.ts new file mode 100644 index 0000000..8019ad9 --- /dev/null +++ b/src/as/renderers/webgl/WebGLAnimation.ts @@ -0,0 +1,58 @@ +/** + * @author mrdoob / http://mrdoob.com/ + * @author Kara Rawson / rawsonkara@gmail.com + */ + +import {WebGLRenderingContext_} from "../WebGLRenderingContext_"; +import {WebGL2RenderingContext_} from "../WebGL2RenderingContext_"; + +/** + * a general purpose classes without a constructor for animating geometry within + * GLAS. This class requires explicitly setting either the 'WebGLRenderingContext' or + * 'WebGL2RenderingContext' depending on the version of GL and GLSL you with to use. + * + * NOTE: This is a terribly overloaded term. Animation in this case actually refers to + * the callback function which is passed by reference into the requestAnimationFrame. + * This is a bit confusing with a mesh's animation sequence which is completely different + * uses the same wording. + */ +export class WebGLAnimation { + + /// Our temporary WebGLContexts, to be implemented + context: WebGLRenderingContext_ | null = null + context2: WebGL2RenderingContext_ | null = null + + /** + * starts our animation loop + */ + start(): void { + /// ... + } + + stop(): void { + /// ... + } + + setAnimationLoop( callback: Function ): void { + /// ... + } + + setContext(gl: WebGLRenderingContext_ | null, gl2: WebGL2RenderingContext_ | null): void { + if(gl) { + this.context = gl + this.context2 = null + return + + } + else if(gl2) { + this.context = null + this.context2 = gl2 + return + } + + /// TODO exception handling not yet supported + //else { + // throw new Exception("webgl or webgl2 must be provided to 'setContext()'") + //} + } +} diff --git a/src/as/renderers/webgl/WebGLShader.spec.ts b/src/as/renderers/webgl/WebGLShader.spec.ts index a1fb288..97f1b01 100644 --- a/src/as/renderers/webgl/WebGLShader.spec.ts +++ b/src/as/renderers/webgl/WebGLShader.spec.ts @@ -2,7 +2,7 @@ import { WebGLShader } from './WebGLShader' /** * @see https://tenner-joshua.gitbook.io/as-pect/as-api - * @author Kara Rawson / https://github.com/ZoeDreams + * @author Kara Rawson / rawsonkara@gmail.com */ describe('Renderers', (): void => { diff --git a/src/as/renderers/webgl/WebGLShader.ts b/src/as/renderers/webgl/WebGLShader.ts index 7f4b6a6..9ed4ad9 100644 --- a/src/as/renderers/webgl/WebGLShader.ts +++ b/src/as/renderers/webgl/WebGLShader.ts @@ -1,9 +1,11 @@ /// THREE.js.r105 /// /** * @author mrdoob / http://mrdoob.com/ - * @author Kara Rawson / https://github.com/ZoeDreams + * @author Kara Rawson / rawsonkara@gmail.com */ + import { WebGLRenderingContext_ } from "../WebGLRenderingContext_"; + /** * A lower level function to compile either a vertex or fragment shader. * @@ -16,7 +18,10 @@ * @todo Update WebGLShader.spec.ts test when we figure out how to load the ctx by as-pect */ -export function WebGLShader(gl: WebGLRenderingContext, type: number, source: string): WebGLShader { +export function WebGLShader(gl: WebGLRenderingContext_, type: number, source: string): WebGLShader { + + /// TODO implement WebGLShader_ placeholder library in the renderer root. + var shader: WebGLShader = gl.createShader(type) gl.shaderSource(shader, source) gl.compileShader(shader) diff --git a/src/as/renderers/webgl/index.spec.ts b/src/as/renderers/webgl/index.spec.ts index 138b952..871a264 100644 --- a/src/as/renderers/webgl/index.spec.ts +++ b/src/as/renderers/webgl/index.spec.ts @@ -1,3 +1,4 @@ +import './WebGLAnimation.spec' import './WebGLLights.spec' import './WebGLProperties.spec' import './WebGLRenderLists.spec' From 07be577be5d0104e84ca9468f4e7e5c45560a728 Mon Sep 17 00:00:00 2001 From: ZoeDreams Date: Wed, 2 Dec 2020 16:17:41 -0500 Subject: [PATCH 03/10] Added WebGLAnimationFrame to recusrively call itself. --- ...spec.ts => WebGL2RenderingContext.spec.ts} | 4 +- src/as/renderers/WebGL2RenderingContext.ts | 27 ++++++ src/as/renderers/WebGL2RenderingContext_.ts | 17 ---- ....spec.ts => WebGLRenderingContext.spec.ts} | 4 +- src/as/renderers/WebGLRenderingContext.ts | 27 ++++++ src/as/renderers/WebGLRenderingContext_.ts | 17 ---- src/as/renderers/index.spec.ts | 4 +- src/as/renderers/webgl/WebGLAnimation.spec.ts | 57 ++++++------ src/as/renderers/webgl/WebGLAnimation.ts | 86 +++++++++++++++---- src/as/renderers/webgl/WebGLShader.ts | 6 +- 10 files changed, 166 insertions(+), 83 deletions(-) rename src/as/renderers/{WebGL2RenderingContext_.spec.ts => WebGL2RenderingContext.spec.ts} (75%) create mode 100644 src/as/renderers/WebGL2RenderingContext.ts delete mode 100644 src/as/renderers/WebGL2RenderingContext_.ts rename src/as/renderers/{WebGLRenderingContext_.spec.ts => WebGLRenderingContext.spec.ts} (75%) create mode 100644 src/as/renderers/WebGLRenderingContext.ts delete mode 100644 src/as/renderers/WebGLRenderingContext_.ts diff --git a/src/as/renderers/WebGL2RenderingContext_.spec.ts b/src/as/renderers/WebGL2RenderingContext.spec.ts similarity index 75% rename from src/as/renderers/WebGL2RenderingContext_.spec.ts rename to src/as/renderers/WebGL2RenderingContext.spec.ts index 57205a0..c0d6602 100644 --- a/src/as/renderers/WebGL2RenderingContext_.spec.ts +++ b/src/as/renderers/WebGL2RenderingContext.spec.ts @@ -2,7 +2,7 @@ * @author Kara Rawson / rawsonkara@gmail.com */ -import { WebGL2RenderingContext_ } from "./WebGL2RenderingContext_"; +import { WebGL2RenderingContext } from "./WebGL2RenderingContext"; /** * Test class used to verify that we have the WebGL2RenderingContext placeholder @@ -10,7 +10,7 @@ import { WebGL2RenderingContext_ } from "./WebGL2RenderingContext_"; */ describe('Renderers', () => { test('WebGL2RenderingContext_', (): void => { - var context: WebGL2RenderingContext_ = new WebGL2RenderingContext_() + var context: WebGL2RenderingContext = new WebGL2RenderingContext() expect(context.context).toBe(2, "Make sure we are using version 2.x of WebGL in the 'WebGL2RenderingContext' class") }) diff --git a/src/as/renderers/WebGL2RenderingContext.ts b/src/as/renderers/WebGL2RenderingContext.ts new file mode 100644 index 0000000..ad3976a --- /dev/null +++ b/src/as/renderers/WebGL2RenderingContext.ts @@ -0,0 +1,27 @@ +/** + * @author Kara Rawson / rawsonkara@gmail.com + */ + +import { WebGLAnimationFrame } from "./webgl/WebGLAnimation"; + +/** + * simple placeholder class until we get support with AS web glue which is meant + * to provide access to the underlying context canvas element that exposes the + * GL layer of the browser. + */ +export class WebGL2RenderingContext { + context: i8 = 2 // version placeholder + + //// TODO needs ASGLue module to access native context canvas of GL in the browser + + // functions or properties required for testing + + requestAnimationFrame(animationLoop: WebGLAnimationFrame): void { + // ... + } +} + +/* lib.dom.d.ts -- interface reference from the domlib +interface WebGL2RenderingContext extends WebGL2RenderingContextBase, WebGL2RenderingContextOverloads, WebGLRenderingContextBase { +} +*/ \ No newline at end of file diff --git a/src/as/renderers/WebGL2RenderingContext_.ts b/src/as/renderers/WebGL2RenderingContext_.ts deleted file mode 100644 index f9a04d7..0000000 --- a/src/as/renderers/WebGL2RenderingContext_.ts +++ /dev/null @@ -1,17 +0,0 @@ - /** - * @author Kara Rawson / rawsonkara@gmail.com - */ - - /** - * simple placeholder class until we get support with AS web glue which is meant - * to provide access to the underlying context canvas element that exposes the - * GL layer of the browser. - */ - export class WebGL2RenderingContext_ { - context: i8 = 2 // version placeholder - - //// TODO needs ASGLue module to access native context canvas of GL in the browser - - // functions or properties required for testing - // ... - } \ No newline at end of file diff --git a/src/as/renderers/WebGLRenderingContext_.spec.ts b/src/as/renderers/WebGLRenderingContext.spec.ts similarity index 75% rename from src/as/renderers/WebGLRenderingContext_.spec.ts rename to src/as/renderers/WebGLRenderingContext.spec.ts index 0a76864..eca654d 100644 --- a/src/as/renderers/WebGLRenderingContext_.spec.ts +++ b/src/as/renderers/WebGLRenderingContext.spec.ts @@ -2,7 +2,7 @@ * @author Kara Rawson / rawsonkara@gmail.com */ -import { WebGLRenderingContext_ } from "./WebGLRenderingContext_"; +import { WebGLRenderingContext } from "./WebGLRenderingContext"; /** * Test class used to verify that we have the WebGLRenderingContext placeholder @@ -10,7 +10,7 @@ import { WebGLRenderingContext_ } from "./WebGLRenderingContext_"; */ describe('Renderers', () => { test('WebGLRenderingContext_', (): void => { - var context: WebGLRenderingContext_ = new WebGLRenderingContext_() + var context: WebGLRenderingContext = new WebGLRenderingContext() expect(context.context).toBe(1, "Make sure we are using version 1.x of WebGL in the 'WebGLRenderingContext' class") }) diff --git a/src/as/renderers/WebGLRenderingContext.ts b/src/as/renderers/WebGLRenderingContext.ts new file mode 100644 index 0000000..7d2c248 --- /dev/null +++ b/src/as/renderers/WebGLRenderingContext.ts @@ -0,0 +1,27 @@ +/** + * @author Kara Rawson / rawsonkara@gmail.com + */ + +import { WebGLAnimationFrame } from './webgl/WebGLAnimation' + +/** + * simple placeholder class until we get support with AS web glue which is meant + * to provide access to the underlying context canvas element that exposes the + * GL layer of the browser. + */ +export class WebGLRenderingContext { + context: i8 = 1 // version placeholder + + //// TODO needs ASGLue module to access native context canvas of GL in the browser + + // functions or properties required for testing + + requestAnimationFrame(animationLoop: WebGLAnimationFrame): void { + // animationLoop.onAnimationFrame(0,0,animationLoop) + } +} + +/* lib.dom.d.ts -- interface reference from the domlib +interface WebGL2RenderingContext extends WebGL2RenderingContextBase, WebGL2RenderingContextOverloads, WebGLRenderingContextBase { +} +*/ \ No newline at end of file diff --git a/src/as/renderers/WebGLRenderingContext_.ts b/src/as/renderers/WebGLRenderingContext_.ts deleted file mode 100644 index f648999..0000000 --- a/src/as/renderers/WebGLRenderingContext_.ts +++ /dev/null @@ -1,17 +0,0 @@ - /** - * @author Kara Rawson / rawsonkara@gmail.com - */ - - /** - * simple placeholder class until we get support with AS web glue which is meant - * to provide access to the underlying context canvas element that exposes the - * GL layer of the browser. - */ - export class WebGLRenderingContext_ { - context: i8 = 1 // version placeholder - - //// TODO needs ASGLue module to access native context canvas of GL in the browser - - // functions or properties required for testing - // ... - } \ No newline at end of file diff --git a/src/as/renderers/index.spec.ts b/src/as/renderers/index.spec.ts index 50a1384..a37e6c3 100644 --- a/src/as/renderers/index.spec.ts +++ b/src/as/renderers/index.spec.ts @@ -1,3 +1,3 @@ import './webgl/index.spec' -import './WebGLRenderingContext_.spec' -import './WebGL2RenderingContext_.spec' \ No newline at end of file +import './WebGLRenderingContext.spec' +import './WebGL2RenderingContext.spec' \ No newline at end of file diff --git a/src/as/renderers/webgl/WebGLAnimation.spec.ts b/src/as/renderers/webgl/WebGLAnimation.spec.ts index 9fd3a80..ee49551 100644 --- a/src/as/renderers/webgl/WebGLAnimation.spec.ts +++ b/src/as/renderers/webgl/WebGLAnimation.spec.ts @@ -1,34 +1,39 @@ - /** - * @author Kara Rawson / rawsonkara@gmail.com - */ +/** + * @author Kara Rawson / rawsonkara@gmail.com + */ -import {WebGLAnimation} from './WebGLAnimation' -import {WebGLRenderingContext_} from "../WebGLRenderingContext_"; -import {WebGL2RenderingContext_} from "../WebGL2RenderingContext_"; +import { WebGLAnimation } from './WebGLAnimation' +import { WebGLRenderingContext } from "../WebGLRenderingContext"; +import { WebGL2RenderingContext } from "../WebGL2RenderingContext"; + +/** + * @todo make sure we test the WebGLAnimationFrame + */ describe('Renderers', () => { - describe('WebGL', () => { - describe('WebGLAnimation', () => { - todo('start') - todo('stop') - todo('setAnimationLoop') - test('setContext', (): void => { - var animation = new WebGLAnimation() - var gl: WebGLRenderingContext_ = new WebGLRenderingContext_() - var gl2: WebGL2RenderingContext_ = new WebGL2RenderingContext_() + describe('WebGL', () => { + describe('WebGLAnimation', () => { + todo('start') + todo('stop') + todo('setAnimationLoop') + todo('WebGlAnimationFrame_callback') + test('setContext', (): void => { + var animation = new WebGLAnimation() + var gl: WebGLRenderingContext = new WebGLRenderingContext() + var gl2: WebGL2RenderingContext = new WebGL2RenderingContext() - animation.setContext(gl, null) + animation.setContext(gl, null) - expect(animation.context).not.toBeNull("WebGLRenderingContext should not be null") - expect(animation.context2).toBeNull("WebGL2RenderingContext should be null") - expect(animation.context).toStrictEqual(gl, "WebGLRenderingContext should be type gl") + expect(animation.context).not.toBeNull("WebGLRenderingContext should not be null") + expect(animation.context2).toBeNull("WebGL2RenderingContext should be null") + expect(animation.context).toStrictEqual(gl, "WebGLRenderingContext should be type gl") - animation.setContext(null, gl2) + animation.setContext(null, gl2) - expect(animation.context).toBeNull("WebGLRenderingContext should be null") - expect(animation.context2).not.toBeNull("WebGL2RenderingContext should not be null") - expect(animation.context2).toStrictEqual(gl2, "WebGLRenderingContext should be type gl2") - }) - }) - }) + expect(animation.context).toBeNull("WebGLRenderingContext should be null") + expect(animation.context2).not.toBeNull("WebGL2RenderingContext should not be null") + expect(animation.context2).toStrictEqual(gl2, "WebGLRenderingContext should be type gl2") + }) + }) + }) }) diff --git a/src/as/renderers/webgl/WebGLAnimation.ts b/src/as/renderers/webgl/WebGLAnimation.ts index 8019ad9..1d31feb 100644 --- a/src/as/renderers/webgl/WebGLAnimation.ts +++ b/src/as/renderers/webgl/WebGLAnimation.ts @@ -3,8 +3,37 @@ * @author Kara Rawson / rawsonkara@gmail.com */ -import {WebGLRenderingContext_} from "../WebGLRenderingContext_"; -import {WebGL2RenderingContext_} from "../WebGL2RenderingContext_"; +import { WebGLRenderingContext } from "../WebGLRenderingContext"; +import { WebGL2RenderingContext } from "../WebGL2RenderingContext"; + +/** + * our requestion animation frames root callback function. Recusrively calls itself + * unless isAnimating flag is set to false + * + * @todo this could be optimized to not have an if check.. make two types of animators for gl and gl2 + */ +export class WebGLAnimationFrame { + + /** + * recursive callback function which is called by the WebGLRenderingContext for gl or gl2 + * @param time the current time as an unsigned integer. This could overflow.. really big number + * @param frame the amount of times the gl_scene has rendered within our context + * @param animator the webgl animation class that handles the recursive callback + */ + onAnimationFrame(time: u64, frame: u64, animator: WebGLAnimation): void { + if (!animator.isAnimating) return; + + this.onAnimationFrame(time, frame, animator); + + if (animator.context) { + animator.context.requestAnimationFrame(animator.animationLoop); + return + } + if (animator.context2) { + animator.context2.requestAnimationFrame(animator.animationLoop); + } + } +} /** * a general purpose classes without a constructor for animating geometry within @@ -18,37 +47,64 @@ import {WebGL2RenderingContext_} from "../WebGL2RenderingContext_"; */ export class WebGLAnimation { - /// Our temporary WebGLContexts, to be implemented - context: WebGLRenderingContext_ | null = null - context2: WebGL2RenderingContext_ | null = null + context: WebGLRenderingContext | null = null + context2: WebGL2RenderingContext | null = null + + isAnimating: bool = false + animationLoop: WebGLAnimationFrame = new WebGLAnimationFrame() /** - * starts our animation loop + * starts our animation loop in gl land */ start(): void { - /// ... + + if (this.isAnimating) return + if (this.setAnimationLoop === null) return + + if (this.context) { + this.context.requestAnimationFrame(this.animationLoop) + } + else if (!this.context && this.context2) { + this.context2.requestAnimationFrame(this.animationLoop) + } + + this.isAnimating = true } + /** + * stops our animation loop in gl land + */ stop(): void { - /// ... + this.isAnimating = false } - setAnimationLoop( callback: Function ): void { - /// ... + /** + * a recursive call back function that is used to call itself to loop the update of the + * GLAS webgl scene and gl_objects + * @param callback sets our animation frame that is looped. aka animation loop + */ + setAnimationLoop(callback: WebGLAnimationFrame): void { + this.animationLoop = callback } - setContext(gl: WebGLRenderingContext_ | null, gl2: WebGL2RenderingContext_ | null): void { - if(gl) { + /** + * sets our local redering context which is used by our animator that calls rendering animation + * frame recursively + * @param gl version 1 of webgl used by most browsers + * @param gl2 version 2 of webgl which supports additional texture features and custom XR and VR devices + */ + setContext(gl: WebGLRenderingContext | null, gl2: WebGL2RenderingContext | null): void { + if (gl) { this.context = gl this.context2 = null return - } - else if(gl2) { + } + else if (gl2) { this.context = null this.context2 = gl2 return - } + } /// TODO exception handling not yet supported //else { diff --git a/src/as/renderers/webgl/WebGLShader.ts b/src/as/renderers/webgl/WebGLShader.ts index 9ed4ad9..b5fcff0 100644 --- a/src/as/renderers/webgl/WebGLShader.ts +++ b/src/as/renderers/webgl/WebGLShader.ts @@ -4,7 +4,7 @@ * @author Kara Rawson / rawsonkara@gmail.com */ - import { WebGLRenderingContext_ } from "../WebGLRenderingContext_"; + import { WebGLRenderingContext } from "../WebGLRenderingContext"; /** * A lower level function to compile either a vertex or fragment shader. @@ -16,9 +16,11 @@ * @see https://threejs.org/docs/#api/en/renderers/webgl/WebGLShader * * @todo Update WebGLShader.spec.ts test when we figure out how to load the ctx by as-pect + * @todo need to add gl2 argument. must be strong typed -- no unions + * @todo need to create wrapper class for webglshader */ -export function WebGLShader(gl: WebGLRenderingContext_, type: number, source: string): WebGLShader { +export function WebGLShader(gl: WebGLRenderingContext, type: number, source: string): WebGLShader { /// TODO implement WebGLShader_ placeholder library in the renderer root. From e98ff59b7c93858d65c7a9ac87454cbcf06f0eec Mon Sep 17 00:00:00 2001 From: Kara Rawson Date: Fri, 15 Jan 2021 20:31:44 -0500 Subject: [PATCH 04/10] update index.spec.ts with new test --- src/as/index.spec.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/as/index.spec.ts b/src/as/index.spec.ts index 8170266..cb21b59 100644 --- a/src/as/index.spec.ts +++ b/src/as/index.spec.ts @@ -1,11 +1,12 @@ -// import './cameras/index.spec' -// import './core/index.spec' -// import './lights/index.spec' -// import './materials/index.spec' -// import './math/index.spec' -// import './objects/index.spec' +import './cameras/index.spec' +import './core/index.spec' +import './geometries/index.spec' +import './lights/index.spec' +import './materials/index.spec' +import './math/index.spec' +import './objects/index.spec' import './renderers/index.spec' -// import './scenes/index.spec' +import './scenes/index.spec' -// import './constants.spec' -// import './utils.spec' +import './constants.spec' +import './utils.spec' From 97aefbc4f9b64fb353d7f4adf5d700fa824d7db7 Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Sun, 22 Nov 2020 19:20:37 -0800 Subject: [PATCH 05/10] BufferGeometry addGroup and clearGroups methods --- src/as/core/BufferGeometry.spec.ts | 55 +++++++++++++----------------- src/as/core/BufferGeometry.ts | 41 +++++++++------------- 2 files changed, 41 insertions(+), 55 deletions(-) diff --git a/src/as/core/BufferGeometry.spec.ts b/src/as/core/BufferGeometry.spec.ts index 191a7a5..f1cb376 100644 --- a/src/as/core/BufferGeometry.spec.ts +++ b/src/as/core/BufferGeometry.spec.ts @@ -4,7 +4,7 @@ * @author corruptedzulu / https://github.com/corruptedzulu */ -import {BufferGeometry} from './BufferGeometry' +import {BufferGeometry, BufferGeometryGroup} from './BufferGeometry' import { BufferAttribute, Uint16BufferAttribute, @@ -120,10 +120,6 @@ function compareUvs(uvs: f32[], u: Vector2[]): bool { } describe('BufferGeometry', () => { - // INHERITANCE - todo('Extending') - // INSTANCING - todo('Instancing') // PUBLIC STUFF todo('isBufferGeometry') @@ -175,32 +171,29 @@ describe('BufferGeometry', () => { expect(geometry.attributes.has(attributeName)).toBe(false) }) - //TODO: uncomment when group methods are implemented - // test('addGroup', () => { - // var a = new BufferGeometry() - // var expected = [ - // { - // start: 0, - // count: 1, - // materialIndex: 0, - // }, - // { - // start: 1, - // count: 2, - // materialIndex: 2, - // }, - // ] - - // a.addGroup(0, 1, 0) - // a.addGroup(1, 2, 2) - - // expect(a.groups).toStrictEqual(expected) - - // a.clearGroups() - // expect(a.groups.length).toBe(0) - // }) - - todo('clearGroups') + test('addGroup/clearGroups', () => { + var a = new BufferGeometry() + var expected: BufferGeometryGroup[] = [ + { + start: 0, + count: 1, + materialIndex: 0, + } as BufferGeometryGroup, + { + start: 1, + count: 2, + materialIndex: 2, + } as BufferGeometryGroup, + ] + + a.addGroup(0, 1) + a.addGroup(1, 2, 2) + + expect(a.groups).toStrictEqual(expected) + + a.clearGroups() + expect(a.groups.length).toBe(0) + }) //TODO: uncomment when appropriate methods are implemented // test('setDrawRange', () => { diff --git a/src/as/core/BufferGeometry.ts b/src/as/core/BufferGeometry.ts index b34ef43..b9a60b2 100644 --- a/src/as/core/BufferGeometry.ts +++ b/src/as/core/BufferGeometry.ts @@ -1,3 +1,10 @@ +/** + * @author alteredq / http://alteredqualia.com/ + * @author mrdoob / http://mrdoob.com/ + * @author corruptedzulu / http://github.com/corruptedzulu + * @author Joe Pea / http://github.com/trusktr + */ + import {Vector3} from '../math/Vector3' import {Box3} from '../math/Box3' import {EventDispatcher} from './EventDispatcher' @@ -24,22 +31,10 @@ import {fillUint32ArrayWithValues, fillUint16ArrayWithValues} from './TypedArray // import {Mesh} from '../objects/Mesh' // import {Line} from '../objects/Line' -/** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author corruptedzulu / http://github.com/corruptedzulu - */ - -class BufferGeometryGroup { +export class BufferGeometryGroup { start: i32 count: i32 materialIndex: i32 - - constructor(s: i32, c: i32, m: i32) { - this.start = s - this.count = c - this.materialIndex = m - } } class BufferGeometryDrawRange { @@ -88,7 +83,6 @@ export class BufferGeometry extends EventDispatcher { return this.index } - // setIndex(array: B) { setIndex(array: B): void { if (!(array instanceof BufferAttribute)) throw new Error('expected a BufferAttribute') this.setIndexFromBufferAttribute(array) @@ -109,6 +103,9 @@ export class BufferGeometry extends EventDispatcher { if (!(index.arrayType === ArrayType.Uint16 || index.arrayType === ArrayType.Uint32)) throw new TypeError('index must be a BufferAttribute with type Uint16 or Uint32') + // Three.js uses an item size 1 + if (index.itemSize != 1) throw new Error('index itemSize should be 1') + if ( (index.arrayType === ArrayType.Uint16 && index.arrays.Uint16.length == 0) || (index.arrayType === ArrayType.Uint32 && index.arrays.Uint32.length == 0) @@ -150,17 +147,13 @@ export class BufferGeometry extends EventDispatcher { return this } - // addGroup(start: f32, count: f32, materialIndex?: f32): void { - // this.groups.push(new BufferGeometryGroup(start, count, materialIndex)) - // // start: start, - // // count: count, - // // materialIndex: materialIndex !== undefined ? materialIndex : 0, - // // }) - // } + addGroup(start: i32, count: i32, materialIndex: i32 = 0): void { + this.groups.push({start, count, materialIndex} as BufferGeometryGroup) + } - // clearGroups(): void { - // this.groups = [] - // } + clearGroups(): void { + this.groups.length = 0 + } // setDrawRange(start: f32, count: f32): void { // this.drawRange.start = start From aa7a6741a97d75a582d29515945174a907676354 Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Sun, 22 Nov 2020 19:30:45 -0800 Subject: [PATCH 06/10] initial BoxBufferGeometry class completed We can skip BoxGeometry and just use BoxBufferGeometry for now. --- src/as/core/BufferAttribute.ts | 19 +- src/as/core/Face3.ts | 10 +- src/as/core/Geometry.ts | 472 +++++++++++++------------- src/as/core/TypedArrayUtils.ts | 8 +- src/as/geometries/BoxGeometry.spec.ts | 68 ++++ src/as/geometries/BoxGeometry.ts | 234 +++++++------ src/as/geometries/index.spec.ts | 1 + src/as/math/Vector3.ts | 100 +++--- src/as/test-utils.ts | 72 ++-- 9 files changed, 555 insertions(+), 429 deletions(-) create mode 100644 src/as/geometries/BoxGeometry.spec.ts create mode 100644 src/as/geometries/index.spec.ts diff --git a/src/as/core/BufferAttribute.ts b/src/as/core/BufferAttribute.ts index ad6c61c..6870411 100644 --- a/src/as/core/BufferAttribute.ts +++ b/src/as/core/BufferAttribute.ts @@ -8,6 +8,7 @@ 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' class UpdateRange { offset: f32 @@ -257,7 +258,7 @@ export class BufferAttribute { throw new Error( 'Wrong array type provided. Expected it to be an array of ' + getArrayTypeName(arrayType) + '.' ) - // TODO Also tell which type of array the user provided. + // TODO Also tell the user which type of array the user provided. } } @@ -483,6 +484,22 @@ export class BufferAttribute { // }; // } + + // TODO Make more of the following static from* methods as needed... + + 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) + attr.copyArray(fillUint32ArrayWithValues(array)) + return attr + } + + static fromArrayOfFloat32(array: f32[], itemSize: i32, normalized: boolean = false): Float32BufferAttribute { + if (array.length % itemSize != 0) throw new Error('itemSize does not fit into the array length') + const attr = new Float32BufferAttribute(array.length / itemSize, itemSize, normalized) + attr.copyArray(fillFloat32ArrayWithValues(array)) + return attr + } } export class Int8BufferAttribute extends BufferAttribute { diff --git a/src/as/core/Face3.ts b/src/as/core/Face3.ts index a72e75a..2a58a8e 100644 --- a/src/as/core/Face3.ts +++ b/src/as/core/Face3.ts @@ -20,6 +20,8 @@ import {Color} from './../math/Color' * @source https://github.com/mrdoob/three.js/blob/master/src/core/Face3.js */ export class Face3 { + id: i32 = 0 + /** * @param a Vertex A index. * @param b Vertex B index. @@ -33,12 +35,12 @@ export class Face3 { * @param materialIndex (optional) Material index (points to {@link Geometry.materials}). Default: 0. */ constructor( - public a: f32, - public b: f32, - public c: f32, + public a: i32, + public b: i32, + public c: i32, normals: Array = [], colors: Array = [], - public materialIndex: f32 = 0 + public materialIndex: i32 = 0 ) { let len = normals.length if (!(len === 0 || len === 1 || len === 3)) diff --git a/src/as/core/Geometry.ts b/src/as/core/Geometry.ts index ef8a6e6..50facd1 100644 --- a/src/as/core/Geometry.ts +++ b/src/as/core/Geometry.ts @@ -339,101 +339,102 @@ export class Geometry extends EventDispatcher { // this.applyMatrix(obj.matrix) // } - //TODO: uncomment when BufferGeometry is implemented - // fromBufferGeometry(geometry: BufferGeometry): Geometry { - // var scope = this + // TODO + // fromBufferGeometry(geometry: BufferGeometry): this { - // var indices = geometry.index !== null ? geometry.index.array : undefined - // var attributes = geometry.attributes + // const attr = geometry.index + // var indices: ArrayBufferView | null = null + // if (attr) indices = attr.arrays.Float32 + // // var attributes = geometry.attributes - // var positions = attributes.position.array - // var normals = attributes.normal !== undefined ? attributes.normal.array : undefined - // var colors = attributes.color !== undefined ? attributes.color.array : undefined - // var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined - // var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined + // // var positions = attributes.position.array + // // var normals = attributes.normal !== undefined ? attributes.normal.array : undefined + // // var colors = attributes.color !== undefined ? attributes.color.array : undefined + // // var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined + // // var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined - // if (uvs2 !== undefined) this.faceVertexUvs[1] = [] + // // if (uvs2 !== undefined) this.faceVertexUvs[1] = [] - // for (var i = 0; i < positions.length; i += 3) { - // scope.vertices.push(new Vector3().fromArray(positions, i)) + // // for (var i = 0; i < positions.length; i += 3) { + // // this.vertices.push(new Vector3().fromArray(positions, i)) - // if (colors !== undefined) { - // scope.colors.push(new Color().fromArray(colors, i)) - // } - // } - - // function addFace(a: f32, b: f32, c: f32, materialIndex: f32) { - // var vertexColors = - // colors === undefined ? [] : [scope.colors[a].clone(), scope.colors[b].clone(), scope.colors[c].clone()] - - // var vertexNormals = - // normals === undefined - // ? [] - // : [ - // new Vector3().fromArray(normals, a * 3), - // new Vector3().fromArray(normals, b * 3), - // new Vector3().fromArray(normals, c * 3), - // ] - - // var face = new Face3(a, b, c, vertexNormals, vertexColors, materialIndex) - - // scope.faces.push(face) - - // if (uvs !== undefined) { - // scope.faceVertexUvs[0].push([ - // new Vector2().fromArray(uvs, a * 2), - // new Vector2().fromArray(uvs, b * 2), - // new Vector2().fromArray(uvs, c * 2), - // ]) - // } - - // if (uvs2 !== undefined) { - // scope.faceVertexUvs[1].push([ - // new Vector2().fromArray(uvs2, a * 2), - // new Vector2().fromArray(uvs2, b * 2), - // new Vector2().fromArray(uvs2, c * 2), - // ]) - // } - // } - - // var groups = geometry.groups - - // if (groups.length > 0) { - // for (var i = 0; i < groups.length; i++) { - // var group = groups[i] + // // if (colors !== undefined) { + // // this.colors.push(new Color().fromArray(colors, i)) + // // } + // // } - // var start = group.start - // var count = group.count + // // const addFace = (a: f32, b: f32, c: f32, materialIndex: f32) => { + // // var vertexColors = + // // colors === undefined ? [] : [this.colors[a].clone(), this.colors[b].clone(), this.colors[c].clone()] + + // // var vertexNormals = + // // normals === undefined + // // ? [] + // // : [ + // // new Vector3().fromArray(normals, a * 3), + // // new Vector3().fromArray(normals, b * 3), + // // new Vector3().fromArray(normals, c * 3), + // // ] + + // // var face = new Face3(a, b, c, vertexNormals, vertexColors, materialIndex) + + // // this.faces.push(face) + + // // if (uvs !== undefined) { + // // this.faceVertexUvs[0].push([ + // // new Vector2().fromArray(uvs, a * 2), + // // new Vector2().fromArray(uvs, b * 2), + // // new Vector2().fromArray(uvs, c * 2), + // // ]) + // // } + + // // if (uvs2 !== undefined) { + // // this.faceVertexUvs[1].push([ + // // new Vector2().fromArray(uvs2, a * 2), + // // new Vector2().fromArray(uvs2, b * 2), + // // new Vector2().fromArray(uvs2, c * 2), + // // ]) + // // } + // // } - // for (var j = start, jl = start + count; j < jl; j += 3) { - // if (indices !== undefined) { - // addFace(indices[j], indices[j + 1], indices[j + 2], group.materialIndex) - // } else { - // addFace(j, j + 1, j + 2, group.materialIndex) - // } - // } - // } - // } else { - // if (indices !== undefined) { - // for (var i = 0; i < indices.length; i += 3) { - // addFace(indices[i], indices[i + 1], indices[i + 2], 0) - // } - // } else { - // for (var i = 0; i < positions.length / 3; i += 3) { - // addFace(i, i + 1, i + 2, 0) - // } - // } - // } + // // var groups = geometry.groups + + // // if (groups.length > 0) { + // // for (var i = 0; i < groups.length; i++) { + // // var group = groups[i] + + // // var start = group.start + // // var count = group.count + + // // for (var j = start, jl = start + count; j < jl; j += 3) { + // // if (indices !== undefined) { + // // addFace(indices[j], indices[j + 1], indices[j + 2], group.materialIndex) + // // } else { + // // addFace(j, j + 1, j + 2, group.materialIndex) + // // } + // // } + // // } + // // } else { + // // if (indices !== undefined) { + // // for (var i = 0; i < indices.length; i += 3) { + // // addFace(indices[i], indices[i + 1], indices[i + 2], 0) + // // } + // // } else { + // // for (var i = 0; i < positions.length / 3; i += 3) { + // // addFace(i, i + 1, i + 2, 0) + // // } + // // } + // // } - // this.computeFaceNormals() + // // this.computeFaceNormals() - // if (geometry.boundingBox !== null) { - // this.boundingBox = geometry.boundingBox.clone() - // } + // // if (geometry.boundingBox !== null) { + // // this.boundingBox = geometry.boundingBox.clone() + // // } - // if (geometry.boundingSphere !== null) { - // this.boundingSphere = geometry.boundingSphere.clone() - // } + // // if (geometry.boundingSphere !== null) { + // // this.boundingSphere = geometry.boundingSphere.clone() + // // } // return this // } @@ -843,18 +844,23 @@ export class Geometry extends EventDispatcher { */ mergeVertices(): i32 { var verticesMap: Map = new Map() // Hashmap for looking up vertices by position coordinates (and making sure they are unique) - var unique = [], - changes: f32[] = [] + var unique: Vector3[] = [], + changes: i32[] = [] var v: Vector3, key: string - var precisionPoints = 4 // number of decimal points, e.g. 4 for epsilon of 0.0001 - var precision = Mathf.pow(10, precisionPoints) + var precisionPoints: f32 = 4.0 // number of decimal points, e.g. 4 for epsilon of 0.0001 + var precision = Mathf.pow(10.0, precisionPoints) var i: i32, il: i32, face: Face3 - var indices: f32[], j: i32, jl: i32 + var indices: i32[], j: i32, jl: i32 for (i = 0, il = this.vertices.length; i < il; i++) { v = this.vertices[i] - key = Mathf.round(v.x * precision) + '_' + Mathf.round(v.y * precision) + '_' + Mathf.round(v.z * precision) + key = + Mathf.round(v.x * precision).toString() + + '_' + + Mathf.round(v.y * precision).toString() + + '_' + + Mathf.round(v.z * precision).toString() if (!verticesMap.has(key)) { verticesMap.set(key, i) @@ -868,7 +874,7 @@ export class Geometry extends EventDispatcher { // if faces are completely degenerate after merging vertices, we // have to remove them from the geometry. - var faceIndicesToRemove = [] + var faceIndicesToRemove: i32[] = [] for (i = 0, il = this.faces.length; i < il; i++) { face = this.faces[i] @@ -967,179 +973,175 @@ export class Geometry extends EventDispatcher { if (didSetUvs2) this.faceVertexUvs[1] = newUvs2 } - toJSON(): any { - var data: any = { - metadata: { - version: 4.5, - type: 'Geometry', - generator: 'Geometry.toJSON', - }, - uuid: '', - type: '', - name: '', - data: { - vertices: [], - normals: [], - faces: [], - colors: [], - }, - } - - // standard Geometry serialization - - data.uuid = this.uuid - data.type = this.type - if (this.name !== '') data.name = this.name - - //Commenting out until Parameters are actually needed - // if ( this.parameters !== undefined ) { - - // var parameters = this.parameters; + // TODO? Do we need to/fromJSON? + // toJSON(): any { + // var data: any = { + // metadata: { + // version: 4.5, + // type: 'Geometry', + // generator: 'Geometry.toJSON', + // }, + // uuid: '', + // type: '', + // name: '', + // data: { + // vertices: [], + // normals: [], + // faces: [], + // colors: [], + // }, + // } - // for ( var key in parameters ) { + // // standard Geometry serialization - // if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + // data.uuid = this.uuid + // data.type = this.type + // if (this.name !== '') data.name = this.name - // } + // if (this.parameters !== undefined) { + // var parameters = this.parameters - // return data; + // for (var key in parameters) { + // if (parameters[key] !== undefined) data[key] = parameters[key] + // } - // } + // return data + // } - var vertices = [] + // var vertices = [] - for (var i = 0; i < this.vertices.length; i++) { - var vertex = this.vertices[i] - vertices.push(vertex.x) - vertices.push(vertex.y) - vertices.push(vertex.z) - } + // for (var i = 0; i < this.vertices.length; i++) { + // var vertex = this.vertices[i] + // vertices.push(vertex.x) + // vertices.push(vertex.y) + // vertices.push(vertex.z) + // } - var faces = [] - var normals: Vector3[] = [] - var normalsHash: Map = new Map() - var colors: string[] = [] - var colorsHash: Map = new Map() - var uvs: Vector2[] = [] - var uvsHash: Map = new Map() - - for (var i = 0; i < this.faces.length; i++) { - var face = this.faces[i] - - var hasMaterial = true - var hasFaceUv = false // deprecated - var hasFaceVertexUv = this.faceVertexUvs[0][i] !== undefined - var hasFaceNormal = face.normal.length() > 0 - var hasFaceVertexNormal = face.vertexNormals.length > 0 - var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1 - var hasFaceVertexColor = face.vertexColors.length > 0 - - var faceType = 0 - - faceType = setBit(faceType, 0, false) // isQuad - faceType = setBit(faceType, 1, hasMaterial) - faceType = setBit(faceType, 2, hasFaceUv) - faceType = setBit(faceType, 3, hasFaceVertexUv) - faceType = setBit(faceType, 4, hasFaceNormal) - faceType = setBit(faceType, 5, hasFaceVertexNormal) - faceType = setBit(faceType, 6, hasFaceColor) - faceType = setBit(faceType, 7, hasFaceVertexColor) - - faces.push(faceType) - faces.push(face.a) - faces.push(face.b) - faces.push(face.c) - faces.push(face.materialIndex) - - if (hasFaceVertexUv) { - var faceVertexUvs = this.faceVertexUvs[0][i] - - faces.push(getUvIndex(faceVertexUvs[0])) - faces.push(getUvIndex(faceVertexUvs[1])) - faces.push(getUvIndex(faceVertexUvs[2])) - } + // var faces = [] + // var normals: Vector3[] = [] + // var normalsHash: Map = new Map() + // var colors: string[] = [] + // var colorsHash: Map = new Map() + // var uvs: Vector2[] = [] + // var uvsHash: Map = new Map() + + // for (var i = 0; i < this.faces.length; i++) { + // var face = this.faces[i] + + // var hasMaterial = true + // var hasFaceUv = false // deprecated + // var hasFaceVertexUv = this.faceVertexUvs[0][i] !== undefined + // var hasFaceNormal = face.normal.length() > 0 + // var hasFaceVertexNormal = face.vertexNormals.length > 0 + // var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1 + // var hasFaceVertexColor = face.vertexColors.length > 0 + + // var faceType = 0 + + // faceType = setBit(faceType, 0, false) // isQuad + // faceType = setBit(faceType, 1, hasMaterial) + // faceType = setBit(faceType, 2, hasFaceUv) + // faceType = setBit(faceType, 3, hasFaceVertexUv) + // faceType = setBit(faceType, 4, hasFaceNormal) + // faceType = setBit(faceType, 5, hasFaceVertexNormal) + // faceType = setBit(faceType, 6, hasFaceColor) + // faceType = setBit(faceType, 7, hasFaceVertexColor) + + // faces.push(faceType) + // faces.push(face.a) + // faces.push(face.b) + // faces.push(face.c) + // faces.push(face.materialIndex) + + // if (hasFaceVertexUv) { + // var faceVertexUvs = this.faceVertexUvs[0][i] + + // faces.push(getUvIndex(faceVertexUvs[0])) + // faces.push(getUvIndex(faceVertexUvs[1])) + // faces.push(getUvIndex(faceVertexUvs[2])) + // } - if (hasFaceNormal) { - faces.push(getNormalIndex(face.normal)) - } + // if (hasFaceNormal) { + // faces.push(getNormalIndex(face.normal)) + // } - if (hasFaceVertexNormal) { - var vertexNormals: Vector3[] = face.vertexNormals + // if (hasFaceVertexNormal) { + // var vertexNormals: Vector3[] = face.vertexNormals - faces.push(getNormalIndex(vertexNormals[0])) - faces.push(getNormalIndex(vertexNormals[1])) - faces.push(getNormalIndex(vertexNormals[2])) - } + // faces.push(getNormalIndex(vertexNormals[0])) + // faces.push(getNormalIndex(vertexNormals[1])) + // faces.push(getNormalIndex(vertexNormals[2])) + // } - if (hasFaceColor) { - faces.push(getColorIndex(face.color)) - } + // if (hasFaceColor) { + // faces.push(getColorIndex(face.color)) + // } - if (hasFaceVertexColor) { - var vertexColors = face.vertexColors + // if (hasFaceVertexColor) { + // var vertexColors = face.vertexColors - faces.push(getColorIndex(vertexColors[0])) - faces.push(getColorIndex(vertexColors[1])) - faces.push(getColorIndex(vertexColors[2])) - } - } + // faces.push(getColorIndex(vertexColors[0])) + // faces.push(getColorIndex(vertexColors[1])) + // faces.push(getColorIndex(vertexColors[2])) + // } + // } - function setBit(value: f32, position: f32, enabled: boolean) { - return enabled ? value | (1 << position) : value & ~(1 << position) - } + // function setBit(value: f32, position: f32, enabled: boolean) { + // return enabled ? value | (1 << position) : value & ~(1 << position) + // } - function getNormalIndex(normal: Vector3) { - var hash: string = normal.x.toString() + normal.y.toString() + normal.z.toString() + // function getNormalIndex(normal: Vector3) { + // var hash: string = normal.x.toString() + normal.y.toString() + normal.z.toString() - if (normalsHash.has(hash)) { - return normalsHash.get(hash) - } + // if (normalsHash.has(hash)) { + // return normalsHash.get(hash) + // } - normalsHash.set(hash, normals.length / 3) - // normals.push( normal.x, normal.y, normal.z ); - normals.push(new Vector3(normal.x, normal.y, normal.z)) + // normalsHash.set(hash, normals.length / 3) + // // normals.push( normal.x, normal.y, normal.z ); + // normals.push(new Vector3(normal.x, normal.y, normal.z)) - return normalsHash.get(hash) - } + // return normalsHash.get(hash) + // } - function getColorIndex(color: Color) { - var hash: string = color.r.toString() + color.g.toString() + color.b.toString() + // function getColorIndex(color: Color) { + // var hash: string = color.r.toString() + color.g.toString() + color.b.toString() - if (colorsHash.has(hash)) { - return colorsHash.get(hash) - } + // if (colorsHash.has(hash)) { + // return colorsHash.get(hash) + // } - colorsHash.set(hash, colors.length) - colors.push(color.getHex().toString()) - // colors.push(color.getHex()) + // colorsHash.set(hash, colors.length) + // colors.push(color.getHex().toString()) + // // colors.push(color.getHex()) - return colorsHash.get(hash) - } + // return colorsHash.get(hash) + // } - function getUvIndex(uv: Vector2) { - var hash = uv.x.toString() + uv.y.toString() + // function getUvIndex(uv: Vector2) { + // var hash = uv.x.toString() + uv.y.toString() - if (uvsHash.has(hash)) { - return uvsHash.get(hash) - } + // if (uvsHash.has(hash)) { + // return uvsHash.get(hash) + // } - uvsHash.set(hash, uvs.length / 2) - // uvs.push( uv.x, uv.y ); - uvs.push(new Vector2(uv.x, uv.y)) + // uvsHash.set(hash, uvs.length / 2) + // // uvs.push( uv.x, uv.y ); + // uvs.push(new Vector2(uv.x, uv.y)) - return uvsHash.get(hash) - } + // return uvsHash.get(hash) + // } - data.data = {} + // data.data = {} - data.data.vertices = vertices - data.data.normals = normals - if (colors.length > 0) data.data.colors = colors - if (uvs.length > 0) data.data.uvs = [uvs] // temporal backward compatibility - data.data.faces = faces + // data.data.vertices = vertices + // data.data.normals = normals + // if (colors.length > 0) data.data.colors = colors + // if (uvs.length > 0) data.data.uvs = [uvs] // temporal backward compatibility + // data.data.faces = faces - return data - } + // return data + // } /** * Creates a new clone of the Geometry. diff --git a/src/as/core/TypedArrayUtils.ts b/src/as/core/TypedArrayUtils.ts index ab3572a..dfa02c3 100644 --- a/src/as/core/TypedArrayUtils.ts +++ b/src/as/core/TypedArrayUtils.ts @@ -26,16 +26,12 @@ export function fillUint16ArrayWithValues(source: u16[], typedArray: Uint16Array return typedArray } -export function fillUint32ArrayWithValues(source: A, typedArray: Uint32Array | null = null): Uint32Array { +export function fillUint32ArrayWithValues(source: u32[], typedArray: Uint32Array | null = null): Uint32Array { if (!Array.isArray(source)) throw new Error('source must be an Array') let length = source.length - // if (typedArray && length != typedArray.length) throw new Error('Length mismatch.') - - // if (length == 0) throw new Error('Nothing to copy. Why are you doing that?') - - // if (!isFloat(source[0]) || !isInteger(source[0])) throw new Error('Expected a number array') + if (typedArray && length != typedArray.length) throw new Error('Length mismatch.') if (!typedArray) typedArray = new Uint32Array(length) diff --git a/src/as/geometries/BoxGeometry.spec.ts b/src/as/geometries/BoxGeometry.spec.ts new file mode 100644 index 0000000..3320526 --- /dev/null +++ b/src/as/geometries/BoxGeometry.spec.ts @@ -0,0 +1,68 @@ +/** + * @author TristanVALCKE / https://github.com/Itee + */ + +import {runStdGeometryTests} from '../test-utils' +import {BoxBufferGeometry, BoxGeometryParameters} from './BoxGeometry' +import {BufferGeometry} from '../core/BufferGeometry' +import {Float32BufferAttribute} from '../core/BufferAttribute' + +let geometries: BufferGeometry[] = [] + +describe('Geometries', (): void => { + describe('BoxBufferGeometry', (): void => { + beforeEach((): void => { + const parameters = { + width: 10, + height: 20, + depth: 30, + widthSegments: 2, + heightSegments: 3, + depthSegments: 4, + } as BoxGeometryParameters + + geometries = [ + new BoxBufferGeometry(), + new BoxBufferGeometry(parameters.width, parameters.height, parameters.depth), + new BoxBufferGeometry( + parameters.width, + parameters.height, + parameters.depth, + parameters.widthSegments, + parameters.heightSegments, + parameters.depthSegments + ), + ] + }) + + // OTHERS + test('Standard geometry tests', (): void => { + runStdGeometryTests(geometries) + }) + + test('the box has the vertext shape we expect', () => { + const geom = new BoxBufferGeometry(4, 4, 4) + + expect(geom.attributes.has('position') && geom.attributes.has('normal') && geom.attributes.has('uv')).toBe( + true, + 'it should have attributes' + ) + + const positionAttr = geom.attributes.get('position') as Float32BufferAttribute + + expect(positionAttr.arrays.Float32.length).toBeGreaterThan(0, 'it should have vertices') + // TODO test how many items the array should have. + + // The box is centered on its local origin, so because the size is + // 4x4x4 then the absolute value of the vertex positions should all + // be 2. + + for (let i = 0; i < positionAttr.arrays.Float32.length; i++) { + const coordinate = Math.abs(positionAttr.arrays.Float32[i]) + expect(coordinate).toBe(2.0, 'absolute vertex position should be 2') + } + }) + + todo('more-detailed tests') + }) +}) diff --git a/src/as/geometries/BoxGeometry.ts b/src/as/geometries/BoxGeometry.ts index 12d8874..4cbae02 100644 --- a/src/as/geometries/BoxGeometry.ts +++ b/src/as/geometries/BoxGeometry.ts @@ -7,76 +7,148 @@ import {Geometry} from '../core/Geometry' import {BufferGeometry} from '../core/BufferGeometry' -import {Float32BufferAttribute} from '../core/BufferAttribute' +import {BufferAttribute} from '../core/BufferAttribute' import {Vector3} from '../math/Vector3' +export class BoxGeometryParameters { + public width: f32 + public height: f32 + public depth: f32 + public widthSegments: i32 + public heightSegments: i32 + public depthSegments: i32 +} + +/** + * BoxGeometry is the quadrilateral primitive geometry class. It is typically used for creating a cube or irregular quadrilateral of the dimensions provided within the (optional) 'width', 'height', & 'depth' constructor arguments. + */ +export class BoxGeometry extends Geometry { + // Used for JSON serialization (we only need to import/export these + // parameters, the rest is state created by the class at runtime). + parameters: BoxGeometryParameters + + /** + * @param width — Width of the sides on the X axis. + * @param height — Height of the sides on the Y axis. + * @param depth — Depth of the sides on the Z axis. + * @param widthSegments — Number of segmented faces along the width of the sides. + * @param heightSegments — Number of segmented faces along the height of the sides. + * @param depthSegments — Number of segmented faces along the depth of the sides. + */ + constructor( + width: f32 = 1, + height: f32 = 1, + depth: f32 = 1, + widthSegments: i32 = 1, + heightSegments: i32 = 1, + depthSegments: i32 = 1 + ) { + super() + + this.type = 'BoxGeometry' + + this.parameters = { + width, + height, + depth, + widthSegments, + heightSegments, + depthSegments, + } as BoxGeometryParameters + + // TODO For the initial demo we'll just use BoxBufferGeometry (which is + // already implemented) instead of BoxGeometry. We can add BoxGeometry + // later. BoxGeometry is a convenience wrapper for BoxBufferGeometry. + //this.fromBufferGeometry( + // new BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) + //) + + this.mergeVertices() + } +} + +var vector = new Vector3() + // Extras / Geometries ///////////////////////////////////////////////////////////////////// export class BoxBufferGeometry extends BufferGeometry { - parameters: { - width: f32 - height: f32 - depth: f32 - widthSegments: f32 - heightSegments: f32 - depthSegments: f32 - } + // Used for JSON serialization (we only need to import/export these + // parameters, the rest is state created by the class at runtime). + parameters: BoxGeometryParameters - indices: f32[] = [] - vertices: f32[] = [] - normals: f32[] = [] - uvs: f32[] = [] + // In Three.js this maps to either a Uint16BufferAttribute or a + // Uint32BufferAttribute. For now we'll just use Uint32BufferAttribute. + // TODO? Support both? + private indices: u32[] = [] - // helper variables + private vertices: f32[] = [] + private normals: f32[] = [] + private uvs: f32[] = [] - numberOfVertices = 0 - groupStart = 0 + // helper variables - scope = this + private numberOfVertices: i32 = 0 + private groupStart: i32 = 0 constructor( width: f32 = 1, height: f32 = 1, depth: f32 = 1, - widthSegments: f32 = 1, - heightSegments: f32 = 1, - depthSegments: f32 = 1 + widthSegments: i32 = 1, + heightSegments: i32 = 1, + depthSegments: i32 = 1 ) { super() - this.buildPlane('z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0) // px - this.buildPlane('z', 'y', 'x', 1, -1, depth, height, -width, depthSegments, heightSegments, 1) // nx - this.buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2) // py - this.buildPlane('x', 'z', 'y', 1, -1, width, depth, -height, widthSegments, depthSegments, 3) // ny - this.buildPlane('x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4) // pz - this.buildPlane('x', 'y', 'z', -1, -1, width, height, -depth, widthSegments, heightSegments, 5) // nz + this.type = 'BoxBufferGeometry' + + this.parameters = { + width, + height, + depth, + widthSegments, + heightSegments, + depthSegments, + } as BoxGeometryParameters + + this.__buildPlane('z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0) // px + this.__buildPlane('z', 'y', 'x', 1, -1, depth, height, -width, depthSegments, heightSegments, 1) // nx + this.__buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2) // py + this.__buildPlane('x', 'z', 'y', 1, -1, width, depth, -height, widthSegments, depthSegments, 3) // ny + this.__buildPlane('x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4) // pz + this.__buildPlane('x', 'y', 'z', -1, -1, width, height, -depth, widthSegments, heightSegments, 5) // nz // build geometry - this.setIndex(this.indices) - this.addAttribute('position', new Float32BufferAttribute(this.vertices, 3)) - this.addAttribute('normal', new Float32BufferAttribute(this.normals, 3)) - this.addAttribute('uv', new Float32BufferAttribute(this.uvs, 2)) + // Note, Three.js creates the index with itemSize of 1. Not sure that it + // really matters in this case, it may just read the underlying typed + // array directly. + // TODO Ability to pass this.indices directly into this.setIndex. + this.setIndex(BufferAttribute.fromArrayOfUint32(this.indices, 1)) + + this.addAttribute('position', BufferAttribute.fromArrayOfFloat32(this.vertices, 3)) + this.addAttribute('normal', BufferAttribute.fromArrayOfFloat32(this.normals, 3)) + this.addAttribute('uv', BufferAttribute.fromArrayOfFloat32(this.uvs, 2)) } - buildPlane( + private __buildPlane( u: string, v: string, w: string, - udir: i64, - vdir: i64, - width: i64, - height: i64, - depth: i64, - gridX: i64, - gridY: i64, - materialIndex: i64 - ) { - var segmentWidth = width / gridX - var segmentHeight = height / gridY - - var widthHalf = width / 2 - var heightHalf = height / 2 - var depthHalf = depth / 2 + udir: f32, + vdir: f32, + width: f32, + height: f32, + depth: f32, + gridX: i32, + gridY: i32, + materialIndex: i32 + ): void { + var segmentWidth = width / (gridX as f32) + var segmentHeight = height / (gridY as f32) + + var widthHalf = width / 2.0 + var heightHalf = height / 2.0 + var depthHalf = depth / 2.0 var gridX1 = gridX + 1 var gridY1 = gridY + 1 @@ -84,23 +156,21 @@ export class BoxBufferGeometry extends BufferGeometry { var vertexCounter = 0 var groupCount = 0 - var ix, iy - - var vector = new Vector3() + var ix: i32, iy: i32 // generate vertices, normals and uvs for (iy = 0; iy < gridY1; iy++) { - var y = iy * segmentHeight - heightHalf + var y = (iy as f32) * segmentHeight - heightHalf for (ix = 0; ix < gridX1; ix++) { - var x = ix * segmentWidth - widthHalf + var x = (ix as f32) * segmentWidth - widthHalf // set values to correct vector component - vector.setX(x * udir) - vector.setY(y * vdir) - vector.setZ(depthHalf) + vector.setComponent(u, x * udir) + vector.setComponent(v, y * vdir) + vector.setComponent(w, depthHalf) // now apply vector to vertex buffer @@ -110,9 +180,9 @@ export class BoxBufferGeometry extends BufferGeometry { // set values to correct vector component - vector.setX(0) - vector.setY(0) - vector.setZ(depth > 0 ? 1 : -1) + vector.setComponent(u, 0) + vector.setComponent(v, 0) + vector.setComponent(w, depth > 0 ? 1 : -1) // now apply vector to normal buffer @@ -122,8 +192,8 @@ export class BoxBufferGeometry extends BufferGeometry { // uvs - this.uvs.push(ix / gridX) - this.uvs.push(1 - iy / gridY) + this.uvs.push((ix as f32) / (gridX as f32)) + this.uvs.push(1.0 - (iy as f32) / (gridY as f32)) // counters @@ -139,10 +209,10 @@ export class BoxBufferGeometry extends BufferGeometry { for (iy = 0; iy < gridY; iy++) { for (ix = 0; ix < gridX; ix++) { - var a = this.numberOfVertices + ix + gridX1 * iy - var b = this.numberOfVertices + ix + gridX1 * (iy + 1) - var c = this.numberOfVertices + (ix + 1) + gridX1 * (iy + 1) - var d = this.numberOfVertices + (ix + 1) + gridX1 * iy + var a: u32 = this.numberOfVertices + ix + gridX1 * iy + var b: u32 = this.numberOfVertices + ix + gridX1 * (iy + 1) + var c: u32 = this.numberOfVertices + (ix + 1) + gridX1 * (iy + 1) + var d: u32 = this.numberOfVertices + (ix + 1) + gridX1 * iy // faces @@ -161,7 +231,7 @@ export class BoxBufferGeometry extends BufferGeometry { // add a group to the geometry. this will ensure multi material support - this.scope.addGroup(this.groupStart, groupCount, materialIndex) + this.addGroup(this.groupStart, groupCount, materialIndex) // calculate new start value for groups @@ -172,39 +242,3 @@ export class BoxBufferGeometry extends BufferGeometry { this.numberOfVertices += vertexCounter } } - -/** - * BoxGeometry is the quadrilateral primitive geometry class. It is typically used for creating a cube or irregular quadrilateral of the dimensions provided within the (optional) 'width', 'height', & 'depth' constructor arguments. - */ -export class BoxGeometry extends Geometry { - width: f32 - height: f32 - depth: f32 - widthSegments: f32 - heightSegments: f32 - depthSegments: f32 - - /** - * @param width — Width of the sides on the X axis. - * @param height — Height of the sides on the Y axis. - * @param depth — Depth of the sides on the Z axis. - * @param widthSegments — Number of segmented faces along the width of the sides. - * @param heightSegments — Number of segmented faces along the height of the sides. - * @param depthSegments — Number of segmented faces along the depth of the sides. - */ - constructor( - width: f32 = 1, - height: f32 = 1, - depth: f32 = 1, - widthSegments: f32 = 1, - heightSegments: f32 = 1, - depthSegments: f32 = 1 - ) { - super() - - this.fromBufferGeometry( - new BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) - ) - this.mergeVertices() - } -} diff --git a/src/as/geometries/index.spec.ts b/src/as/geometries/index.spec.ts new file mode 100644 index 0000000..2b2dc04 --- /dev/null +++ b/src/as/geometries/index.spec.ts @@ -0,0 +1 @@ +import './BoxGeometry.spec' diff --git a/src/as/math/Vector3.ts b/src/as/math/Vector3.ts index 28e6f12..7652e94 100644 --- a/src/as/math/Vector3.ts +++ b/src/as/math/Vector3.ts @@ -67,63 +67,63 @@ export class Vector3 /*implements Vector*/ { // return this // } - // /** - // * Sets x value of this vector. - // */ - // setX(x: f32): Vector3 { - // this.x = x - - // return this - // } + /** + * Sets x value of this vector. + */ + setX(x: f32): this { + this.x = x - // /** - // * Sets y value of this vector. - // */ - // setY(y: f32): Vector3 { - // this.y = y + return this + } - // return this - // } + /** + * Sets y value of this vector. + */ + setY(y: f32): this { + this.y = y - // /** - // * Sets z value of this vector. - // */ - // setZ(z: f32): Vector3 { - // this.z = z + return this + } - // return this - // } + /** + * Sets z value of this vector. + */ + setZ(z: f32): this { + this.z = z - // setComponent(index: f32, value: f32): this { - // switch (index) { - // case 0: - // this.x = value - // break - // case 1: - // this.y = value - // break - // case 2: - // this.z = value - // break - // default: - // throw new Error('index is out of range: ' + index) - // } + return this + } - // return this - // } + private __xChar: u32 = u32('x'.charCodeAt(0)) + private __yChar: u32 = u32('y'.charCodeAt(0)) + private __zChar: u32 = u32('z'.charCodeAt(0)) + private __invalidNameMsg: string = 'Invalid component name. Exected "x", "y", or "z".' + + setComponent(name: string, value: f32): this { + if (name.length != 1) throw new Error(this.__invalidNameMsg) + + // prettier-ignore + // Note, AS only supports u32 values (f.e. enums) in switch statements, that's why we cast. + switch (u32(name.charCodeAt(0))) { + case this.__xChar: return this.setX(value) + case this.__yChar: return this.setY(value) + case this.__zChar: return this.setZ(value) + default: throw new Error(this.__invalidNameMsg) + } + } - // getComponent(index: f32): f32 { - // switch (index) { - // case 0: - // return this.x - // case 1: - // return this.y - // case 2: - // return this.z - // default: - // throw new Error('index is out of range: ' + index) - // } - // } + getComponent(name: string): f32 { + if (name.length != 1) throw new Error(this.__invalidNameMsg) + + // prettier-ignore + // Note, AS only supports u32 values (f.e. enums) in switch statements, that's why we cast. + switch (u32(name.charCodeAt(0))) { + case this.__xChar: return this.x + case this.__yChar: return this.y + case this.__zChar: return this.z + default: throw new Error(this.__invalidNameMsg) + } + } // /** // * Clones this vector. diff --git a/src/as/test-utils.ts b/src/as/test-utils.ts index a508c3b..6b82b57 100644 --- a/src/as/test-utils.ts +++ b/src/as/test-utils.ts @@ -1,6 +1,8 @@ import {Light} from './lights/Light' import {PointLight} from './lights/PointLight' import {Color} from './math/Color' +import {BufferGeometry} from './core/BufferGeometry' +import {Geometry} from './core/Geometry' // // Custom QUnit assertions. @@ -66,15 +68,16 @@ import {Color} from './math/Color' // }) // } -// // -// // GEOMETRY TEST HELPERS -// // +// +// GEOMETRY TEST HELPERS +// -// function checkGeometryClone(geom) { +// TODO +// function checkGeometryClone(geom: BufferGeometry) { // // Clone // var copy = geom.clone() -// QUnit.assert.notEqual(copy.uuid, geom.uuid, 'clone uuid should differ from original') -// QUnit.assert.notEqual(copy.id, geom.id, 'clone id should differ from original') +// expect(copy.uuid).not.toStrictEqual( geom.uuid, 'clone uuid should differ from original') +// expect(copy.id).not.toStrictEqual(geom.id, 'clone id should differ from original') // var excludedProperties = ['parameters', 'widthSegments', 'heightSegments', 'depthSegments'] @@ -84,8 +87,8 @@ import {Color} from './math/Color' // differingProp = getDifferingProp(copy, geom, excludedProperties) // QUnit.assert.ok(differingProp === undefined, 'properties are equal') -// // json round trip with clone -// checkGeometryJsonRoundtrip(copy) +// // TODO? json round trip with clone +// // checkGeometryJsonRoundtrip(copy) // } // function getDifferingProp(geometryA, geometryB, excludedProperties) { @@ -167,40 +170,43 @@ import {Color} from './math/Color' // checkGeometryJsonReading(json, geom) // } -// // Look for undefined and NaN values in numerical fieds. -// function checkFinite(geom) { -// var allVerticesAreFinite = true +// Look for undefined and NaN values in numerical fieds. +function checkFinite(geom: G): void { + var allVerticesAreFinite = true -// var vertices = geom.vertices || [] + if (geom instanceof Geometry) { + var vertices = geom.vertices -// for (var i = 0, l = vertices.length; i < l; i++) { -// var v = geom.vertices[i] + for (var i = 0, l = vertices.length; i < l; i++) { + var v = geom.vertices[i] -// if (!(isFinite(v.x) || isFinite(v.y) || isFinite(v.z))) { -// allVerticesAreFinite = false -// break -// } -// } + if (!(isFinite(v.x) || isFinite(v.y) || isFinite(v.z))) { + allVerticesAreFinite = false + break + } + } + } -// // TODO Buffers, normal, etc. + // TODO BufferGeometry, normal, etc. + todo('runStdGeometryTests for BufferGeometry too') -// QUnit.assert.ok(allVerticesAreFinite, 'contains only finite coordinates') -// } + expect(allVerticesAreFinite).toBe(true, 'contains only finite coordinates') +} -// // Run common geometry tests. -// export function runStdGeometryTests(assert, geometries) { -// for (var i = 0, l = geometries.length; i < l; i++) { -// var geom = geometries[i] +// Run common geometry tests. +export function runStdGeometryTests(geometries: G[]): void { + for (var i = 0, l = geometries.length; i < l; i++) { + var geom = geometries[i] -// checkFinite(geom) + checkFinite(geom) -// // Clone -// checkGeometryClone(geom) + // TODO Clone + // checkGeometryClone(geom) -// // json round trip -// checkGeometryJsonRoundtrip(geom) -// } -// } + // TODO? json round trip + // checkGeometryJsonRoundtrip(geom) + } +} // // // // LIGHT TEST HELPERS From 81a190bbf7d3fed0479e42849b119d7c011829df Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Mon, 23 Nov 2020 00:17:05 -0800 Subject: [PATCH 07/10] port MeshPhongMaterial That was too easy. WebGLRenderer will map from the material to the actual GLSL shader. --- src/as/materials/Material.spec.ts | 5 +- src/as/materials/Material.ts | 5 +- src/as/materials/MeshPhongMaterial.d.ts | 85 ----------- src/as/materials/MeshPhongMaterial.js | 166 -------------------- src/as/materials/MeshPhongMaterial.spec.ts | 16 ++ src/as/materials/MeshPhongMaterial.ts | 169 +++++++++++++++++++++ src/as/materials/index.spec.ts | 1 + src/as/objects/Mesh.spec.ts | 38 ++--- src/as/objects/Mesh.ts | 111 ++++++++------ 9 files changed, 266 insertions(+), 330 deletions(-) delete mode 100644 src/as/materials/MeshPhongMaterial.d.ts delete mode 100644 src/as/materials/MeshPhongMaterial.js create mode 100644 src/as/materials/MeshPhongMaterial.spec.ts create mode 100644 src/as/materials/MeshPhongMaterial.ts diff --git a/src/as/materials/Material.spec.ts b/src/as/materials/Material.spec.ts index b5345fa..59b9dcb 100644 --- a/src/as/materials/Material.spec.ts +++ b/src/as/materials/Material.spec.ts @@ -2,7 +2,10 @@ import {Material} from './Material' describe('Materials', () => { describe('Material', () => { - todo('isMaterial') + test('isMaterial', () => { + const mat = new Material() + expect(mat.isMaterial).toBe(true, 'it should be true') + }) todo('onBeforeCompile') todo('setValues') todo('toJSON') diff --git a/src/as/materials/Material.ts b/src/as/materials/Material.ts index dcd5ea1..5d1cef8 100644 --- a/src/as/materials/Material.ts +++ b/src/as/materials/Material.ts @@ -502,15 +502,14 @@ export class Material extends EventDispatcher { // }, /** - * Return a new material with the same parameters as this material. + * Return a new material with the same properties as this material. */ clone(): Material { return new Material().copy(this) } /** - * Copy the parameters from the passed material into this material. - * @param material + * Copy the properties from the passed material into this material. */ copy(source: Material): this { this.name = source.name diff --git a/src/as/materials/MeshPhongMaterial.d.ts b/src/as/materials/MeshPhongMaterial.d.ts deleted file mode 100644 index 06c9c32..0000000 --- a/src/as/materials/MeshPhongMaterial.d.ts +++ /dev/null @@ -1,85 +0,0 @@ -import {Color} from './../math/Color' -import {Texture} from './../textures/Texture' -import {Vector2} from './../math/Vector2' -import {MaterialParameters, Material} from './Material' -import {Combine, NormalMapTypes} from '../constants' - -export interface MeshPhongMaterialParameters extends MaterialParameters { - /** geometry color in hexadecimal. Default is 0xffffff. */ - color?: Color | string | f32 - specular?: Color | string | f32 - shininess?: f32 - opacity?: f32 - map?: Texture - lightMap?: Texture - lightMapIntensity?: f32 - aoMap?: Texture - aoMapIntensity?: f32 - emissive?: Color | string | f32 - emissiveIntensity?: f32 - emissiveMap?: Texture - bumpMap?: Texture - bumpScale?: f32 - normalMap?: Texture - normalMapType?: NormalMapTypes - normalScale?: Vector2 - displacementMap?: Texture - displacementScale?: f32 - displacementBias?: f32 - specularMap?: Texture - alphaMap?: Texture - envMap?: Texture - combine?: Combine - reflectivity?: f32 - refractionRatio?: f32 - wireframe?: boolean - wireframeLinewidth?: f32 - wireframeLinecap?: string - wireframeLinejoin?: string - skinning?: boolean - morphTargets?: boolean - morphNormals?: boolean -} - -export class MeshPhongMaterial extends Material { - constructor(parameters?: MeshPhongMaterialParameters) - - color: Color - specular: Color - shininess: f32 - map: Texture | null - lightMap: Texture | null - lightMapIntensity: f32 - aoMap: Texture | null - aoMapIntensity: f32 - emissive: Color - emissiveIntensity: f32 - emissiveMap: Texture | null - bumpMap: Texture | null - bumpScale: f32 - normalMap: Texture | null - normalMapType: NormalMapTypes - normalScale: Vector2 - displacementMap: Texture | null - displacementScale: f32 - displacementBias: f32 - specularMap: Texture | null - alphaMap: Texture | null - envMap: Texture | null - combine: Combine - reflectivity: f32 - refractionRatio: f32 - wireframe: boolean - wireframeLinewidth: f32 - wireframeLinecap: string - wireframeLinejoin: string - skinning: boolean - morphTargets: boolean - morphNormals: boolean - /** - * @deprecated Use {@link MeshStandardMaterial THREE.MeshStandardMaterial} instead. - */ - metal: boolean - - setValues(parameters: MeshPhongMaterialParameters): void -} diff --git a/src/as/materials/MeshPhongMaterial.js b/src/as/materials/MeshPhongMaterial.js deleted file mode 100644 index c279195..0000000 --- a/src/as/materials/MeshPhongMaterial.js +++ /dev/null @@ -1,166 +0,0 @@ -import {MultiplyOperation, TangentSpaceNormalMap} from '../constants.js' -import {Material} from './Material.js' -import {Vector2} from '../math/Vector2' -import {Color} from '../math/Color' - -/** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * specular: , - * shininess: , - * opacity: , - * - * map: new THREE.Texture( ), - * - * lightMap: new THREE.Texture( ), - * lightMapIntensity: - * - * aoMap: new THREE.Texture( ), - * aoMapIntensity: - * - * emissive: , - * emissiveIntensity: - * emissiveMap: new THREE.Texture( ), - * - * bumpMap: new THREE.Texture( ), - * bumpScale: , - * - * normalMap: new THREE.Texture( ), - * normalMapType: THREE.TangentSpaceNormalMap, - * normalScale: , - * - * displacementMap: new THREE.Texture( ), - * displacementScale: , - * displacementBias: , - * - * specularMap: new THREE.Texture( ), - * - * alphaMap: new THREE.Texture( ), - * - * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), - * combine: THREE.Multiply, - * reflectivity: , - * refractionRatio: , - * - * wireframe: , - * wireframeLinewidth: , - * - * skinning: , - * morphTargets: , - * morphNormals: - * } - */ - -function MeshPhongMaterial(parameters) { - Material.call(this) - - this.type = 'MeshPhongMaterial' - - this.color = new Color(0xffffff) // diffuse - this.specular = new Color(0x111111) - this.shininess = 30 - - this.map = null - - this.lightMap = null - this.lightMapIntensity = 1.0 - - this.aoMap = null - this.aoMapIntensity = 1.0 - - this.emissive = new Color(0x000000) - this.emissiveIntensity = 1.0 - this.emissiveMap = null - - this.bumpMap = null - this.bumpScale = 1 - - this.normalMap = null - this.normalMapType = TangentSpaceNormalMap - this.normalScale = new Vector2(1, 1) - - this.displacementMap = null - this.displacementScale = 1 - this.displacementBias = 0 - - this.specularMap = null - - this.alphaMap = null - - this.envMap = null - this.combine = MultiplyOperation - this.reflectivity = 1 - this.refractionRatio = 0.98 - - this.wireframe = false - this.wireframeLinewidth = 1 - this.wireframeLinecap = 'round' - this.wireframeLinejoin = 'round' - - this.skinning = false - this.morphTargets = false - this.morphNormals = false - - this.setValues(parameters) -} - -MeshPhongMaterial.prototype = Object.create(Material.prototype) -MeshPhongMaterial.prototype.constructor = MeshPhongMaterial - -MeshPhongMaterial.prototype.isMeshPhongMaterial = true - -MeshPhongMaterial.prototype.copy = function(source) { - Material.prototype.copy.call(this, source) - - this.color.copy(source.color) - this.specular.copy(source.specular) - this.shininess = source.shininess - - this.map = source.map - - this.lightMap = source.lightMap - this.lightMapIntensity = source.lightMapIntensity - - this.aoMap = source.aoMap - this.aoMapIntensity = source.aoMapIntensity - - this.emissive.copy(source.emissive) - this.emissiveMap = source.emissiveMap - this.emissiveIntensity = source.emissiveIntensity - - this.bumpMap = source.bumpMap - this.bumpScale = source.bumpScale - - this.normalMap = source.normalMap - this.normalMapType = source.normalMapType - this.normalScale.copy(source.normalScale) - - this.displacementMap = source.displacementMap - this.displacementScale = source.displacementScale - this.displacementBias = source.displacementBias - - this.specularMap = source.specularMap - - this.alphaMap = source.alphaMap - - this.envMap = source.envMap - this.combine = source.combine - this.reflectivity = source.reflectivity - this.refractionRatio = source.refractionRatio - - this.wireframe = source.wireframe - this.wireframeLinewidth = source.wireframeLinewidth - this.wireframeLinecap = source.wireframeLinecap - this.wireframeLinejoin = source.wireframeLinejoin - - this.skinning = source.skinning - this.morphTargets = source.morphTargets - this.morphNormals = source.morphNormals - - return this -} - -export {MeshPhongMaterial} diff --git a/src/as/materials/MeshPhongMaterial.spec.ts b/src/as/materials/MeshPhongMaterial.spec.ts new file mode 100644 index 0000000..ea2bbef --- /dev/null +++ b/src/as/materials/MeshPhongMaterial.spec.ts @@ -0,0 +1,16 @@ +/** + * @author TristanVALCKE / https://github.com/Itee + */ + +import {MeshPhongMaterial} from './MeshPhongMaterial' + +describe('Materials', () => { + describe('MeshPhongMaterial', () => { + test('type', () => { + const mat = new MeshPhongMaterial() + expect(mat.type).toBe('MeshPhongMaterial', 'it should be true') + }) + + todo('copy') + }) +}) diff --git a/src/as/materials/MeshPhongMaterial.ts b/src/as/materials/MeshPhongMaterial.ts new file mode 100644 index 0000000..5efdca1 --- /dev/null +++ b/src/as/materials/MeshPhongMaterial.ts @@ -0,0 +1,169 @@ +/** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * @author Joe Pea / https://github.com/trusktr + */ + +import {Color} from '../math/Color' +import {Texture} from '../textures/Texture' +import {Vector2} from '../math/Vector2' +import {/*MaterialParameters,*/ Material} from './Material' +import {Combine, NormalMapTypes, MultiplyOperation, TangentSpaceNormalMap} from '../constants' + +// This is soaking WET, let's not use this. +// export interface MeshPhongMaterialParameters extends MaterialParameters { +// /** geometry color in hexadecimal. Default is 0xffffff. */ +// color?: Color | string | f32 +// specular?: Color | string | f32 +// shininess?: f32 +// opacity?: f32 +// map?: Texture +// lightMap?: Texture +// lightMapIntensity?: f32 +// aoMap?: Texture +// aoMapIntensity?: f32 +// emissive?: Color | string | f32 +// emissiveIntensity?: f32 +// emissiveMap?: Texture +// bumpMap?: Texture +// bumpScale?: f32 +// normalMap?: Texture +// normalMapType?: NormalMapTypes +// normalScale?: Vector2 +// displacementMap?: Texture +// displacementScale?: f32 +// displacementBias?: f32 +// specularMap?: Texture +// alphaMap?: Texture +// envMap?: Texture +// combine?: Combine +// reflectivity?: f32 +// refractionRatio?: f32 +// wireframe?: boolean +// wireframeLinewidth?: f32 +// wireframeLinecap?: string +// wireframeLinejoin?: string +// skinning?: boolean +// morphTargets?: boolean +// morphNormals?: boolean +// } + +export class MeshPhongMaterial extends Material { + isMeshPhongMaterial: true = true + + color: Color = new Color(0xffffff) // diffuse + specular: Color = new Color(0x111111) + shininess: f32 = 30 + + map: Texture | null = null + + lightMap: Texture | null = null + lightMapIntensity: f32 = 1.0 + + aoMap: Texture | null = null + aoMapIntensity: f32 = 1.0 + + emissive: Color = new Color(0x000000) + emissiveIntensity: f32 = 1.0 + emissiveMap: Texture | null = null + + bumpMap: Texture | null = null + bumpScale: f32 = 1 + + normalMap: Texture | null = null + normalMapType: NormalMapTypes = TangentSpaceNormalMap + normalScale: Vector2 = new Vector2(1, 1) + + displacementMap: Texture | null = null + displacementScale: f32 = 1 + displacementBias: f32 = 0 + + specularMap: Texture | null = null + + alphaMap: Texture | null = null + + envMap: Texture | null = null + combine: Combine = MultiplyOperation + reflectivity: f32 = 1 + refractionRatio: f32 = 0.98 + + wireframe: boolean = false + wireframeLinewidth: f32 = 1 + wireframeLinecap: string = 'round' + wireframeLinejoin: string = 'round' + + skinning: boolean = false + morphTargets: boolean = false + morphNormals: boolean = false + + constructor(/*parameters?: MeshPhongMaterialParameters*/) { + super() + + this.type = 'MeshPhongMaterial' + + // this.setValues(parameters) + } + + // setValues(parameters: MeshPhongMaterialParameters): void + + /** + * Return a new material with the same properties as this material. + */ + clone(): MeshPhongMaterial { + return new MeshPhongMaterial().copy(this) + } + + /** + * Copy the properties from the passed material into this material. + */ + copy(source: MeshPhongMaterial): this { + super.copy(source) + + this.color.copy(source.color) + this.specular.copy(source.specular) + this.shininess = source.shininess + + this.map = source.map + + this.lightMap = source.lightMap + this.lightMapIntensity = source.lightMapIntensity + + this.aoMap = source.aoMap + this.aoMapIntensity = source.aoMapIntensity + + this.emissive.copy(source.emissive) + this.emissiveMap = source.emissiveMap + this.emissiveIntensity = source.emissiveIntensity + + this.bumpMap = source.bumpMap + this.bumpScale = source.bumpScale + + this.normalMap = source.normalMap + this.normalMapType = source.normalMapType + this.normalScale.copy(source.normalScale) + + this.displacementMap = source.displacementMap + this.displacementScale = source.displacementScale + this.displacementBias = source.displacementBias + + this.specularMap = source.specularMap + + this.alphaMap = source.alphaMap + + this.envMap = source.envMap + this.combine = source.combine + this.reflectivity = source.reflectivity + this.refractionRatio = source.refractionRatio + + this.wireframe = source.wireframe + this.wireframeLinewidth = source.wireframeLinewidth + this.wireframeLinecap = source.wireframeLinecap + this.wireframeLinejoin = source.wireframeLinejoin + + this.skinning = source.skinning + this.morphTargets = source.morphTargets + this.morphNormals = source.morphNormals + + return this + } +} diff --git a/src/as/materials/index.spec.ts b/src/as/materials/index.spec.ts index 63e6795..48f087c 100644 --- a/src/as/materials/index.spec.ts +++ b/src/as/materials/index.spec.ts @@ -1 +1,2 @@ import './Material.spec' +import './MeshPhongMaterial.spec' diff --git a/src/as/objects/Mesh.spec.ts b/src/as/objects/Mesh.spec.ts index 433b07d..03707c8 100644 --- a/src/as/objects/Mesh.spec.ts +++ b/src/as/objects/Mesh.spec.ts @@ -1,35 +1,15 @@ -// import {Mesh} from './Mesh' +import {Mesh} from './Mesh' +import {BufferGeometry} from '../core/BufferGeometry' describe('Mesh', (): void => { - test('.Extending', (): void => { - // expect(a.x).toBe(0) - }) - - test('.Instancing', (): void => { - // expect(a.x).toBe(0) - }) - test('.isMesh', (): void => { - // expect(a.x).toBe(0) + const m = new Mesh(new BufferGeometry()) + expect(m.isMesh).toBe(true) }) - test('.setDrawMode', (): void => { - // expect(a.x).toBe(0) - }) - - test('.copy', (): void => { - // expect(a.x).toBe(0) - }) - - test('.updateMorphTargets', (): void => { - // expect(a.x).toBe(0) - }) - - test('.raycast', (): void => { - // expect(a.x).toBe(0) - }) - - test('.clone', (): void => { - // expect(a.x).toBe(0) - }) + todo('.setDrawMode') + todo('.copy') + todo('.updateMorphTargets') + todo('.raycast') + todo('.clone') }) diff --git a/src/as/objects/Mesh.ts b/src/as/objects/Mesh.ts index fe292d9..79e3d12 100644 --- a/src/as/objects/Mesh.ts +++ b/src/as/objects/Mesh.ts @@ -9,39 +9,58 @@ import {Geometry} from '../core/Geometry' import {Material} from '../materials/Material' -import {Raycaster} from '../core/Raycaster' +// import {Raycaster, Intersection} from '../core/Raycaster' import {Object3D} from '../core/Object3D' import {BufferGeometry} from '../core/BufferGeometry' -import {Intersection} from '../core/Raycaster' import {TrianglesDrawModes} from '../constants' -import {EventDispatcher} from '../core/EventDispatcher' import {Vector3} from '../math/Vector3' import {Vector2} from '../math/Vector2' // import {Sphere} from '../math/Sphere.js' // import {Ray} from '../math/Ray.js' import {Matrix4} from '../math/Matrix4' -import {Triangle} from '../math/Triangle' +// import {Triangle} from '../math/Triangle' import {Face3} from '../core/Face3' import {Side, TrianglesDrawMode} from '../constants' -import {MeshBasicMaterial} from '../materials/MeshBasicMaterial' +import {MeshPhongMaterial} from '../materials/MeshPhongMaterial' +import {Color} from '../math/Color' + +// TODO `` defaults to BufferGeometry for now, but Geometry is easier to use +// for beginners. We can change the default to Geometry once we implement +// Geometry, but for now the initial demo will use BufferGeometry. +export class Mesh extends Object3D { + isMesh: true = true -export class Mesh extends Object3D { geometry: T - // no unions in AS. How should we handle one material vs multiple materials? - material: Material - materials: Material[] | null = [] + // In Three.js this is typed as `material | material[]`, but there are no + // unions in AS. Instead, we only accept a material[]. To have only one + // material, just pass an array with one material. + /** + * Materials for the mesh. In most cases, or if you're not sure, you'll + * just pass a single material in the array. + */ + materials: Material[] drawMode: TrianglesDrawModes - morphTargetInfluences?: f32[] - morphTargetDictionary?: {[key: string]: f32} - isMesh: true - type: string + morphTargetInfluences: f32[] | null + morphTargetDictionary: Map | null - constructor(geometry: T, material?: Material | Material[]) { + // TODO We're going for MeshPhongMaterial in the initial demo, but the + // default arg for material should be MeshPhongMaterial, which we can add + // later and then set the default materials arg back to MeshBasicMaterial. + constructor(geometry: T, materials: Material[] = []) { super() + + this.type = 'Mesh' + + if (!materials.length) { + const defaultMat = new MeshPhongMaterial() + defaultMat.color = new Color(Mathf.random() * 0xffffff) + materials.push(defaultMat) + } + this.geometry = geometry - this.material = material !== undefined ? material : new MeshBasicMaterial({color: Mathf.random() * 0xffffff}) + this.materials = materials this.drawMode = TrianglesDrawMode @@ -68,38 +87,38 @@ export class Mesh extends Object3D { // this.drawMode = drawMode // } + /** + * Note, the updateMorphTargets method only works on Meshes that have + * BufferGeometry instances, not Meshes with Geometry instances. + */ + // TODO + // because there are no morphAttributes. updateMorphTargets(): void { var geometry = this.geometry - var m, ml, name - - if (geometry instanceof BufferGeometry) { - var morphAttributes = geometry.morphAttributes - var keys: string[] = morphAttributes.keys() - - if (keys.length > 0) { - var morphAttribute = morphAttributes.get(keys[0]) - - if (morphAttribute !== undefined) { - this.morphTargetInfluences = [] - this.morphTargetDictionary = {} - - for (m = 0, ml = morphAttribute.length; m < ml; m++) { - name = morphAttribute[m].name || m.toString() - - this.morphTargetInfluences.push(0) - this.morphTargetDictionary[name] = m - } - } - } - } else { - var morphTargets = ((geometry)).morphTargets - - // if ( morphTargets !== undefined && morphTargets.length > 0 ) { - - // console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' ); - - // } - } + // var m, ml, name + + // if (geometry instanceof BufferGeometry) { + // var morphAttributes = geometry.morphAttributes + // var keys: string[] = morphAttributes.keys() + + // if (keys.length > 0) { + // var morphAttribute = morphAttributes.get(keys[0]) + + // if (morphAttribute !== undefined) { + // this.morphTargetInfluences = [] + // this.morphTargetDictionary = new Map() + + // for (m = 0, ml = morphAttribute.length; m < ml; m++) { + // name = morphAttribute[m].name || m.toString() + + // this.morphTargetInfluences.push(0) + // this.morphTargetDictionary.set(name, m) + // } + // } + // } + // } else if (geometry instanceof Geometry) { + // throw new Error('Mesh.updateMorphTargets() no longer supports Geometry. Use BufferGeometry instead.') + // } } // raycast(raycaster: Raycaster, intersects: Intersection[]): void { @@ -425,6 +444,6 @@ export class Mesh extends Object3D { // } // clone(): Mesh { - // return new Mesh(this.geometry, this.material).copy(this) + // return new Mesh(this.geometry, this.materials).copy(this) // } } From 3ae84b4e3d0f182107b3311f3766b90309fb91b0 Mon Sep 17 00:00:00 2001 From: ZoeDreams Date: Wed, 25 Nov 2020 18:38:03 -0500 Subject: [PATCH 08/10] Strongly type BufferGeometryGroup as an Array over any[]; added additiona tests to check clearing memory --- src/as/core/BufferGeometry.spec.ts | 20 ++++++++++-- src/as/core/BufferGeometry.ts | 29 +++++++++++++++-- src/as/core/Face3.spec.ts | 4 +++ src/as/core/Face3.ts | 1 + src/as/core/Geometry.ts | 51 +++++++++++++++++++++++++++--- 5 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/as/core/BufferGeometry.spec.ts b/src/as/core/BufferGeometry.spec.ts index f1cb376..1ef849c 100644 --- a/src/as/core/BufferGeometry.spec.ts +++ b/src/as/core/BufferGeometry.spec.ts @@ -2,6 +2,7 @@ * @author simonThiele / https://github.com/simonThiele * @author TristanVALCKE / https://github.com/Itee * @author corruptedzulu / https://github.com/corruptedzulu + * @author Kara Rawson / https://github.com/zoedreams */ import {BufferGeometry, BufferGeometryGroup} from './BufferGeometry' @@ -173,6 +174,12 @@ describe('BufferGeometry', () => { test('addGroup/clearGroups', () => { var a = new BufferGeometry() + var b = new Array() + var c: BufferGeometryGroup = { + start: 0, + count: 42, + materialIndex: 37, + } as BufferGeometryGroup var expected: BufferGeometryGroup[] = [ { start: 0, @@ -185,14 +192,23 @@ describe('BufferGeometry', () => { materialIndex: 2, } as BufferGeometryGroup, ] - + a.addGroup(0, 1) a.addGroup(1, 2, 2) expect(a.groups).toStrictEqual(expected) a.clearGroups() - expect(a.groups.length).toBe(0) + expect(a.groups).not.toBe([]) + expect(a.groups).toHaveLength(0) + expect(a.groups).toStrictEqual(b) + + a.addGroup(0, 42, 37) + expect(a.groups).toHaveLength(1) + expect(a.groups[0]).toStrictEqual(c) + expect(a.groups[0].start).toBe(0) + expect(a.groups[0].count).toBe(42) + expect(a.groups[0].materialIndex).toBe(37) }) //TODO: uncomment when appropriate methods are implemented diff --git a/src/as/core/BufferGeometry.ts b/src/as/core/BufferGeometry.ts index b9a60b2..bcf42b5 100644 --- a/src/as/core/BufferGeometry.ts +++ b/src/as/core/BufferGeometry.ts @@ -3,6 +3,7 @@ * @author mrdoob / http://mrdoob.com/ * @author corruptedzulu / http://github.com/corruptedzulu * @author Joe Pea / http://github.com/trusktr + * @author Kara Rawson / https://github.com/zoedreams */ import {Vector3} from '../math/Vector3' @@ -31,12 +32,18 @@ import {fillUint32ArrayWithValues, fillUint16ArrayWithValues} from './TypedArray // import {Mesh} from '../objects/Mesh' // import {Line} from '../objects/Line' +/** + * simple struct to store our box geometry info in an array. + */ export class BufferGeometryGroup { start: i32 count: i32 materialIndex: i32 } +/** + * how much of the geometry faces we are going to draw from the buffer. + */ class BufferGeometryDrawRange { start: i32 count: f32 @@ -49,6 +56,13 @@ class BufferGeometryDrawRange { let bufferGeometryId = 1 // BufferGeometry uses odd numbers as Id +/** + * our general purpose box geometry which represents simple geometric structures. These + * as store in buffer like arrays which is used by the rendering engine to project the + * geometry onto our scene. + * + * @source https://github.com/mrdoob/three.js/blob/master/src/core/BufferGeometry.js + */ export class BufferGeometry extends EventDispatcher { /** * Unique number of this buffergeometry instance @@ -66,7 +80,7 @@ export class BufferGeometry extends EventDispatcher { morphAttributes: Map = new Map() //^ per BufferGeometryLoader.js in the original three.js, geometry.morphAttributes[key] is loaded with array of BufferAttributes - groups: BufferGeometryGroup[] = [] + groups: BufferGeometryGroup[] = new Array() boundingBox: Box3 = new Box3() boundingSphere: Sphere = new Sphere() @@ -147,12 +161,23 @@ export class BufferGeometry extends EventDispatcher { return this } + /** + * a simple helper function used to push / add new geometry groups into our array that contains + * the objects that we are going to render + * @param start is the beginning position we wish to offset for, use case? + * @param count how big of an array we are going to create in memory + * @param materialIndex the integer referenc + */ addGroup(start: i32, count: i32, materialIndex: i32 = 0): void { this.groups.push({start, count, materialIndex} as BufferGeometryGroup) } + /** + * clears buffer geometery group arrays by allocating a new empty array in place. This is required + * to properly invoke the GC within the heap stack. + */ clearGroups(): void { - this.groups.length = 0 + this.groups = new Array() } // setDrawRange(start: f32, count: f32): void { diff --git a/src/as/core/Face3.spec.ts b/src/as/core/Face3.spec.ts index e5c240e..4611d27 100644 --- a/src/as/core/Face3.spec.ts +++ b/src/as/core/Face3.spec.ts @@ -2,6 +2,10 @@ import {Face3} from './Face3' import {Color} from '../math/Color' import {Vector3} from '../math/Vector3' +/** + * @author Joe Pea / http://github.com/trusktr + */ + describe('Core', () => { describe('Face3', () => { test('invalid constructor args', () => { diff --git a/src/as/core/Face3.ts b/src/as/core/Face3.ts index 2a58a8e..69b6718 100644 --- a/src/as/core/Face3.ts +++ b/src/as/core/Face3.ts @@ -12,6 +12,7 @@ import {Color} from './../math/Color' * @author bhouston / http://clara.io * @author corruptedzulu / http://github.com/corruptedzulu * @author Joe Pea / http://github.com/trusktr + * @author Kara Rawson / https://github.com/zoedreams */ /** diff --git a/src/as/core/Geometry.ts b/src/as/core/Geometry.ts index 50facd1..d7dd8c2 100644 --- a/src/as/core/Geometry.ts +++ b/src/as/core/Geometry.ts @@ -358,10 +358,51 @@ export class Geometry extends EventDispatcher { // // for (var i = 0; i < positions.length; i += 3) { // // this.vertices.push(new Vector3().fromArray(positions, i)) - // // if (colors !== undefined) { - // // this.colors.push(new Color().fromArray(colors, i)) - // // } - // // } + // if (colors !== undefined) { + // scope.colors.push(new Color().fromArray(colors, i)) + // } + // } + + /// WRONG should be i32s + // function addFace(a: f32, b: f32, c: f32, materialIndex: f32) { + // var vertexColors = + // colors === undefined ? [] : [scope.colors[a].clone(), scope.colors[b].clone(), scope.colors[c].clone()] + + // var vertexNormals = + // normals === undefined + // ? [] + // : [ + // new Vector3().fromArray(normals, a * 3), + // new Vector3().fromArray(normals, b * 3), + // new Vector3().fromArray(normals, c * 3), + // ] + + // var face = new Face3(a, b, c, vertexNormals, vertexColors, materialIndex) + + // scope.faces.push(face) + + // if (uvs !== undefined) { + // scope.faceVertexUvs[0].push([ + // new Vector2().fromArray(uvs, a * 2), + // new Vector2().fromArray(uvs, b * 2), + // new Vector2().fromArray(uvs, c * 2), + // ]) + // } + + // if (uvs2 !== undefined) { + // scope.faceVertexUvs[1].push([ + // new Vector2().fromArray(uvs2, a * 2), + // new Vector2().fromArray(uvs2, b * 2), + // new Vector2().fromArray(uvs2, c * 2), + // ]) + // } + // } + + // var groups = geometry.groups + + // if (groups.length > 0) { + // for (var i = 0; i < groups.length; i++) { + // var group = groups[i] // // const addFace = (a: f32, b: f32, c: f32, materialIndex: f32) => { // // var vertexColors = @@ -959,7 +1000,7 @@ export class Geometry extends EventDispatcher { } for (var i = 0; i < length; i++) { - var id = faces[i].id + var id = faces[i] if (didSetUvs1) { newUvs1.push(uvs1[id]) From 8e4ca09e18485b35b5d590b2d79f20d620c1c0c3 Mon Sep 17 00:00:00 2001 From: Kara Rawson Date: Fri, 15 Jan 2021 20:21:00 -0500 Subject: [PATCH 09/10] added shorthand for 'new Arrays' AS will optimize this to the proper type automagically. --- src/as/core/BufferGeometry.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/as/core/BufferGeometry.ts b/src/as/core/BufferGeometry.ts index bcf42b5..bd3d6f7 100644 --- a/src/as/core/BufferGeometry.ts +++ b/src/as/core/BufferGeometry.ts @@ -80,7 +80,7 @@ export class BufferGeometry extends EventDispatcher { morphAttributes: Map = new Map() //^ per BufferGeometryLoader.js in the original three.js, geometry.morphAttributes[key] is loaded with array of BufferAttributes - groups: BufferGeometryGroup[] = new Array() + groups: BufferGeometryGroup[] = [] boundingBox: Box3 = new Box3() boundingSphere: Sphere = new Sphere() @@ -177,7 +177,7 @@ export class BufferGeometry extends EventDispatcher { * to properly invoke the GC within the heap stack. */ clearGroups(): void { - this.groups = new Array() + this.groups = [] } // setDrawRange(start: f32, count: f32): void { From 6e8c949b2267fa87a0b3e5a78b8d594acd75db2f Mon Sep 17 00:00:00 2001 From: Kara Rawson Date: Fri, 15 Jan 2021 20:23:47 -0500 Subject: [PATCH 10/10] added shortcut for creating or reusing array memory. --- src/as/core/BufferGeometry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/as/core/BufferGeometry.ts b/src/as/core/BufferGeometry.ts index bd3d6f7..323cc78 100644 --- a/src/as/core/BufferGeometry.ts +++ b/src/as/core/BufferGeometry.ts @@ -177,7 +177,7 @@ export class BufferGeometry extends EventDispatcher { * to properly invoke the GC within the heap stack. */ clearGroups(): void { - this.groups = [] + this.groups.length = 0; } // setDrawRange(start: f32, count: f32): void {