Skip to content

Conversation

@yomotsu
Copy link
Contributor

@yomotsu yomotsu commented Aug 3, 2020

A part of #19986

This PR contains:

  • Vector2
  • Vector3
  • Vector4
  • Matrix3
  • Matrix4
  • Quaternion
  • Euler

The rest of the math folder will be continued in separate PR.


The following are already completed in other PRs :

@yomotsu yomotsu changed the title Move to es6 classes/math math: move to es6 classes Aug 3, 2020
import { Quaternion } from './Quaternion.js';

const _vector = new Vector3();
let _vector;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hoisting does not work anymore, because Vector3 is not a function.
Vec3 instance will be assigned at the end of this file.

@mrdoob mrdoob added this to the r120 milestone Aug 3, 2020
@DefinitelyMaybe DefinitelyMaybe mentioned this pull request Aug 3, 2020
43 tasks
@yomotsu yomotsu marked this pull request as ready for review August 3, 2020 12:51
@yomotsu
Copy link
Contributor Author

yomotsu commented Aug 3, 2020

I have converted the following classes in the math folder so far:

  • Vector2
  • Vector3
  • Vector4
  • Matrix3
  • Matrix4
  • Quaternion
  • Euler

@mrdoob @Mugen87
Would you mind reviewing them, please? 🙇‍♂️

If these are okay to merge, I will continue the rest of the math folder on other PR.

} );
}

_vector = new Vector3();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work to do const _vector = new Vector3(); here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works! (I tested)
So, other internal use instances should be declared at the bottom of the file too?

Such as: const _quaternion = new Quaternion(); in

import { MathUtils } from './MathUtils.js';
import { Quaternion } from './Quaternion.js';
let _vector;
const _quaternion = new Quaternion();
class Vector3 {

and
import { Vector3 } from './Vector3.js';
const _v1 = new Vector3();
let _m1;
const _zero = new Vector3( 0, 0, 0 );
const _one = new Vector3( 1, 1, 1 );
const _x = new Vector3();
const _y = new Vector3();
const _z = new Vector3();
class Matrix4 {

also maybe
import { MathUtils } from './MathUtils.js';
const _matrix = new Matrix4();
const _quaternion = new Quaternion();
class Euler {

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, other internal use instances should be declared at the bottom of the file too?

Yes, I think so!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, done it with 8bcfccd


this._x = value;
this._onChangeCallback();
static get DefaultOrder() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do a setter for this one too.

Copy link
Contributor Author

@yomotsu yomotsu Aug 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrdoob

Thank you for reviewing.
Sorry, I got it wrong, I thought DefaultOrder is read-only too.
I will fix it.

Before that, I have a question: How do we declare Public class fields?

The readable-writable static value can be declare like

class MyClass {

  static xxx = 1;

  constructor( x ) {
    this.x = x
  }

}

However It seems Buble transpiler does not support the syntax, while Babel support that

Which option would be preferable in three.js (with Buble)?

class MyClass {

  constructor( x ) {
    this.x = x
  }

}

MyClass.xxx = 1;

or using Object.defineProperty

class MyClass {

  constructor( x ) {
    this.x = x
  }

}

Object.defineProperty(
  MyClass,
  'xxx',
  {
    value: 1,
    configurable: true,
    writable: true
  }
);

or

let _xxx = 1;

class MyClass {

  static get xxx = () => {
    return _xxx;
  }

  static set xxx = ( value ) => {
    _xxx = value;
  }

  constructor( x ) {
    this.x = x
  }

}

or other?
Thank you in advance🙇‍♂️

maybe @DefinitelyMaybe or @ianpurvis could give a suggestion?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class MyClass {

  constructor( x ) {
    this.x = x
  }

}

MyClass.xxx = 1;

I think this style is nice for read/write 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll do that then!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future reference:
There are only three things in the current r120 dev build where Buble is being used.
Curves, Geometries and Materials.
When Buble is no longer needed, i.e. after converting everything to es6 classes, we should have a look back into this

class MyClass {

  static xxx = 1;

  constructor( x ) {
    this.x = x
  }

}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm. I've got Buble's purpose backwards. Buble is our 'convert classes back to support IE' tool and output it as build/three.js.

@DefinitelyMaybe
Copy link
Contributor

DefinitelyMaybe commented Aug 9, 2020

static is a keyword for methods last time I checked. will have a look around.

ah. here we go

@yomotsu
Copy link
Contributor Author

yomotsu commented Aug 9, 2020

Fixed Euler.DefaultOrder to be readable-writable🙇‍♂️

@mrdoob
Copy link
Owner

mrdoob commented Aug 11, 2020

Can you also revert RotationOrders?

Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];

@mrdoob
Copy link
Owner

mrdoob commented Aug 11, 2020

Should we also do Euler.isEuler = true;?

@yomotsu
Copy link
Contributor Author

yomotsu commented Aug 11, 2020

I'll revert Euler.RotationOrders.

However, I personally think is*** properties can be getters, such as Euler.isEuler.

Sould we do Euler.isEuler = true;?

@ianpurvis
Copy link
Contributor

I think we should give the read-only getter a try? That feels like the right spirit for type checking. I'm not a benchmark master, but I ran my cheap benchmark on some different type checking. TLDR, performance is all similar.

Vanilla instanceof seems fast these days. That has got to be the nicest semantically, might be a good direction for after all the ES6 class changes stabilize.

@mrdoob
Copy link
Owner

mrdoob commented Aug 13, 2020

I think we should give the read-only getter a try?

I don't think this is the right time to give things a try.
I think we should focus on porting the code to es6 classes with the least side effects as possible.

Vanilla instanceof seems fast these days

We used to use instanceof. We changed it to is*** to allow tree-shaking.

@mrdoob
Copy link
Owner

mrdoob commented Aug 13, 2020

However, I personally think is*** properties can be getters, such as Euler.isEuler.

It doesn't feel good to turn isEuler into a function. These variables get accessed a lot per frame.

@ianpurvis
Copy link
Contributor

Fair enough, let's go with Euler.isEuler = true; 👍

@yomotsu
Copy link
Contributor Author

yomotsu commented Aug 14, 2020

I understand performance is paramount.
I changed is** to be a prototype value a53fcce

Also, I checked some in the example folder and working correctly.

@mrdoob mrdoob merged commit ff37eaa into mrdoob:dev Aug 14, 2020
@mrdoob
Copy link
Owner

mrdoob commented Aug 14, 2020

Thanks!

@yomotsu
Copy link
Contributor Author

yomotsu commented Aug 14, 2020

Thank you so much for your kind advice and all help🙇‍♂️

@yomotsu
Copy link
Contributor Author

yomotsu commented Aug 14, 2020

FYI:
this.isVector3 is not allowed because of the test:

assert.propEqual( obj.position, {
x: 1,
y: 1.23,
z: - 4.56
} );

The properties of Vector3 can only contain x, y, z, and not isVector3.
But isVector3.prototype.isVector3 can pass the test.

I think we should declare is** as TheClass.prototype.is*** = true;

cc @DefinitelyMaybe @ianpurvis

@DefinitelyMaybe
Copy link
Contributor

DefinitelyMaybe commented Aug 15, 2020

thank you! I was starting to look into why my unit tests were failing and was approaching a similar conclusion. I hadn't figured out how to work around it though. Great stuff!

cc @linbingquan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants