respect camera target (#1421)

* respect camera target

* make default planes scale

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Kurt Hutten
2024-02-17 07:04:24 +11:00
committed by GitHub
parent 198feb7d44
commit 3747a1b993
9 changed files with 156 additions and 15 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

@ -26,7 +26,7 @@ function useShouldHideScene(): { hideClient: boolean; hideServer: boolean } {
if (DEBUG_SHOW_BOTH_SCENES || !isCamMoving) if (DEBUG_SHOW_BOTH_SCENES || !isCamMoving)
return { hideClient: false, hideServer: false } return { hideClient: false, hideServer: false }
let hideServer = state.matches('Sketch') || state.matches('Sketch no face') let hideServer = state.matches('Sketch')
if (isTween) { if (isTween) {
hideServer = false hideServer = false
} }

View File

@ -22,6 +22,7 @@ import {
DEFAULT_PLANES, DEFAULT_PLANES,
DefaultPlane, DefaultPlane,
defaultPlaneColor, defaultPlaneColor,
getSceneScale,
INTERSECTION_PLANE_LAYER, INTERSECTION_PLANE_LAYER,
isQuaternionVertical, isQuaternionVertical,
RAYCASTABLE_PLANE, RAYCASTABLE_PLANE,
@ -195,11 +196,18 @@ class SceneEntities {
this.axisGroup = new Group() this.axisGroup = new Group()
const gridHelper = createGridHelper({ size: 100, divisions: 10 }) const gridHelper = createGridHelper({ size: 100, divisions: 10 })
gridHelper.renderOrder = -3 // is this working? gridHelper.renderOrder = -3 // is this working?
gridHelper.name = 'gridHelper'
const sceneScale = getSceneScale(
sceneInfra.camera,
sceneInfra.controls.target
)
gridHelper.scale.set(sceneScale, sceneScale, sceneScale)
this.axisGroup.add(xAxisMesh, yAxisMesh, gridHelper) this.axisGroup.add(xAxisMesh, yAxisMesh, gridHelper)
this.currentSketchQuaternion && this.currentSketchQuaternion &&
this.axisGroup.setRotationFromQuaternion(this.currentSketchQuaternion) this.axisGroup.setRotationFromQuaternion(this.currentSketchQuaternion)
this.axisGroup.userData = { type: AXIS_GROUP } this.axisGroup.userData = { type: AXIS_GROUP }
this.axisGroup.name = AXIS_GROUP
this.axisGroup.layers.set(SKETCH_LAYER) this.axisGroup.layers.set(SKETCH_LAYER)
this.axisGroup.traverse((child) => { this.axisGroup.traverse((child) => {
child.layers.set(SKETCH_LAYER) child.layers.set(SKETCH_LAYER)

View File

@ -66,6 +66,7 @@ interface ThreeCamValues {
quaternion: Quaternion quaternion: Quaternion
zoom: number zoom: number
isPerspective: boolean isPerspective: boolean
target: Vector3
} }
const lastCmdDelay = 50 const lastCmdDelay = 50
@ -123,6 +124,7 @@ const throttledUpdateEngineFov = throttle(
quaternion: Quaternion quaternion: Quaternion
zoom: number zoom: number
fov: number fov: number
target: Vector3
}) => { }) => {
const cmd: EngineCommand = { const cmd: EngineCommand = {
type: 'modeling_cmd_req', type: 'modeling_cmd_req',
@ -402,12 +404,20 @@ class SceneInfra {
}, 200) }, 200)
onCameraChange = () => { onCameraChange = () => {
this.camera.position.distanceTo(this.controls.target) const scale = getSceneScale(this.camera, this.controls.target)
const planesGroup = this.scene.getObjectByName(DEFAULT_PLANES)
const axisGroup = this.scene
.getObjectByName(AXIS_GROUP)
?.getObjectByName('gridHelper')
planesGroup && planesGroup.scale.set(scale, scale, scale)
axisGroup?.name === 'gridHelper' && axisGroup.scale.set(scale, scale, scale)
throttledUpdateEngineCamera({ throttledUpdateEngineCamera({
quaternion: this.camera.quaternion, quaternion: this.camera.quaternion,
position: this.camera.position, position: this.camera.position,
zoom: this.camera.zoom, zoom: this.camera.zoom,
isPerspective: this.isPerspective, isPerspective: this.isPerspective,
target: this.controls.target,
}) })
this.deferReactUpdate({ this.deferReactUpdate({
type: type:
@ -733,6 +743,7 @@ class SceneInfra {
position: newPosition, position: newPosition,
quaternion: this.camera.quaternion, quaternion: this.camera.quaternion,
zoom: this.camera.zoom, zoom: this.camera.zoom,
target: this.controls.target,
}) })
} }
getPlaneIntersectPoint = (): { getPlaneIntersectPoint = (): {
@ -958,21 +969,14 @@ class SceneInfra {
type: DefaultPlane type: DefaultPlane
): Mesh => { ): Mesh => {
const planeGeometry = new PlaneGeometry(100, 100) const planeGeometry = new PlaneGeometry(100, 100)
const planeEdges = new EdgesGeometry(planeGeometry)
const lineMaterial = new LineBasicMaterial({
color: defaultPlaneColor(type, 0.45, 1),
opacity: 0.9,
})
const planeMaterial = new MeshBasicMaterial({ const planeMaterial = new MeshBasicMaterial({
color: defaultPlaneColor(type), color: defaultPlaneColor(type),
transparent: true, transparent: true,
opacity: 0.35, opacity: 0.0,
side: DoubleSide, side: DoubleSide,
depthTest: false, // needed to avoid transparency issues depthTest: false, // needed to avoid transparency issues
}) })
const plane = new Mesh(planeGeometry, planeMaterial) const plane = new Mesh(planeGeometry, planeMaterial)
const edges = new LineSegments(planeEdges, lineMaterial)
plane.add(edges)
plane.rotation.x = rotation.x plane.rotation.x = rotation.x
plane.rotation.y = rotation.y plane.rotation.y = rotation.y
plane.rotation.z = rotation.z plane.rotation.z = rotation.z
@ -980,15 +984,14 @@ class SceneInfra {
plane.name = type plane.name = type
return plane return plane
} }
const gridHelper = createGridHelper({ size: 100, divisions: 10 })
const planes = [ const planes = [
addPlane({ x: 0, y: Math.PI / 2, z: 0 }, YZ_PLANE), addPlane({ x: 0, y: Math.PI / 2, z: 0 }, YZ_PLANE),
addPlane({ x: 0, y: 0, z: 0 }, XY_PLANE), addPlane({ x: 0, y: 0, z: 0 }, XY_PLANE),
addPlane({ x: -Math.PI / 2, y: 0, z: 0 }, XZ_PLANE), addPlane({ x: -Math.PI / 2, y: 0, z: 0 }, XZ_PLANE),
gridHelper,
] ]
const planesGroup = new Group() const planesGroup = new Group()
planesGroup.userData.type = DEFAULT_PLANES planesGroup.userData.type = DEFAULT_PLANES
planesGroup.name = DEFAULT_PLANES
planesGroup.add(...planes) planesGroup.add(...planes)
planesGroup.traverse((child) => { planesGroup.traverse((child) => {
if (child instanceof Mesh) { if (child instanceof Mesh) {
@ -996,6 +999,8 @@ class SceneInfra {
} }
}) })
planesGroup.layers.enable(SKETCH_LAYER) planesGroup.layers.enable(SKETCH_LAYER)
const sceneScale = getSceneScale(this.camera, this.controls.target)
planesGroup.scale.set(sceneScale, sceneScale, sceneScale)
this.scene.add(planesGroup) this.scene.add(planesGroup)
} }
removeDefaultPlanes() { removeDefaultPlanes() {
@ -1030,6 +1035,7 @@ class SceneInfra {
export const sceneInfra = new SceneInfra() export const sceneInfra = new SceneInfra()
function convertThreeCamValuesToEngineCam({ function convertThreeCamValuesToEngineCam({
target,
position, position,
quaternion, quaternion,
zoom, zoom,
@ -1052,7 +1058,7 @@ function convertThreeCamValuesToEngineCam({
const upVector = new Vector3(0, 1, 0).applyEuler(euler).normalize() const upVector = new Vector3(0, 1, 0).applyEuler(euler).normalize()
if (isPerspective) { if (isPerspective) {
return { return {
center: lookAtVector, center: target,
up: upVector, up: upVector,
vantage: position, vantage: position,
} }

View File

@ -391,6 +391,26 @@ class KclManager {
} }
return returnVal return returnVal
} }
get defaultPlanes() {
return this?.engineCommandManager?.defaultPlanes
}
getPlaneId(axis: 'xy' | 'xz' | 'yz'): string {
return this.defaultPlanes[axis]
}
showPlanes() {
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, false)
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, false)
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xz, false)
}
hidePlanes() {
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, true)
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, true)
void this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xz, true)
}
} }
export const kclManager = new KclManager(engineCommandManager) export const kclManager = new KclManager(engineCommandManager)

View File

@ -920,6 +920,11 @@ export class EngineCommandManager {
outSequence = 1 outSequence = 1
inSequence = 1 inSequence = 1
engineConnection?: EngineConnection engineConnection?: EngineConnection
defaultPlanes: { xy: string; yz: string; xz: string } = {
xy: '',
yz: '',
xz: '',
}
_commandLogs: CommandLog[] = [] _commandLogs: CommandLog[] = []
_commandLogCallBack: (command: CommandLog[]) => void = () => {} _commandLogCallBack: (command: CommandLog[]) => void = () => {}
// Folks should realize that wait for ready does not get called _everytime_ // Folks should realize that wait for ready does not get called _everytime_
@ -1014,7 +1019,9 @@ export class EngineCommandManager {
}) })
sceneInfra.onStreamStart() sceneInfra.onStreamStart()
executeCode(undefined, true) this.initPlanes().then(() => {
executeCode(undefined, true)
})
}, },
onClose: () => { onClose: () => {
setIsStreamReady(false) setIsStreamReady(false)
@ -1564,6 +1571,102 @@ export class EngineCommandManager {
artifactMap: this.artifactMap, artifactMap: this.artifactMap,
} }
} }
private async initPlanes() {
const [xy, yz, xz] = [
await this.createPlane({
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
color: { r: 0.7, g: 0.28, b: 0.28, a: 0.4 },
}),
await this.createPlane({
x_axis: { x: 0, y: 1, z: 0 },
y_axis: { x: 0, y: 0, z: 1 },
color: { r: 0.28, g: 0.7, b: 0.28, a: 0.4 },
}),
await this.createPlane({
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 0, z: 1 },
color: { r: 0.28, g: 0.28, b: 0.7, a: 0.4 },
}),
]
this.defaultPlanes = { xy, yz, xz }
this.subscribeTo({
event: 'select_with_point',
callback: ({ data }) => {
if (!data?.entity_id) return
if (
![
this.defaultPlanes.xy,
this.defaultPlanes.yz,
this.defaultPlanes.xz,
].includes(data.entity_id)
)
return
this.onPlaneSelectCallback(data.entity_id)
},
})
}
planesInitialized(): boolean {
return (
this.defaultPlanes.xy !== '' &&
this.defaultPlanes.yz !== '' &&
this.defaultPlanes.xz !== ''
)
}
onPlaneSelectCallback = (id: string) => {}
onPlaneSelected(callback: (id: string) => void) {
this.onPlaneSelectCallback = callback
}
async setPlaneHidden(id: string, hidden: boolean): Promise<string> {
return await this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'object_visible',
object_id: id,
hidden: hidden,
},
})
}
private async createPlane({
x_axis,
y_axis,
color,
}: {
x_axis: Models['Point3d_type']
y_axis: Models['Point3d_type']
color: Models['Color_type']
}): Promise<string> {
const planeId = uuidv4()
await this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'make_plane',
size: 100,
origin: { x: 0, y: 0, z: 0 },
x_axis,
y_axis,
clobber: false,
hide: true,
},
cmd_id: planeId,
})
await this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'plane_set_color',
plane_id: planeId,
color,
},
cmd_id: uuidv4(),
})
await this.setPlaneHidden(planeId, true)
return planeId
}
} }
export const engineCommandManager = new EngineCommandManager() export const engineCommandManager = new EngineCommandManager()

View File

@ -605,7 +605,10 @@ export const modelingMachine = createMachine(
if (!sketchPathToNode) return {} if (!sketchPathToNode) return {}
return getSketchMetadataFromPathToNode(sketchPathToNode) return getSketchMetadataFromPathToNode(sketchPathToNode)
}), }),
'hide default planes': () => sceneInfra.removeDefaultPlanes(), 'hide default planes': () => {
sceneInfra.removeDefaultPlanes()
kclManager.hidePlanes()
},
'reset sketch metadata': assign({ 'reset sketch metadata': assign({
sketchPathToNode: null, sketchPathToNode: null,
sketchEnginePathId: '', sketchEnginePathId: '',
@ -783,6 +786,7 @@ export const modelingMachine = createMachine(
'show default planes': () => { 'show default planes': () => {
sceneInfra.showDefaultPlanes() sceneInfra.showDefaultPlanes()
sceneEntitiesManager.setupDefaultPlaneHover() sceneEntitiesManager.setupDefaultPlaneHover()
kclManager.showPlanes()
}, },
'setup noPoints onClick listener': ({ sketchPathToNode }) => { 'setup noPoints onClick listener': ({ sketchPathToNode }) => {
sceneEntitiesManager.createIntersectionPlane() sceneEntitiesManager.createIntersectionPlane()