fix sketch plan orientation

This commit is contained in:
Kurt Hutten IrevDev
2023-01-04 01:28:26 +11:00
parent a1f844b0b1
commit 0779befc65
8 changed files with 100 additions and 50 deletions

View File

@ -41,6 +41,7 @@ function App() {
ast, ast,
setError, setError,
errorState, errorState,
setProgramMemory,
} = useStore((s) => ({ } = useStore((s) => ({
editorView: s.editorView, editorView: s.editorView,
setEditorView: s.setEditorView, setEditorView: s.setEditorView,
@ -58,6 +59,7 @@ function App() {
formatCode: s.formatCode, formatCode: s.formatCode,
setError: s.setError, setError: s.setError,
errorState: s.errorState, errorState: s.errorState,
setProgramMemory: s.setProgramMemory,
})) }))
// const onChange = React.useCallback((value: string, viewUpdate: ViewUpdate) => { // const onChange = React.useCallback((value: string, viewUpdate: ViewUpdate) => {
const onChange = (value: string, viewUpdate: ViewUpdate) => { const onChange = (value: string, viewUpdate: ViewUpdate) => {
@ -103,6 +105,7 @@ function App() {
}, },
_sketch: [], _sketch: [],
}) })
setProgramMemory(programMemory)
const geos: ViewerArtifact[] = const geos: ViewerArtifact[] =
programMemory?.return?.flatMap( programMemory?.return?.flatMap(
({ name }: { name: string }) => ({ name }: { name: string }) =>

View File

@ -28,6 +28,7 @@ export const Toolbar = () => {
sketchMode: 'sketchEdit', sketchMode: 'sketchEdit',
pathToNode: guiMode.pathToNode, pathToNode: guiMode.pathToNode,
quaternion: guiMode.quaternion, quaternion: guiMode.quaternion,
position: guiMode.position,
}) })
}} }}
className="border m-1 px-1 rounded" className="border m-1 px-1 rounded"

View File

@ -65,6 +65,7 @@ export const BasePlanes = () => {
mode: 'sketch', mode: 'sketch',
sketchMode: 'sketchEdit', sketchMode: 'sketchEdit',
quaternion, quaternion,
position: [0, 0, 0],
pathToNode, pathToNode,
}) })

View File

@ -4,6 +4,7 @@ import {
getNodeFromPath, getNodeFromPath,
CallExpression, CallExpression,
changeArguments, changeArguments,
VariableDeclarator,
} from '../lang/abstractSyntaxTree' } from '../lang/abstractSyntaxTree'
import { ViewerArtifact } from '../lang/executor' import { ViewerArtifact } from '../lang/executor'
import { BufferGeometry } from 'three' import { BufferGeometry } from 'three'
@ -11,6 +12,7 @@ import { useStore } from '../useStore'
import { isOverlapping } from '../lib/utils' import { isOverlapping } from '../lib/utils'
import { LineGeos } from '../lang/engine' import { LineGeos } from '../lang/engine'
import { Vector3, DoubleSide, Quaternion, Vector2 } from 'three' import { Vector3, DoubleSide, Quaternion, Vector2 } from 'three'
import { combineTransformsAlt } from '../lang/sketch'
function SketchLine({ function SketchLine({
geo, geo,
@ -129,9 +131,7 @@ function MovingSphere({
const { setHighlightRange, guiMode, ast, updateAst } = useStore((s) => ({ const { setHighlightRange, guiMode, ast, updateAst } = useStore((s) => ({
setHighlightRange: s.setHighlightRange, setHighlightRange: s.setHighlightRange,
selectionRange: s.selectionRange,
guiMode: s.guiMode, guiMode: s.guiMode,
setGuiMode: s.setGuiMode,
ast: s.ast, ast: s.ast,
updateAst: s.updateAst, updateAst: s.updateAst,
})) }))
@ -173,11 +173,13 @@ function MovingSphere({
}, [isMouseDown, ast]) }, [isMouseDown, ast])
let clickDetectPlaneQuaternion = new Quaternion() let clickDetectPlaneQuaternion = new Quaternion()
let position = new Vector3(0, 0, 0)
if ( if (
guiMode.mode === 'canEditSketch' || guiMode.mode === 'canEditSketch' ||
(guiMode.mode === 'sketch' && guiMode.sketchMode === 'sketchEdit') (guiMode.mode === 'sketch' && guiMode.sketchMode === 'sketchEdit')
) { ) {
clickDetectPlaneQuaternion = guiMode.quaternion.clone() clickDetectPlaneQuaternion = guiMode.quaternion.clone()
position = new Vector3(...guiMode.position)
} }
return ( return (
@ -201,7 +203,7 @@ function MovingSphere({
</mesh> </mesh>
{isMouseDown && ( {isMouseDown && (
<mesh <mesh
position={[0, 0, -0.05]} position={position}
quaternion={clickDetectPlaneQuaternion} quaternion={clickDetectPlaneQuaternion}
onPointerMove={(a) => { onPointerMove={(a) => {
const point = a.point const point = a.point
@ -264,12 +266,13 @@ export function RenderViewerArtifacts({
artifact: ViewerArtifact artifact: ViewerArtifact
forceHighlight?: boolean forceHighlight?: boolean
}) { }) {
const { selectionRange, guiMode, ast, setGuiMode } = useStore( const { selectionRange, guiMode, ast, setGuiMode, programMemory } = useStore(
({ selectionRange, guiMode, ast, setGuiMode }) => ({ ({ selectionRange, guiMode, ast, setGuiMode, programMemory }) => ({
selectionRange, selectionRange,
guiMode, guiMode,
ast, ast,
setGuiMode, setGuiMode,
programMemory,
}) })
) )
const [editorCursor, setEditorCursor] = useState(false) const [editorCursor, setEditorCursor] = useState(false)
@ -287,20 +290,16 @@ export function RenderViewerArtifacts({
ast ast
) { ) {
const pathToNode = getNodePathFromSourceRange(ast, artifact.sourceRange) const pathToNode = getNodePathFromSourceRange(ast, artifact.sourceRange)
const piper = getNodeFromPath(ast, pathToNode, 'PipeExpression') const varDec: VariableDeclarator = getNodeFromPath(
const quaternion = new Quaternion() ast,
if (piper.type === 'PipeExpression') { pathToNode,
const rotateName = piper?.body?.[1]?.callee?.name 'VariableDeclarator'
const rotateValue = piper?.body?.[1]?.arguments[0].value )
let rotateAxis = new Vector3(1, 0, 0) const varName = varDec?.id?.name
if (rotateName === 'ry') { const { quaternion, position } = combineTransformsAlt(
rotateAxis = new Vector3(0, 1, 0) programMemory.root[varName]
} else if (rotateName === 'rz') { )
rotateAxis = new Vector3(0, 0, 1) setGuiMode({ mode: 'canEditSketch', pathToNode, quaternion, position })
}
quaternion.setFromAxisAngle(rotateAxis, (Math.PI * rotateValue) / 180)
}
setGuiMode({ mode: 'canEditSketch', pathToNode, quaternion })
} else if ( } else if (
!shouldHighlight && !shouldHighlight &&
guiMode.mode === 'canEditSketch' && guiMode.mode === 'canEditSketch' &&

View File

@ -26,6 +26,7 @@ export const SketchPlane = () => {
new Vector3(1, 0, 0), new Vector3(1, 0, 0),
Math.PI / 2 Math.PI / 2
) )
let position = guiMode.position
const gridQuaternion = new Quaternion().multiplyQuaternions( const gridQuaternion = new Quaternion().multiplyQuaternions(
guiMode.quaternion, guiMode.quaternion,
temp temp
@ -35,6 +36,7 @@ export const SketchPlane = () => {
<> <>
<mesh <mesh
quaternion={clickDetectQuaternion} quaternion={clickDetectQuaternion}
position={position}
name={sketchGridName} name={sketchGridName}
onClick={(e) => { onClick={(e) => {
if (guiMode.sketchMode !== 'points') { if (guiMode.sketchMode !== 'points') {
@ -77,6 +79,7 @@ export const SketchPlane = () => {
<gridHelper <gridHelper
args={[30, 40, 'blue', 'hotpink']} args={[30, 40, 'blue', 'hotpink']}
quaternion={gridQuaternion} quaternion={gridQuaternion}
position={position}
/> />
</> </>
) )

View File

@ -377,7 +377,7 @@ function makeValue(
throw new Error('Expected a previous Value if statement to match') throw new Error('Expected a previous Value if statement to match')
} }
interface VariableDeclarator extends GeneralStatement { export interface VariableDeclarator extends GeneralStatement {
type: 'VariableDeclarator' type: 'VariableDeclarator'
id: Identifier id: Identifier
init: Value init: Value

View File

@ -193,8 +193,6 @@ export const sketchFns = {
if (!_programMemory._sketch) { if (!_programMemory._sketch) {
throw new Error('No sketch to draw on') throw new Error('No sketch to draw on')
} }
const lastPath: Path =
_programMemory._sketch[_programMemory._sketch.length - 1]
let from = getCoordsFromPaths( let from = getCoordsFromPaths(
programMemory?._sketch, programMemory?._sketch,
programMemory?._sketch.length - 1 programMemory?._sketch.length - 1
@ -238,33 +236,8 @@ export const sketchFns = {
: (sketchVal as SketchGeo) // TODO fix types : (sketchVal as SketchGeo) // TODO fix types
} }
type PreviousTransforms = {
rotation: Quaternion
transform: [number, number, number]
}[]
const collectTransforms = (
sketchVal: SketchGeo | ExtrudeGeo | Transform,
previousTransforms: PreviousTransforms = []
): PreviousTransforms => {
if (sketchVal.type !== 'transform') return previousTransforms
const newTransforms = [
...previousTransforms,
{
rotation: sketchVal.rotation,
transform: sketchVal.transform,
},
]
return collectTransforms(sketchVal.sketch, newTransforms)
}
const sketch = getSketchGeo(sketchVal) const sketch = getSketchGeo(sketchVal)
const previousTransforms = collectTransforms(sketchVal) const { position, quaternion } = combineTransforms(sketchVal)
const position = new Vector3(0, 0, 0)
const quaternion = new Quaternion()
previousTransforms.forEach(({ rotation, transform }) => {
quaternion.multiply(rotation)
position.applyQuaternion(rotation.clone().invert())
position.add(new Vector3(...transform))
})
const extrudeFaces: ExtrudeFace[] = [] const extrudeFaces: ExtrudeFace[] = []
sketch.sketch.map((line, index) => { sketch.sketch.map((line, index) => {
@ -284,7 +257,7 @@ export const sketchFns = {
extrudeFaces.push({ extrudeFaces.push({
type: 'extrudeFace', type: 'extrudeFace',
quaternion, quaternion,
translate: [position.x, position.y, position.z], translate: position,
geo, geo,
sourceRanges: [line.sourceRange, sourceRange], sourceRanges: [line.sourceRange, sourceRange],
}) })
@ -333,3 +306,65 @@ function translate(
sourceRange, sourceRange,
} }
} }
type PreviousTransforms = {
rotation: Quaternion
transform: [number, number, number]
}[]
function collectTransforms(
sketchVal: SketchGeo | ExtrudeGeo | Transform,
previousTransforms: PreviousTransforms = []
): PreviousTransforms {
if (sketchVal.type !== 'transform') return previousTransforms
const newTransforms = [
...previousTransforms,
{
rotation: sketchVal.rotation,
transform: sketchVal.transform,
},
]
return collectTransforms(sketchVal.sketch, newTransforms)
}
export function combineTransforms(
sketchVal: SketchGeo | ExtrudeGeo | Transform
): {
quaternion: Quaternion
position: [number, number, number]
} {
const previousTransforms = collectTransforms(sketchVal)
const position = new Vector3(0, 0, 0)
const quaternion = new Quaternion()
previousTransforms.forEach(({ rotation, transform }) => {
quaternion.multiply(rotation)
position.applyQuaternion(rotation.clone().invert())
position.add(new Vector3(...transform))
})
return {
quaternion,
position: [position.x, position.y, position.z],
}
}
export function combineTransformsAlt(
sketchVal: SketchGeo | ExtrudeGeo | Transform
): {
quaternion: Quaternion
position: [number, number, number]
} {
const previousTransforms = collectTransforms(sketchVal)
let rotationQuaternion = new Quaternion()
let position = new Vector3(0, 0, 0)
previousTransforms.reverse().forEach(({ rotation, transform }) => {
const newQuant = rotation.clone()
newQuant.multiply(rotationQuaternion)
rotationQuaternion.copy(newQuant)
position.applyQuaternion(rotation)
position.add(new Vector3(...transform))
})
return {
quaternion: rotationQuaternion,
position: [position.x, position.y, position.z],
}
}

View File

@ -1,14 +1,15 @@
import create from 'zustand' import create from 'zustand'
import { addLineHighlight, EditorView } from './editor/highlightextension' import { addLineHighlight, EditorView } from './editor/highlightextension'
import { Program, abstractSyntaxTree } from './lang/abstractSyntaxTree' import { Program, abstractSyntaxTree } from './lang/abstractSyntaxTree'
import { ProgramMemory } from './lang/executor'
import { recast } from './lang/recast' import { recast } from './lang/recast'
import { lexer } from './lang/tokeniser' import { lexer } from './lang/tokeniser'
import { Quaternion } from 'three' import { Quaternion } from 'three'
export type Range = [number, number] export type Range = [number, number]
type Plane = 'xy' | 'xz' | 'yz'
type PathToNode = (string | number)[] type PathToNode = (string | number)[]
type Position = [number, number, number]
type GuiModes = type GuiModes =
| { | {
@ -18,6 +19,7 @@ type GuiModes =
mode: 'sketch' mode: 'sketch'
sketchMode: 'points' sketchMode: 'points'
quaternion: Quaternion quaternion: Quaternion
position: Position
id?: string id?: string
pathToNode: PathToNode pathToNode: PathToNode
} }
@ -25,6 +27,7 @@ type GuiModes =
mode: 'sketch' mode: 'sketch'
sketchMode: 'sketchEdit' sketchMode: 'sketchEdit'
quaternion: Quaternion quaternion: Quaternion
position: Position
pathToNode: PathToNode pathToNode: PathToNode
} }
| { | {
@ -35,6 +38,7 @@ type GuiModes =
mode: 'canEditSketch' mode: 'canEditSketch'
pathToNode: PathToNode pathToNode: PathToNode
quaternion: Quaternion quaternion: Quaternion
position: Position
} }
interface StoreState { interface StoreState {
@ -62,6 +66,8 @@ interface StoreState {
error: string error: string
} }
setError: (error?: string) => void setError: (error?: string) => void
programMemory: ProgramMemory
setProgramMemory: (programMemory: ProgramMemory) => void
} }
export const useStore = create<StoreState>()((set, get) => ({ export const useStore = create<StoreState>()((set, get) => ({
@ -123,4 +129,6 @@ export const useStore = create<StoreState>()((set, get) => ({
setError: (error = '') => { setError: (error = '') => {
set({ errorState: { isError: !!error, error } }) set({ errorState: { isError: !!error, error } })
}, },
programMemory: { root: {}, _sketch: [] },
setProgramMemory: (programMemory) => set({ programMemory }),
})) }))