pixijs / pixi-react

Write PIXI apps using React declarative style
https://pixijs.io/pixi-react/
MIT License
2.42k stars 180 forks source link

Bug: SimpleMesh not updating geometry buffers when props change #417

Open maximtwo opened 1 year ago

maximtwo commented 1 year ago

Current Behavior

When the uvs or indices props changes on the SimpleMesh component the underlying buffers are not being updated as expected. Here's what's happening:

Expected Behavior

I expect that when any of the props related to geometry change, the underlying buffers should be updated and the mesh should render using these new values.

Steps to Reproduce

I have included below a basic example that demonstrates the issue:

import { SimpleMesh, Stage } from "@pixi/react";
import { SimpleMesh as PixiSimpleMesh } from "pixi.js";
import { useCallback, useRef, useState } from "react";

export default function SimpleMeshBug() {
    const meshRef = useRef<PixiSimpleMesh>(null);

    const nextVertices = new Float32Array(
        [
            [0, 0],
            [0, 256],
            [256, 256],
            [256, 0],
        ].flat()
    );

    const nextTexCoords = new Float32Array(
        [
            [0, 0],
            [0, 1],
            [1, 1],
            [1, 0],
        ].flat()
    );

    const nextIndices = new Uint16Array([1, 0, 3, 1, 3, 2]);

    const [vertices, setVertices] = useState<Float32Array>(new Float32Array());
    const [texCoords, setTexCoords] = useState<Float32Array>(new Float32Array());
    const [indices, setIndices] = useState<Uint16Array>(new Uint16Array());

    const updateMesh = useCallback(() => {
        console.log("buffer pos", meshRef.current?.geometry.getBuffer("aVertexPosition").data);
        console.log("buffer uvs", meshRef.current?.geometry.getBuffer("aTextureCoord").data);
        console.log("indices", meshRef.current?.geometry.getIndex());
        setVertices(nextVertices);
        setTexCoords(nextTexCoords);
        setIndices(nextIndices);
    }, []);

    setTimeout(updateMesh, 1000);

    const image = "https://placekitten.com/g/256/256";

    return (
        <Stage width={800} height={600}>
            <SimpleMesh ref={meshRef} autoUpdate image={image} vertices={vertices} uvs={texCoords} indices={indices} />
        </Stage>
    );
}

Environment

Possible Solution

For anyone else experiencing this issue, I have worked around the issue for now using the following code:

function TexturedFillRenderer(shape: TexturedFill) {
    const { texCoords, indices, positions, texture } = shape;

    const [geometry, setGeometry] = useState<Geometry>();

    useEffect(() => {
        const geometry = new Geometry();

        geometry.addAttribute("aVertexPosition", positions, 2);
        geometry.addAttribute("aTextureCoord", texCoords, 2);
        geometry.addIndex(indices);

        setGeometry(geometry);

        return () => {
            geometry.destroy();
        };
    }, [shape]);

    return <SimpleMesh geometry={geometry} image={texture.url} />;
}

Additional Information

I just wanted to take the time to congratulate you all on making such an amazing library! My productivity has been insane while using it (and all of Pixi.js in general). Seriously, incredible work!