add support for orthographic camera!

This commit is contained in:
Yeicor
2024-02-10 19:56:47 +01:00
parent e9b24fd333
commit 3804ae5376
3 changed files with 39 additions and 5 deletions

View File

@@ -63,10 +63,8 @@ let modelViewerInfo: Ref<typeof ModelViewerInfo | null> = ref(null);
<!--suppress CssUnusedSymbol --> <!--suppress CssUnusedSymbol -->
<style> <style>
html, body, #main { html, body {
height: 100%; height: 100%;
margin: 0;
padding: 0;
overflow: hidden; overflow: hidden;
} }
</style> </style>

View File

@@ -40,6 +40,10 @@ function createGizmo(expectedParent: HTMLElement, scene: ModelScene): HTMLElemen
//console.log("New camera position", newLookFrom) //console.log("New camera position", newLookFrom)
scene.getCamera().position.copy(newLookFrom); scene.getCamera().position.copy(newLookFrom);
scene.getCamera().lookAt(lookAt); scene.getCamera().lookAt(lookAt);
if ((scene as any).__perspectiveCamera) { // HACK: Make the hacky ortho also work
(scene as any).__perspectiveCamera.position.copy(newLookFrom);
(scene as any).__perspectiveCamera.lookAt(lookAt);
}
scene.queueRender(); scene.queueRender();
} }
return gizmo; return gizmo;

View File

@@ -1,21 +1,53 @@
<script setup lang="ts"> <script setup lang="ts">
import {VBtn, VIcon} from "vuetify/lib/components"; import {VBtn, VIcon} from "vuetify/lib/components";
import {ref} from "vue";
import OrientationGizmo from "./OrientationGizmo.vue"; import OrientationGizmo from "./OrientationGizmo.vue";
import type {ModelScene} from "@google/model-viewer/lib/three-components/ModelScene";
import {OrthographicCamera} from "three";
const props = defineProps({ const props = defineProps({
modelViewerInfo: Object modelViewerInfo: Object
}); });
function syncOrthoCamera(force: boolean) {
if (!props.modelViewerInfo) return;
let scene: ModelScene = props.modelViewerInfo.scene
let perspectiveCam = (scene as any).__perspectiveCamera;
if (force || perspectiveCam && scene.camera != perspectiveCam) {
// Get zoom level from perspective camera
let dist = scene.getTarget().distanceToSquared(perspectiveCam.position);
let w = scene.aspect * dist ** 1.1 / 4000;
let h = dist ** 1.1 / 4000;
(scene as any).camera = new OrthographicCamera(-w, w, h, -h, perspectiveCam.near, perspectiveCam.far);
scene.camera.position.copy(perspectiveCam.position);
scene.camera.lookAt(scene.getTarget().clone().add(scene.target.position));
requestAnimationFrame(() => syncOrthoCamera(false));
}
}
let toggleProjectionText = ref('PERSP'); // Default to perspective camera
function toggleProjection() { function toggleProjection() {
if (!props.modelViewerInfo) return; if (!props.modelViewerInfo) return;
console.log('Toggling projection', props.modelViewerInfo); let scene: ModelScene = props.modelViewerInfo.scene
let prevCam = scene.camera;
let wasPerspectiveCamera = prevCam.isPerspectiveCamera;
if (wasPerspectiveCamera) {
(scene as any).__perspectiveCamera = prevCam; // Save the default perspective camera
// This hack also needs to sync the camera position and target
requestAnimationFrame(() => syncOrthoCamera(true));
} else {
// Restore the default perspective camera
scene.camera = (scene as any).__perspectiveCamera;
}
toggleProjectionText.value = wasPerspectiveCamera ? 'ORTHO' : 'PERSP';
} }
</script> </script>
<template> <template>
<orientation-gizmo v-if="props.modelViewerInfo" :scene="props.modelViewerInfo.scene"/> <orientation-gizmo v-if="props.modelViewerInfo" :scene="props.modelViewerInfo.scene"/>
<v-btn icon="mdi-projector" @click="toggleProjection"><span class="icon-detail">PERSP</span> <v-btn icon="mdi-projector" @click="toggleProjection"><span class="icon-detail">{{ toggleProjectionText }}</span>
<v-icon icon="mdi-projector"></v-icon> <v-icon icon="mdi-projector"></v-icon>
</v-btn> </v-btn>
</template> </template>