|
@@ -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) => {
|