Browse Source

3D模型添加颜色和材质纹理光照

dsy 2 days ago
parent
commit
df0b46b70f

+ 91 - 2
src/views/book/courseware/preview/components/3d_model/3DModelPreview.vue

@@ -20,6 +20,7 @@ import * as THREE from 'three';
 import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
 import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
 import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
+import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js';
 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
 
 import { get3DModelData } from '@/views/book/courseware/data/3dModel';
@@ -88,17 +89,28 @@ export default {
       this.renderer.setSize(width, height);
       this.renderer.shadowMap.enabled = true;
       this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
+
+      // 启用颜色管理和正确的色彩空间
+      this.renderer.outputColorSpace = THREE.SRGBColorSpace;
+      this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
+      this.renderer.toneMappingExposure = 1.0;
+
       container.appendChild(this.renderer.domElement);
 
       // 添加光源
-      const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
+      const ambientLight = new THREE.AmbientLight(0x404040, 1.0); // 增加环境光强度
       this.scene.add(ambientLight);
 
-      const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
+      const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0); // 增加方向光强度
       directionalLight.position.set(10, 10, 5);
       directionalLight.castShadow = true;
       this.scene.add(directionalLight);
 
+      // 添加额外的填充光
+      const fillLight = new THREE.DirectionalLight(0xffffff, 0.5);
+      fillLight.position.set(-10, -10, -5);
+      this.scene.add(fillLight);
+
       // 添加控制器
       this.controls = new OrbitControls(this.camera, this.renderer.domElement);
       this.controls.enableDamping = true;
@@ -150,6 +162,25 @@ export default {
         url,
         (gltf) => {
           const model = gltf.scene;
+
+          // 确保所有材质正确处理
+          model.traverse((child) => {
+            if (child.isMesh) {
+              child.castShadow = true;
+              child.receiveShadow = true;
+
+              // 确保材质使用正确的色彩空间
+              if (child.material) {
+                if (child.material.map) {
+                  child.material.map.colorSpace = THREE.SRGBColorSpace;
+                }
+                if (child.material.emissiveMap) {
+                  child.material.emissiveMap.colorSpace = THREE.SRGBColorSpace;
+                }
+              }
+            }
+          });
+
           this.addModelToScene(model);
 
           // 如果模型有动画,播放第一个动画
@@ -175,6 +206,24 @@ export default {
       loader.load(
         url,
         (fbx) => {
+          // 确保FBX模型的材质正确处理
+          fbx.traverse((child) => {
+            if (child.isMesh) {
+              child.castShadow = true;
+              child.receiveShadow = true;
+
+              // 如果没有材质或材质有问题,创建默认材质
+              if (!child.material) {
+                child.material = new THREE.MeshPhongMaterial({
+                  color: 0x888888,
+                  shininess: 30,
+                });
+              } else if (child.material.map) {
+                child.material.map.colorSpace = THREE.SRGBColorSpace;
+              }
+            }
+          });
+
           this.addModelToScene(fbx);
         },
         (progress) => {
@@ -190,9 +239,49 @@ export default {
     },
 
     loadOBJ(loader, url) {
+      // 首先尝试加载MTL材质文件
+      const mtlUrl = url.replace(/\.obj$/i, '.mtl');
+      const mtlLoader = new MTLLoader();
+
+      // 设置材质加载路径
+      const basePath = url.substring(0, url.lastIndexOf('/') + 1);
+      mtlLoader.setPath(basePath);
+
+      mtlLoader.load(
+        mtlUrl,
+        (materials) => {
+          // 材质文件加载成功
+          materials.preload();
+          loader.setMaterials(materials);
+          this.loadOBJModel(loader, url);
+        },
+        undefined,
+        (error) => {
+          // 材质文件加载失败,使用默认材质
+          console.warn('MTL材质文件加载失败,使用默认材质:', error);
+          this.loadOBJModel(loader, url);
+        },
+      );
+    },
+
+    loadOBJModel(loader, url) {
       loader.load(
         url,
         (obj) => {
+          // 如果没有材质,为模型添加默认材质
+          obj.traverse((child) => {
+            if (child.isMesh) {
+              if (!child.material || !child.material.map) {
+                // 创建一个基本的彩色材质
+                child.material = new THREE.MeshPhongMaterial({
+                  color: 0x888888,
+                  shininess: 30,
+                });
+              }
+              child.castShadow = true;
+              child.receiveShadow = true;
+            }
+          });
           this.addModelToScene(obj);
         },
         (progress) => {

+ 0 - 0
src/views/book/courseware/preview/components/3d_model/3DModelPreview_fixed.vue


+ 2 - 2
src/views/personal_workbench/project/ProductionEditorialManage.vue

@@ -56,14 +56,14 @@
           </div>
           <div
             class="producer nowrap-ellipsis"
-            :style="{ color: isEnable(is_inherited_producer) ? '#ff4757' : 'default' }"
+            :style="{ color: !isEnable(is_root) && isEnable(is_inherited_producer) ? '#ff4757' : 'default' }"
             :title="producer_list.map((producer) => producer.name).join(';')"
           >
             <span>{{ producer_list.map((producer) => producer.name).join(';') }}</span>
           </div>
           <div
             class="audit nowrap-ellipsis"
-            :style="{ color: isEnable(is_inherited_auditor) ? '#ff4757' : 'default' }"
+            :style="{ color: !isEnable(is_root) && isEnable(is_inherited_auditor) ? '#ff4757' : 'default' }"
             :title="auditor_desc"
           >
             {{ auditor_desc }}