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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -193,8 +193,6 @@ export const sketchFns = {
if (!_programMemory._sketch) {
throw new Error('No sketch to draw on')
}
const lastPath: Path =
_programMemory._sketch[_programMemory._sketch.length - 1]
let from = getCoordsFromPaths(
programMemory?._sketch,
programMemory?._sketch.length - 1
@ -238,33 +236,8 @@ export const sketchFns = {
: (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 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))
})
const { position, quaternion } = combineTransforms(sketchVal)
const extrudeFaces: ExtrudeFace[] = []
sketch.sketch.map((line, index) => {
@ -284,7 +257,7 @@ export const sketchFns = {
extrudeFaces.push({
type: 'extrudeFace',
quaternion,
translate: [position.x, position.y, position.z],
translate: position,
geo,
sourceRanges: [line.sourceRange, sourceRange],
})
@ -333,3 +306,65 @@ function translate(
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 { addLineHighlight, EditorView } from './editor/highlightextension'
import { Program, abstractSyntaxTree } from './lang/abstractSyntaxTree'
import { ProgramMemory } from './lang/executor'
import { recast } from './lang/recast'
import { lexer } from './lang/tokeniser'
import { Quaternion } from 'three'
export type Range = [number, number]
type Plane = 'xy' | 'xz' | 'yz'
type PathToNode = (string | number)[]
type Position = [number, number, number]
type GuiModes =
| {
@ -18,6 +19,7 @@ type GuiModes =
mode: 'sketch'
sketchMode: 'points'
quaternion: Quaternion
position: Position
id?: string
pathToNode: PathToNode
}
@ -25,6 +27,7 @@ type GuiModes =
mode: 'sketch'
sketchMode: 'sketchEdit'
quaternion: Quaternion
position: Position
pathToNode: PathToNode
}
| {
@ -35,6 +38,7 @@ type GuiModes =
mode: 'canEditSketch'
pathToNode: PathToNode
quaternion: Quaternion
position: Position
}
interface StoreState {
@ -62,6 +66,8 @@ interface StoreState {
error: string
}
setError: (error?: string) => void
programMemory: ProgramMemory
setProgramMemory: (programMemory: ProgramMemory) => void
}
export const useStore = create<StoreState>()((set, get) => ({
@ -123,4 +129,6 @@ export const useStore = create<StoreState>()((set, get) => ({
setError: (error = '') => {
set({ errorState: { isError: !!error, error } })
},
programMemory: { root: {}, _sketch: [] },
setProgramMemory: (programMemory) => set({ programMemory }),
}))