chenlei недель назад: 2
Сommit
d168d5aec4
52 измененных файлов с 530882 добавлено и 0 удалено
  1. 30 0
      .gitignore
  2. 3 0
      .vscode/extensions.json
  3. 3 0
      README.md
  4. 13 0
      index.html
  5. 8 0
      jsconfig.json
  6. 21 0
      package.json
  7. 1634 0
      pnpm-lock.yaml
  8. BIN
      public/whole/1-J10.jpg
  9. BIN
      public/whole/1-J11.jpg
  10. BIN
      public/whole/1-J12.jpg
  11. BIN
      public/whole/1-J4.jpg
  12. BIN
      public/whole/1-J5.jpg
  13. BIN
      public/whole/1-J6.jpg
  14. BIN
      public/whole/1-J7.jpg
  15. BIN
      public/whole/1-J8.jpg
  16. BIN
      public/whole/1-J9.jpg
  17. BIN
      public/whole/2-J10.jpg
  18. BIN
      public/whole/2-J11.jpg
  19. BIN
      public/whole/2-J12.jpg
  20. BIN
      public/whole/2-J13.jpg
  21. BIN
      public/whole/2-J14.jpg
  22. BIN
      public/whole/2-J15.jpg
  23. BIN
      public/whole/2-J16.jpg
  24. BIN
      public/whole/2-J17.jpg
  25. BIN
      public/whole/2-J18.jpg
  26. BIN
      public/whole/2-J19.jpg
  27. BIN
      public/whole/2-J2.jpg
  28. BIN
      public/whole/2-J20.jpg
  29. BIN
      public/whole/2-J21.jpg
  30. BIN
      public/whole/2-J22.jpg
  31. BIN
      public/whole/2-J23.jpg
  32. BIN
      public/whole/2-J24.jpg
  33. BIN
      public/whole/2-J24_2.jpg
  34. BIN
      public/whole/2-J25.jpg
  35. BIN
      public/whole/2-J26.jpg
  36. BIN
      public/whole/2-J27.jpg
  37. BIN
      public/whole/2-J28.jpg
  38. BIN
      public/whole/2-J29.jpg
  39. BIN
      public/whole/2-J30.jpg
  40. BIN
      public/whole/2-J31.jpg
  41. BIN
      public/whole/2-J6.jpg
  42. BIN
      public/whole/2-J7.jpg
  43. BIN
      public/whole/2-J8.jpg
  44. BIN
      public/whole/2-J9.jpg
  45. 571 0
      public/whole/whole.mtl
  46. 528201 0
      public/whole/whole.obj
  47. 368 0
      src/App.vue
  48. BIN
      src/assets/images/back.png
  49. BIN
      src/assets/images/logo.png
  50. 5 0
      src/main.js
  51. 3 0
      src/style.css
  52. 22 0
      vite.config.js

+ 30 - 0
.gitignore

@@ -0,0 +1,30 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.DS_Store
+dist
+dist-ssr
+coverage
+*.local
+
+/cypress/videos/
+/cypress/screenshots/
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+*.tsbuildinfo

+ 3 - 0
.vscode/extensions.json

@@ -0,0 +1,3 @@
+{
+  "recommendations": ["Vue.volar"]
+}

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# 武汉公安碎尸案模型
+
+node >= 24.x

+ 13 - 0
index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="UTF-8">
+    <link rel="icon" href="/favicon.ico">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>武汉碎尸案建模</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>

+ 8 - 0
jsconfig.json

@@ -0,0 +1,8 @@
+{
+  "compilerOptions": {
+    "paths": {
+      "@/*": ["./src/*"]
+    }
+  },
+  "exclude": ["node_modules", "dist"]
+}

+ 21 - 0
package.json

@@ -0,0 +1,21 @@
+{
+  "name": "wh-ga-cold-case-model",
+  "version": "0.0.0",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "gsap": "^3.13.0",
+    "three": "^0.178.0",
+    "vue": "^3.5.17"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^6.0.0",
+    "vite": "^7.0.0",
+    "vite-plugin-vue-devtools": "^7.7.7"
+  }
+}

Разница между файлами не показана из-за своего большого размера
+ 1634 - 0
pnpm-lock.yaml


BIN
public/whole/1-J10.jpg


BIN
public/whole/1-J11.jpg


BIN
public/whole/1-J12.jpg


BIN
public/whole/1-J4.jpg


BIN
public/whole/1-J5.jpg


BIN
public/whole/1-J6.jpg


BIN
public/whole/1-J7.jpg


BIN
public/whole/1-J8.jpg


BIN
public/whole/1-J9.jpg


BIN
public/whole/2-J10.jpg


BIN
public/whole/2-J11.jpg


BIN
public/whole/2-J12.jpg


BIN
public/whole/2-J13.jpg


BIN
public/whole/2-J14.jpg


BIN
public/whole/2-J15.jpg


BIN
public/whole/2-J16.jpg


BIN
public/whole/2-J17.jpg


BIN
public/whole/2-J18.jpg


BIN
public/whole/2-J19.jpg


BIN
public/whole/2-J2.jpg


BIN
public/whole/2-J20.jpg


BIN
public/whole/2-J21.jpg


BIN
public/whole/2-J22.jpg


BIN
public/whole/2-J23.jpg


BIN
public/whole/2-J24.jpg


BIN
public/whole/2-J24_2.jpg


BIN
public/whole/2-J25.jpg


BIN
public/whole/2-J26.jpg


BIN
public/whole/2-J27.jpg


BIN
public/whole/2-J28.jpg


BIN
public/whole/2-J29.jpg


BIN
public/whole/2-J30.jpg


BIN
public/whole/2-J31.jpg


BIN
public/whole/2-J6.jpg


BIN
public/whole/2-J7.jpg


BIN
public/whole/2-J8.jpg


BIN
public/whole/2-J9.jpg


+ 571 - 0
public/whole/whole.mtl

@@ -0,0 +1,571 @@
+# 3ds Max Wavefront OBJ Exporter v0.99 - (c)2007 guruware
+# ´´½¨µÄÎļþ:04.08.2025 20:05:12
+
+newmtl 1_J10
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5200
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J10.jpg
+
+newmtl 1_J11
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J11.jpg
+
+newmtl 1_J12
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J12.jpg
+
+newmtl 1_J4
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J4.jpg
+
+newmtl 1_J5
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J5.jpg
+
+newmtl 1_J6
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J6.jpg
+
+newmtl 1_J7
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J7.jpg
+
+newmtl 1_J8
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J8.jpg
+
+newmtl 1_J9
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 1-J9.jpg
+
+newmtl 2_J10
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J10.jpg
+
+newmtl 2_J11
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J11.jpg
+
+newmtl 2_J12
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J12.jpg
+
+newmtl 2_J13
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J13.jpg
+
+newmtl 2_J14
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J14.jpg
+
+newmtl 2_J15
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J15.jpg
+
+newmtl 2_J16
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J16.jpg
+
+newmtl 2_J17
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J17.jpg
+
+newmtl 2_J18
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J18.jpg
+
+newmtl 2_J19
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J19.jpg
+
+newmtl 2_J20
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J20.jpg
+
+newmtl 2_J21
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J21.jpg
+
+newmtl 2_J22
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J22.jpg
+
+newmtl 2_J23
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J23.jpg
+
+newmtl 2_J24
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J24.jpg
+
+newmtl 2_J24_2
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J24_2.jpg
+
+newmtl 2_J25
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J25.jpg
+
+newmtl 2_J26
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J26.jpg
+
+newmtl 2_J27
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J27.jpg
+
+newmtl 2_J28
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J28.jpg
+
+newmtl 2_J29
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J29.jpg
+
+newmtl 2_J2
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J2.jpg
+
+newmtl 2_J30
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J30.jpg
+
+newmtl 2_J31
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J31.jpg
+
+newmtl 2_J6
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J6.jpg
+
+newmtl 2_J7
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J7.jpg
+
+newmtl 2_J8
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J8.jpg
+
+newmtl 2_J9
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2
+	map_Kd 2-J9.jpg
+
+newmtl defaultMat
+	Kd 0.5000 0.5000 0.5000
+	Ks 1.0000 1.0000 1.0000
+	Tr 0.0000
+	d 1.0000
+	Tf 1.0000 1.0000 1.0000
+	Pr 0.0000
+	Pm 0.0000
+	Pc 0.0000
+	Pcr 0.0000
+	Ni 1.5000
+	Ke 0.0000 0.0000 0.0000
+	illum 2

Разница между файлами не показана из-за своего большого размера
+ 528201 - 0
public/whole/whole.obj


+ 368 - 0
src/App.vue

@@ -0,0 +1,368 @@
+<script setup>
+import * as THREE from "three";
+import { ref, onMounted } from "vue";
+import { gsap } from "gsap";
+import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
+import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
+import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
+
+let scene,
+  camera,
+  controls,
+  renderer,
+  raycaster,
+  mouse = null;
+let isDragging = false;
+let isInertiaMoving = false;
+let inertiaEndFrames = 0;
+let lastPosition = new THREE.Vector3();
+let lastQuaternion = new THREE.Quaternion();
+let originalPositions = new Map();
+const zoomedIn = ref(false);
+const INERTIA_END_THRESHOLD = 1;
+const canvasContainer = ref(null);
+const selectedObject = ref(null);
+const loadingProgress = ref(0);
+
+const initThree = () => {
+  // 创建场景
+  scene = new THREE.Scene();
+
+  // 创建相机
+  camera = new THREE.PerspectiveCamera(
+    75,
+    window.innerWidth / window.innerHeight,
+    0.1,
+    1000
+  );
+  camera.position.z = 140;
+
+  // 创建渲染器
+  renderer = new THREE.WebGLRenderer({ antialias: true });
+  renderer.setSize(window.innerWidth, window.innerHeight);
+  renderer.setClearColor(0xececec);
+  canvasContainer.value.appendChild(renderer.domElement);
+
+  // 添加光源
+  const ambientLight = new THREE.AmbientLight(0xffffff, 5);
+  scene.add(ambientLight);
+
+  const highlightDirectionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
+  scene.add(highlightDirectionalLight);
+
+  raycaster = new THREE.Raycaster();
+  mouse = new THREE.Vector2();
+
+  // 监听窗口大小变化
+  window.addEventListener("resize", () => {
+    camera.aspect = window.innerWidth / window.innerHeight;
+    camera.updateProjectionMatrix();
+    renderer.setSize(window.innerWidth, window.innerHeight);
+  });
+};
+
+const render = () => {
+  renderer.render(scene, camera);
+};
+
+const animate = () => {
+  requestAnimationFrame(animate);
+  if (!document.hidden) {
+    controls.update();
+    renderer.render(scene, camera);
+  }
+};
+
+const checkInertia = () => {
+  const positionChanged = camera.position.distanceTo(lastPosition) > 0.001;
+  const rotationChanged = camera.quaternion.angleTo(lastQuaternion) > 0.001;
+
+  if (positionChanged || rotationChanged) {
+    isInertiaMoving = true;
+    inertiaEndFrames = 0; // 重置计数器
+  } else if (isInertiaMoving) {
+    inertiaEndFrames++;
+    if (inertiaEndFrames >= INERTIA_END_THRESHOLD) {
+      isInertiaMoving = false;
+    }
+  }
+
+  lastPosition.copy(camera.position);
+  lastQuaternion.copy(camera.quaternion);
+  requestAnimationFrame(checkInertia);
+};
+
+const initControls = () => {
+  controls = new OrbitControls(camera, renderer.domElement);
+  controls.addEventListener("change", render);
+  controls.enableDamping = true;
+  controls.dampingFactor = 0.05;
+  controls.minDistance = 5;
+  controls.maxDistance = 200;
+
+  controls.addEventListener("start", () => {
+    isDragging = true;
+  });
+  controls.addEventListener("end", () => {
+    isDragging = false;
+  });
+  checkInertia();
+};
+
+const initModel = () => {
+  // 加载模型
+  const loadingManager = new THREE.LoadingManager(
+    () => {
+      loadingProgress.value = 100;
+    },
+    (item, loaded, total) => {
+      loadingProgress.value = (loaded / total) * 100;
+    }
+  );
+  const mtlLoader = new MTLLoader(loadingManager);
+  const objLoader = new OBJLoader(loadingManager);
+
+  mtlLoader.load("whole/whole.mtl", (materials) => {
+    materials.preload();
+
+    objLoader.setMaterials(materials);
+
+    objLoader.load("whole/whole.obj", (obj) => {
+      // 加载纹理并应用到模型
+      obj.position.y = -80;
+
+      obj.traverse((child) => {
+        if (child instanceof THREE.Mesh && child.name !== "1") {
+          child.userData.isModelPart = true;
+        }
+      });
+
+      scene.add(obj);
+      renderer.domElement.addEventListener("mousemove", onMouseMove);
+      renderer.domElement.addEventListener("click", onMouseClick);
+
+      // 动画循环
+      animate();
+    });
+  });
+};
+
+const onMouseMove = (event) => {
+  if (isDragging || isInertiaMoving || zoomedIn.value) return;
+
+  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
+  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
+
+  raycaster.setFromCamera(mouse, camera);
+
+  const intersects = raycaster.intersectObjects(scene.children, true);
+
+  if (selectedObject.value) {
+    selectedObject.value.material.color.copy(
+      selectedObject.value.userData.originalColor
+    );
+    selectedObject.value = null;
+  }
+
+  if (intersects.length > 0) {
+    const firstIntersected = intersects[0].object;
+
+    if (
+      firstIntersected instanceof THREE.Mesh &&
+      firstIntersected.userData.isModelPart
+    ) {
+      selectedObject.value = firstIntersected;
+      selectedObject.value.userData.originalColor =
+        selectedObject.value.material.color.clone();
+      selectedObject.value.material.color.set(0x00ff00);
+    }
+  }
+};
+
+const onMouseClick = () => {
+  if (!selectedObject.value) return;
+
+  selectedObject.value.material.color.copy(
+    selectedObject.value.userData.originalColor
+  );
+  if (!zoomedIn.value) {
+    zoomToChild(selectedObject.value);
+  }
+};
+
+const restoreOriginalView = () => {
+  // 恢复所有子模型的可见性
+  scene.traverse((obj) => {
+    obj.visible = true;
+  });
+
+  gsap.to(camera.position, {
+    x: 0,
+    y: 0,
+    z: 140,
+    duration: 2,
+    ease: "power2.inOut",
+    onUpdate: () => {
+      controls.target.set(0, 0, 0);
+      controls.update();
+    },
+    onComplete: () => {
+      zoomedIn.value = false;
+    },
+  });
+};
+
+const storeOriginalStates = () => {
+  originalPositions.clear();
+  scene.traverse((obj) => {
+    if (obj.userData.isModelPart) {
+      originalPositions.set(obj, {
+        visible: obj.visible,
+      });
+    }
+  });
+};
+
+const hideOtherChildren = (target) => {
+  scene.traverse((obj) => {
+    if (obj.name && obj.name !== target.name) {
+      obj.visible = false;
+    }
+  });
+};
+
+const zoomToChild = (child) => {
+  storeOriginalStates();
+
+  hideOtherChildren(child);
+
+  const bbox = new THREE.Box3().setFromObject(child);
+  const center = bbox.getCenter(new THREE.Vector3());
+  const size = bbox.getSize(new THREE.Vector3());
+  const maxDim = Math.max(size.x, size.y, size.z);
+  const cameraDistance = maxDim * 1.5;
+
+  controls.target.copy(center);
+  controls.update();
+
+  gsap.to(camera.position, {
+    x: center.x,
+    y: center.y + cameraDistance * 0.1, // 稍微抬高视角
+    z: center.z + cameraDistance,
+    duration: 1,
+    ease: "power2.inOut",
+    onUpdate: () => {
+      controls.update();
+    },
+  });
+
+  zoomedIn.value = true;
+};
+
+onMounted(() => {
+  initThree();
+  initControls();
+  initModel();
+});
+</script>
+
+<template>
+  <div v-if="loadingProgress < 100" class="loading-wrap">
+    <div class="loading-container">
+      <div class="progress-bar" :style="{ width: loadingProgress + '%' }"></div>
+      <div class="progress-text">{{ loadingProgress.toFixed(0) }}%</div>
+    </div>
+  </div>
+  <div v-if="zoomedIn" class="icon-back" @click="restoreOriginalView" />
+
+  <div ref="canvasContainer" class="canvas" />
+
+  <div class="logo">
+    <div class="img"></div>
+    <div class="logotxt">提 供 技 术 支 持</div>
+  </div>
+</template>
+
+<style scoped>
+.canvas {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+}
+
+.icon-back {
+  position: absolute;
+  top: 20px;
+  left: 20px;
+  width: 40px;
+  height: 40px;
+  cursor: pointer;
+  background: url("@/assets/images/back.png") no-repeat center / contain;
+  z-index: 999;
+}
+
+.logo {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 9999;
+  width: 90vw;
+  position: absolute;
+  left: 50%;
+  transform: translateX(-50%);
+  bottom: 10px;
+  height: 50px;
+}
+.logo .img {
+  background: url("@/assets/images/logo.png");
+  background-size: 100% 100%;
+  max-width: 40vw;
+  max-height: 50px;
+  height: 40px;
+  width: 150px;
+}
+.logo .logotxt {
+  padding-bottom: 5px;
+  color: #666;
+  border-bottom: 1px solid #666;
+}
+
+.loading-wrap {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: #ececec;
+  z-index: 1000;
+}
+
+.loading-container {
+  position: absolute;
+  top: 50%;
+  left: 20%;
+  width: 60%;
+  height: 20px;
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 10px;
+  transform: translateY(-50%);
+}
+
+.progress-bar {
+  height: 100%;
+  background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
+  border-radius: 10px;
+  transition: width 0.3s ease;
+}
+
+.progress-text {
+  position: absolute;
+  top: -30px;
+  width: 100%;
+  text-align: center;
+  color: #333;
+  font-weight: bold;
+}
+</style>

BIN
src/assets/images/back.png


BIN
src/assets/images/logo.png


+ 5 - 0
src/main.js

@@ -0,0 +1,5 @@
+import { createApp } from 'vue'
+import './style.css'
+import App from './App.vue'
+
+createApp(App).mount('#app')

+ 3 - 0
src/style.css

@@ -0,0 +1,3 @@
+body {
+  margin: 0;
+}

+ 22 - 0
vite.config.js

@@ -0,0 +1,22 @@
+import { fileURLToPath, URL } from "node:url";
+
+import { defineConfig } from "vite";
+import vue from "@vitejs/plugin-vue";
+// import vueDevTools from 'vite-plugin-vue-devtools'
+
+// https://vite.dev/config/
+export default defineConfig({
+  base: "./",
+  plugins: [
+    vue(),
+    // vueDevTools(),
+  ],
+  resolve: {
+    alias: {
+      "@": fileURLToPath(new URL("./src", import.meta.url)),
+    },
+  },
+  server: {
+    host: "0.0.0.0",
+  },
+});