firtoz / react-three-renderer

Render into a three.js canvas using React.
https://toxicfork.github.com/react-three-renderer-example/
MIT License
1.49k stars 155 forks source link

applyMatrix #120

Open martunta opened 7 years ago

martunta commented 7 years ago

Code I am trying to port has a lot of parts like this:

var transform = new THREE.Matrix4();
transform.elements = storedTransformMatrix.Values.slice();
transform.transpose();
meshToMove.applyMatrix(transform);

it is operating some functions on a mesh, to transpose it, or change in some other manner. What do you think would be best way how to do similar exercise in the more declarative and react way?

taking a need above as an example - there is a Object3D that needs to be placed somewhere on scene, but before placement it needs be transposed using some data that are taken from somewhere else.

martunta commented 7 years ago

Hmm, I guess best way would be if I could just pass it as a prop matrix to Object3D, but looks like this THREE.Object3D property is not implemented in as a prop in react component. Same with caseShadow, visible and some other attributes. Maybe those could be just passed over to THREE object? They don't need much logic in react-three-renderer side?

Or is there some other way how to pass down those properties?

toxicFork commented 7 years ago

For now ( until the properties are implemented by me or contributors ) you can use the ref property to get a handle to the mesh e.g.

componentDidMount() {
    // ... calculate matrix
    this.mesh.applyMatrix(...);
}

meshRef(mesh) {
    this.mesh = mesh;
}

componentDidUpdate(){
    // ... update matrix from props?
    this.mesh.applyMatrix(...);
}

render(){
    return <mesh ref={this.meshRef} ... />;
}
martunta commented 7 years ago

your solution works! Now I am trying to create pull request to create it as a prop. But somehow just replicating what is done with rotation or quaternion in Object3DDescriptor.js does not work.

Any pointers of where should I look to make it work? :)

toxicFork commented 7 years ago

Hmm I will take a look and give hints :)

toxicFork commented 7 years ago

Hmm I will take a look and give hints :)

On Wed, 26 Oct 2016, 18:47 Martins Untals, notifications@github.com wrote:

your solution works! Now I am trying to create pull request to create it as a prop. But somehow just replicating what is done with rotation or quaternion in Object3DDescriptor.js does not work.

Any pointers of where should I look to make it work? :)

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/toxicFork/react-three-renderer/issues/120#issuecomment-256425066, or mute the thread https://github.com/notifications/unsubscribe-auth/AA0iLbX6_dkgRZB9JsUIynqx4ONLVwbhks5q35IygaJpZM4KgaHD .

martunta commented 7 years ago

see here https://github.com/martunta/react-three-renderer/tree/adding-matrix-prop not sure how to link it better. but it is change in src/lib/descriptors/Object/Object3DDescriptor.js

toxicFork commented 7 years ago

You can create a diff like this : https://github.com/toxicFork/react-three-renderer/compare/master...martunta:adding-matrix-prop?expand=1 .

Looking at it I cannot see any obvious reasons for it not to work from the r3r side, but perhaps on the THREEjs side. May be worth looking at matrixWorldNeedsUpdate . I will hopefully be able to take a deeper look this weekend and see if I can give even more hints :)

martunta commented 7 years ago

ok, matrixWorldNeedsUpdate = true or 'updateMatrixdid not work, so I changed it to simply doapplyMatrix(matrix)` and now it works. Somehow it does feel a bit less declarative, on the other hand, it is done similarly with lookAt

martunta commented 7 years ago

hmm. little separate but related question - I tried to do the same for Scene, but somehow it does not work. The same with ref and componentDidMount. could it work somehow differently for setup like this:

  constructor(props) {
    super(props);
    this.sceneRef = this.sceneRef.bind(this);
  }

  componentDidMount() {    
    var transform = new THREE.Matrix4();
    transform.set(1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1);
    this.scene.applyMatrix(RhinoTransform);
  }

  sceneRef(scene) {
    this.scene = scene;
  }

...

<React3 mainCamera="maincamera2" width={this.props.width} height={this.props.height} {...renderprops}>
              <scene ref={this.sceneRef}>
                <Light />
                <perspectiveCamera ref="camera2" name="maincamera2" {...cameraprops} />
                <GreenBoxMesh />
                <MoreMeshes />
              </scene>
          </React3>

looks like refs are executing, new matrix is planted into scene object ... but somehow picture does not change

martunta commented 7 years ago

yeah, If I apply it to the this mesh wrapped in scene tag above, then mesh gets transformed. But scene itself does not.

<mesh ref={this.sceneRef}>
  <boxGeometry width={10000} height={4000} depth={7000} />
  <meshPhongMaterial color={0x00ee00} />
</mesh>
toxicFork commented 7 years ago

One hypothesis of mine: Perhaps after applying the matrix some flags may need to be set for children objects...

To be confirmed.

kaikokivi commented 7 years ago

On the separate but related question about Scene. Scene is actually an extended Object3D and behaves exactly the same with its children.

The problem in there is that the camera is also a 3D positioned object (extended Object3D) and it is within the same Scene. If the wrapping Scene is transformed it moves the camera along with everything else. That is why the picture does not change even though the scene is actually transformed.

Here is a solution. Just need to leave the camera out of the transformed scene:

<React3 mainCamera="maincamera2" width={this.props.width} height={this.props.height} {...renderprops}>
              <scene> // don't transform this scene
                <perspectiveCamera ref="camera2" name="maincamera2" {...cameraprops} />

                <scene ref={this.sceneRef}> // but instead this here
                  <Light />
                  <GreenBoxMesh />
                  <MoreMeshes />
                </scene>

              </scene>
          </React3>
toxicFork commented 7 years ago

Oh you can use a group in that case instead of scene within a scene! I'm case a three js update makes scenes a different thing or something :)

On Tue, Nov 29, 2016, 22:25 kaikokivi notifications@github.com wrote:

On the separate but related question about Scene. Scene is actually an extended Object3D and behaves exactly the same with its children.

The problem in there is that the camera is also a 3D positioned object (extended Object3D) and it is within the same Scene. If the wrapping Scene is transformed it moves the camera along with everything else. That is why the picture does not change even though the scene is actually transformed.

Here is a solution. Just need to leave the camera out of the transformed scene:

<React3 mainCamera="maincamera2" width={this.props.width} height={this.props.height} {...renderprops}

// don't transform this scene
            <scene ref={this.sceneRef}> // but instead this here
              <Light />
              <GreenBoxMesh />
              <MoreMeshes />
            </scene>

          </scene>
      </React3>

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/toxicFork/react-three-renderer/issues/120#issuecomment-263719957, or mute the thread https://github.com/notifications/unsubscribe-auth/AA0iLaatt6re0Pdm1FBcfeCd_LWvGF-1ks5rDKZPgaJpZM4KgaHD .

kaikokivi commented 7 years ago

Hm. Did not know groups existed. It is nowhere in THREE docs. :) Could just use an Object3d as well, but perhaps the lights need to be in the scene then.

toxicFork commented 7 years ago

Yes it's an undocumented three class that extends object, like a scene, but I like to use it to contain multiple other objects and move them together

On Tue, Nov 29, 2016, 23:48 kaikokivi notifications@github.com wrote:

Hm. Did not know groups existed. It is nowhere in THREE docs. :) Could just use an Object3d as well, but perhaps the lights need to be in the scene then.

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/toxicFork/react-three-renderer/issues/120#issuecomment-263737853, or mute the thread https://github.com/notifications/unsubscribe-auth/AA0iLeIJof4h5pOcf14p6i2PI3SMqgtRks5rDLnbgaJpZM4KgaHD .