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

Support for imported geometry?

Open AndrewRayCode opened this issue 9 years ago • 8 comments
trafficstars

I'm glancing around the source but not sure how to approach this - is there a way to use imported (obj, etc) raw geometry in this library yet?

AndrewRayCode avatar Dec 20 '15 17:12 AndrewRayCode

We could write a wrapper for the importers, or use an importer to populate a mesh instead?

toxicFork avatar Jan 06 '16 01:01 toxicFork

I also need to do this, but I'm not quite sure where to start. Can you point me in the right direction?

eadlam avatar Feb 19 '16 15:02 eadlam

This is basically how I handle it now. I have a <Mesh /> component that takes the model object as a prop. If the model geometry is present, it renders the geometry by accessing the props needed for <geometry />.

This method allows you to load the geometry async and still use the react component in your render tree until the geometry is available.

export default class Mesh extends Component {

    constructor( props, context ) {
        super( props, context );
    }

    render() {

        const { mesh } = this.props;

        if( !mesh ) {
            return <mesh />;
        }

        // Look up your actual geometry object
        const meshData = mesh.geometry[ 1 ];

        return <mesh>
            <geometry
                faces={ meshData.faces }
                vertices={ meshData.vertices }
                colors={ meshData.colors }
                faceVertexUvs={ meshData.faceVertexUvs }
            />
            <materialResource
                resourceId="someMaterial"
            />
        </mesh>;

    }

}

You can pass in the geometry as a prop however you want. For me, I load it in my app, and store the loaded object in a redux store, then I pass it to my component using the @connect decorator:

@connect(
    state => ({ mesh: state.assets.loadedObject })
)
export default class Mesh extends Component {
...

But you could just as easily pass it from a parent component <Mesh mesh={ myModel } />

One improvement over this pattern could be just to store the geometry in the store directly, not the raw object returned by the Three loader. This would avoid the lookup mesh.geometry[ 1 ]; in the code above.

Also note that I don't actually have a generic Mesh class, although I probably should. Right now I duplicate the above class into things like <House />, <Chair /> etc, because some models require specific transformations after loading (like scale adjustment, or rotation from origin, or specific material handling, etc).

My question around this approach is: is this efficient to put model data in the scene? Should I be concerned about performance hits or unnecessary updates by injecting geometry into an existing mesh component?

AndrewRayCode avatar Feb 19 '16 21:02 AndrewRayCode

unnecessary updates by injecting geometry into an existing mesh component

Well, essentially it's similar to:

var geom = new THREE.Geometry();
geom.vertices = meshData.vertices;
geom.faces = meshData.faces;
...

mesh.geometry = geom;

And if you have a pure component then nothing should be updated unnecessarily.

Efficiency: a little improvement could be to wrap <geometry> only, this way if for example you want to set a position property on the mesh it won't cause a rerender of the other props. But that's just "comparing 5 props (position, faces, vertices, colors, facevertexuvs)" versus "comparing 2 props (position, mesh)", and is usually negligible. If you're sharing geometries you can also place it within the <resources> ( similar to how you showed the materialResource there, except it'd be a geometryResource :) )

Example for wrapping geometry:

export default class Mesh extends Component {

    constructor( props, context ) {
        super( props, context );
    }

    render() {

        const { mesh } = this.props;

        if( !mesh ) {
            return <mesh />;
        }

        // Look up your actual geometry object
        const meshData = mesh.geometry[ 1 ];

        return <mesh>
            <Geometry meshData={meshData} />
            <materialResource
                resourceId="someMaterial"
            />
        </mesh>;
    }
}

toxicFork avatar Feb 21 '16 12:02 toxicFork

Here is some code that parses an externally loaded 3D model into (merged) geometries and materials.

You can use it for both react-three-renderer and react-three. Here is some example code that shows you how to use it.

abudaan avatar Feb 23 '16 00:02 abudaan

I also ran into this issue and decided to write a plugin to load objects and materials with this library as well. Hopefully some other folks find it useful: https://www.npmjs.com/package/react-three-renderer-objects

zhuber avatar Jan 26 '18 23:01 zhuber

@zhuber yes, this is cool! :D I had tried a bit of it to have it "work natively" for the fiber implementation but an external package feels best.

toxicFork avatar Feb 08 '18 19:02 toxicFork

@zhuber 我用了你的插件包,导入对象之后并没有显示,请问可能是什么原因呢? `import React from 'react'; import React3 from 'react-three-renderer'; import * as THREE from 'three'; import ReactDOM from 'react-dom'; import ObjectModel from 'react-three-renderer-objects'; import exampleObject from "../../assets/Man_Pose006.obj"; import exampleMaterial from "../../assets/Man_Pose006.mtl"; export default class Gis extends React.Component{ render(){ return(

<Simple/>
) } }

class Simple extends React.Component { constructor(props) { super(props); this.state = { scene: {} }; }

componentDidMount() { const { scene } = this.refs; this.setState({ scene }); }

render() { return ( <React3 mainCamera="camera" width={500} height={500} alpha={true} > <perspectiveCamera key={perspectiveCamera} name="camera" fov={75} aspect={1} near={0.1} far={1000} position={new THREE.Vector3(0, 0, 25)} lookAt={new THREE.Vector3(0, 0, 0)} />

      <group name="exampleGroup">
        <ObjectModel
          name="exampleObject"
          material={exampleMaterial}
          model={exampleObject}
          scene={this.state.scene}
          group="exampleGroup"
        />
      </group>
    </scene>
  </React3>
);

} }` 对象文件没有损坏

liyue118 avatar May 01 '18 11:05 liyue118