@react-three/drei 9.41.0 → 9.41.2

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.
package/README.md CHANGED
@@ -2635,16 +2635,48 @@ This component makes its contents float or hover.
2635
2635
 
2636
2636
  [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/staging-stage--stage-st)
2637
2637
 
2638
- Creates a "stage" with proper studio lighting, content centered and planar, shadows and ground-contact shadows.
2638
+ Creates a "stage" with proper studio lighting, content centered and planar, model-shadows and ground-shadows. Make sure to set `makeDefault` on your controls when `adjustCamera` is true!
2639
2639
 
2640
- Make sure to set the `makeDefault` prop on your controls, in that case you do not need to provide `controls` via prop.
2640
+ ```tsx
2641
+ type StageShadows = Partial<AccumulativeShadowsProps> &
2642
+ Partial<ContactShadowsProps> & {
2643
+ type: 'contact' | 'accumulative'
2644
+ bias?: number
2645
+ size?: number
2646
+ }
2647
+
2648
+ type StageProps = JSX.IntrinsicElements['group'] & {
2649
+ /** Lighting setup, default: "rembrandt" */
2650
+ preset?: keyof typeof presets
2651
+ /** Controls the ground shadows, default: "contact" */
2652
+ shadows?: boolean | 'contact' | 'accumulative' | StageShadows
2653
+ /** Optionally wraps and thereby centers the models using <Bounds>, can also be a margin, default: true */
2654
+ adjustCamera?: boolean | number
2655
+ /** The default environment, default: "city" */
2656
+ environment?: PresetsType | null
2657
+ /** The lighting intensity, default: 0.5 */
2658
+ intensity?: number
2659
+ }
2660
+ ```
2661
+
2662
+ By default it gives you contact shadows and auto-centering.
2641
2663
 
2642
2664
  ```jsx
2643
- <Stage contactShadow shadows adjustCamera intensity={1} environment="city" preset="rembrandt" controls={controlsRef}>
2665
+ <Stage>
2644
2666
  <mesh />
2645
2667
  </Stage>
2646
2668
  ```
2647
2669
 
2670
+ For a little more realistic results enable accumulative shadows, which requires that the canvas, and models, can handle shadows.
2671
+
2672
+ ```jsx
2673
+ <Canvas shadows>
2674
+ <Stage shadows="accumulative">
2675
+ <mesh castShadows />
2676
+ </Stage>
2677
+ </Canvas>
2678
+ ```
2679
+
2648
2680
  #### Backdrop
2649
2681
 
2650
2682
  <p>
@@ -1,6 +1,19 @@
1
1
  import * as THREE from 'three';
2
2
  import * as React from 'react';
3
3
  import { ReactThreeFiber } from '@react-three/fiber';
4
+ export declare type AccumulativeShadowsProps = {
5
+ frames?: number;
6
+ blend?: number;
7
+ limit?: number;
8
+ scale?: number;
9
+ temporal?: boolean;
10
+ opacity?: number;
11
+ alphaTest?: number;
12
+ color?: string;
13
+ colorBlend?: number;
14
+ resolution?: number;
15
+ toneMapped?: boolean;
16
+ };
4
17
  interface AccumulativeContext {
5
18
  lights: Map<any, any>;
6
19
  temporal: boolean;
@@ -46,19 +59,7 @@ export declare const AccumulativeShadows: React.ForwardRefExoticComponent<Pick<O
46
59
  quaternion?: ReactThreeFiber.Quaternion | undefined;
47
60
  layers?: ReactThreeFiber.Layers | undefined;
48
61
  dispose?: (() => void) | null | undefined;
49
- } & import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers & {
50
- frames?: number | undefined;
51
- blend?: number | undefined;
52
- limit?: number | undefined;
53
- scale?: number | undefined;
54
- temporal?: boolean | undefined;
55
- opacity?: number | undefined;
56
- alphaTest?: number | undefined;
57
- color?: string | undefined;
58
- colorBlend?: number | undefined;
59
- resolution?: number | undefined;
60
- toneMapped?: boolean | undefined;
61
- }, "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "color" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "alphaTest" | "opacity" | "toneMapped" | "resolution" | "frames" | "blend" | "temporal" | "limit" | "colorBlend"> & React.RefAttributes<AccumulativeContext>>;
62
+ } & import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers & AccumulativeShadowsProps, "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | keyof AccumulativeShadowsProps> & React.RefAttributes<AccumulativeContext>>;
62
63
  export declare const RandomizedLight: React.ForwardRefExoticComponent<Pick<Omit<ReactThreeFiber.ExtendedColors<ReactThreeFiber.Overwrite<Partial<THREE.Group>, ReactThreeFiber.NodeProps<THREE.Group, typeof THREE.Group>>>, ReactThreeFiber.NonFunctionKeys<{
63
64
  position?: ReactThreeFiber.Vector3 | undefined;
64
65
  up?: ReactThreeFiber.Vector3 | undefined;
package/core/Clone.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("lodash.pick");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function n(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var a=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,a.get?a:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var o=a(e),c=n(t),i=a(r);function l(e,{keys:t=["near","far","color","distance","decay","penumbra","angle","intensity","skeleton","visible","castShadow","receiveShadow","morphTargetDictionary","morphTargetInfluences","name","geometry","material","position","rotation","scale","up","userData"],deep:r,inject:a,castShadow:n,receiveShadow:o}){let l=i.default(e,t);return r&&(l.geometry&&"materialsOnly"!==r&&(l.geometry=l.geometry.clone()),l.material&&"geometriesOnly"!==r&&(l.material=l.material.clone())),a&&(l="function"==typeof a?{...l,children:a(e)}:c.isValidElement(a)?{...l,children:a}:{...l,...a}),"Mesh"===e.type&&(n&&(l.castShadow=!0),o&&(l.receiveShadow=!0)),l}const u=c.forwardRef((({object:e,children:t,deep:r,castShadow:a,receiveShadow:n,inject:i,keys:d,...s},f)=>{const p={keys:d,deep:r,inject:i,castShadow:a,receiveShadow:n};if(Array.isArray(e))return c.createElement("group",o.default({},s,{ref:f}),e.map((e=>c.createElement(u,o.default({key:e.uuid,object:e},p)))),t);const{children:y,...m}=l(e,p),h=e.type[0].toLowerCase()+e.type.slice(1);return c.createElement(h,o.default({},m,s,{ref:f}),(null==e?void 0:e.children).map((e=>{let t={},r=e.type[0].toLowerCase()+e.type.slice(1);return"group"===r||"object3D"===r?(r=u,t={object:e,...p}):t=l(e,p),c.createElement(r,o.default({key:e.uuid},t))})),t,y)}));exports.Clone=u;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react"),a=require("lodash.pick"),i=require("three-stdlib");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var a=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,a.get?a:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var c=n(e),l=o(t),d=o(r),u=n(a);const s=d.forwardRef((({isChild:e=!1,object:t,children:r,deep:a,castShadow:n,receiveShadow:o,inject:f,keys:y,...h},m)=>{var p;const b={keys:y,deep:a,inject:f,castShadow:n,receiveShadow:o};if(t=d.useMemo((()=>{if(!1===e&&!Array.isArray(t)){let e=!1;if(t.traverse((t=>{t.isSkinnedMesh&&(e=!0)})),e)return i.SkeletonUtils.clone(t)}return t}),[t,e]),Array.isArray(t))return d.createElement("group",c.default({},h,{ref:m}),t.map((e=>d.createElement(s,c.default({key:e.uuid,object:e},b)))),r);const{children:v,...j}=function(e,{keys:t=["near","far","color","distance","decay","penumbra","angle","intensity","skeleton","visible","castShadow","receiveShadow","morphTargetDictionary","morphTargetInfluences","name","geometry","material","position","rotation","scale","up","userData","bindMode","bindMatrix","bindMatrixInverse","skeleton"],deep:r,inject:a,castShadow:i,receiveShadow:n}){let o=u.default(e,t);return r&&(o.geometry&&"materialsOnly"!==r&&(o.geometry=o.geometry.clone()),o.material&&"geometriesOnly"!==r&&(o.material=o.material.clone())),a&&(o="function"==typeof a?{...o,children:a(e)}:d.isValidElement(a)?{...o,children:a}:{...o,...a}),e instanceof l.Mesh&&(i&&(o.castShadow=!0),n&&(o.receiveShadow=!0)),o}(t,b),w=t.type[0].toLowerCase()+t.type.slice(1);return d.createElement(w,c.default({},j,h,{ref:m}),(null==(p=t)?void 0:p.children).map((e=>"Bone"===e.type?d.createElement("primitive",c.default({key:e.uuid,object:e},b)):d.createElement(s,c.default({key:e.uuid,object:e},b,{isChild:!0})))),r,v)}));exports.Clone=s;
package/core/Clone.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import * as THREE from 'three';
1
2
  import * as React from 'react';
2
3
  import { MeshProps } from '@react-three/fiber';
3
4
  export declare const Clone: React.ForwardRefExoticComponent<Pick<Omit<import("@react-three/fiber").GroupProps, "children"> & {
@@ -8,4 +9,5 @@ export declare const Clone: React.ForwardRefExoticComponent<Pick<Omit<import("@r
8
9
  inject?: React.ReactNode | MeshProps | ((object: THREE.Object3D) => React.ReactNode);
9
10
  castShadow?: boolean | undefined;
10
11
  receiveShadow?: boolean | undefined;
11
- }, "object" | "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "keys" | "deep" | "inject"> & React.RefAttributes<import("three").Group>>;
12
+ isChild?: boolean | undefined;
13
+ }, "object" | "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "keys" | "deep" | "inject" | "isChild"> & React.RefAttributes<THREE.Group>>;
package/core/Clone.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import _extends from '@babel/runtime/helpers/esm/extends';
2
+ import * as THREE from 'three';
2
3
  import * as React from 'react';
3
4
  import pick from 'lodash.pick';
5
+ import { SkeletonUtils } from 'three-stdlib';
4
6
 
5
7
  function createSpread(child, {
6
- keys = ['near', 'far', 'color', 'distance', 'decay', 'penumbra', 'angle', 'intensity', 'skeleton', 'visible', 'castShadow', 'receiveShadow', 'morphTargetDictionary', 'morphTargetInfluences', 'name', 'geometry', 'material', 'position', 'rotation', 'scale', 'up', 'userData'],
8
+ keys = ['near', 'far', 'color', 'distance', 'decay', 'penumbra', 'angle', 'intensity', 'skeleton', 'visible', 'castShadow', 'receiveShadow', 'morphTargetDictionary', 'morphTargetInfluences', 'name', 'geometry', 'material', 'position', 'rotation', 'scale', 'up', 'userData', 'bindMode', 'bindMatrix', 'bindMatrixInverse', 'skeleton'],
7
9
  deep,
8
10
  inject,
9
11
  castShadow,
@@ -26,7 +28,7 @@ function createSpread(child, {
26
28
  };
27
29
  }
28
30
 
29
- if (child.type === 'Mesh') {
31
+ if (child instanceof THREE.Mesh) {
30
32
  if (castShadow) spread.castShadow = true;
31
33
  if (receiveShadow) spread.receiveShadow = true;
32
34
  }
@@ -35,6 +37,7 @@ function createSpread(child, {
35
37
  }
36
38
 
37
39
  const Clone = /*#__PURE__*/React.forwardRef(({
40
+ isChild = false,
38
41
  object,
39
42
  children,
40
43
  deep,
@@ -44,13 +47,26 @@ const Clone = /*#__PURE__*/React.forwardRef(({
44
47
  keys,
45
48
  ...props
46
49
  }, forwardRef) => {
50
+ var _object;
51
+
47
52
  const config = {
48
53
  keys,
49
54
  deep,
50
55
  inject,
51
56
  castShadow,
52
57
  receiveShadow
53
- }; // Deal with arrayed clones
58
+ };
59
+ object = React.useMemo(() => {
60
+ if (isChild === false && !Array.isArray(object)) {
61
+ let isSkinned = false;
62
+ object.traverse(object => {
63
+ if (object.isSkinnedMesh) isSkinned = true;
64
+ });
65
+ if (isSkinned) return SkeletonUtils.clone(object);
66
+ }
67
+
68
+ return object;
69
+ }, [object, isChild]); // Deal with arrayed clones
54
70
 
55
71
  if (Array.isArray(object)) {
56
72
  return /*#__PURE__*/React.createElement("group", _extends({}, props, {
@@ -69,23 +85,17 @@ const Clone = /*#__PURE__*/React.forwardRef(({
69
85
  const Element = object.type[0].toLowerCase() + object.type.slice(1);
70
86
  return /*#__PURE__*/React.createElement(Element, _extends({}, spread, props, {
71
87
  ref: forwardRef
72
- }), (object == null ? void 0 : object.children).map(child => {
73
- let spread = {};
74
- let Element = child.type[0].toLowerCase() + child.type.slice(1);
75
-
76
- if (Element === 'group' || Element === 'object3D') {
77
- Element = Clone;
78
- spread = {
79
- object: child,
80
- ...config
81
- };
82
- } else {
83
- spread = createSpread(child, config);
84
- }
85
-
86
- return /*#__PURE__*/React.createElement(Element, _extends({
87
- key: child.uuid
88
- }, spread));
88
+ }), ((_object = object) == null ? void 0 : _object.children).map(child => {
89
+ if (child.type === 'Bone') return /*#__PURE__*/React.createElement("primitive", _extends({
90
+ key: child.uuid,
91
+ object: child
92
+ }, config));
93
+ return /*#__PURE__*/React.createElement(Clone, _extends({
94
+ key: child.uuid,
95
+ object: child
96
+ }, config, {
97
+ isChild: true
98
+ }));
89
99
  }), children, injectChildren);
90
100
  });
91
101
 
@@ -1,15 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import * as THREE from 'three';
3
- export declare const ContactShadows: React.ForwardRefExoticComponent<Pick<Omit<import("@react-three/fiber").GroupProps, "scale"> & {
4
- opacity?: number | undefined;
5
- width?: number | undefined;
6
- height?: number | undefined;
7
- blur?: number | undefined;
8
- far?: number | undefined;
9
- smooth?: boolean | undefined;
10
- resolution?: number | undefined;
11
- frames?: number | undefined;
12
- scale?: number | [x: number, y: number] | undefined;
13
- color?: THREE.ColorRepresentation | undefined;
14
- depthWrite?: boolean | undefined;
15
- }, "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "scale" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "color" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | "smooth" | "far" | "depthWrite" | "opacity" | "width" | "height" | "blur" | "resolution" | "frames"> & React.RefAttributes<unknown>>;
3
+ export declare type ContactShadowsProps = {
4
+ opacity?: number;
5
+ width?: number;
6
+ height?: number;
7
+ blur?: number;
8
+ far?: number;
9
+ smooth?: boolean;
10
+ resolution?: number;
11
+ frames?: number;
12
+ scale?: number | [x: number, y: number];
13
+ color?: THREE.ColorRepresentation;
14
+ depthWrite?: boolean;
15
+ };
16
+ export declare const ContactShadows: React.ForwardRefExoticComponent<Pick<Omit<import("@react-three/fiber").GroupProps, "scale"> & ContactShadowsProps, "visible" | "attach" | "args" | "children" | "key" | "onUpdate" | "position" | "up" | "rotation" | "matrix" | "quaternion" | "layers" | "dispose" | "type" | "isGroup" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | keyof import("@react-three/fiber/dist/declarations/src/core/events").EventHandlers | keyof ContactShadowsProps> & React.RefAttributes<unknown>>;
package/core/Stage.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("three"),n=require("@react-three/fiber"),i=require("./Environment.cjs.js"),a=require("./ContactShadows.cjs.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("three-stdlib"),require("../helpers/environment-assets.cjs.js");var u=o(e),c=s(t),l=s(r);const f={rembrandt:{main:[1,2,1],fill:[-2,-.5,-2]},portrait:{main:[-1,2,.5],fill:[-1,.5,-1.5]},upfront:{main:[0,2,1],fill:[-1,.5,-1.5]},soft:{main:[-2,4,4],fill:[-1,.5,-1.5]}};exports.Stage=function({children:e,controls:t,shadows:r=!0,adjustCamera:o=!0,environment:s="city",intensity:d=1,preset:m="rembrandt",shadowBias:h=0,contactShadow:p={blur:2,opacity:.5,position:[0,0,0]},...b}){const g=f[m],y=n.useThree((e=>e.camera)),j=n.useThree((e=>e.controls)),w=c.useRef(null),E=c.useRef(null),[{radius:x,width:v,height:q},O]=c.useState({radius:0,width:0,height:0});return c.useLayoutEffect((()=>{w.current.position.set(0,0,0),w.current.updateWorldMatrix(!0,!0);const e=(new l.Box3).setFromObject(E.current),t=new l.Vector3,r=new l.Sphere,n=e.max.y-e.min.y,i=e.max.x-e.min.x;e.getCenter(t),e.getBoundingSphere(r),O({radius:r.radius,width:i,height:n}),w.current.position.set(-t.x,-t.y+n/2,-t.z)}),[e]),c.useLayoutEffect((()=>{if(o){const e=x/(q>v?1.5:2.5);y.position.set(0,.5*x,2.5*x),y.near=.1,y.far=Math.max(5e3,4*x),y.lookAt(0,e,0);const r=j||(null==t?void 0:t.current);r&&(r.target.set(0,e,0),r.update())}}),[j,x,q,v,o]),c.createElement("group",b,c.createElement("group",{ref:w},c.createElement("group",{ref:E},e)),p&&c.createElement(a.ContactShadows,u.default({scale:2*x,far:x/2},p)),s&&c.createElement(i.Environment,{preset:s}),c.createElement("ambientLight",{intensity:d/3}),c.createElement("spotLight",{penumbra:1,position:[g.main[0]*x,g.main[1]*x,g.main[2]*x],intensity:2*d,castShadow:r,"shadow-bias":h}),c.createElement("pointLight",{position:[g.fill[0]*x,g.fill[1]*x,g.fill[2]*x],intensity:d}))};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("./Environment.cjs.js"),i=require("./ContactShadows.cjs.js"),n=require("./Center.cjs.js"),a=require("./AccumulativeShadows.cjs.js"),s=require("./Bounds.cjs.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function l(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,i.get?i:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("@react-three/fiber"),require("three"),require("three-stdlib"),require("../helpers/environment-assets.cjs.js"),require("./shaderMaterial.cjs.js");var o=u(e),c=l(t);const d={rembrandt:{main:[1,2,1],fill:[-2,-.5,-2]},portrait:{main:[-1,2,.5],fill:[-1,.5,-1.5]},upfront:{main:[0,2,1],fill:[-1,.5,-1.5]},soft:{main:[-2,4,4],fill:[-1,.5,-1.5]}};function m({radius:e,adjustCamera:t}){const r=s.useBounds();return c.useEffect((()=>{t&&r.refresh().clip().fit()}),[e,t]),null}exports.Stage=function({children:e,adjustCamera:t=!0,intensity:u=.5,shadows:l="contact",environment:f="city",preset:h="rembrandt",...p}){var b,j,v;const g=d[h],[{radius:E,height:y},q]=c.useState({radius:0,width:0,height:0,depth:0}),w=null!==(b=null==l?void 0:l.bias)&&void 0!==b?b:-1e-4,S=null!==(j=null==l?void 0:l.size)&&void 0!==j?j:1024,C=null!==(v=null==l?void 0:l.offset)&&void 0!==v?v:0,O="contact"===l||"contact"===(null==l?void 0:l.type),z="accumulative"===l||"accumulative"===(null==l?void 0:l.type),L={..."object"==typeof l?l:{}};return c.createElement(c.Fragment,null,c.createElement("ambientLight",{intensity:u/3}),c.createElement("spotLight",{penumbra:1,position:[g.main[0]*E,g.main[1]*E,g.main[2]*E],intensity:2*u,castShadow:!!l,"shadow-bias":w,"shadow-mapSize":S}),c.createElement("pointLight",{position:[g.fill[0]*E,g.fill[1]*E,g.fill[2]*E],intensity:u}),c.createElement(s.Bounds,o.default({fit:!!t,clip:!!t,margin:Number(t),observe:!0},p),c.createElement(m,{radius:E,adjustCamera:t}),c.createElement(n.Center,{onCentered:({width:e,height:t,depth:r,boundingSphere:i,...n})=>q({radius:i.radius,width:e,height:t,depth:r})},e)),c.createElement("group",{position:[0,-y/2-C,0]},O&&c.createElement(i.ContactShadows,o.default({scale:4*E,far:E,blur:2},L)),z&&c.createElement(a.AccumulativeShadows,o.default({temporal:!0,frames:100,alphaTest:.9,toneMapped:!0,scale:4*E},L),c.createElement(a.RandomizedLight,{amount:8,radius:E,ambient:.5,intensity:1,position:[g.main[0]*E,g.main[1]*E,g.main[2]*E],size:4*E,bias:-w,mapSize:S}))),f&&c.createElement(r.Environment,{preset:f}))};
package/core/Stage.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import * as React from 'react';
2
- import * as THREE from 'three';
1
+ /// <reference types="react" />
2
+ import { ContactShadowsProps } from './ContactShadows';
3
+ import { AccumulativeShadowsProps } from './AccumulativeShadows';
3
4
  import { PresetsType } from '../helpers/environment-assets';
4
5
  declare const presets: {
5
6
  rembrandt: {
@@ -19,24 +20,18 @@ declare const presets: {
19
20
  fill: number[];
20
21
  };
21
22
  };
22
- declare type ControlsProto = {
23
- update(): void;
24
- target: THREE.Vector3;
23
+ declare type StageShadows = Partial<AccumulativeShadowsProps> & Partial<ContactShadowsProps> & {
24
+ type: 'contact' | 'accumulative';
25
+ offset?: number;
26
+ bias?: number;
27
+ size?: number;
25
28
  };
26
- declare type Props = JSX.IntrinsicElements['group'] & {
27
- shadows?: boolean;
28
- adjustCamera?: boolean;
29
+ declare type StageProps = JSX.IntrinsicElements['group'] & {
30
+ preset?: keyof typeof presets;
31
+ shadows?: boolean | 'contact' | 'accumulative' | StageShadows;
32
+ adjustCamera?: boolean | number;
29
33
  environment?: PresetsType | null;
30
34
  intensity?: number;
31
- ambience?: number;
32
- controls?: React.MutableRefObject<ControlsProto>;
33
- preset?: keyof typeof presets;
34
- shadowBias?: number;
35
- contactShadow?: {
36
- blur: number;
37
- opacity?: number;
38
- position?: [x: number, y: number, z: number];
39
- } | false;
40
35
  };
41
- export declare function Stage({ children, controls, shadows, adjustCamera, environment, intensity, preset, shadowBias, contactShadow, ...props }: Props): JSX.Element;
36
+ export declare function Stage({ children, adjustCamera, intensity, shadows, environment, preset, ...props }: StageProps): JSX.Element;
42
37
  export {};
package/core/Stage.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import _extends from '@babel/runtime/helpers/esm/extends';
2
2
  import * as React from 'react';
3
- import * as THREE from 'three';
4
- import { useThree } from '@react-three/fiber';
5
3
  import { Environment } from './Environment.js';
6
4
  import { ContactShadows } from './ContactShadows.js';
5
+ import { Center } from './Center.js';
6
+ import { AccumulativeShadows, RandomizedLight } from './AccumulativeShadows.js';
7
+ import { Bounds, useBounds } from './Bounds.js';
7
8
 
8
9
  const presets = {
9
10
  rembrandt: {
@@ -23,89 +24,102 @@ const presets = {
23
24
  fill: [-1, 0.5, -1.5]
24
25
  }
25
26
  };
27
+
28
+ function Refit({
29
+ radius,
30
+ adjustCamera
31
+ }) {
32
+ const api = useBounds();
33
+ React.useEffect(() => {
34
+ if (adjustCamera) api.refresh().clip().fit();
35
+ }, [radius, adjustCamera]);
36
+ return null;
37
+ }
38
+
26
39
  function Stage({
27
40
  children,
28
- controls,
29
- shadows = true,
30
41
  adjustCamera = true,
42
+ intensity = 0.5,
43
+ shadows = 'contact',
31
44
  environment = 'city',
32
- intensity = 1,
33
45
  preset = 'rembrandt',
34
- shadowBias = 0,
35
- contactShadow = {
36
- blur: 2,
37
- opacity: 0.5,
38
- position: [0, 0, 0]
39
- },
40
46
  ...props
41
47
  }) {
42
- const config = presets[preset];
43
- const camera = useThree(state => state.camera); // @ts-expect-error new in @react-three/fiber@7.0.5
48
+ var _bias, _size, _offset;
44
49
 
45
- const defaultControls = useThree(state => state.controls);
46
- const outer = React.useRef(null);
47
- const inner = React.useRef(null);
50
+ const config = presets[preset];
48
51
  const [{
49
52
  radius,
50
- width,
51
53
  height
52
54
  }, set] = React.useState({
53
55
  radius: 0,
54
56
  width: 0,
55
- height: 0
57
+ height: 0,
58
+ depth: 0
56
59
  });
57
- React.useLayoutEffect(() => {
58
- outer.current.position.set(0, 0, 0);
59
- outer.current.updateWorldMatrix(true, true);
60
- const box3 = new THREE.Box3().setFromObject(inner.current);
61
- const center = new THREE.Vector3();
62
- const sphere = new THREE.Sphere();
63
- const height = box3.max.y - box3.min.y;
64
- const width = box3.max.x - box3.min.x;
65
- box3.getCenter(center);
66
- box3.getBoundingSphere(sphere);
67
- set({
68
- radius: sphere.radius,
69
- width,
70
- height
71
- });
72
- outer.current.position.set(-center.x, -center.y + height / 2, -center.z);
73
- }, [children]);
74
- React.useLayoutEffect(() => {
75
- if (adjustCamera) {
76
- const y = radius / (height > width ? 1.5 : 2.5);
77
- camera.position.set(0, radius * 0.5, radius * 2.5);
78
- camera.near = 0.1;
79
- camera.far = Math.max(5000, radius * 4);
80
- camera.lookAt(0, y, 0);
81
- const ctrl = defaultControls || (controls == null ? void 0 : controls.current);
82
-
83
- if (ctrl) {
84
- ctrl.target.set(0, y, 0);
85
- ctrl.update();
86
- }
87
- }
88
- }, [defaultControls, radius, height, width, adjustCamera]);
89
- return /*#__PURE__*/React.createElement("group", props, /*#__PURE__*/React.createElement("group", {
90
- ref: outer
91
- }, /*#__PURE__*/React.createElement("group", {
92
- ref: inner
93
- }, children)), contactShadow && /*#__PURE__*/React.createElement(ContactShadows, _extends({
94
- scale: radius * 2,
95
- far: radius / 2
96
- }, contactShadow)), environment && /*#__PURE__*/React.createElement(Environment, {
97
- preset: environment
98
- }), /*#__PURE__*/React.createElement("ambientLight", {
60
+ const shadowBias = (_bias = shadows == null ? void 0 : shadows.bias) !== null && _bias !== void 0 ? _bias : -0.0001;
61
+ const shadowSize = (_size = shadows == null ? void 0 : shadows.size) !== null && _size !== void 0 ? _size : 1024;
62
+ const shadowOffset = (_offset = shadows == null ? void 0 : shadows.offset) !== null && _offset !== void 0 ? _offset : 0;
63
+ const contactShadow = shadows === 'contact' || (shadows == null ? void 0 : shadows.type) === 'contact';
64
+ const accumulativeShadow = shadows === 'accumulative' || (shadows == null ? void 0 : shadows.type) === 'accumulative';
65
+ const shadowSpread = { ...(typeof shadows === 'object' ? shadows : {})
66
+ };
67
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("ambientLight", {
99
68
  intensity: intensity / 3
100
69
  }), /*#__PURE__*/React.createElement("spotLight", {
101
70
  penumbra: 1,
102
71
  position: [config.main[0] * radius, config.main[1] * radius, config.main[2] * radius],
103
72
  intensity: intensity * 2,
104
- castShadow: shadows,
105
- "shadow-bias": shadowBias
73
+ castShadow: !!shadows,
74
+ "shadow-bias": shadowBias,
75
+ "shadow-mapSize": shadowSize
106
76
  }), /*#__PURE__*/React.createElement("pointLight", {
107
77
  position: [config.fill[0] * radius, config.fill[1] * radius, config.fill[2] * radius],
108
78
  intensity: intensity
79
+ }), /*#__PURE__*/React.createElement(Bounds, _extends({
80
+ fit: !!adjustCamera,
81
+ clip: !!adjustCamera,
82
+ margin: Number(adjustCamera),
83
+ observe: true
84
+ }, props), /*#__PURE__*/React.createElement(Refit, {
85
+ radius: radius,
86
+ adjustCamera: adjustCamera
87
+ }), /*#__PURE__*/React.createElement(Center, {
88
+ onCentered: ({
89
+ width,
90
+ height,
91
+ depth,
92
+ boundingSphere,
93
+ ...data
94
+ }) => set({
95
+ radius: boundingSphere.radius,
96
+ width,
97
+ height,
98
+ depth
99
+ })
100
+ }, children)), /*#__PURE__*/React.createElement("group", {
101
+ position: [0, -height / 2 - shadowOffset, 0]
102
+ }, contactShadow && /*#__PURE__*/React.createElement(ContactShadows, _extends({
103
+ scale: radius * 4,
104
+ far: radius,
105
+ blur: 2
106
+ }, shadowSpread)), accumulativeShadow && /*#__PURE__*/React.createElement(AccumulativeShadows, _extends({
107
+ temporal: true,
108
+ frames: 100,
109
+ alphaTest: 0.9,
110
+ toneMapped: true,
111
+ scale: radius * 4
112
+ }, shadowSpread), /*#__PURE__*/React.createElement(RandomizedLight, {
113
+ amount: 8,
114
+ radius: radius,
115
+ ambient: 0.5,
116
+ intensity: 1,
117
+ position: [config.main[0] * radius, config.main[1] * radius, config.main[2] * radius],
118
+ size: radius * 4,
119
+ bias: -shadowBias,
120
+ mapSize: shadowSize
121
+ }))), environment && /*#__PURE__*/React.createElement(Environment, {
122
+ preset: environment
109
123
  }));
110
124
  }
111
125