@react-three/drei 9.41.2 → 9.42.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.
- package/README.md +22 -6
- package/core/Bounds.cjs.js +1 -1
- package/core/Bounds.js +26 -1
- package/core/Stage.cjs.js +1 -1
- package/core/Stage.d.ts +1 -19
- package/core/Stage.js +2 -1
- package/index.cjs.js +1 -1
- package/package.json +1 -1
- package/web/View.cjs.js +1 -1
- package/web/View.d.ts +10 -2
- package/web/View.js +70 -11
package/README.md
CHANGED
|
@@ -2312,7 +2312,13 @@ function Effects() {
|
|
|
2312
2312
|
|
|
2313
2313
|
Views use gl.scissor to cut the viewport into segments. You tie a view to a tracking div which then controls the position and bounds of the viewport. This allows you to have multiple views with a single, performant canvas. These views will follow their tracking elements, scroll along, resize, etc.
|
|
2314
2314
|
|
|
2315
|
-
It is advisable to re-connect the event system to a parent that contains both the canvas and the html content.
|
|
2315
|
+
It is advisable to re-connect the event system to a parent that contains both the canvas and the html content.
|
|
2316
|
+
This ensures that both are accessible/selectable and even allows you to mount controls or other deeper
|
|
2317
|
+
integrations into your view.
|
|
2318
|
+
|
|
2319
|
+
> Note that `@react-three/fiber` newer than `^8.1.0` is required for `View` to work correctly if the
|
|
2320
|
+
> canvas/react three fiber root is not fullscreen. A warning will be logged if drei is used with older
|
|
2321
|
+
> versions of `@react-three/fiber`.
|
|
2316
2322
|
|
|
2317
2323
|
```tsx
|
|
2318
2324
|
<View
|
|
@@ -2558,8 +2564,7 @@ Calculates a boundary box and centers the camera accordingly. If you are using c
|
|
|
2558
2564
|
<mesh />
|
|
2559
2565
|
</Bounds>
|
|
2560
2566
|
```
|
|
2561
|
-
|
|
2562
|
-
The Bounds component also acts as a context provider, use the `useBounds` hook to refresh the bounds, fit the camera, clip near/far planes or focus objects. `refresh(object?: THREE.Object3D | THREE.Box3)` will recalculate bounds. Since this can be expensive only call it when you know the view has changed. `clip` sets the cameras near/far planes. `fit` zooms and centers the view.
|
|
2567
|
+
The Bounds component also acts as a context provider, use the `useBounds` hook to refresh the bounds, fit the camera, clip near/far planes, go to camera orientations or focus objects. `refresh(object?: THREE.Object3D | THREE.Box3)` will recalculate bounds, since this can be expensive only call it when you know the view has changed. `clip` sets the cameras near/far planes. `to` sets a position and target for the camera. `fit` zooms and centers the view.
|
|
2563
2568
|
|
|
2564
2569
|
```jsx
|
|
2565
2570
|
function Foo() {
|
|
@@ -2567,10 +2572,13 @@ function Foo() {
|
|
|
2567
2572
|
useEffect(() => {
|
|
2568
2573
|
// Calculate scene bounds
|
|
2569
2574
|
bounds.refresh().clip().fit()
|
|
2575
|
+
|
|
2570
2576
|
// Or, focus a specific object or box3
|
|
2571
2577
|
// bounds.refresh(ref.current).clip().fit()
|
|
2572
2578
|
// bounds.refresh(new THREE.Box3()).clip().fit()
|
|
2573
2579
|
|
|
2580
|
+
// Or, send the camera to a specific orientatin
|
|
2581
|
+
// bounds.to({position: [0, 10, 10], target: {[5, 5, 0]}})
|
|
2574
2582
|
<Bounds>
|
|
2575
2583
|
<Foo />
|
|
2576
2584
|
```
|
|
@@ -2635,22 +2643,30 @@ This component makes its contents float or hover.
|
|
|
2635
2643
|
|
|
2636
2644
|
[](https://drei.pmnd.rs/?path=/story/staging-stage--stage-st)
|
|
2637
2645
|
|
|
2638
|
-
|
|
2646
|
+
<p>
|
|
2647
|
+
<a href="https://codesandbox.io/s/57iefg"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/57iefg/screenshot.png" alt="Demo"/></a>
|
|
2648
|
+
</p>
|
|
2649
|
+
|
|
2650
|
+
Creates a "stage" with proper studio lighting, 0/0/0 top-centred, model-shadows, ground-shadows and optional zoom to fit. Make sure to set `makeDefault` on your controls when `adjustCamera` is true!
|
|
2639
2651
|
|
|
2640
2652
|
```tsx
|
|
2641
2653
|
type StageShadows = Partial<AccumulativeShadowsProps> &
|
|
2642
2654
|
Partial<ContactShadowsProps> & {
|
|
2643
2655
|
type: 'contact' | 'accumulative'
|
|
2656
|
+
/** Shadow plane offset, default: 0 */
|
|
2657
|
+
offset?: number
|
|
2658
|
+
/** Shadow bias, default: -0.0001 */
|
|
2644
2659
|
bias?: number
|
|
2660
|
+
/** Shadow map size, default: 1024 */
|
|
2645
2661
|
size?: number
|
|
2646
2662
|
}
|
|
2647
2663
|
|
|
2648
2664
|
type StageProps = JSX.IntrinsicElements['group'] & {
|
|
2649
2665
|
/** Lighting setup, default: "rembrandt" */
|
|
2650
|
-
preset?:
|
|
2666
|
+
preset?: 'rembrandt' | 'portrait' | 'upfront' | 'soft'
|
|
2651
2667
|
/** Controls the ground shadows, default: "contact" */
|
|
2652
2668
|
shadows?: boolean | 'contact' | 'accumulative' | StageShadows
|
|
2653
|
-
/**
|
|
2669
|
+
/** Optional zoom-to-fit using <Bounds>, can also be a margin, default: true */
|
|
2654
2670
|
adjustCamera?: boolean | number
|
|
2655
2671
|
/** The default environment, default: "city" */
|
|
2656
2672
|
environment?: PresetsType | null
|
package/core/Bounds.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("three"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("three"),o=require("@react-three/fiber");function r(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(o){if("default"!==o){var r=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,r.get?r:{enumerable:!0,get:function(){return e[o]}})}})),t.default=e,Object.freeze(t)}var a=r(e),n=r(t);const i=e=>e&&e.isOrthographicCamera,c=a.createContext(null);exports.Bounds=function({children:e,damping:t=6,fit:r,clip:s,observe:u,margin:m=1.2,eps:f=.01,onFit:p}){const l=a.useRef(null),{camera:x,invalidate:y,size:z,controls:d}=o.useThree(),h=d,g=a.useRef(p);function M(e,t){return Math.abs(e.x-t.x)<f&&Math.abs(e.y-t.y)<f&&Math.abs(e.z-t.z)<f}function b(e,t,o,r){e.x=n.MathUtils.damp(e.x,t.x,o,r),e.y=n.MathUtils.damp(e.y,t.y,o,r),e.z=n.MathUtils.damp(e.z,t.z,o,r)}g.current=p;const[w]=a.useState((()=>({animating:!1,focus:new n.Vector3,camera:new n.Vector3,zoom:1}))),[v]=a.useState((()=>({focus:new n.Vector3,camera:new n.Vector3,zoom:1}))),[V]=a.useState((()=>new n.Box3)),j=a.useMemo((()=>{function e(){const e=V.getSize(new n.Vector3),t=V.getCenter(new n.Vector3),o=Math.max(e.x,e.y,e.z),r=i(x)?4*o:o/(2*Math.atan(Math.PI*x.fov/360)),a=i(x)?4*o:r/x.aspect,c=m*Math.max(r,a);return{box:V,size:e,center:t,distance:c}}return{getSize:e,refresh(t){if((o=t)&&o.isBox3)V.copy(t);else{const e=t||l.current;e.updateWorldMatrix(!0,!0),V.setFromObject(e)}var o;if(V.isEmpty()){const e=x.position.length()||10;V.setFromCenterAndSize(new n.Vector3,new n.Vector3(e,e,e))}if("OrthographicTrackballControls"===(null==h?void 0:h.constructor.name)){const{distance:t}=e(),o=x.position.clone().sub(h.target).normalize().multiplyScalar(t),r=h.target.clone().add(o);x.position.copy(r)}return this},clip(){const{distance:t}=e();return h&&(h.maxDistance=10*t),x.near=t/100,x.far=100*t,x.updateProjectionMatrix(),h&&h.update(),y(),this},to({position:o,target:r}){w.camera.copy(x.position);const{center:a}=e();return v.camera.set(...o),r?v.focus.set(...r):v.focus.copy(a),t?w.animating=!0:x.position.set(...o),this},fit(){w.camera.copy(x.position),h&&w.focus.copy(h.target);const{center:o,distance:r}=e(),a=o.clone().sub(x.position).normalize().multiplyScalar(r);if(v.camera.copy(o).sub(a),v.focus.copy(o),i(x)){w.zoom=x.zoom;let e=0,r=0;const a=[new n.Vector3(V.min.x,V.min.y,V.min.z),new n.Vector3(V.min.x,V.max.y,V.min.z),new n.Vector3(V.min.x,V.min.y,V.max.z),new n.Vector3(V.min.x,V.max.y,V.max.z),new n.Vector3(V.max.x,V.max.y,V.max.z),new n.Vector3(V.max.x,V.max.y,V.min.z),new n.Vector3(V.max.x,V.min.y,V.max.z),new n.Vector3(V.max.x,V.min.y,V.min.z)];o.applyMatrix4(x.matrixWorldInverse);for(const t of a)t.applyMatrix4(x.matrixWorldInverse),e=Math.max(e,Math.abs(t.y-o.y)),r=Math.max(r,Math.abs(t.x-o.x));e*=2,r*=2;const i=(x.top-x.bottom)/e,c=(x.right-x.left)/r;v.zoom=Math.min(i,c)/m,t||(x.zoom=v.zoom,x.updateProjectionMatrix())}return t?w.animating=!0:(x.position.copy(v.camera),x.lookAt(v.focus),h&&(h.target.copy(v.focus),h.update())),g.current&&g.current(this.getSize()),y(),this}}}),[V,x,h,m,t,y]);a.useLayoutEffect((()=>{if(h){const e=()=>w.animating=!1;return h.addEventListener("start",e),()=>h.removeEventListener("start",e)}}),[h]);const O=a.useRef(0);return a.useLayoutEffect((()=>{(u||0==O.current++)&&(j.refresh(),r&&j.fit(),s&&j.clip())}),[z,s,r,u,x,h]),o.useFrame(((e,o)=>{if(w.animating){if(b(w.focus,v.focus,t,o),b(w.camera,v.camera,t,o),w.zoom=n.MathUtils.damp(w.zoom,v.zoom,t,o),x.position.copy(w.camera),i(x)&&(x.zoom=w.zoom,x.updateProjectionMatrix()),h?(h.target.copy(w.focus),h.update()):x.lookAt(w.focus),y(),i(x)&&!(Math.abs(w.zoom-v.zoom)<f))return;if(!i(x)&&!M(w.camera,v.camera))return;if(h&&!M(w.focus,v.focus))return;w.animating=!1}})),a.createElement("group",{ref:l},a.createElement(c.Provider,{value:j},e))},exports.useBounds=function(){return a.useContext(c)};
|
package/core/Bounds.js
CHANGED
|
@@ -82,7 +82,7 @@ function Bounds({
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
if ((controls == null ? void 0 : controls.constructor.name) === 'OrthographicTrackballControls') {
|
|
85
|
-
// Put camera on a sphere along which it should
|
|
85
|
+
// Put camera on a sphere along which it should move
|
|
86
86
|
const {
|
|
87
87
|
distance
|
|
88
88
|
} = getSize();
|
|
@@ -107,6 +107,31 @@ function Bounds({
|
|
|
107
107
|
return this;
|
|
108
108
|
},
|
|
109
109
|
|
|
110
|
+
to({
|
|
111
|
+
position,
|
|
112
|
+
target
|
|
113
|
+
}) {
|
|
114
|
+
current.camera.copy(camera.position);
|
|
115
|
+
const {
|
|
116
|
+
center
|
|
117
|
+
} = getSize();
|
|
118
|
+
goal.camera.set(...position);
|
|
119
|
+
|
|
120
|
+
if (target) {
|
|
121
|
+
goal.focus.set(...target);
|
|
122
|
+
} else {
|
|
123
|
+
goal.focus.copy(center);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (damping) {
|
|
127
|
+
current.animating = true;
|
|
128
|
+
} else {
|
|
129
|
+
camera.position.set(...position);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return this;
|
|
133
|
+
},
|
|
134
|
+
|
|
110
135
|
fit() {
|
|
111
136
|
current.camera.copy(camera.position);
|
|
112
137
|
if (controls) current.focus.copy(controls.target);
|
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"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),i=require("./Environment.cjs.js"),r=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(i){if("default"!==i){var r=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,r.get?r:{enumerable:!0,get:function(){return e[i]}})}})),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 i=s.useBounds();return c.useEffect((()=>{t&&i.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,{position:[0,C/2,0],onCentered:({width:e,height:t,depth:i,boundingSphere:r,...n})=>q({radius:r.radius,width:e,height:t,depth:i})},e)),c.createElement("group",{position:[0,-y/2-C/2,0]},O&&c.createElement(r.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(i.Environment,{preset:f}))};
|
package/core/Stage.d.ts
CHANGED
|
@@ -2,24 +2,6 @@
|
|
|
2
2
|
import { ContactShadowsProps } from './ContactShadows';
|
|
3
3
|
import { AccumulativeShadowsProps } from './AccumulativeShadows';
|
|
4
4
|
import { PresetsType } from '../helpers/environment-assets';
|
|
5
|
-
declare const presets: {
|
|
6
|
-
rembrandt: {
|
|
7
|
-
main: number[];
|
|
8
|
-
fill: number[];
|
|
9
|
-
};
|
|
10
|
-
portrait: {
|
|
11
|
-
main: number[];
|
|
12
|
-
fill: number[];
|
|
13
|
-
};
|
|
14
|
-
upfront: {
|
|
15
|
-
main: number[];
|
|
16
|
-
fill: number[];
|
|
17
|
-
};
|
|
18
|
-
soft: {
|
|
19
|
-
main: number[];
|
|
20
|
-
fill: number[];
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
5
|
declare type StageShadows = Partial<AccumulativeShadowsProps> & Partial<ContactShadowsProps> & {
|
|
24
6
|
type: 'contact' | 'accumulative';
|
|
25
7
|
offset?: number;
|
|
@@ -27,7 +9,7 @@ declare type StageShadows = Partial<AccumulativeShadowsProps> & Partial<ContactS
|
|
|
27
9
|
size?: number;
|
|
28
10
|
};
|
|
29
11
|
declare type StageProps = JSX.IntrinsicElements['group'] & {
|
|
30
|
-
preset?:
|
|
12
|
+
preset?: 'rembrandt' | 'portrait' | 'upfront' | 'soft';
|
|
31
13
|
shadows?: boolean | 'contact' | 'accumulative' | StageShadows;
|
|
32
14
|
adjustCamera?: boolean | number;
|
|
33
15
|
environment?: PresetsType | null;
|
package/core/Stage.js
CHANGED
|
@@ -85,6 +85,7 @@ function Stage({
|
|
|
85
85
|
radius: radius,
|
|
86
86
|
adjustCamera: adjustCamera
|
|
87
87
|
}), /*#__PURE__*/React.createElement(Center, {
|
|
88
|
+
position: [0, shadowOffset / 2, 0],
|
|
88
89
|
onCentered: ({
|
|
89
90
|
width,
|
|
90
91
|
height,
|
|
@@ -98,7 +99,7 @@ function Stage({
|
|
|
98
99
|
depth
|
|
99
100
|
})
|
|
100
101
|
}, children)), /*#__PURE__*/React.createElement("group", {
|
|
101
|
-
position: [0, -height / 2 - shadowOffset, 0]
|
|
102
|
+
position: [0, -height / 2 - shadowOffset / 2, 0]
|
|
102
103
|
}, contactShadow && /*#__PURE__*/React.createElement(ContactShadows, _extends({
|
|
103
104
|
scale: radius * 4,
|
|
104
105
|
far: radius,
|