Jelajahi Sumber

feat: 添加非附属图例对准

bill 1 bulan lalu
induk
melakukan
c3678d998a

+ 56 - 0
src/core/renderer-three/components/icon/index.vue

@@ -0,0 +1,56 @@
+<template></template>
+
+<script lang="ts" setup>
+import { useRender, useStageProps, useTree } from "../../hook/use-stage";
+import { fullMesh, getModel } from "../line-icon/resource";
+import { Group, MathUtils, Matrix4 } from "three";
+import { computed, ref, watch, watchEffect } from "vue";
+import { setMat } from "../../util";
+import { IconData } from "@/core/components/icon";
+import { Transform } from "konva/lib/Util";
+
+const props = defineProps<{ data: IconData }>();
+const render = useRender();
+
+const group = new Group();
+watch(
+  () => props.data.url,
+  async (type, _, onCleanup) => {
+    let typeModel = await getModel(type);
+    if (typeModel && type === props.data.url) {
+      typeModel = typeModel.clone();
+      group.add(typeModel);
+      render();
+      onCleanup(() => {
+        group.remove(typeModel!);
+        render();
+      });
+    }
+  },
+  { immediate: true }
+);
+
+const getScaleZ = () => 1;
+const mat = computed(() => {
+  const data = props.data;
+  const dec = new Transform(data.mat).decompose();
+  const mat = new Matrix4()
+    .makeTranslation(dec.x, 0, dec.y)
+    .multiply(new Matrix4().makeScale(dec.scaleX, 1, dec.scaleY))
+    .multiply(new Matrix4().makeScale(props.data.width, 100, props.data.height))
+    .multiply(new Matrix4().makeRotationY(MathUtils.degToRad(dec.rotation)))
+    .multiply(new Matrix4().makeTranslation(0, 0.5, 0));
+  return mat;
+});
+
+watch(
+  mat,
+  (mat) => {
+    setMat(group, mat);
+    render();
+  },
+  { immediate: true }
+);
+
+useTree().value = group;
+</script>

+ 3 - 1
src/core/renderer-three/components/index.ts

@@ -1,10 +1,12 @@
 import { ShapeType } from "@/core/components";
 import Line from './line/index.vue'
 import LineIcon from './line-icon/index.vue'
+import Icon from './icon/index.vue'
 
 export const components: {
   [key in ShapeType]?: (data: {data: any}) => void
 } = {}
 
 components.line = Line as any
-components.lineIcon = LineIcon as any
+components.lineIcon = LineIcon as any
+components.icon = Icon as any

+ 15 - 2
src/core/renderer-three/components/line-icon/resource.ts

@@ -14,13 +14,18 @@ const gltfLoader = new GLTFLoader().setPath("/static/models/");
 const objLoader = new OBJLoader().setPath("/static/models/");
 const mtlLoader = new MTLLoader().setPath("/static/models/");
 
-const normalized = async (model: Object3D) => {
+const normalized = async (model: Object3D, pub = true) => {
   const parent = new Object3D();
   parent.add(model);
 
   const bbox = new Box3().setFromObject(parent);
   const size = bbox.getSize(new Vector3());
-  parent.scale.set(1 / size.x, 1 / size.y, 1 / size.z);
+  if (pub) {
+    parent.scale.set(1 / size.x, 1 / size.y, 1 / size.z);
+  } else {
+    const min = Math.max(size.x, size.y, size.z)
+    parent.scale.set(1 / min, 1 / min, 1 / min);
+  }
   model.traverse((child: any) => {
     if (child.isMesh) {
       child.receiveShadow = true;
@@ -33,6 +38,7 @@ const normalized = async (model: Object3D) => {
 
   return parent;
 };
+
 const resources: Record<string, () => Promise<Object3D>> = {
   "men_l.svg": async () => {
     const gltf = await gltfLoader.loadAsync("door_with_frame/scene.gltf");
@@ -85,6 +91,13 @@ const resources: Record<string, () => Promise<Object3D>> = {
     });
     return await normalized(gltf.scene);
   },
+  "DoubleBed.svg": async () => {
+    const gltf = await gltfLoader.loadAsync(
+      "bed/scene.gltf"
+    );
+    return await normalized(gltf.scene);
+
+  }
 };
 
 export const getModel = (() => {