Filament: Does filament module need fs to work ? Even in browser ?

Created on 17 Jan 2019  路  12Comments  路  Source: google/filament

Describe the bug
Trying to import filament from nodes_modules in a gatsby react website but facing this issue:

Module not found: Error: Can't resolve 'fs' in '.../node_modules/filament'

To Reproduce

import React, { useState } from 'react';
import Filament from 'filament';

export default const Index = () => {
    return (<div>Test Filament</div>)
};

Expected behavior
Why do filament need fs ? How can I avoid this issue ?
I expect module variable ENVIRONMENT_IS_NODE being true when doing a gatsby develop on my website, but how can I force it to be false and ENVIRONMENT_IS_WEB to be true ?.

Additional context
filament 1.1.0
gatsbyjs
react

All 12 comments

Filament never uses fs but emscripten emits JS bindings that conditionally uses it in a nodejs environment. If you're using webpack, you can skip over their "require" statements by declaring them as external, as done here.

Does this help?

A lot, thank you, it solve this problem but raise another one.. sigh !

Now it seems that it is looking for filament.wasm but is trying to get it from the browser side. Do you know how can I force him to import it from/during the webpack ? Is it why it needed fs ?

GET http://localhost:8000/filament.wasm 404 (Not Found)

Oh, wait, I will try to copy paste from your link

    plugins: [
        new CopyWebpackPlugin([
            { from: 'node_modules/filament/filament.wasm' },
            // { from: 'src/index.html' }
        ])
    ],

Ok, now it suceeded to import filament.wasm. Thank you !

Also, for future readers, if you are trying to use Filament right away, it may not work as Filament runtime will not be yet Initialized, you need to put a callback like so (see here why):

Filament["onRuntimeInitialized"] = () =>  {
... // for example: setFilamentReady(true)
}

The Filament.init function takes a callback for that very reason, as described in the tutorial.

I just saw that, thank you !

@prideout Do you know why I'm getting

FEngine (32 bits) created at 0x51d7f0 (threading is disabled) 256[.WebGL-0x7fdb05984000]GL ERROR :GL_INVALID_OPERATION : glDrawElements: uniform buffers : buffer or buffer range at index 0 not large enough

localhost/:1 WebGL: too many errors, no more errors will be reported to the console for this context.

Here is my code (a modified tutorial_triangle.js):

import Filament from 'filament';
import { mat4 } from 'gl-matrix';

export default class App {
    constructor(canvas, assets) {
        console.log("Starting triangle tutorial")
        this.canvas = canvas;
        console.log(canvas);
        const engine = this.engine = Filament.Engine.create(this.canvas);
        this.scene = engine.createScene();
        this.triangle = Filament.EntityManager.get()
            .create();
        this.scene.addEntity(this.triangle);
        const TRIANGLE_POSITIONS = new Float32Array([
            1, 0,
            Math.cos(Math.PI * 2 / 3), Math.sin(Math.PI * 2 / 3),
            Math.cos(Math.PI * 4 / 3), Math.sin(Math.PI * 4 / 3),
        ]);
        const TRIANGLE_COLORS = new Uint32Array([0xffff0000, 0xff00ff00, 0xff0000ff]);
        const VertexAttribute = Filament.VertexAttribute;
        const AttributeType = Filament.VertexBuffer$AttributeType;
        this.vb = Filament.VertexBuffer.Builder()
            .vertexCount(3)
            .bufferCount(2)
            .attribute(VertexAttribute.POSITION, 0, AttributeType.FLOAT2, 0, 8)
            .attribute(VertexAttribute.COLOR, 1, AttributeType.UBYTE4, 0, 4)
            .normalized(VertexAttribute.COLOR)
            .build(engine);
        this.vb.setBufferAt(engine, 0, TRIANGLE_POSITIONS);
        this.vb.setBufferAt(engine, 1, TRIANGLE_COLORS);
        this.ib = Filament.IndexBuffer.Builder()
            .indexCount(3)
            .bufferType(Filament.IndexBuffer$IndexType.USHORT)
            .build(engine);
        this.ib.setBuffer(engine, new Uint16Array([0, 1, 2]));
        const mat = engine.createMaterial(assets[0]);
        const matinst = mat.getDefaultInstance();
        Filament.RenderableManager.Builder(1)
            .boundingBox([
                [-1, -1, -1],
                [1, 1, 1]
            ])
            .material(0, matinst)
            .geometry(0, Filament.RenderableManager$PrimitiveType.TRIANGLES, this.vb, this.ib)
            .build(engine, this.triangle);
        this.swapChain = engine.createSwapChain();
        this.renderer = engine.createRenderer();
        this.camera = engine.createCamera();
        this.view = engine.createView();
        this.view.setCamera(this.camera);
        this.view.setScene(this.scene);
        this.view.setClearColor([0.1, 0.2, 0.3, 1.0]); // blue-green background
        this.resize(); // adjust the initial viewport
        this.render = this.render.bind(this);
        this.resize = this.resize.bind(this);
        window.addEventListener('resize', this.resize);
        window.requestAnimationFrame(this.render);
    }
    render() {
        // Rotate the triangle.
        const radians = Date.now() / 1000;
        const transform = mat4.fromRotation(mat4.create(), radians, [0, 0, 1]);
        const tcm = this.engine.getTransformManager();
        const inst = tcm.getInstance(this.triangle);
        tcm.setTransform(inst, transform);
        inst.delete();
        // Render the frame.
        this.renderer.render(this.swapChain, this.view);
        window.requestAnimationFrame(this.render);
    }
    resize() {
        const dpr = 1;
        const width = this.canvas.width = window.innerWidth * dpr;
        const height = this.canvas.height = window.innerHeight * dpr;
        this.view.setViewport([0, 0, width, height]);
        const aspect = width / height;
        const Projection = Filament.Camera$Projection;
        this.camera.setProjection(Projection.ORTHO, -aspect, aspect, -1, 1, 0, 1);
    }
}

Should I open a new issue ticket ?

That looks exactly like the tutorial except for the devicePixelRatio, and the fact that you're using the npm version of Filament, correct?

I think your bug will go away after we update the npm package, it reminds me of a regression that we fixed a few weeks ago.

Yes, exactly, I also get the canvas and assets namefiles from passed parameters like this:

import React, { useRef } from 'react';
import Filament from 'filament';
import TriangleScene from './triangle' // tweaked tutorial_triangle.js as shown above.

export default () => {
    var scene;
    let canvasRef = useRef();
    let assets = ['/assets/filamat/triangle.filamat'];
    Filament.init(assets, () => {
        scene = new TriangleScene(canvasRef.current, assets)
    });
    return <canvas ref={canvasRef}/>
};

Did you build triangle.filamat yourself? If so, did you use the matc that was bundled in the 1.1.0 release or a more recent version of matc?

I took it from Sceneform 1.7pr2 release here

The current npm version of Filament is 1.1.0, so you need to use the matc from our 1.1.0 release.

It is working !! Thank you so much for your time and your work here !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NathanBWaters picture NathanBWaters  路  6Comments

but0n picture but0n  路  8Comments

molysgaard picture molysgaard  路  6Comments

jiqimaogou picture jiqimaogou  路  6Comments

j6lim picture j6lim  路  5Comments