port over to quanternions
This commit is contained in:
@ -28,6 +28,7 @@ export const Toolbar = () => {
|
||||
sketchMode: 'sketchEdit',
|
||||
pathToNode: guiMode.pathToNode,
|
||||
axis: guiMode.axis,
|
||||
quaternion: guiMode.quaternion,
|
||||
})
|
||||
}}
|
||||
className="border m-1 px-1 rounded"
|
||||
@ -51,10 +52,13 @@ export const Toolbar = () => {
|
||||
className={`border m-1 px-1 rounded ${
|
||||
guiMode.sketchMode === 'points' && 'bg-gray-400'
|
||||
}`}
|
||||
onClick={() => setGuiMode({
|
||||
...guiMode,
|
||||
sketchMode: guiMode.sketchMode === 'points' ? 'sketchEdit' :'points',
|
||||
})}
|
||||
onClick={() =>
|
||||
setGuiMode({
|
||||
...guiMode,
|
||||
sketchMode:
|
||||
guiMode.sketchMode === 'points' ? 'sketchEdit' : 'points',
|
||||
})
|
||||
}
|
||||
>
|
||||
LineTo{guiMode.sketchMode === 'points' && '✅'}
|
||||
</button>
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { useState } from 'react'
|
||||
import { DoubleSide } from 'three'
|
||||
import { DoubleSide, Vector3 } from 'three'
|
||||
import { useStore } from '../useStore'
|
||||
import { Intersection } from '@react-three/fiber'
|
||||
import { Text } from '@react-three/drei'
|
||||
import { addSketchTo, Program } from '../lang/abstractSyntaxTree'
|
||||
import { Quaternion } from 'three'
|
||||
|
||||
const opacity = 0.1
|
||||
|
||||
@ -52,12 +53,19 @@ export const BasePlanes = () => {
|
||||
body: [],
|
||||
}
|
||||
const axis = axisIndex === 0 ? 'xy' : axisIndex === 1 ? 'xz' : 'yz'
|
||||
const quaternion = new Quaternion()
|
||||
if (axisIndex === 1) {
|
||||
quaternion.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI / 2)
|
||||
} else if (axisIndex === 2) {
|
||||
quaternion.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / 2)
|
||||
}
|
||||
const { modifiedAst, id, pathToNode } = addSketchTo(_ast, axis)
|
||||
|
||||
setGuiMode({
|
||||
mode: 'sketch',
|
||||
sketchMode: 'sketchEdit',
|
||||
axis,
|
||||
quaternion,
|
||||
pathToNode,
|
||||
})
|
||||
|
||||
@ -88,10 +96,20 @@ export const BasePlanes = () => {
|
||||
transparent
|
||||
opacity={opacity + (axisIndex === index ? 0.3 : 0)}
|
||||
/>
|
||||
<Text fontSize={1} color="#555" position={[1, 1, 0.01]} font={'/roboto.woff'}>
|
||||
<Text
|
||||
fontSize={1}
|
||||
color="#555"
|
||||
position={[1, 1, 0.01]}
|
||||
font={'/roboto.woff'}
|
||||
>
|
||||
{index === 0 ? 'xy' : index === 1 ? 'xz' : 'yz'}
|
||||
</Text>
|
||||
<Text fontSize={1} color="#555" position={[1, 1, -0.01]} font={'/roboto.woff'}>
|
||||
<Text
|
||||
fontSize={1}
|
||||
color="#555"
|
||||
position={[1, 1, -0.01]}
|
||||
font={'/roboto.woff'}
|
||||
>
|
||||
{index === 0 ? 'xy' : index === 1 ? 'xz' : 'yz'}
|
||||
</Text>
|
||||
</mesh>
|
||||
|
@ -10,7 +10,7 @@ import { BufferGeometry } from 'three'
|
||||
import { useStore } from '../useStore'
|
||||
import { isOverlapping } from '../lib/utils'
|
||||
import { LineGeos } from '../lang/engine'
|
||||
import { Vector3 } from 'three'
|
||||
import { Vector3, DoubleSide, Quaternion, Vector2 } from 'three'
|
||||
|
||||
function useHeightlight(sourceRange: [number, number]) {
|
||||
const { selectionRange, guiMode, setGuiMode, ast } = useStore((s) => ({
|
||||
@ -29,13 +29,25 @@ function useHeightlight(sourceRange: [number, number]) {
|
||||
if (shouldHighlight && guiMode.mode === 'default' && ast) {
|
||||
const pathToNode = getNodePathFromSourceRange(ast, 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)
|
||||
}
|
||||
const axis =
|
||||
piper.type !== 'PipeExpression'
|
||||
? 'xy'
|
||||
: piper?.body?.[1]?.callee?.name === 'rx'
|
||||
? 'xz'
|
||||
: 'yz'
|
||||
setGuiMode({ mode: 'canEditSketch', pathToNode, axis })
|
||||
setGuiMode({ mode: 'canEditSketch', pathToNode, axis, quaternion }) // TODO needs fix
|
||||
setDidSetCanEdit(true)
|
||||
} else if (
|
||||
!shouldHighlight &&
|
||||
@ -122,7 +134,9 @@ function MovingSphere({
|
||||
editorCursor: boolean
|
||||
}) {
|
||||
const ref = useRef<BufferGeometry | undefined>() as any
|
||||
const detectionPlaneRef = useRef<BufferGeometry | undefined>() as any
|
||||
const lastPointerRef = useRef<Vector3>(new Vector3())
|
||||
const point2DRef = useRef<Vector2>(new Vector2())
|
||||
const [hovered, setHover] = useState(false)
|
||||
const [isMouseDown, setIsMouseDown] = useState(false)
|
||||
|
||||
@ -141,7 +155,6 @@ function MovingSphere({
|
||||
const [xArg, yArg] = callExpression?.arguments || []
|
||||
const x = xArg?.type === 'Literal' ? xArg.value : -1
|
||||
const y = yArg?.type === 'Literal' ? yArg.value : -1
|
||||
console.log(callExpression)
|
||||
return {
|
||||
originalXY: [x, y],
|
||||
}
|
||||
@ -155,11 +168,11 @@ function MovingSphere({
|
||||
const handleMouseUp = () => {
|
||||
if (isMouseDown && ast) {
|
||||
const thePath = getNodePathFromSourceRange(ast, sourceRange)
|
||||
const theNewPoints: [number, number] = [
|
||||
roundOff(lastPointerRef.current.x, 2),
|
||||
roundOff(lastPointerRef.current.y, 2),
|
||||
let [x, y] = [
|
||||
roundOff(point2DRef.current.x, 2),
|
||||
roundOff(point2DRef.current.y, 2),
|
||||
]
|
||||
console.log('theNewPoints', theNewPoints)
|
||||
let theNewPoints: [number, number] = [x, y]
|
||||
const { modifiedAst } = changeArguments(ast, thePath, theNewPoints)
|
||||
updateAst(modifiedAst)
|
||||
ref.current.position.set(0, 0, 0)
|
||||
@ -172,6 +185,14 @@ function MovingSphere({
|
||||
}
|
||||
}, [isMouseDown, ast])
|
||||
|
||||
let clickDetectPlaneQuaternion = new Quaternion()
|
||||
if (
|
||||
guiMode.mode === 'canEditSketch' ||
|
||||
(guiMode.mode === 'sketch' && guiMode.sketchMode === 'sketchEdit')
|
||||
) {
|
||||
clickDetectPlaneQuaternion = guiMode.quaternion.clone()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh
|
||||
@ -193,9 +214,23 @@ function MovingSphere({
|
||||
</mesh>
|
||||
{isMouseDown && (
|
||||
<mesh
|
||||
position={[0, 0, 0.05]}
|
||||
position={[0, 0, -0.05]}
|
||||
quaternion={clickDetectPlaneQuaternion}
|
||||
onPointerMove={(a) => {
|
||||
const point = a.point
|
||||
|
||||
const transformedPoint = point.clone()
|
||||
let inverseQuaternion = new Quaternion()
|
||||
if (
|
||||
guiMode.mode === 'canEditSketch' ||
|
||||
(guiMode.mode === 'sketch' && guiMode.sketchMode === 'sketchEdit')
|
||||
) {
|
||||
inverseQuaternion = guiMode.quaternion.clone()
|
||||
}
|
||||
inverseQuaternion = inverseQuaternion.invert()
|
||||
transformedPoint.applyQuaternion(inverseQuaternion)
|
||||
point2DRef.current.set(transformedPoint.x, transformedPoint.y)
|
||||
|
||||
if (
|
||||
lastPointerRef.current.x === 0 &&
|
||||
lastPointerRef.current.y === 0 &&
|
||||
@ -223,8 +258,13 @@ function MovingSphere({
|
||||
}}
|
||||
name="my-mesh"
|
||||
>
|
||||
<planeGeometry args={[50, 50]} />
|
||||
<meshStandardMaterial color="blue" transparent opacity={0.2} />
|
||||
<planeGeometry args={[50, 50]} ref={detectionPlaneRef} />
|
||||
<meshStandardMaterial
|
||||
side={DoubleSide}
|
||||
color="blue"
|
||||
transparent
|
||||
opacity={0}
|
||||
/>
|
||||
</mesh>
|
||||
)}
|
||||
</>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useStore } from '../useStore'
|
||||
import { DoubleSide } from 'three'
|
||||
import { DoubleSide, Vector3, Quaternion } from 'three'
|
||||
import { addLine, Program } from '../lang/abstractSyntaxTree'
|
||||
|
||||
export const SketchPlane = () => {
|
||||
@ -14,28 +14,27 @@ export const SketchPlane = () => {
|
||||
if (guiMode.mode !== 'sketch') {
|
||||
return null
|
||||
}
|
||||
if (guiMode.sketchMode !== 'points' && guiMode.sketchMode !== 'sketchEdit' ) {
|
||||
if (guiMode.sketchMode !== 'points' && guiMode.sketchMode !== 'sketchEdit') {
|
||||
return null
|
||||
}
|
||||
|
||||
const sketchGridName = 'sketchGrid'
|
||||
|
||||
const ninety = Math.PI / 2
|
||||
const gridRotation: [number, number, number] = [0, 0, 0]
|
||||
const clickDetectPlaneRotation: [number, number, number] = [0, 0, 0]
|
||||
if (guiMode.axis === 'xy') {
|
||||
gridRotation[0] = ninety
|
||||
} else if (guiMode.axis === 'xz') {
|
||||
clickDetectPlaneRotation[0] = ninety
|
||||
} else if (guiMode.axis === 'yz') {
|
||||
gridRotation[2] = ninety
|
||||
clickDetectPlaneRotation[1] = ninety
|
||||
}
|
||||
let clickDetectQuaternion = guiMode.quaternion.clone()
|
||||
|
||||
let temp = new Quaternion().setFromAxisAngle(
|
||||
new Vector3(1, 0, 0),
|
||||
Math.PI / 2
|
||||
)
|
||||
const gridQuaternion = new Quaternion().multiplyQuaternions(
|
||||
guiMode.quaternion,
|
||||
temp
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh
|
||||
rotation={clickDetectPlaneRotation}
|
||||
quaternion={clickDetectQuaternion}
|
||||
name={sketchGridName}
|
||||
onClick={(e) => {
|
||||
if (guiMode.sketchMode !== 'points') {
|
||||
@ -44,7 +43,12 @@ export const SketchPlane = () => {
|
||||
const sketchGridIntersection = e.intersections.find(
|
||||
({ object }) => object.name === sketchGridName
|
||||
)
|
||||
const point = roundy(sketchGridIntersection?.point)
|
||||
const inverseQuaternion = clickDetectQuaternion.clone().invert()
|
||||
let transformedPoint = sketchGridIntersection?.point.clone()
|
||||
if (transformedPoint)
|
||||
transformedPoint.applyQuaternion(inverseQuaternion)
|
||||
|
||||
const point = roundy(transformedPoint)
|
||||
let _ast: Program = ast
|
||||
? ast
|
||||
: {
|
||||
@ -53,12 +57,7 @@ export const SketchPlane = () => {
|
||||
end: 0,
|
||||
body: [],
|
||||
}
|
||||
let addLinePoint: [number, number] = [point.x, point.y]
|
||||
if (guiMode.axis === 'xz') {
|
||||
addLinePoint = [point.x, point.z]
|
||||
} else if (guiMode.axis === 'yz') {
|
||||
addLinePoint = [point.z, point.y]
|
||||
}
|
||||
const addLinePoint: [number, number] = [point.x, point.y]
|
||||
const { modifiedAst } = addLine(
|
||||
_ast,
|
||||
guiMode.pathToNode,
|
||||
@ -75,7 +74,10 @@ export const SketchPlane = () => {
|
||||
transparent
|
||||
/>
|
||||
</mesh>
|
||||
<gridHelper args={[30, 40, 'blue', 'hotpink']} rotation={gridRotation} />
|
||||
<gridHelper
|
||||
args={[30, 40, 'blue', 'hotpink']}
|
||||
quaternion={gridQuaternion}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1016,8 +1016,8 @@ export function addSketchTo(
|
||||
{
|
||||
type: 'Literal',
|
||||
...dumbyStartend,
|
||||
value: axis === 'yz' ? -90 : 90,
|
||||
raw: axis === 'yz' ? '-90' : '90',
|
||||
value: axis === 'yz' ? 90 : 90,
|
||||
raw: axis === 'yz' ? '90' : '90',
|
||||
},
|
||||
{
|
||||
type: 'PipeSubstitution',
|
||||
|
@ -3,6 +3,7 @@ import { addLineHighlight, EditorView } from './editor/highlightextension'
|
||||
import { Program, abstractSyntaxTree } from './lang/abstractSyntaxTree'
|
||||
import { recast } from './lang/recast'
|
||||
import { lexer } from './lang/tokeniser'
|
||||
import { Quaternion } from 'three'
|
||||
|
||||
export type Range = [number, number]
|
||||
|
||||
@ -17,6 +18,7 @@ type GuiModes =
|
||||
mode: 'sketch'
|
||||
sketchMode: 'points'
|
||||
axis: Plane
|
||||
quaternion: Quaternion
|
||||
id?: string
|
||||
pathToNode: PathToNode
|
||||
}
|
||||
@ -24,8 +26,9 @@ type GuiModes =
|
||||
mode: 'sketch'
|
||||
sketchMode: 'sketchEdit'
|
||||
axis: Plane
|
||||
quaternion: Quaternion
|
||||
pathToNode: PathToNode
|
||||
}
|
||||
}
|
||||
| {
|
||||
mode: 'sketch'
|
||||
sketchMode: 'selectFace'
|
||||
@ -34,7 +37,8 @@ type GuiModes =
|
||||
mode: 'canEditSketch'
|
||||
pathToNode: PathToNode
|
||||
axis: Plane
|
||||
}
|
||||
quaternion: Quaternion
|
||||
}
|
||||
|
||||
interface StoreState {
|
||||
editorView: EditorView | null
|
||||
@ -121,5 +125,5 @@ export const useStore = create<StoreState>()((set, get) => ({
|
||||
},
|
||||
setError: (error = '') => {
|
||||
set({ errorState: { isError: !!error, error } })
|
||||
}
|
||||
},
|
||||
}))
|
||||
|
Reference in New Issue
Block a user