Repository: mrdoob/three.js (JavaScript)

Issue:
NURBSCurve.toJSON doesn't serialize points data
### Description

The JSON object returned from `NURBSCurve.toJSON()` doesn't contain data relating points, knots or control points, but instead contains:

```
{
    "metadata": {
        "version": 4.6,
        "type": "Curve",
        "generator": "Curve.toJSON"
    },
    "arcLengthDivisions": 200,
    "type": "Curve"
}
```

### Reproduction steps

1. Create an instance of NURBSCurve (sample code below), 
2. `console.log` nurbsCurveInstance.toJSON()
3. Notice there is no data relating to the instance, e.g points, knots and control points)


### Code

```js
const nurbsControlPoints = [];
const nurbsKnots = [];
const nurbsDegree = 3;

for (let i = 0; i <= nurbsDegree; i++) {
  nurbsKnots.push(0);
}

for (let i = 0, j = 20; i < j; i++) {
  nurbsControlPoints.push(
    new THREE.Vector4(
      Math.random(),
      Math.random(),
      Math.random(),
      1 // weight of control point: higher means stronger attraction
    )
  );

  const knot = (i + 1) / (j - nurbsDegree);
  nurbsKnots.push(THREE.MathUtils.clamp(knot, 0, 1));
}

const nurbsCurve = new NURBSCurve(nurbsDegree, nurbsKnots, nurbsControlPoints);

console.log(nurbsCurve.toJSON());
```


### Live example

https://codesandbox.io/p/sandbox/threejs-nurbscurve-tojson-bug-s298gc

### Screenshots

_No response_

### Version

168

### Device

Desktop, Mobile

### Browser

Chrome, Firefox, Safari, Edge

### OS

MacOS


Discussion: `NURBSCurve` is part of the addons and there is no JSON support for this class right now. Only curves classes in the core support that.

Even with a proper `NURBSCurve.toJSON()` implementation you also need the `fromJSON()` counterpart to make a deserialization work.
The next problem is that objects deserialized with `ObjectLoader` can't restore instances of `NURBSCurve` because the type is unknown for the core. So we can only add partial serialization/deserialization support right now.
Thanks for the quick reply, Mugen87. 

I'm happy to add the functionality for `NURBSCurve.toJSON` and `NURBSCurve.fromJSON`, and can push a PR shortly.

With regard to [`ObjectLoader`](https://github.com/mrdoob/three.js/blob/a8b6c17696d5cbc001ba9f7685a93cee9ddb0018/src/loaders/ObjectLoader.js), if I understand correctly it appears that there's doesn't exist any support for any type of Curve yet.
`ObjectLoader` can save and load e.g. instances of `ShapeGeometry` which define their outlines via curves. The deserialization is delegated to `CurvePath`. The problematic bit is this:

https://github.com/mrdoob/three.js/blob/be667f12f9f114ab3a4e12bbd45b99f9822ef56f/src/extras/core/CurvePath.js#L244

`Curves` represents what is defined in this file: https://github.com/mrdoob/three.js/blob/be667f12f9f114ab3a4e12bbd45b99f9822ef56f/src/extras/curves/Curves.js
Quick q @Mugen87, I came across the doc, https://github.com/mrdoob/three.js/wiki/Mr.doob%27s-Code-Style%E2%84%A2, but didn't see any mention of a VS Code formatter extension. Is there one available to auto format code for the preferred code style?
If you configure VS code with an ESLint extension, it should automatically detect the lint configuration in https://github.com/mrdoob/three.js/blob/dev/.eslintrc.json.



Fix (patch):
diff --git a/examples/jsm/curves/NURBSCurve.js b/examples/jsm/curves/NURBSCurve.js
index 8be8dde2d61b4b..f0ee02b398a52d 100644
--- a/examples/jsm/curves/NURBSCurve.js
+++ b/examples/jsm/curves/NURBSCurve.js
@@ -26,14 +26,17 @@ class NURBSCurve extends Curve {
 
 		super();
 
+		const knotsLength = knots ? knots.length - 1 : 0;
+		const pointsLength = controlPoints ? controlPoints.length : 0;
+
 		this.degree = degree;
 		this.knots = knots;
 		this.controlPoints = [];
 		// Used by periodic NURBS to remove hidden spans
 		this.startKnot = startKnot || 0;
-		this.endKnot = endKnot || ( this.knots.length - 1 );
+		this.endKnot = endKnot || knotsLength;
 
-		for ( let i = 0; i < controlPoints.length; ++ i ) {
+		for ( let i = 0; i < pointsLength; ++ i ) {
 
 			// ensure Vector4 for control points
 			const point = controlPoints[ i ];
@@ -75,6 +78,34 @@ class NURBSCurve extends Curve {
 
 	}
 
+	toJSON() {
+
+		const data = super.toJSON();
+
+		data.degree = this.degree;
+		data.knots = [ ...this.knots ];
+		data.controlPoints = this.controlPoints.map( p => p.toArray() );
+		data.startKnot = this.startKnot;
+		data.endKnot = this.endKnot;
+
+		return data;
+
+	}
+
+	fromJSON( json ) {
+
+		super.fromJSON( json );
+
+		this.degree = json.degree;
+		this.knots = [ ...json.knots ];
+		this.controlPoints = json.controlPoints.map( p => new Vector4( p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ) );
+		this.startKnot = json.startKnot;
+		this.endKnot = json.endKnot;
+
+		return this;
+
+	}
+
 }
 
-export { NURBSCurve };
+export { NURBSCurve };
\ No newline at end of file