From c827afb25f200e610984a51d8f57539bcc32b3f8 Mon Sep 17 00:00:00 2001 From: Chris Gerth Date: Sun, 9 Oct 2022 22:26:49 -0500 Subject: [PATCH] 3d viewer cleanup (#490) * WIP fiddling with 3js stuff for different viewpoints * more wip viewer cleanup * More cleanups - split out minimap --- .../src/components/pipeline/3D/MiniMap.vue | 89 ++++++++++++++++--- photon-client/src/views/PipelineView.vue | 25 ++++-- .../src/views/PipelineViews/Map3DTab.vue | 53 +++++++++++ .../src/views/PipelineViews/PnPTab.vue | 26 +----- .../src/main/resources/web/index.html | 2 +- 5 files changed, 148 insertions(+), 47 deletions(-) create mode 100644 photon-client/src/views/PipelineViews/Map3DTab.vue diff --git a/photon-client/src/components/pipeline/3D/MiniMap.vue b/photon-client/src/components/pipeline/3D/MiniMap.vue index 6f6126af9..57d5f14ea 100644 --- a/photon-client/src/components/pipeline/3D/MiniMap.vue +++ b/photon-client/src/components/pipeline/3D/MiniMap.vue @@ -22,6 +22,26 @@ style="width:100%;height:100%" /> + + + + First Person + + + + + Third Person + + + @@ -31,6 +51,7 @@ import { ArrowHelper, BoxGeometry, + ConeGeometry, Mesh, MeshNormalMaterial, PerspectiveCamera, @@ -78,29 +99,45 @@ export default { this.renderer = renderer; scene.background = new Color(0xa9a9a9) - + //Set up resize handlers this.onWindowResize(); window.addEventListener( 'resize', this.onWindowResize, false ); - scene.add(new ArrowHelper(new Vector3(1, 0, 0).normalize(), new Vector3(0, 0, 0), + //Add the reference frame cues + this.refFrameCues = [] + // coordinate system + this.refFrameCues.push(new ArrowHelper(new Vector3(1, 0, 0).normalize(), new Vector3(0, 0, 0), 1, // length 0xff0000, - 0.5, - 0.5, + 0.1, + 0.1, )) - scene.add(new ArrowHelper(new Vector3(0, 1, 0).normalize(), new Vector3(0, 0, 0), + this.refFrameCues.push(new ArrowHelper(new Vector3(0, 1, 0).normalize(), new Vector3(0, 0, 0), 1, // length 0x00ff00, - 0.5, - 0.5, + 0.1, + 0.1, )) - scene.add(new ArrowHelper(new Vector3(0, 0, 1).normalize(), new Vector3(0, 0, 0), + this.refFrameCues.push(new ArrowHelper(new Vector3(0, 0, 1).normalize(), new Vector3(0, 0, 0), 1, // length 0x0000ff, - 0.5, - 0.5, + 0.1, + 0.1, )) + //something that looks vaguely like a camera + const camSize = 0.2; + const camBodyGeometry = new BoxGeometry(camSize, camSize, camSize); + const camLensGeometry = new ConeGeometry(camSize*0.4, camSize*0.8, 30); + const camMaterial = new MeshNormalMaterial(); + const camBody = new Mesh(camBodyGeometry, camMaterial); + const camLens = new Mesh(camLensGeometry, camMaterial); + camBody.position.set(0,0,0); + camLens.rotateZ(Math.PI / 2); + camLens.position.set(camSize*0.8,0,0); + this.refFrameCues.push(camBody) + this.refFrameCues.push(camLens) + var controls = new TrackballControls( camera, renderer.domElement @@ -113,11 +150,11 @@ export default { controls.staticMoving = true; controls.dynamicDampingFactor = 0.3; controls.keys = [65, 83, 68]; + this.controls = controls; + this.scene.add(...this.refFrameCues) + this.resetCamFirstPerson(); - camera.position.set(-0.1,0,0); - camera.rotation.set(-90, 0, 90); - camera.up.set(0,0,1); controls.update(); function animate() { @@ -125,6 +162,13 @@ export default { controls.update(); renderer.render(scene, camera); + + //camera.updateMatrixWorld(); + //console.log("================") + //console.log(camera.position); + //console.log(camera.rotation); + //console.log(camera.up); + } this.drawTargets() @@ -185,6 +229,7 @@ export default { if(this.cubes.length > 0) this.scene.add(...this.cubes); }, + onWindowResize() { var container = document.getElementById("MapContainer") if(container){ @@ -195,6 +240,24 @@ export default { this.renderer.setSize( this.canvas.width, this.canvas.height ); } }, + resetCamThirdPerson(){ + //Sets camera to third person position + this.controls.reset(); + this.camera.position.set(-1.39,-1.09,1.17); + this.camera.up.set(0,0,1); + this.controls.target.set(4.0,0.0,0.0); + this.controls.update(); + this.scene.add(...this.refFrameCues) + }, + resetCamFirstPerson(){ + //Sets camera to first person position + this.controls.reset(); + this.camera.position.set(-0.1,0,0); + this.camera.up.set(0,0,1); + this.controls.target.set(0.0,0.0,0.0); + this.controls.update(); + this.scene.remove(...this.refFrameCues) + }, } diff --git a/photon-client/src/views/PipelineView.vue b/photon-client/src/views/PipelineView.vue index 911d9c6c1..30613b146 100644 --- a/photon-client/src/views/PipelineView.vue +++ b/photon-client/src/views/PipelineView.vue @@ -261,6 +261,7 @@ import ThresholdTab from './PipelineViews/ThresholdTab'; import ContoursTab from './PipelineViews/ContoursTab'; import OutputTab from './PipelineViews/OutputTab'; import TargetsTab from "./PipelineViews/TargetsTab"; +import Map3DTab from './PipelineViews/Map3DTab'; import PnPTab from './PipelineViews/PnPTab'; import AprilTagTab from './PipelineViews/AprilTagTab'; @@ -274,6 +275,7 @@ export default { ContoursTab, OutputTab, TargetsTab, + Map3DTab, PnPTab, AprilTagTab, }, @@ -319,12 +321,16 @@ export default { component: "OutputTab", }, targets: { - name: "Target Info", + name: "Targets", component: "TargetsTab", }, pnp: { - name: "3D", + name: "PnP", component: "PnPTab", + }, + map3d: { + name: "3D", + component: "Map3DTab", } }; @@ -341,18 +347,18 @@ export default { } else if (this.$vuetify.breakpoint.mdAndDown || !this.$store.state.compactMode) { // Two tab groups, one with "input, threshold, contours, output" and the other with "target info, 3D" ret[0] = [tabs.input, tabs.threshold, tabs.contours, tabs.apriltag, tabs.output]; - ret[1] = [tabs.targets, tabs.pnp]; + ret[1] = [tabs.targets, tabs.pnp, tabs.map3d]; } else if (this.$vuetify.breakpoint.lgAndDown) { // Three tab groups, one with "input", one with "threshold, contours, output", and the other with "target info, 3D" ret[0] = [tabs.input]; ret[1] = [tabs.threshold, tabs.contours, tabs.apriltag, tabs.output]; - ret[2] = [tabs.targets, tabs.pnp]; + ret[2] = [tabs.targets, tabs.pnp, tabs.map3d]; } else if (this.$vuetify.breakpoint.xl) { // Three tab groups, one with "input", one with "threshold, contours", and the other with "output, target info, 3D" ret[0] = [tabs.input]; ret[1] = [tabs.threshold]; ret[2] = [tabs.contours, tabs.apriltag, tabs.output]; - ret[3] = [tabs.targets, tabs.pnp]; + ret[3] = [tabs.targets, tabs.pnp, tabs.map3d]; } for(let i = 0; i < ret.length; i++) { @@ -360,10 +366,11 @@ export default { // All the tabs we allow const filteredGroup = group.filter(it => - !(!allow3d && it.name === "3D") - && !(isAprilTag && (it.name === "Threshold")) - && !(isAprilTag && (it.name === "Contours")) - && !(!isAprilTag && it.name === "AprilTag") + !(!allow3d && it.name === "3D") //Filter out 3D tab any time 3D isn't calibrated + && !((!allow3d || isAprilTag) && it.name === "PnP") //Filter out the PnP config tab if 3D isn't available, or we're doing Apriltags + && !(isAprilTag && (it.name === "Threshold")) //Filter out threshold tab if we're doing apriltags + && !(isAprilTag && (it.name === "Contours")) //Filter out contours if we're doing Apriltag + && !(!isAprilTag && it.name === "AprilTag") //Filter out apriltag unless we actually are doing Apriltags ); ret[i] = filteredGroup; } diff --git a/photon-client/src/views/PipelineViews/Map3DTab.vue b/photon-client/src/views/PipelineViews/Map3DTab.vue new file mode 100644 index 000000000..6b30bb403 --- /dev/null +++ b/photon-client/src/views/PipelineViews/Map3DTab.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/photon-client/src/views/PipelineViews/PnPTab.vue b/photon-client/src/views/PipelineViews/PnPTab.vue index f888e018c..74a660ef7 100644 --- a/photon-client/src/views/PipelineViews/PnPTab.vue +++ b/photon-client/src/views/PipelineViews/PnPTab.vue @@ -6,7 +6,6 @@ type="file" accept=".csv" style="display: none;" - @change="readFile" > @@ -32,11 +31,7 @@ @input="handlePipelineData('cornerDetectionAccuracyPercentage')" @rollback="e => rollback('cornerDetectionAccuracyPercentage', e)" /> - + import Papa from 'papaparse'; - import miniMap from '../../components/pipeline/3D/MiniMap'; import CVslider from '../../components/common/cv-slider' export default { name: "PnP", components: { - CVslider, - miniMap + CVslider }, data() { return { @@ -87,21 +80,6 @@ this.$store.commit("mutatePipeline", {"cornerDetectionAccuracyPercentage": val}); } }, - targets: { - get() { - return this.$store.getters.currentPipelineResults.targets; - } - }, - horizontalFOV: { - get() { - let index = this.$store.getters.currentPipelineSettings.cameraVideoModeIndex; - let FOV = this.$store.getters.currentCameraSettings.fov; - let resolution = this.$store.getters.videoFormatList[index]; - let diagonalView = FOV * (Math.PI / 180); - let diagonalAspect = Math.hypot(resolution.width, resolution.height); - return Math.atan(Math.tan(diagonalView / 2) * (resolution.width / diagonalAspect)) * 2 * (180 / Math.PI) - } - }, }, methods: { readFile(event) { diff --git a/photon-server/src/main/resources/web/index.html b/photon-server/src/main/resources/web/index.html index f008dfd12..e0cf11547 100644 --- a/photon-server/src/main/resources/web/index.html +++ b/photon-server/src/main/resources/web/index.html @@ -1 +1 @@ -

UI has not been copied!

\ No newline at end of file +PhotonVision
\ No newline at end of file