react-three-legacy icon indicating copy to clipboard operation
react-three-legacy copied to clipboard

Merged geometries

Open parris opened this issue 8 years ago • 4 comments

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>

parris avatar Nov 23 '15 06:11 parris

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.

Izzimach avatar Nov 23 '15 16:11 Izzimach

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 avatar Nov 24 '15 05:11 parris

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;

parris avatar Nov 25 '15 21:11 parris

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.

Izzimach avatar Dec 01 '15 18:12 Izzimach