Skip to content

Commit

Permalink
feat: webgl 3d put
Browse files Browse the repository at this point in the history
  • Loading branch information
plantain-00 committed Jun 17, 2024
1 parent f273f89 commit 83a9cda
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 9 deletions.
101 changes: 101 additions & 0 deletions dev/webgl-3d-put.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as React from "react"
import { createWebgl3DRenderer, Graphic3d, useWindowSize, angleToRadian, Vec3, useGlobalKeyDown, Nullable, useUndoRedo, metaKeyIfMacElseCtrlKey } from "../src"

export default () => {
const ref = React.useRef<HTMLCanvasElement | null>(null)
const renderer = React.useRef<ReturnType<typeof createWebgl3DRenderer>>()
const size = useWindowSize()
const width = size.width / 2
const height = size.height
const eye: Vec3 = [0, -90, 90]
const { state, undo, redo } = useUndoRedo<Graphic3d[]>([
{
geometry: {
type: 'triangle strip',
points: [-50, -50, 0, -50, 50, 0, 50, -50, 0, 50, 50, 0],
},
color: [0.6, 0.6, 0.6, 1],
position: [0, 0, 0],
},
])
const [preview, setPreview] = React.useState<Graphic3d>()

React.useEffect(() => {
if (!ref.current || renderer.current) {
return
}
renderer.current = createWebgl3DRenderer(ref.current)
}, [ref.current])

useGlobalKeyDown(e => {
if (metaKeyIfMacElseCtrlKey(e)) {
if (e.code === 'KeyZ') {
if (e.shiftKey) {
redo(e)
} else {
undo(e)
}
}
}
})
const render = (g: Nullable<Graphic3d>[]) => {
renderer.current?.render?.(
g,
{
eye,
up: [0, 1, 0],
target: [0, 0, 0],
fov: angleToRadian(60),
near: 0.1,
far: 1000,
},
{
position: [1000, -1000, 1000],
color: [1, 1, 1, 1],
specular: [1, 1, 1, 1],
shininess: 50,
specularFactor: 1,
},
[1, 1, 1, 1],
)
}

React.useEffect(() => {
const graphics = [...state]
if (preview) {
graphics.push(preview)
}
render(graphics)
}, [state, preview])

return (
<div
style={{
position: 'absolute',
inset: '0px',
}}
>
<canvas
ref={ref}
width={width}
height={height}
onMouseMove={e => {
if (renderer.current) {
const info = renderer.current.pickingDrawObjectsInfo[0]
if (info) {
const target = renderer.current.getTarget(e.clientX, e.clientY, eye, 0, info.reversedProjection)
setPreview({
geometry: {
type: 'cube',
size: 5,
},
color: [1, 0, 0, 1],
position: [target[0], target[1], 5],
})
}
}
}}
/>
</div>
)
}
26 changes: 17 additions & 9 deletions src/components/webgl-3d-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -337,21 +337,25 @@ export function createWebgl3DRenderer(canvas: HTMLCanvasElement) {
return index === 0xffffff ? undefined : index
}

const pickPoint = (inputX: number, inputY: number, eye: Vec3, z: number, filter: (graphic: Graphic3d, index: number) => boolean = () => true): Vec3 | undefined => {
const rect = canvas.getBoundingClientRect();
const getTarget = (inputX: number, inputY: number, eye: Vec3, z: number, reversedProjection: m4.Mat4): Vec3 => {
const rect = canvas.getBoundingClientRect()
const x = (inputX - rect.left) / canvas.clientWidth * 2 - 1
const y = -((inputY - rect.top) / canvas.clientHeight * 2 - 1)
const a = m4.transformPoint(reversedProjection, [x, y, 1])
const b = (z - eye[2]) / (a[2] - eye[2])
return [
eye[0] + (a[0] - eye[0]) * b,
eye[1] + (a[1] - eye[1]) * b,
z,
]
}

const pickPoint = (inputX: number, inputY: number, eye: Vec3, z: number, filter: (graphic: Graphic3d, index: number) => boolean = () => true): Vec3 | undefined => {
const index = pick(inputX, inputY, filter)
if (index !== undefined) {
const info = pickingDrawObjectsInfo.find(p => p && p.index === index)
if (info && info.graphic.geometry.type === 'vertices') {
const a = m4.transformPoint(info.reversedProjection, [x, y, 1])
const b = (z - eye[2]) / (a[2] - eye[2])
const target: Vec3 = [
eye[0] + (a[0] - eye[0]) * b,
eye[1] + (a[1] - eye[1]) * b,
z,
]
const target = getTarget(inputX, inputY, eye, z, info.reversedProjection)
const line = new verb.geom.Line(eye, target)
const intersections = verb.geom.Intersect.curveAndSurface(line, info.graphic.geometry.nurbs, 1e-3)
if (intersections.length > 0) {
Expand All @@ -367,6 +371,10 @@ export function createWebgl3DRenderer(canvas: HTMLCanvasElement) {
render,
pick,
pickPoint,
getTarget,
get pickingDrawObjectsInfo() {
return pickingDrawObjectsInfo
},
}
}

Expand Down

0 comments on commit 83a9cda

Please sign in to comment.