Skip to content

Commit 03ec846

Browse files
authored
Merge pull request #3 from baseten/improve-example
Improve Cubes Example
2 parents ef5a22b + 88b4e15 commit 03ec846

File tree

12 files changed

+380
-224
lines changed

12 files changed

+380
-224
lines changed

examples/3d-cubes/src/components/Cube.tsx

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
Transform3dProps,
77
useFactoryRef,
88
} from 'react-css-transform';
9-
import { FlatMaterial } from './FlatMaterial';
9+
import { Face } from './Face';
1010
import { halfPi, yAxis, xAxis } from '../constants';
1111

1212
const propTypes = {
@@ -46,36 +46,42 @@ export const Cube = ({ faceSize, color, ...otherProps }: CubeProps) => {
4646

4747
return (
4848
<Transform3d {...otherProps}>
49-
<Transform3d translate={pos1.current} rotate={-halfPi} rotateAxis={yAxis}>
50-
<FlatMaterial color={color}>
51-
<div style={faceStyle} className="face" />
52-
</FlatMaterial>
53-
</Transform3d>
54-
<Transform3d translate={pos2.current} rotate={halfPi} rotateAxis={yAxis}>
55-
<FlatMaterial color={color}>
56-
<div style={faceStyle} className="face" />
57-
</FlatMaterial>
58-
</Transform3d>
59-
<Transform3d translate={pos3.current} rotate={halfPi} rotateAxis={xAxis}>
60-
<FlatMaterial color={color}>
61-
<div style={faceStyle} className="face" />
62-
</FlatMaterial>
63-
</Transform3d>
64-
<Transform3d translate={pos4.current} rotate={-halfPi} rotateAxis={xAxis}>
65-
<FlatMaterial color={color}>
66-
<div style={faceStyle} className="face" />
67-
</FlatMaterial>
68-
</Transform3d>
69-
<Transform3d translate={pos5.current} rotate={Math.PI} rotateAxis={yAxis}>
70-
<FlatMaterial color={color}>
71-
<div style={faceStyle} className="face" />
72-
</FlatMaterial>
73-
</Transform3d>
74-
<Transform3d translate={pos6.current}>
75-
<FlatMaterial color={color}>
76-
<div style={faceStyle} className="face" />
77-
</FlatMaterial>
78-
</Transform3d>
49+
<Face
50+
translate={pos1.current}
51+
rotate={-halfPi}
52+
rotateAxis={yAxis}
53+
color={color}
54+
style={faceStyle}
55+
/>
56+
<Face
57+
translate={pos2.current}
58+
rotate={halfPi}
59+
rotateAxis={yAxis}
60+
color={color}
61+
style={faceStyle}
62+
/>
63+
<Face
64+
translate={pos3.current}
65+
rotate={halfPi}
66+
rotateAxis={xAxis}
67+
color={color}
68+
style={faceStyle}
69+
/>
70+
<Face
71+
translate={pos4.current}
72+
rotate={-halfPi}
73+
rotateAxis={xAxis}
74+
color={color}
75+
style={faceStyle}
76+
/>
77+
<Face
78+
translate={pos5.current}
79+
rotate={Math.PI}
80+
rotateAxis={yAxis}
81+
color={color}
82+
style={faceStyle}
83+
/>
84+
<Face translate={pos6.current} color={color} style={faceStyle} />
7985
</Transform3d>
8086
);
8187
};

examples/3d-cubes/src/components/DimensionsContext.tsx

Lines changed: 0 additions & 50 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { merge3dMatrixWithStyles, use3dTransformations } from 'react-css-transform';
2+
import { useGlobalContext } from './GlobalContext';
3+
import { useFlatShading } from '../useFlatShading';
4+
import { vec3 } from 'gl-matrix';
5+
import { useMemo } from 'react';
6+
import { blendHex } from '../utils';
7+
8+
import type { CSSProperties } from 'react';
9+
import type { Transform3dProps } from 'react-css-transform';
10+
11+
type FaceProps = Transform3dProps & {
12+
color: string;
13+
style: CSSProperties;
14+
};
15+
16+
// local position is always 0, outer transform will apply positioning
17+
const objectLocalPosition = vec3.fromValues(0, 0, 0);
18+
// local normal is always z: 1, outer transform will apply positioning
19+
const objectLocalNormal = vec3.fromValues(0, 0, 1);
20+
21+
export const Face = ({ color, style, ...transform3dProps }: FaceProps) => {
22+
const { matrixWorld } = use3dTransformations(transform3dProps);
23+
24+
const { lightPosition, lightColor } = useGlobalContext();
25+
26+
const { diffuseColor, emissiveColor } = useMemo(() => {
27+
return {
28+
diffuseColor: blendHex(color, '#ffffff', 0.1),
29+
emissiveColor: blendHex(color, '#000000', 0.5),
30+
};
31+
}, [color]);
32+
33+
const { outputColorString } = useFlatShading({
34+
diffuseColor,
35+
emissiveColor,
36+
lightColor,
37+
objectLocalPosition,
38+
objectLocalNormal,
39+
lightWorldPosition: lightPosition,
40+
parentMatrixWorld: matrixWorld.current,
41+
});
42+
43+
const faceStyle = useMemo(() => {
44+
return merge3dMatrixWithStyles(matrixWorld.current, {
45+
...style,
46+
backgroundColor: outputColorString,
47+
});
48+
}, [matrixWorld, style, outputColorString]);
49+
50+
return <div style={faceStyle} className="face" />;
51+
};

examples/3d-cubes/src/components/FlatMaterial.tsx

Lines changed: 0 additions & 128 deletions
This file was deleted.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { createContext, useContext, useEffect, useState } from 'react';
2+
import { vec3 } from 'gl-matrix';
3+
import type { ReactNode } from 'react';
4+
5+
type GlobalState = {
6+
width: number;
7+
height: number;
8+
perspective: number;
9+
lightPosition: vec3;
10+
lightColor: string;
11+
};
12+
13+
const updatePerspective = (height: number) => (500 / 750) * height;
14+
15+
const updateLightPosition = (width: number, height: number, v: vec3) =>
16+
vec3.set(v, width / 4, height / 4, 100);
17+
18+
const getDefaultState = (width: number, height: number): GlobalState => ({
19+
width,
20+
height,
21+
perspective: updatePerspective(height),
22+
lightPosition: updateLightPosition(width, height, vec3.create()),
23+
lightColor: '#ffffff',
24+
});
25+
26+
const updateGlobalStateDimensions = (
27+
width: number,
28+
height: number,
29+
state: GlobalState,
30+
): GlobalState => {
31+
return {
32+
...state,
33+
width,
34+
height,
35+
perspective: updatePerspective(height),
36+
lightPosition: updateLightPosition(width, height, state.lightPosition),
37+
};
38+
};
39+
40+
const GlobalContext = createContext<GlobalState>(
41+
getDefaultState(window.innerWidth, window.innerHeight),
42+
);
43+
44+
export const useGlobalContext = () => useContext<GlobalState>(GlobalContext);
45+
46+
type DimensionsProviderProps = {
47+
children: ReactNode;
48+
};
49+
export const GlobalStateProvider = ({ children }: DimensionsProviderProps) => {
50+
const [globalState, setGlobalState] = useState(() =>
51+
getDefaultState(window.innerWidth, window.innerHeight),
52+
);
53+
54+
useEffect(() => {
55+
const handleResize = () => {
56+
setGlobalState((state) =>
57+
updateGlobalStateDimensions(
58+
window.innerWidth,
59+
window.innerHeight,
60+
state,
61+
),
62+
);
63+
};
64+
65+
window.addEventListener('resize', handleResize);
66+
return () => window.removeEventListener('resize', handleResize);
67+
}, []);
68+
69+
return (
70+
<GlobalContext.Provider value={globalState}>
71+
{children}
72+
</GlobalContext.Provider>
73+
);
74+
};

0 commit comments

Comments
 (0)