-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
58 changes: 58 additions & 0 deletions
58
packages/static/content/examples/basic/context-bridge/ContextBridge.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { Color3, Vector3 } from '@babylonjs/core/Maths/math' | ||
import React from 'react' | ||
import { Engine, Scene } from 'react-babylonjs' | ||
|
||
const ThemeContext = React.createContext({ | ||
color: Color3.Red(), | ||
position: Vector3.Zero(), | ||
name: 'default context', | ||
}) | ||
|
||
const ThemedBox = () => { | ||
const ctx = React.useContext(ThemeContext) | ||
return ( | ||
<box name={ctx.name} position={ctx.position}> | ||
<standardMaterial name="mat" diffuseColor={ctx.color} specularColor={Color3.Black()} /> | ||
</box> | ||
) | ||
} | ||
|
||
const EngineScene = () => ( | ||
<div style={{ flex: 1, display: 'flex', maxWidth: '80%' }}> | ||
<ThemeContext.Consumer> | ||
{(value) => ( | ||
<Engine antialias adaptToDeviceRatio canvasId="babylon-js"> | ||
<Scene> | ||
<ThemeContext.Provider value={value}> | ||
<arcRotateCamera | ||
name="arc" | ||
target={Vector3.Zero()} | ||
minZ={0.001} | ||
alpha={-Math.PI / 4} | ||
beta={Math.PI / 4} | ||
radius={5} | ||
/> | ||
<hemisphericLight name="light1" intensity={0.7} direction={Vector3.Up()} /> | ||
<ground name="ground1" width={6} height={6} subdivisions={2} /> | ||
<ThemedBox /> | ||
</ThemeContext.Provider> | ||
</Scene> | ||
</Engine> | ||
)} | ||
</ThemeContext.Consumer> | ||
</div> | ||
) | ||
|
||
const BridgedContext = () => ( | ||
<ThemeContext.Provider | ||
value={{ | ||
color: Color3.FromHexString('#FFAF00'), | ||
position: new Vector3(0, 1, 0), | ||
name: 'testing', | ||
}} | ||
> | ||
<EngineScene /> | ||
</ThemeContext.Provider> | ||
) | ||
|
||
export default BridgedContext |
15 changes: 15 additions & 0 deletions
15
packages/static/content/examples/basic/context-bridge/index.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
title: 'Context Bridge' | ||
--- | ||
|
||
These can be used to bring context across renderer boundaries. | ||
|
||
In `react-babylonjs` that will be on the Engine and Scene components. So, | ||
capture (Consumer) the context outside and "Provide" inside the Scene. | ||
|
||
Example is given here - you would need these for Themes or libraries like Redux | ||
that depend on context. If you are using Redux and your project is not too far | ||
along consider switching to a state management library that doesn't suffer from | ||
this issue such as Zustand. | ||
|
||
[devtool:ContextBridge.tsx] |
86 changes: 86 additions & 0 deletions
86
packages/static/content/examples/basic/custom-mesh/CustomMesh.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { Vector3 } from '@babylonjs/core/Maths/math.vector' | ||
import { VertexData } from '@babylonjs/core/Meshes/mesh.vertexData' | ||
// this import is just so it works with debug builds. you should import from '@babylonjs/*` directly as above | ||
import { Mesh } from 'react-babylonjs/node_modules/@babylonjs/core/Meshes/mesh' | ||
|
||
import React, { FC, useState } from 'react' | ||
import { Engine, Scene, useScene } from 'react-babylonjs' | ||
|
||
type CustomMeshType = { | ||
name: string | ||
position: Vector3 | ||
useWireframe: boolean | ||
} | ||
|
||
const CustomMesh: FC<CustomMeshType> = (props) => { | ||
const scene = useScene() | ||
|
||
const [customMesh] = useState(() => { | ||
const meshInstance = new Mesh(props.name, scene!) | ||
|
||
//Set arrays for positions and indices | ||
var positions = [-5, 2, -3, -7, -2, -3, -3, -2, -3, 5, 2, 3, 7, -2, 3, 3, -2, 3] | ||
var indices = [0, 1, 2, 3, 4, 5] | ||
var colors = [1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1] | ||
|
||
//Empty array to contain calculated values | ||
var normals: number[] = [] | ||
|
||
var vertexData = new VertexData() | ||
VertexData.ComputeNormals(positions, indices, normals) | ||
|
||
//Assign positions, indices and normals to vertexData | ||
vertexData.positions = positions | ||
vertexData.indices = indices | ||
vertexData.normals = normals | ||
vertexData.colors = colors | ||
|
||
//Apply vertexData to custom mesh | ||
vertexData.applyToMesh(meshInstance) | ||
|
||
return meshInstance | ||
}) | ||
|
||
return ( | ||
<mesh name="mesh" fromInstance={customMesh} disposeInstanceOnUnmount position={props.position}> | ||
<standardMaterial name={`${props.name}-mat`} wireframe={props.useWireframe} /> | ||
</mesh> | ||
) | ||
} | ||
|
||
const CustomMeshes = () => { | ||
const [displayLast, setDisplayLast] = useState(true) | ||
const toggleDisplay = () => { | ||
setDisplayLast((cur) => !cur) | ||
} | ||
return ( | ||
<> | ||
<div> | ||
<button className="btn btn-primary m-2" onClick={toggleDisplay}> | ||
Toggle Top Triangle Visibility | ||
</button> | ||
</div> | ||
<div style={{ flex: 1, display: 'flex' }}> | ||
<Engine antialias adaptToDeviceRatio canvasId="babylon-js"> | ||
<Scene> | ||
<arcRotateCamera | ||
name="camera1" | ||
target={Vector3.Zero()} | ||
alpha={Math.PI / 2} | ||
beta={Math.PI / 2} | ||
radius={20} | ||
/> | ||
<hemisphericLight name="light1" intensity={0.7} direction={Vector3.Up()} /> | ||
<CustomMesh name="custom-0" position={new Vector3(0, 0, 0)} useWireframe={false} /> | ||
<CustomMesh name="custom-2" position={new Vector3(0, 2, 0)} useWireframe={true} /> | ||
{displayLast && ( | ||
<CustomMesh name="custom-4" position={new Vector3(0, 4, 0)} useWireframe={false} /> | ||
)} | ||
</Scene> | ||
</Engine> | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
export default CustomMeshes |
27 changes: 27 additions & 0 deletions
27
packages/static/content/examples/basic/custom-mesh/index.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
title: 'Custom Mesh' | ||
--- | ||
|
||
We're not just limited to basic shapes here, but the real purpose of this | ||
example is to highlight 2 custom properties: | ||
|
||
```tsx | ||
<mesh name="mesh" fromInstance={customMesh} disposeInstanceOnUnmount> | ||
... | ||
</mesh> | ||
``` | ||
|
||
When you supply a `fromInstance` prop then the renderer will substibute what you | ||
provide instead of "newing up" that object for you. You can do this with | ||
Cameras, Textures, etc. Property changes will flow to that instance as usual. | ||
|
||
The renderer will not dispose of this instance when it unmounts the Component, | ||
but you can opt-in by specifying that you would like that done on your behalf. | ||
In our case it's a bit simple - we could have in a useEffect disposed the mesh, | ||
but in some cases you may have something like a texture map that you want | ||
re-used and whenever you use `fromInstance` the renderer will assume you are | ||
managing the lifecycle of that object unless you request automatic disposal with | ||
`disposeInstanceOnUnmount` (which is the same as | ||
`disposeInstanceOnUnmount={true}`) | ||
|
||
[devtool:CustomMesh.tsx] |
130 changes: 130 additions & 0 deletions
130
packages/static/content/examples/basic/instanced-mesh-hex/InstancedMeshHex.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import { Color3, Color4, Vector3 } from '@babylonjs/core' | ||
import React, { useCallback, useEffect, useState } from 'react' | ||
import { Engine, Scene } from 'react-babylonjs' | ||
|
||
type GridItemType = [ | ||
number, | ||
{ | ||
toPoint: () => { x: number; y: number } | ||
width: () => number | ||
height: () => number | ||
color: Color4 | ||
isHovered: boolean | ||
} | ||
] | ||
|
||
type GridType = { | ||
entries: () => Iterable<GridItemType> | ||
} | ||
|
||
const importUMD = async (url: string, module = { exports: {} }) => | ||
(Function('module', 'exports', await (await fetch(url)).text()).call( | ||
module, | ||
module, | ||
module.exports | ||
), | ||
module).exports | ||
|
||
const getGrid = async (): Promise<GridType> => { | ||
// const cdn = 'https://cdn.jsdelivr.net/npm/honeycomb-grid'; await import (cdn) | ||
const importResults = await importUMD( | ||
'https://cdn.jsdelivr.net/npm/honeycomb-grid@3.1.8/dist/honeycomb.min.js' | ||
) | ||
console.log('import results:', importResults) | ||
const { defineGrid, extendHex } = importResults as any | ||
const Hex = extendHex({ | ||
size: 1, // default: 1 | ||
orientation: 'flat', // default: 'pointy' | ||
color: new Color4(0, 0.68, 1), | ||
hovered: false, | ||
}) | ||
|
||
// create a Grid factory that uses the Hex factory: | ||
const Grid = defineGrid(Hex) | ||
|
||
// create a rectangle grid with each tile assigned a random color: | ||
const grid = Grid.rectangle({ | ||
width: GRID_WIDTH, | ||
height: GRID_HEIGHT, | ||
onCreate: (hex: any) => { | ||
hex.color = new Color4(Math.random(), Math.random(), Math.random(), 1) | ||
hex.isHovered = Math.random() < 0.1 | ||
}, | ||
}) | ||
|
||
return grid | ||
} | ||
|
||
const GRID_WIDTH = 60 | ||
const GRID_HEIGHT = 40 | ||
const HOVER_COLOR = new Color4(0.8, 0.8, 0.8, 1) | ||
|
||
const Instances = () => { | ||
// const hexRef = useRef<CreatedInstance<Mesh>>(null); | ||
const [hexMesh, setHexMesh] = useState(null) | ||
const hexRef = useCallback((node) => { | ||
if (node) { | ||
const mesh = node | ||
mesh.registerInstancedBuffer('color', 4) | ||
setHexMesh(mesh) | ||
} | ||
}, []) | ||
|
||
const [grid, setGrid] = useState<null | GridType>(null) | ||
|
||
useEffect(() => { | ||
getGrid().then((grid) => setGrid(grid)) | ||
}, []) | ||
|
||
const createUpdate = () => { | ||
getGrid().then((grid) => setGrid(grid)) | ||
} | ||
|
||
return ( | ||
<div className="App"> | ||
<button className="btn btn-primary m-2" onClick={createUpdate}> | ||
Change hex colours | ||
</button> | ||
<Engine antialias adaptToDeviceRatio canvasId="babylonJS"> | ||
<Scene clearColor={Color4.FromColor3(Color3.White())}> | ||
<arcRotateCamera | ||
name="arc" | ||
target={Vector3.Zero()} | ||
minZ={0.001} | ||
alpha={-Math.PI / 2} | ||
beta={Math.PI / 1.2} | ||
radius={Math.max(GRID_WIDTH, GRID_HEIGHT) * 1.5} | ||
/> | ||
<hemisphericLight name="light1" intensity={0.9} direction={Vector3.Down()} /> | ||
<disc ref={hexRef} name="hex" radius={1} tessellation={6} isVisible={false} /> | ||
{hexMesh && | ||
grid && | ||
Array.from(grid.entries()).map((entry) => { | ||
const [i, tile] = entry | ||
const { x, y } = tile.toPoint() | ||
console.log(`${i}->{${x},${y}} (${tile.width()})`) | ||
return ( | ||
<instancedMesh | ||
source={hexMesh} | ||
key={i} | ||
name={`hex-${i}`} | ||
position={ | ||
new Vector3( | ||
x + tile.width() / 2 - GRID_WIDTH * 0.75, | ||
y + tile.height() / 2 - (Math.sqrt(3) * GRID_HEIGHT) / 2, | ||
0 | ||
) | ||
} | ||
instancedBuffers={{ | ||
color: tile.isHovered ? HOVER_COLOR : tile.color, | ||
}} | ||
/> | ||
) | ||
})} | ||
</Scene> | ||
</Engine> | ||
</div> | ||
) | ||
} | ||
|
||
export default Instances |
32 changes: 32 additions & 0 deletions
32
packages/static/content/examples/basic/instanced-mesh-hex/index.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
--- | ||
title: 'InstancedMesh Hex' | ||
--- | ||
|
||
An alternative to 'fromInstance' prop for meshes is to use | ||
[instanced meshes](https://doc.babylonjs.com/typedoc/classes/BABYLON.InstancedMesh). | ||
You can read up more on "InstancedMesh" in babylon.js, but they have less | ||
overhead of separate instancing hundreds of meshes. | ||
|
||
Essentially in this example we create a single "hex" mesh. Then we add hundreds | ||
of instances using that mesh as a source. Each instance is set with it's own | ||
position and color. | ||
|
||
```tsx | ||
<instancedMesh | ||
source={hexMesh} | ||
key={i} | ||
name={`hex-${i}`} | ||
position={ | ||
new Vector3( | ||
x + tile.width() / 2 - GRID_WIDTH * 0.75, | ||
y + tile.height() / 2 - (Math.sqrt(3) * GRID_HEIGHT) / 2, | ||
0 | ||
) | ||
} | ||
instancedBuffers={{ | ||
color: tile.isHovered ? HOVER_COLOR : tile.color, | ||
}} | ||
/> | ||
``` | ||
|
||
[devtool:InstancedMeshHex.tsx] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters