Odd error while using curves and points from JSON file

Hello,

I’m trying to create a simple curve, the points are from a JSON file, when testing the code this error is shown:

chunk-R3I2WUGT.js?v=b85cb02e:2486 Uncaught TypeError: Cannot read properties of undefined (reading 'x')
    at _Vector3.subVectors (chunk-R3I2WUGT.js?v=b85cb02e:2486:16)
    at CatmullRomCurve3.getPoint (chunk-R3I2WUGT.js?v=b85cb02e:20834:11)
    at CatmullRomCurve3.getPoints (chunk-R3I2WUGT.js?v=b85cb02e:20503:24)
    at MeshManager.initCurve (MeshManager.js?t=1702903561300:56:30)
    at main.js:29:13
initCurve	@	MeshManager.js?t=1702903561300:56
(anonymous)	@	main.js:29
Show 3 more frames

my code is as follow: (note this script is a class and defined in the main js)

initCurve() {

        const curvePoints = [];
        fetch("./src/curve.json").then((res) => { return res.json(); }).then((data) => {
            data.points.forEach(element => {
                curvePoints.push(new THREE.Vector3(element.x, element.y, element.z));
            });
        });
        console.log(curvePoints);

        const curve = new THREE.CatmullRomCurve3(curvePoints);
        const points = curve.getPoints(11);
        const geometry = new THREE.BufferGeometry().setFromPoints(points);
        const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
        const curveObject = new THREE.Line(geometry, material);

        this.scene.add(curveObject);
    }

The JSON decoding part is from the internet and I’m not 100% sure I understand the code fully, though if I log the array curvePoints it looks correct.
I manually typed this JSON file (I just copied the points from blender spreadsheet)

{
    "points": [
        { "x":0,     "z":2,      "y":0},
        { "x":1.286, "z":1.532,  "y":0.444},
        { "x":1.970, "z":0.347,  "y":0.889},
        { "x":1.732, "z":-1,     "y":1.333},
        { "x":0.684, "z":-1.879, "y":1.778},
        { "x":-0.684,"z":-1.879, "y":2.222},
        { "x":-1.732,"z":1,      "y":2.667},
        { "x":-1.970,"z":0.347,  "y":3.111},
        { "x":-1.286,"z":1.532,  "y":3.556},
        { "x":0,     "z":2,      "y":4}
    ]
}

The error is at curve.getPoints, if I just wrote a list of points as new THREE.CatmullRomCurve3([new THREE.Vector3(x,y,z), ...]) it work perfectly. The thing is now it’s a small number from points, I’m just testing later I’ll create large JSON files, what’s wrong with my code?

Thanks

1 Like

Try this

const curvePoints = [];
        fetch("./src/curve.json").then((res) => { return res.json(); }).then((data) => {
            data.points.forEach(element => {
                curvePoints.push(new THREE.Vector3(element.x, element.y, element.z));
            });
          console.log(curvePoints);

          const curve = new THREE.CatmullRomCurve3(curvePoints);
          const points = curve.getPoints(11);
          const geometry = new THREE.BufferGeometry().setFromPoints(points);
          const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
          const curveObject = new THREE.Line(geometry, material);

          this.scene.add(curveObject);
        });
2 Likes

@anidivr So, the error is gone and it worked! But how? If I logged ‘curvePoints’ after the fetch it prints correct values! So the data did transfer to the array correctly?

Thanks for the fix.

1 Like

@anidivr Does is it have anything to do with syncing and .then? The time the curve is being generated, the array hasn’t been populated yet, no?

1 Like

Yes. Whenever you run code in a then (async), assume it might take a second before its executed. If anything depends on it, it needs to be included in the then.

1 Like

Thanks for the replay, but if you don’t mind me asking one more question, in my code I have the async function, then right after it a console.log and it print correctly with the array that is, how come the log read the data but not the curve.getPoints?

1 Like

Its just lucky timing. That’s the major frustration with async code. It might appear to work until you add more CPUs.

1 Like

So basically CatmullRomCurve3 needs a minimum points of two to draw a curve, if you check CatmullRomCurve3 code, you’ll find a subVectors operation which requires two vectors.

Try to check if your array has a minimum of two vector3s before applying the function