react-three-nurbs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +198 -0
  2. package/dist/index.js +821 -0
  3. package/package.json +84 -0
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # react-three-nurbs
2
+
3
+ A React component library for rendering NURBS (Non-Uniform Rational B-Spline) surfaces in Three.js. Built with React Three Fiber, this library provides an easy way to create and visualize complex curved surfaces in your 3D applications.
4
+
5
+ ## Features
6
+
7
+ - 🎯 Simple React component API for NURBS surfaces
8
+ - 📐 Support for arbitrary degree NURBS surfaces
9
+ - 🎨 Customizable surface appearance with R3F materials
10
+ - 🔄 Automatic normal calculation for proper lighting
11
+ - 🎮 Interactive 3D visualization with React Three Fiber
12
+ - 📦 Written in TypeScript with full type support
13
+ - 🎨 Compatible with drei's Line component for curves
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install react-three-nurbs
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### Surface with Default Material
24
+
25
+ ```tsx
26
+ import { NurbsSurface } from 'react-three-nurbs'
27
+ import { Canvas } from '@react-three/fiber'
28
+
29
+ function App() {
30
+ // Define a simple 4x4 control point grid for a surface
31
+ const controlPoints = [
32
+ [[-1, -1, 0], [-1, -0.5, 0], [-1, 0.5, 0], [-1, 1, 0]],
33
+ [[-0.5, -1, 0], [-0.5, -0.5, 1], [-0.5, 0.5, 1], [-0.5, 1, 0]],
34
+ [[0.5, -1, 0], [0.5, -0.5, 1], [0.5, 0.5, 1], [0.5, 1, 0]],
35
+ [[1, -1, 0], [1, -0.5, 0], [1, 0.5, 0], [1, 1, 0]]
36
+ ]
37
+
38
+ // Define weights for each control point (1.0 for uniform B-spline)
39
+ const weights = [
40
+ [1, 1, 1, 1],
41
+ [1, 1, 1, 1],
42
+ [1, 1, 1, 1],
43
+ [1, 1, 1, 1]
44
+ ]
45
+
46
+ return (
47
+ <Canvas>
48
+ <ambientLight intensity={0.5} />
49
+ <pointLight position={[10, 10, 10]} />
50
+ <NurbsSurface
51
+ controlPoints={controlPoints}
52
+ weights={weights}
53
+ degreeU={3}
54
+ degreeV={3}
55
+ color="#ff0000"
56
+ wireframe={false}
57
+ />
58
+ </Canvas>
59
+ )
60
+ }
61
+ ```
62
+
63
+ ### Surface with Custom Material
64
+
65
+ ```tsx
66
+ import { NurbsSurface } from 'react-three-nurbs'
67
+ import { Canvas } from '@react-three/fiber'
68
+ import { MeshStandardMaterial } from 'three'
69
+
70
+ function App() {
71
+ // ... control points and weights as above ...
72
+
73
+ return (
74
+ <Canvas>
75
+ <ambientLight intensity={0.5} />
76
+ <pointLight position={[10, 10, 10]} />
77
+ <NurbsSurface
78
+ controlPoints={controlPoints}
79
+ weights={weights}
80
+ degreeU={3}
81
+ degreeV={3}
82
+ position={[0, 0, 0]}
83
+ rotation={[0, Math.PI / 4, 0]}
84
+ >
85
+ <meshStandardMaterial
86
+ color="#00ff00"
87
+ metalness={0.5}
88
+ roughness={0.5}
89
+ wireframe={true}
90
+ />
91
+ </NurbsSurface>
92
+ </Canvas>
93
+ )
94
+ }
95
+ ```
96
+
97
+ ### NURBS Curve
98
+
99
+ ```tsx
100
+ import { NurbsCurve } from 'react-three-nurbs'
101
+ import { Canvas } from '@react-three/fiber'
102
+
103
+ function App() {
104
+ const points = [
105
+ [0, 0, 0],
106
+ [1, 1, 0],
107
+ [2, 0, 0],
108
+ [3, 1, 0],
109
+ [4, 0, 0],
110
+ ]
111
+
112
+ const knots = [0, 0, 0, 0.5, 1, 1, 1]
113
+
114
+ return (
115
+ <Canvas>
116
+ <NurbsCurve
117
+ points={points}
118
+ knots={knots}
119
+ degree={2}
120
+ color="red"
121
+ dashed={true}
122
+ segments={true}
123
+ vertexColors={[
124
+ [1, 0, 0], // red
125
+ [0, 1, 0], // green
126
+ [0, 0, 1], // blue
127
+ [1, 1, 0], // yellow
128
+ [1, 0, 1], // magenta
129
+ ]}
130
+ />
131
+ </Canvas>
132
+ )
133
+ }
134
+ ```
135
+
136
+ ## Props
137
+
138
+ ### NurbsSurface Props
139
+
140
+ | Prop | Type | Required | Default | Description |
141
+ |------|------|----------|---------|-------------|
142
+ | `controlPoints` | `number[][][]` | Yes | - | 3D control points grid defining the surface shape |
143
+ | `weights` | `number[][]` | Yes | - | Weights for each control point |
144
+ | `degreeU` | `number` | Yes | - | Degree of the surface in U direction |
145
+ | `degreeV` | `number` | Yes | - | Degree of the surface in V direction |
146
+ | `color` | `string` | No | `'#ffffff'` | Surface color (only used if no material is provided) |
147
+ | `wireframe` | `boolean` | No | `false` | Whether to render as wireframe (only used if no material is provided) |
148
+ | `children` | `ReactElement` | No | - | Material component (e.g., `meshStandardMaterial`, `meshPhongMaterial`) |
149
+ | `...meshProps` | `MeshProps` | No | - | All React Three Fiber mesh props are supported |
150
+
151
+ ### NurbsCurve Props
152
+
153
+ | Prop | Type | Required | Default | Description |
154
+ |------|------|----------|---------|-------------|
155
+ | `points` | `number[][]` | Yes | - | Control points defining the curve shape |
156
+ | `knots` | `number[]` | Yes | - | Knot vector defining the curve parameterization |
157
+ | `degree` | `number` | No | `3` | Degree of the curve |
158
+ | `weights` | `number[]` | No | `[1, 1, ...]` | Weights for each control point |
159
+ | `curveResolution` | `number` | No | `50` | Number of points to sample along the curve |
160
+ | `color` | `string` | No | `'black'` | Line color |
161
+ | `segments` | `boolean` | No | `false` | Whether to render as line segments |
162
+ | `dashed` | `boolean` | No | `false` | Whether to render as dashed line |
163
+ | `vertexColors` | `number[][]` | No | - | RGB colors for each vertex |
164
+ | `...lineProps` | `LineProps` | No | - | All drei Line component props are supported |
165
+
166
+ ## Development
167
+
168
+ This project is built with:
169
+ - [React](https://reactjs.org/)
170
+ - [Three.js](https://threejs.org/)
171
+ - [React Three Fiber](https://github.com/pmndrs/react-three-fiber)
172
+ - [verb-nurbs](https://github.com/pboyer/verb) for NURBS calculations
173
+ - [Vite](https://vitejs.dev/) for building
174
+ - [TypeScript](https://www.typescriptlang.org/) for type safety
175
+
176
+ ### Setup
177
+
178
+ ```bash
179
+ # Install dependencies
180
+ npm install
181
+
182
+ # Start development server
183
+ npm run dev
184
+
185
+ # Build the library
186
+ npm run build
187
+
188
+ # Run Storybook
189
+ npm run storybook
190
+ ```
191
+
192
+ ## License
193
+
194
+ MIT
195
+
196
+ ## Contributing
197
+
198
+ Contributions are welcome! Please feel free to submit a Pull Request.
package/dist/index.js ADDED
@@ -0,0 +1,821 @@
1
+ import Ne, { useMemo as Me, useState as pr, useEffect as mr, isValidElement as Ye, Children as br } from "react";
2
+ import { Vector3 as hr, BufferGeometry as yr, Float32BufferAttribute as Ie, MeshPhongMaterial as gr, DoubleSide as Er, Color as _r, Mesh as Rr } from "three";
3
+ import ue from "verb-nurbs";
4
+ import { Line as Sr } from "@react-three/drei";
5
+ import { useThree as Cr } from "@react-three/fiber";
6
+ var ge = { exports: {} }, ee = {};
7
+ /**
8
+ * @license React
9
+ * react-jsx-runtime.production.min.js
10
+ *
11
+ * Copyright (c) Facebook, Inc. and its affiliates.
12
+ *
13
+ * This source code is licensed under the MIT license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ var We;
17
+ function Tr() {
18
+ if (We) return ee;
19
+ We = 1;
20
+ var T = Ne, x = Symbol.for("react.element"), y = Symbol.for("react.fragment"), c = Object.prototype.hasOwnProperty, k = T.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, F = { key: !0, ref: !0, __self: !0, __source: !0 };
21
+ function _(g, f, E) {
22
+ var p, m = {}, R = null, D = null;
23
+ E !== void 0 && (R = "" + E), f.key !== void 0 && (R = "" + f.key), f.ref !== void 0 && (D = f.ref);
24
+ for (p in f) c.call(f, p) && !F.hasOwnProperty(p) && (m[p] = f[p]);
25
+ if (g && g.defaultProps) for (p in f = g.defaultProps, f) m[p] === void 0 && (m[p] = f[p]);
26
+ return { $$typeof: x, type: g, key: R, ref: D, props: m, _owner: k.current };
27
+ }
28
+ return ee.Fragment = y, ee.jsx = _, ee.jsxs = _, ee;
29
+ }
30
+ var re = {};
31
+ /**
32
+ * @license React
33
+ * react-jsx-runtime.development.js
34
+ *
35
+ * Copyright (c) Facebook, Inc. and its affiliates.
36
+ *
37
+ * This source code is licensed under the MIT license found in the
38
+ * LICENSE file in the root directory of this source tree.
39
+ */
40
+ var $e;
41
+ function wr() {
42
+ return $e || ($e = 1, process.env.NODE_ENV !== "production" && function() {
43
+ var T = Ne, x = Symbol.for("react.element"), y = Symbol.for("react.portal"), c = Symbol.for("react.fragment"), k = Symbol.for("react.strict_mode"), F = Symbol.for("react.profiler"), _ = Symbol.for("react.provider"), g = Symbol.for("react.context"), f = Symbol.for("react.forward_ref"), E = Symbol.for("react.suspense"), p = Symbol.for("react.suspense_list"), m = Symbol.for("react.memo"), R = Symbol.for("react.lazy"), D = Symbol.for("react.offscreen"), S = Symbol.iterator, b = "@@iterator";
44
+ function v(e) {
45
+ if (e === null || typeof e != "object")
46
+ return null;
47
+ var r = S && e[S] || e[b];
48
+ return typeof r == "function" ? r : null;
49
+ }
50
+ var C = T.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
51
+ function s(e) {
52
+ {
53
+ for (var r = arguments.length, t = new Array(r > 1 ? r - 1 : 0), n = 1; n < r; n++)
54
+ t[n - 1] = arguments[n];
55
+ W("error", e, t);
56
+ }
57
+ }
58
+ function W(e, r, t) {
59
+ {
60
+ var n = C.ReactDebugCurrentFrame, i = n.getStackAddendum();
61
+ i !== "" && (r += "%s", t = t.concat([i]));
62
+ var u = t.map(function(o) {
63
+ return String(o);
64
+ });
65
+ u.unshift("Warning: " + r), Function.prototype.apply.call(console[e], console, u);
66
+ }
67
+ }
68
+ var H = !1, U = !1, ce = !1, fe = !1, w = !1, l;
69
+ l = Symbol.for("react.module.reference");
70
+ function $(e) {
71
+ return !!(typeof e == "string" || typeof e == "function" || e === c || e === F || w || e === k || e === E || e === p || fe || e === D || H || U || ce || typeof e == "object" && e !== null && (e.$$typeof === R || e.$$typeof === m || e.$$typeof === _ || e.$$typeof === g || e.$$typeof === f || // This needs to include all possible module reference object
72
+ // types supported by any Flight configuration anywhere since
73
+ // we don't know which Flight build this will end up being used
74
+ // with.
75
+ e.$$typeof === l || e.getModuleId !== void 0));
76
+ }
77
+ function N(e, r, t) {
78
+ var n = e.displayName;
79
+ if (n)
80
+ return n;
81
+ var i = r.displayName || r.name || "";
82
+ return i !== "" ? t + "(" + i + ")" : t;
83
+ }
84
+ function B(e) {
85
+ return e.displayName || "Context";
86
+ }
87
+ function j(e) {
88
+ if (e == null)
89
+ return null;
90
+ if (typeof e.tag == "number" && s("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), typeof e == "function")
91
+ return e.displayName || e.name || null;
92
+ if (typeof e == "string")
93
+ return e;
94
+ switch (e) {
95
+ case c:
96
+ return "Fragment";
97
+ case y:
98
+ return "Portal";
99
+ case F:
100
+ return "Profiler";
101
+ case k:
102
+ return "StrictMode";
103
+ case E:
104
+ return "Suspense";
105
+ case p:
106
+ return "SuspenseList";
107
+ }
108
+ if (typeof e == "object")
109
+ switch (e.$$typeof) {
110
+ case g:
111
+ var r = e;
112
+ return B(r) + ".Consumer";
113
+ case _:
114
+ var t = e;
115
+ return B(t._context) + ".Provider";
116
+ case f:
117
+ return N(e, e.render, "ForwardRef");
118
+ case m:
119
+ var n = e.displayName || null;
120
+ return n !== null ? n : j(e.type) || "Memo";
121
+ case R: {
122
+ var i = e, u = i._payload, o = i._init;
123
+ try {
124
+ return j(o(u));
125
+ } catch {
126
+ return null;
127
+ }
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ var M = Object.assign, z = 0, Z, Y, L, I, te, ne, q;
133
+ function J() {
134
+ }
135
+ J.__reactDisabledLog = !0;
136
+ function Le() {
137
+ {
138
+ if (z === 0) {
139
+ Z = console.log, Y = console.info, L = console.warn, I = console.error, te = console.group, ne = console.groupCollapsed, q = console.groupEnd;
140
+ var e = {
141
+ configurable: !0,
142
+ enumerable: !0,
143
+ value: J,
144
+ writable: !0
145
+ };
146
+ Object.defineProperties(console, {
147
+ info: e,
148
+ log: e,
149
+ warn: e,
150
+ error: e,
151
+ group: e,
152
+ groupCollapsed: e,
153
+ groupEnd: e
154
+ });
155
+ }
156
+ z++;
157
+ }
158
+ }
159
+ function Ke() {
160
+ {
161
+ if (z--, z === 0) {
162
+ var e = {
163
+ configurable: !0,
164
+ enumerable: !0,
165
+ writable: !0
166
+ };
167
+ Object.defineProperties(console, {
168
+ log: M({}, e, {
169
+ value: Z
170
+ }),
171
+ info: M({}, e, {
172
+ value: Y
173
+ }),
174
+ warn: M({}, e, {
175
+ value: L
176
+ }),
177
+ error: M({}, e, {
178
+ value: I
179
+ }),
180
+ group: M({}, e, {
181
+ value: te
182
+ }),
183
+ groupCollapsed: M({}, e, {
184
+ value: ne
185
+ }),
186
+ groupEnd: M({}, e, {
187
+ value: q
188
+ })
189
+ });
190
+ }
191
+ z < 0 && s("disabledDepth fell below zero. This is a bug in React. Please file an issue.");
192
+ }
193
+ }
194
+ var le = C.ReactCurrentDispatcher, ve;
195
+ function ae(e, r, t) {
196
+ {
197
+ if (ve === void 0)
198
+ try {
199
+ throw Error();
200
+ } catch (i) {
201
+ var n = i.stack.trim().match(/\n( *(at )?)/);
202
+ ve = n && n[1] || "";
203
+ }
204
+ return `
205
+ ` + ve + e;
206
+ }
207
+ }
208
+ var de = !1, oe;
209
+ {
210
+ var Be = typeof WeakMap == "function" ? WeakMap : Map;
211
+ oe = new Be();
212
+ }
213
+ function Ee(e, r) {
214
+ if (!e || de)
215
+ return "";
216
+ {
217
+ var t = oe.get(e);
218
+ if (t !== void 0)
219
+ return t;
220
+ }
221
+ var n;
222
+ de = !0;
223
+ var i = Error.prepareStackTrace;
224
+ Error.prepareStackTrace = void 0;
225
+ var u;
226
+ u = le.current, le.current = null, Le();
227
+ try {
228
+ if (r) {
229
+ var o = function() {
230
+ throw Error();
231
+ };
232
+ if (Object.defineProperty(o.prototype, "props", {
233
+ set: function() {
234
+ throw Error();
235
+ }
236
+ }), typeof Reflect == "object" && Reflect.construct) {
237
+ try {
238
+ Reflect.construct(o, []);
239
+ } catch (P) {
240
+ n = P;
241
+ }
242
+ Reflect.construct(e, [], o);
243
+ } else {
244
+ try {
245
+ o.call();
246
+ } catch (P) {
247
+ n = P;
248
+ }
249
+ e.call(o.prototype);
250
+ }
251
+ } else {
252
+ try {
253
+ throw Error();
254
+ } catch (P) {
255
+ n = P;
256
+ }
257
+ e();
258
+ }
259
+ } catch (P) {
260
+ if (P && n && typeof P.stack == "string") {
261
+ for (var a = P.stack.split(`
262
+ `), O = n.stack.split(`
263
+ `), d = a.length - 1, h = O.length - 1; d >= 1 && h >= 0 && a[d] !== O[h]; )
264
+ h--;
265
+ for (; d >= 1 && h >= 0; d--, h--)
266
+ if (a[d] !== O[h]) {
267
+ if (d !== 1 || h !== 1)
268
+ do
269
+ if (d--, h--, h < 0 || a[d] !== O[h]) {
270
+ var A = `
271
+ ` + a[d].replace(" at new ", " at ");
272
+ return e.displayName && A.includes("<anonymous>") && (A = A.replace("<anonymous>", e.displayName)), typeof e == "function" && oe.set(e, A), A;
273
+ }
274
+ while (d >= 1 && h >= 0);
275
+ break;
276
+ }
277
+ }
278
+ } finally {
279
+ de = !1, le.current = u, Ke(), Error.prepareStackTrace = i;
280
+ }
281
+ var X = e ? e.displayName || e.name : "", G = X ? ae(X) : "";
282
+ return typeof e == "function" && oe.set(e, G), G;
283
+ }
284
+ function qe(e, r, t) {
285
+ return Ee(e, !1);
286
+ }
287
+ function Ue(e) {
288
+ var r = e.prototype;
289
+ return !!(r && r.isReactComponent);
290
+ }
291
+ function ie(e, r, t) {
292
+ if (e == null)
293
+ return "";
294
+ if (typeof e == "function")
295
+ return Ee(e, Ue(e));
296
+ if (typeof e == "string")
297
+ return ae(e);
298
+ switch (e) {
299
+ case E:
300
+ return ae("Suspense");
301
+ case p:
302
+ return ae("SuspenseList");
303
+ }
304
+ if (typeof e == "object")
305
+ switch (e.$$typeof) {
306
+ case f:
307
+ return qe(e.render);
308
+ case m:
309
+ return ie(e.type, r, t);
310
+ case R: {
311
+ var n = e, i = n._payload, u = n._init;
312
+ try {
313
+ return ie(u(i), r, t);
314
+ } catch {
315
+ }
316
+ }
317
+ }
318
+ return "";
319
+ }
320
+ var Q = Object.prototype.hasOwnProperty, _e = {}, Re = C.ReactDebugCurrentFrame;
321
+ function se(e) {
322
+ if (e) {
323
+ var r = e._owner, t = ie(e.type, e._source, r ? r.type : null);
324
+ Re.setExtraStackFrame(t);
325
+ } else
326
+ Re.setExtraStackFrame(null);
327
+ }
328
+ function ze(e, r, t, n, i) {
329
+ {
330
+ var u = Function.call.bind(Q);
331
+ for (var o in e)
332
+ if (u(e, o)) {
333
+ var a = void 0;
334
+ try {
335
+ if (typeof e[o] != "function") {
336
+ var O = Error((n || "React class") + ": " + t + " type `" + o + "` is invalid; it must be a function, usually from the `prop-types` package, but received `" + typeof e[o] + "`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.");
337
+ throw O.name = "Invariant Violation", O;
338
+ }
339
+ a = e[o](r, o, n, t, null, "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED");
340
+ } catch (d) {
341
+ a = d;
342
+ }
343
+ a && !(a instanceof Error) && (se(i), s("%s: type specification of %s `%s` is invalid; the type checker function must return `null` or an `Error` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).", n || "React class", t, o, typeof a), se(null)), a instanceof Error && !(a.message in _e) && (_e[a.message] = !0, se(i), s("Failed %s type: %s", t, a.message), se(null));
344
+ }
345
+ }
346
+ }
347
+ var Ge = Array.isArray;
348
+ function pe(e) {
349
+ return Ge(e);
350
+ }
351
+ function Je(e) {
352
+ {
353
+ var r = typeof Symbol == "function" && Symbol.toStringTag, t = r && e[Symbol.toStringTag] || e.constructor.name || "Object";
354
+ return t;
355
+ }
356
+ }
357
+ function Ve(e) {
358
+ try {
359
+ return Se(e), !1;
360
+ } catch {
361
+ return !0;
362
+ }
363
+ }
364
+ function Se(e) {
365
+ return "" + e;
366
+ }
367
+ function Ce(e) {
368
+ if (Ve(e))
369
+ return s("The provided key is an unsupported type %s. This value must be coerced to a string before before using it here.", Je(e)), Se(e);
370
+ }
371
+ var Te = C.ReactCurrentOwner, Xe = {
372
+ key: !0,
373
+ ref: !0,
374
+ __self: !0,
375
+ __source: !0
376
+ }, we, je;
377
+ function He(e) {
378
+ if (Q.call(e, "ref")) {
379
+ var r = Object.getOwnPropertyDescriptor(e, "ref").get;
380
+ if (r && r.isReactWarning)
381
+ return !1;
382
+ }
383
+ return e.ref !== void 0;
384
+ }
385
+ function Ze(e) {
386
+ if (Q.call(e, "key")) {
387
+ var r = Object.getOwnPropertyDescriptor(e, "key").get;
388
+ if (r && r.isReactWarning)
389
+ return !1;
390
+ }
391
+ return e.key !== void 0;
392
+ }
393
+ function Qe(e, r) {
394
+ typeof e.ref == "string" && Te.current;
395
+ }
396
+ function er(e, r) {
397
+ {
398
+ var t = function() {
399
+ we || (we = !0, s("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)", r));
400
+ };
401
+ t.isReactWarning = !0, Object.defineProperty(e, "key", {
402
+ get: t,
403
+ configurable: !0
404
+ });
405
+ }
406
+ }
407
+ function rr(e, r) {
408
+ {
409
+ var t = function() {
410
+ je || (je = !0, s("%s: `ref` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props)", r));
411
+ };
412
+ t.isReactWarning = !0, Object.defineProperty(e, "ref", {
413
+ get: t,
414
+ configurable: !0
415
+ });
416
+ }
417
+ }
418
+ var tr = function(e, r, t, n, i, u, o) {
419
+ var a = {
420
+ // This tag allows us to uniquely identify this as a React Element
421
+ $$typeof: x,
422
+ // Built-in properties that belong on the element
423
+ type: e,
424
+ key: r,
425
+ ref: t,
426
+ props: o,
427
+ // Record the component responsible for creating this element.
428
+ _owner: u
429
+ };
430
+ return a._store = {}, Object.defineProperty(a._store, "validated", {
431
+ configurable: !1,
432
+ enumerable: !1,
433
+ writable: !0,
434
+ value: !1
435
+ }), Object.defineProperty(a, "_self", {
436
+ configurable: !1,
437
+ enumerable: !1,
438
+ writable: !1,
439
+ value: n
440
+ }), Object.defineProperty(a, "_source", {
441
+ configurable: !1,
442
+ enumerable: !1,
443
+ writable: !1,
444
+ value: i
445
+ }), Object.freeze && (Object.freeze(a.props), Object.freeze(a)), a;
446
+ };
447
+ function nr(e, r, t, n, i) {
448
+ {
449
+ var u, o = {}, a = null, O = null;
450
+ t !== void 0 && (Ce(t), a = "" + t), Ze(r) && (Ce(r.key), a = "" + r.key), He(r) && (O = r.ref, Qe(r, i));
451
+ for (u in r)
452
+ Q.call(r, u) && !Xe.hasOwnProperty(u) && (o[u] = r[u]);
453
+ if (e && e.defaultProps) {
454
+ var d = e.defaultProps;
455
+ for (u in d)
456
+ o[u] === void 0 && (o[u] = d[u]);
457
+ }
458
+ if (a || O) {
459
+ var h = typeof e == "function" ? e.displayName || e.name || "Unknown" : e;
460
+ a && er(o, h), O && rr(o, h);
461
+ }
462
+ return tr(e, a, O, i, n, Te.current, o);
463
+ }
464
+ }
465
+ var me = C.ReactCurrentOwner, Oe = C.ReactDebugCurrentFrame;
466
+ function V(e) {
467
+ if (e) {
468
+ var r = e._owner, t = ie(e.type, e._source, r ? r.type : null);
469
+ Oe.setExtraStackFrame(t);
470
+ } else
471
+ Oe.setExtraStackFrame(null);
472
+ }
473
+ var be;
474
+ be = !1;
475
+ function he(e) {
476
+ return typeof e == "object" && e !== null && e.$$typeof === x;
477
+ }
478
+ function Pe() {
479
+ {
480
+ if (me.current) {
481
+ var e = j(me.current.type);
482
+ if (e)
483
+ return `
484
+
485
+ Check the render method of \`` + e + "`.";
486
+ }
487
+ return "";
488
+ }
489
+ }
490
+ function ar(e) {
491
+ return "";
492
+ }
493
+ var xe = {};
494
+ function or(e) {
495
+ {
496
+ var r = Pe();
497
+ if (!r) {
498
+ var t = typeof e == "string" ? e : e.displayName || e.name;
499
+ t && (r = `
500
+
501
+ Check the top-level render call using <` + t + ">.");
502
+ }
503
+ return r;
504
+ }
505
+ }
506
+ function ke(e, r) {
507
+ {
508
+ if (!e._store || e._store.validated || e.key != null)
509
+ return;
510
+ e._store.validated = !0;
511
+ var t = or(r);
512
+ if (xe[t])
513
+ return;
514
+ xe[t] = !0;
515
+ var n = "";
516
+ e && e._owner && e._owner !== me.current && (n = " It was passed a child from " + j(e._owner.type) + "."), V(e), s('Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.', t, n), V(null);
517
+ }
518
+ }
519
+ function Ae(e, r) {
520
+ {
521
+ if (typeof e != "object")
522
+ return;
523
+ if (pe(e))
524
+ for (var t = 0; t < e.length; t++) {
525
+ var n = e[t];
526
+ he(n) && ke(n, r);
527
+ }
528
+ else if (he(e))
529
+ e._store && (e._store.validated = !0);
530
+ else if (e) {
531
+ var i = v(e);
532
+ if (typeof i == "function" && i !== e.entries)
533
+ for (var u = i.call(e), o; !(o = u.next()).done; )
534
+ he(o.value) && ke(o.value, r);
535
+ }
536
+ }
537
+ }
538
+ function ir(e) {
539
+ {
540
+ var r = e.type;
541
+ if (r == null || typeof r == "string")
542
+ return;
543
+ var t;
544
+ if (typeof r == "function")
545
+ t = r.propTypes;
546
+ else if (typeof r == "object" && (r.$$typeof === f || // Note: Memo only checks outer props here.
547
+ // Inner props are checked in the reconciler.
548
+ r.$$typeof === m))
549
+ t = r.propTypes;
550
+ else
551
+ return;
552
+ if (t) {
553
+ var n = j(r);
554
+ ze(t, e.props, "prop", n, e);
555
+ } else if (r.PropTypes !== void 0 && !be) {
556
+ be = !0;
557
+ var i = j(r);
558
+ s("Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?", i || "Unknown");
559
+ }
560
+ typeof r.getDefaultProps == "function" && !r.getDefaultProps.isReactClassApproved && s("getDefaultProps is only used on classic React.createClass definitions. Use a static property named `defaultProps` instead.");
561
+ }
562
+ }
563
+ function sr(e) {
564
+ {
565
+ for (var r = Object.keys(e.props), t = 0; t < r.length; t++) {
566
+ var n = r[t];
567
+ if (n !== "children" && n !== "key") {
568
+ V(e), s("Invalid prop `%s` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.", n), V(null);
569
+ break;
570
+ }
571
+ }
572
+ e.ref !== null && (V(e), s("Invalid attribute `ref` supplied to `React.Fragment`."), V(null));
573
+ }
574
+ }
575
+ var Fe = {};
576
+ function De(e, r, t, n, i, u) {
577
+ {
578
+ var o = $(e);
579
+ if (!o) {
580
+ var a = "";
581
+ (e === void 0 || typeof e == "object" && e !== null && Object.keys(e).length === 0) && (a += " You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.");
582
+ var O = ar();
583
+ O ? a += O : a += Pe();
584
+ var d;
585
+ e === null ? d = "null" : pe(e) ? d = "array" : e !== void 0 && e.$$typeof === x ? (d = "<" + (j(e.type) || "Unknown") + " />", a = " Did you accidentally export a JSX literal instead of a component?") : d = typeof e, s("React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", d, a);
586
+ }
587
+ var h = nr(e, r, t, i, u);
588
+ if (h == null)
589
+ return h;
590
+ if (o) {
591
+ var A = r.children;
592
+ if (A !== void 0)
593
+ if (n)
594
+ if (pe(A)) {
595
+ for (var X = 0; X < A.length; X++)
596
+ Ae(A[X], e);
597
+ Object.freeze && Object.freeze(A);
598
+ } else
599
+ s("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
600
+ else
601
+ Ae(A, e);
602
+ }
603
+ if (Q.call(r, "key")) {
604
+ var G = j(e), P = Object.keys(r).filter(function(dr) {
605
+ return dr !== "key";
606
+ }), ye = P.length > 0 ? "{key: someKey, " + P.join(": ..., ") + ": ...}" : "{key: someKey}";
607
+ if (!Fe[G + ye]) {
608
+ var vr = P.length > 0 ? "{" + P.join(": ..., ") + ": ...}" : "{}";
609
+ s(`A props object containing a "key" prop is being spread into JSX:
610
+ let props = %s;
611
+ <%s {...props} />
612
+ React keys must be passed directly to JSX without using spread:
613
+ let props = %s;
614
+ <%s key={someKey} {...props} />`, ye, G, vr, G), Fe[G + ye] = !0;
615
+ }
616
+ }
617
+ return e === c ? sr(h) : ir(h), h;
618
+ }
619
+ }
620
+ function ur(e, r, t) {
621
+ return De(e, r, t, !0);
622
+ }
623
+ function cr(e, r, t) {
624
+ return De(e, r, t, !1);
625
+ }
626
+ var fr = cr, lr = ur;
627
+ re.Fragment = c, re.jsx = fr, re.jsxs = lr;
628
+ }()), re;
629
+ }
630
+ process.env.NODE_ENV === "production" ? ge.exports = Tr() : ge.exports = wr();
631
+ var K = ge.exports;
632
+ const jr = ({
633
+ points: T,
634
+ degree: x = 3,
635
+ weights: y,
636
+ knots: c,
637
+ curveResolution: k = 50,
638
+ color: F = "black",
639
+ segments: _,
640
+ dashed: g = !1,
641
+ vertexColors: f,
642
+ ...E
643
+ }) => {
644
+ const p = Me(() => {
645
+ if (!c)
646
+ return console.error("NurbsCurve requires knots to be provided"), [];
647
+ try {
648
+ const m = Array(T.length).fill(1), R = ue.geom.NurbsCurve.byKnotsControlPointsWeights(
649
+ x,
650
+ c,
651
+ T,
652
+ y ?? m
653
+ );
654
+ return Array.from({ length: k + 1 }, (D, S) => {
655
+ const b = S / k, v = R.point(b);
656
+ return new hr(v[0], v[1], v[2]);
657
+ });
658
+ } catch (m) {
659
+ return console.error("Error creating NURBS curve:", m), [];
660
+ }
661
+ }, [T, x, y, c, k]);
662
+ return p.length === 0 ? null : /* @__PURE__ */ K.jsx(
663
+ Sr,
664
+ {
665
+ points: p,
666
+ color: F,
667
+ segments: _,
668
+ dashed: g,
669
+ vertexColors: f,
670
+ ...E
671
+ }
672
+ );
673
+ };
674
+ function Fr({
675
+ controlPoints: T,
676
+ weights: x,
677
+ degreeU: y,
678
+ degreeV: c,
679
+ color: k = "#ffffff",
680
+ wireframe: F = !1,
681
+ children: _,
682
+ ...g
683
+ }) {
684
+ const { scene: f } = Cr(), [E, p] = pr(null);
685
+ return mr(() => {
686
+ const m = T.length + y + 1, R = T[0].length + c + 1, D = Array(m).fill(0).map((w, l) => l < y + 1 ? 0 : l >= m - y - 1 ? 1 : (l - y) / (m - 2 * y - 1)), S = Array(R).fill(0).map((w, l) => l < c + 1 ? 0 : l >= R - c - 1 ? 1 : (l - c) / (R - 2 * c - 1)), b = ue.geom.NurbsSurface.byKnotsControlPointsWeights(
687
+ y,
688
+ c,
689
+ D,
690
+ S,
691
+ T,
692
+ x
693
+ ), v = new yr(), C = [], s = [], W = [], H = 20, U = 20, ce = 1 / H, fe = 1 / U;
694
+ for (let w = 0; w <= H; w++)
695
+ for (let l = 0; l <= U; l++) {
696
+ const $ = w * ce, N = l * fe, B = b.point($, N), j = 1e-4, M = b.point($ + j, N), z = b.point($, N + j), Z = b.point($, N), Y = M.map((q, J) => (q - Z[J]) / j), L = z.map((q, J) => (q - Z[J]) / j), I = [
697
+ Y[1] * L[2] - Y[2] * L[1],
698
+ Y[2] * L[0] - Y[0] * L[2],
699
+ Y[0] * L[1] - Y[1] * L[0]
700
+ ], te = Math.sqrt(
701
+ I[0] * I[0] + I[1] * I[1] + I[2] * I[2]
702
+ ), ne = I.map((q) => q / te);
703
+ C.push(...B), s.push(...ne);
704
+ }
705
+ for (let w = 0; w < H; w++)
706
+ for (let l = 0; l < U; l++) {
707
+ const $ = w * (U + 1) + l, N = $ + 1, B = (w + 1) * (U + 1) + l, j = B + 1;
708
+ W.push($, N, B), W.push(N, j, B);
709
+ }
710
+ if (v.setAttribute("position", new Ie(C, 3)), v.setAttribute("normal", new Ie(s, 3)), v.setIndex(W), p(v), !_) {
711
+ const w = new gr({
712
+ color: new _r(k),
713
+ side: Er,
714
+ wireframe: F
715
+ }), l = new Rr(v, w);
716
+ return f.add(l), () => {
717
+ f.remove(l), v.dispose(), w.dispose();
718
+ };
719
+ }
720
+ return () => {
721
+ v.dispose();
722
+ };
723
+ }, [
724
+ T,
725
+ x,
726
+ y,
727
+ c,
728
+ k,
729
+ F,
730
+ f,
731
+ _
732
+ ]), E && _ ? !Ye(_) || !_.type.toString().includes("Material") ? (console.warn("NurbsSurface children must be a material component"), null) : /* @__PURE__ */ K.jsxs("mesh", { ...g, children: [
733
+ /* @__PURE__ */ K.jsx("primitive", { object: E, attach: "geometry" }),
734
+ _
735
+ ] }) : null;
736
+ }
737
+ const Dr = ({
738
+ degreeV: T = 3,
739
+ knotsV: x,
740
+ resolutionU: y = 20,
741
+ resolutionV: c = 20,
742
+ color: k = "#ff0000",
743
+ wireframe: F = !1,
744
+ children: _
745
+ }) => {
746
+ const g = Me(() => {
747
+ const f = br.toArray(_).filter(
748
+ (E) => Ye(E) && E.type === jr
749
+ );
750
+ if (f.length < 2)
751
+ return console.error("LoftedSurface requires at least 2 NurbsCurve children"), null;
752
+ try {
753
+ const E = f.map((S) => {
754
+ const { points: b, degree: v = 3, weights: C, knots: s } = S.props, W = Array(b.length).fill(1);
755
+ return ue.geom.NurbsCurve.byKnotsControlPointsWeights(
756
+ v,
757
+ s,
758
+ b,
759
+ C ?? W
760
+ );
761
+ }), p = ue.geom.NurbsSurface.byLoftingCurves(
762
+ E,
763
+ T
764
+ ), m = [], R = [], D = [];
765
+ for (let S = 0; S <= y; S++)
766
+ for (let b = 0; b <= c; b++) {
767
+ const v = S / y, C = b / c, s = p.point(v, C);
768
+ m.push(s[0], s[1], s[2]), D.push(v, C);
769
+ }
770
+ for (let S = 0; S < y; S++)
771
+ for (let b = 0; b < c; b++) {
772
+ const v = S * (c + 1) + b, C = v + 1, s = (S + 1) * (c + 1) + b, W = s + 1;
773
+ R.push(v, C, s), R.push(C, W, s);
774
+ }
775
+ return {
776
+ vertices: m,
777
+ indices: R,
778
+ uvs: D
779
+ };
780
+ } catch (E) {
781
+ return console.error("Error creating lofted surface:", E), null;
782
+ }
783
+ }, [_, T, x, y, c]);
784
+ return g ? /* @__PURE__ */ K.jsxs("mesh", { children: [
785
+ /* @__PURE__ */ K.jsxs("bufferGeometry", { children: [
786
+ /* @__PURE__ */ K.jsx(
787
+ "bufferAttribute",
788
+ {
789
+ attach: "attributes-position",
790
+ count: g.vertices.length / 3,
791
+ array: new Float32Array(g.vertices),
792
+ itemSize: 3
793
+ }
794
+ ),
795
+ /* @__PURE__ */ K.jsx(
796
+ "bufferAttribute",
797
+ {
798
+ attach: "attributes-uv",
799
+ count: g.uvs.length / 2,
800
+ array: new Float32Array(g.uvs),
801
+ itemSize: 2
802
+ }
803
+ ),
804
+ /* @__PURE__ */ K.jsx(
805
+ "bufferAttribute",
806
+ {
807
+ attach: "index",
808
+ count: g.indices.length,
809
+ array: new Uint32Array(g.indices),
810
+ itemSize: 1
811
+ }
812
+ )
813
+ ] }),
814
+ /* @__PURE__ */ K.jsx("meshStandardMaterial", { color: k, wireframe: F })
815
+ ] }) : null;
816
+ };
817
+ export {
818
+ Dr as LoftedSurface,
819
+ jr as NurbsCurve,
820
+ Fr as NurbsSurface
821
+ };
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "react-three-nurbs",
3
+ "private": false,
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "author": "Tommaso Turchi",
10
+ "license": "MIT",
11
+ "main": "./dist/index.js",
12
+ "module": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "import": "./dist/index.js",
17
+ "types": "./dist/index.d.ts"
18
+ }
19
+ },
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "tsc && vite build",
23
+ "lint": "eslint .",
24
+ "preview": "vite preview",
25
+ "storybook": "npx storybook dev -p 6006",
26
+ "build-storybook": "npx storybook build",
27
+ "prepublishOnly": "npm run build",
28
+ "preversion": "npm run lint"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/tommasoturchi/react-three-nurbs.git"
36
+ },
37
+ "keywords": [
38
+ "react",
39
+ "three.js",
40
+ "react-three-fiber",
41
+ "nurbs",
42
+ "curves",
43
+ "surfaces",
44
+ "3d"
45
+ ],
46
+ "bugs": {
47
+ "url": "https://github.com/tommasoturchi/react-three-nurbs/issues"
48
+ },
49
+ "homepage": "https://react-three-nurbs.trx.li/",
50
+ "dependencies": {
51
+ "@react-three/drei": "^9.99.0",
52
+ "@react-three/fiber": "^8.15.16",
53
+ "react": "^18.2.0",
54
+ "react-dom": "^18.2.0",
55
+ "three": "^0.161.0",
56
+ "verb": "^0.8.10",
57
+ "verb-nurbs": "^3.0.3"
58
+ },
59
+ "devDependencies": {
60
+ "@storybook/addon-essentials": "^8.6.12",
61
+ "@storybook/addon-interactions": "^8.6.12",
62
+ "@storybook/addon-links": "^8.6.12",
63
+ "@storybook/blocks": "^8.6.12",
64
+ "@storybook/builder-vite": "^8.6.12",
65
+ "@storybook/react": "^8.6.12",
66
+ "@storybook/react-vite": "^8.6.12",
67
+ "@types/node": "^22.15.17",
68
+ "@types/react": "^18.2.55",
69
+ "@types/react-dom": "^18.2.19",
70
+ "@types/three": "^0.161.2",
71
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
72
+ "@typescript-eslint/parser": "^6.21.0",
73
+ "@vitejs/plugin-react": "^4.2.1",
74
+ "eslint": "^8.56.0",
75
+ "eslint-plugin-react-hooks": "^4.6.0",
76
+ "eslint-plugin-react-refresh": "^0.4.5",
77
+ "typescript": "^5.2.2",
78
+ "vite": "^5.1.0"
79
+ },
80
+ "peerDependencies": {
81
+ "react": "^18.2.0",
82
+ "react-dom": "^18.2.0"
83
+ }
84
+ }