Izzimach / react-three-legacy

React bindings to create and control a 3D scene using three.js
Other
1.52k stars 127 forks source link

Merged geometries #61

Open parris opened 9 years ago

parris commented 9 years ago

Is there anyway to easily merge geometries yet?

Something like this would be cool:

<MergedMesh>
   <Mesh
      geometry={sphereGeo}
      material={sceneMat}
      position={{x:0, y:0, z:0}}
      quaternion={rotation}
  />
  <Line
      geometry={sphereGeo}
      material={lineMat}
      position={{x:0, y:0, z:0}}
      quaternion={rotation}
  />
</MergedMesh>
Izzimach commented 9 years ago

I guess you mean using the merge utils?

http://learningthreejs.com/blog/2011/10/05/performance-merging-geometry/

This would probably not be a core thing but would fall under an extra component for #34.

Still, doesn't look TOO hard. The problem really is figuring out when the child geometry has changed.

parris commented 9 years ago

Yea, that's what I mean.

I started messing with this earlier today actually. I don't think its too bad. I found that I needed to access this.props.children[0].theGeneratedMesh.matrix, of course, it seemed like I couldn't actually access the generated mesh.

parris commented 9 years ago

Here's what I have so far, and some comments about the problems I see with it.

import React, {Component} from 'react';
import {Mesh} from 'react-three';
import THREE from 'three';

class MergedMesh extends Component {

    render() {
        // is it wise to cache the mergedGeometry so we aren't re-merging on each render if relevant props haven't changed.
        let mergedGeometry = new THREE.Geometry();
        let materials = [];

        this.props.children.forEach((child, i) => {
            // bug here with the material indexing
            materials.push(child.props.material);
            let materialIndex = materials.length - 1;

            mergedGeometry.merge(
                child.props.geometry,
                // Currently this is not accessible
                child._somePrivateReferenceToTheMesh.matrix,
                materialIndex
            );
        });

        // can we cache this, or are we creating a new MeshFaceMaterial every time
        let mats = new THREE.MeshFaceMaterial(materials);

        return (
            <Mesh
                geometry={mergedGeometry}
                material={mats}
            />
        );
    }
}

export default MergedMesh;
Izzimach commented 8 years ago

You can try to cache the material in local state using setState or whatever.

Regarding the matrix that you need for merging, you would probably have to build the matrix yourself from the position, rotation and scale properties that were passed into the child props. The Matrix class has a compose method for this: http://threejs.org/docs/#Reference/Math/Matrix4

There could be problems if people try to merge meshes with different materials, but for now I suppose you can just check for that and throw and error.