// 全局变量 let scene, camera, renderer, controls; let water, sun, sky; let windTurbineModels = []; // 改为数组存储多个风电机组 let clock = new THREE.Clock(); // 在全局变量部分添加 let pointerLockControls; let moveForward = false; let moveBackward = false; let moveLeft = false; let moveRight = false; let moveUp = false; let moveDown = false; let velocity = new THREE.Vector3(); let direction = new THREE.Vector3(); let prevTime = performance.now(); // 初始化Three.js场景 function init() { console.log('开始初始化Three.js场景'); // 创建场景 scene = new THREE.Scene(); //scene.fog = new THREE.Fog(0x006994, 1, 1000); console.log('场景创建完成'); //天空盒 scene.background = new THREE.CubeTextureLoader() .setPath('./assets/sky/') .load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']); //环境光 const ambientLight = new THREE.AmbientLight(0x666666, 20); // 柔和的白光 scene.add(ambientLight); // 创建相机 // 增大远裁剪面距离,确保远处的缩小模型也能显示 camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 5000); // 向右旋转270度的相机位置设置(根据你的代码) const cameraRotationAngle = THREE.MathUtils.degToRad(0); const cameraRadius = 800; // 相机距离原点的距离 const cameraHeight = 50; // 降低相机高度,使其更接近水面 // 计算旋转后的位置(修复变量名错误) const cameraX = cameraRadius * Math.sin(cameraRotationAngle); const cameraZ = cameraRadius * Math.cos(cameraRotationAngle); // 修复:使用cameraRotationAngle而不是cameraAngle camera.position.set(cameraX, cameraHeight, cameraZ); camera.lookAt(0, 0, 0); // 确保相机朝向场景中心 console.log('相机创建完成,位置:', camera.position.x, camera.position.y, camera.position.z); //创建渲染器 renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true,//设置对数深度缓冲区,优化深度冲突问题 preserveDrawingBuffer: true,//把canvas画布上内容下载到本地,保存图片 antialias: true, // 正确开启抗锯齿 stencil: true,//开启模版缓存区,用于高级渲染技术,如阴影体积、遮挡剔除等 powerPreference: 'high-performance',//指定渲染器使用的 GPU 功率模式。默认 "default" physicalCorrectLights: true,//是否使用物理上正确的照明模式;默认为 false localClippingEnabled: true,//启用局部裁剪;默认为 false alpha: true,//背景透明 }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setClearColor(0x87CEEB, 1); // 确保canvas添加到正确的容器 const container = document.getElementById('container'); if (container) { container.appendChild(renderer.domElement); console.log('渲染器canvas已添加到container'); } else { document.body.appendChild(renderer.domElement); console.log('渲染器canvas已添加到body'); } // 设置canvas样式确保可见 renderer.domElement.style.display = 'block'; renderer.domElement.style.position = 'absolute'; renderer.domElement.style.top = '0'; renderer.domElement.style.left = '0'; renderer.domElement.style.zIndex = '1'; console.log('渲染器创建完成,canvas尺寸:', renderer.domElement.width, 'x', renderer.domElement.height); // 初始化指针锁定控制器 if (typeof THREE.PointerLockControls !== 'undefined') { pointerLockControls = new THREE.PointerLockControls(camera, document.body); // 添加点击进入指针锁定的事件 document.addEventListener('click', function() { if (pointerLockControls) { pointerLockControls.lock(); } }); // 添加键盘控制事件 document.addEventListener('keydown', onKeyDown, false); document.addEventListener('keyup', onKeyUp, false); console.log('指针锁定控制器创建完成'); } else { console.warn('PointerLockControls未加载,使用OrbitControls'); // 保留原有的OrbitControls作为备选 initOrbitControls(); } // 添加相机控制 (OrbitControls 作为备选) function initOrbitControls() { if (typeof THREE.OrbitControls !== 'undefined') { controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.screenSpacePanning = false; controls.minDistance = 10; // 减小最小距离 controls.maxDistance = 3000; // 最大距离 controls.maxPolarAngle = Math.PI / 2 - 0.1; // 限制垂直旋转角度,防止看到水面以下 controls.target.set(0, 0, 0); controls.addEventListener('change', function () { // 限制相机高度,防止进入水面以下 if (camera.position.y < 5) { camera.position.y = 5; } }); console.log('相机控制器创建完成'); } else { console.warn('OrbitControls未加载,跳过相机控制器'); } } // const ambientLight = new THREE.AmbientLight(0x404040); // 环境光 // ambientLight.intensity = 0.5; // 光照强度 // scene.add(ambientLight); addLights(); // loadHDRTexture() // // 创建场景元素 // createSkybox(); // 创建天空盒 createOcean(); // 创建海洋 // 加载海上风电机组模型 loadWindTurbineField(); // 监听窗口大小变化 window.addEventListener('resize', onWindowResize, false); console.log('Three.js场景初始化完成'); } // 加载HDR环境纹理 function loadHDRTexture() { // 检查RGBELoader是否可用 if (typeof THREE.RGBELoader === 'undefined') { console.warn('RGBELoader未加载,跳过HDR纹理加载'); return; } const hdrLoader = new THREE.RGBELoader(); hdrLoader.load("./textures/023.hdr", (texture) => { // 设置背景和环境纹理 texture.mapping = THREE.EquirectangularReflectionMapping; scene.background = texture; scene.environment = texture; console.log('HDR纹理加载完成'); }, undefined, (error) => { console.error('HDR纹理加载失败:', error); }); } // 修改后的 createSkybox 函数:// 创建天空盒 function createSkybox() { const skyGeometry = new THREE.SphereGeometry(1800, 24, 18); // 增大天空盒半径 const textureLoader = new THREE.TextureLoader().load('./textures/sky.jpg'); textureLoader.colorSpace = THREE.SRGBColorSpace; // 创建天空材质(通常使用全景纹理) const skyMaterial = new THREE.MeshBasicMaterial({ map: textureLoader, side: THREE.BackSide // 重要:让材质渲染在球体内侧 }); // 创建天空网格 const skySphere = new THREE.Mesh(skyGeometry, skyMaterial); scene.add(skySphere); } // 创建天空效果 function createSky() { // 注释掉Sky.js的高级天空效果 sky = new THREE.Sky(); sky.scale.setScalar(450000); scene.add(sky); // 创建太阳 sun = new THREE.Vector3(); // 配置天空参数(正午阳光设置) const skyUniforms = sky.material.uniforms; skyUniforms['turbidity'].value = 2; // 降低湍流度,营造清澈的正午天空 skyUniforms['rayleigh'].value = 3; // 增强瑞利散射,让天空更蓝 skyUniforms['mieCoefficient'].value = 0.005; skyUniforms['mieDirectionalG'].value = 0.8; // 设置太阳位置(正午阳光效果) const phi = THREE.MathUtils.degToRad(90 - 85); // 仰角 - 太阳接近天顶 const theta = THREE.MathUtils.degToRad(0); // 方位角 - 正南方向 sun.setFromSphericalCoords(1, phi, theta); skyUniforms['sunPosition'].value.copy(sun); // 使用sky.jpg作为天空盒纹理 const textureLoader = new THREE.TextureLoader(); textureLoader.load('./textures/sky.jpg', function (texture) { // 创建天空盒几何体 const skyBoxGeometry = new THREE.SphereGeometry(2000, 32, 32); const skyBoxMaterial = new THREE.MeshBasicMaterial({ map: texture, side: THREE.BackSide }); const skyBox = new THREE.Mesh(skyBoxGeometry, skyBoxMaterial); scene.add(skyBox); console.log('Sky texture loaded as skybox'); }, undefined, function (error) { console.error('Sky texture loading failed:', error); // 创建备用天空颜色 const skyGeometry = new THREE.SphereGeometry(500, 32, 32); const skyMaterial = new THREE.MeshBasicMaterial({ color: 0x87CEEB, side: THREE.BackSide }); const sky = new THREE.Mesh(skyGeometry, skyMaterial); scene.add(sky); console.log('Fallback sky color created'); }); console.log('Sky created using sky.jpg texture'); } // 创建海洋效果 function createOcean() { // 加载水面法线纹理 const textureLoader = new THREE.TextureLoader(); const waterNormals = textureLoader.load('./textures/waternormals.jpg', function (texture) { // 设置法线纹理的重复模式,增强水面效果 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set(2, 2); // 调整重复次数以控制波浪密度 console.log('水面法线纹理加载成功'); }, undefined, function (error) { console.error('水面法线纹理加载失败:', error); }); // 设置法线纹理的包装模式(即使纹理加载失败也要设置默认值) waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping; waterNormals.repeat.set(2, 2); // 增加重复次数以获得更细腻的波浪效果 // 创建水面几何体,增大尺寸以匹配天空盒尺寸 const waterGeometry = new THREE.PlaneGeometry(10600, 10600); // 比天空盒稍大以确保完全覆盖 // 使用Water.js创建高级水面效果 // 其他碧绿色选项: // waterColor: 0x0077be, // 经典碧绿色 // waterColor: 0x00a86b, // 绿松石色 // waterColor: 0x2a52be, // 地中海蓝 // waterColor: 0x008080, // 水鸭色 // waterColor: 0x40e0d0, // 青绿色 water = new THREE.Water(waterGeometry, { textureWidth: 512, textureHeight: 512, waterNormals: waterNormals, sunDirection: new THREE.Vector3(0.70707, 0.70707, 0.0), sunColor: 0xffffff, waterColor: 0x0077be,//0x001e0f 0x40e0d0 distortionScale: 3.7, // 控制波浪的扭曲程度 fog: scene.fog !== undefined, alpha: 1.0, // 水面透明度 foam: 0.1 // 泡沫效果 }); water.rotation.x = -Math.PI / 2; water.position.y = 0; // 确保水面在y=0位置 scene.add(water); // 将water赋值给全局ocean变量以保持兼容性 ocean = water; console.log('高级水面效果创建完成,使用法线纹理增强波浪凹凸效果'); } // 修改 addLights 函数,增强光照效果// 修改 addLights 函数,进一步增强光照效果 function addLights() { // 大幅增强环境光强度 const ambientLight = new THREE.AmbientLight(0xffffff, 1.2); // 使用白色光,强度更高 scene.add(ambientLight); // 主方向光(太阳光)- 进一步调整位置和强度 const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5); // 增加强度到1.5 directionalLight.position.set(100, 150, 100); // 调整到更合理的位置 directionalLight.castShadow = true; directionalLight.shadow.mapSize.width = 2048; directionalLight.shadow.mapSize.height = 2048; directionalLight.shadow.camera.near = 0.5; directionalLight.shadow.camera.far = 2000; // 增加远裁剪面 directionalLight.shadow.camera.left = -800; directionalLight.shadow.camera.right = 800; directionalLight.shadow.camera.top = 800; directionalLight.shadow.camera.bottom = -800; scene.add(directionalLight); // 添加更强的补光 - 减少阴影 const fillLight = new THREE.DirectionalLight(0xffffff, 0.8); // 增加补光强度到0.8 fillLight.position.set(-100, 100, -100); scene.add(fillLight); // 添加天光 - 模拟天空反射 const hemiLight = new THREE.HemisphereLight(0x80deea, 0x4caf50, 0.5); // 增加强度到0.5 hemiLight.position.set(0, 200, 0); scene.add(hemiLight); // 添加背面光,确保模型背面也有光照 const backLight = new THREE.DirectionalLight(0xffffff, 0.6); backLight.position.set(0, 50, -200); scene.add(backLight); } // 加载海上风电场(20个风电机组) function loadWindTurbineField() { console.log('开始加载海上风电场'); const loader = new THREE.GLTFLoader(); // 定义风电场布局 - 4行5列的排列(增加两排) const positions = [ // 第一排 // { x: -400, z: -600 }, // { x: -200, z: -600 }, // { x: 0, z: -600 }, // { x: 200, z: -600 }, // { x: 400, z: -600 }, // // 第二排 // { x: -400, z: -400 }, // { x: -200, z: -400 }, // { x: 0, z: -400 }, // { x: 200, z: -400 }, // { x: 400, z: -400 }, // 第三排 { x: -400, z: -200 }, { x: -200, z: -200 }, { x: 0, z: -200 }, { x: 200, z: -200 }, { x: 400, z: -200 }, // 第四排 { x: -400, z: 200 }, { x: -200, z: 200 }, { x: 0, z: 200 }, { x: 200, z: 200 }, { x: 400, z: 200 } ]; // 旋转角度(右转50度) const rotationAngle = THREE.MathUtils.degToRad(50); // 转换为弧度 const cosAngle = Math.cos(rotationAngle); const sinAngle = Math.sin(rotationAngle); let loadedCount = 0; const totalCount = positions.length; positions.forEach((position, index) => { // 应用旋转变换到每个风电机组的位置 const rotatedX = position.x * cosAngle - position.z * sinAngle; const rotatedZ = position.x * sinAngle + position.z * cosAngle; loader.load( './models/风电组.glb', function (gltf) { console.log(`风电组.glb模型 ${index + 1} 加载成功`); const model = gltf.scene.clone(); // 克隆模型以创建多个实例 // 调整模型缩放和位置(使用旋转后的位置) model.scale.set(0.8, 0.8, 0.8); // 将风机位置设置在水面上(y=0) model.position.set(rotatedX, 0, rotatedZ); // 设置模型的旋转角度(使风机面向正确的方向) model.rotation.y = -rotationAngle; // 负号是因为我们希望风机正面朝向旋转方向 // 调整模型材质 // 调整模型材质,使其更亮 model.traverse(function (child) { if (child.isMesh) { child.castShadow = true; child.receiveShadow = true; child.frustumCulled = false; // 如果材质存在,调整其属性 if (child.material) { // 添加更强的自发光效果 child.material.emissive = new THREE.Color(0x444444); // 增加自发光强度 // 调整材质颜色,使其更亮 if (child.material.color) { // 可以稍微提亮原始颜色 child.material.color.multiplyScalar(1.2); } // 确保材质响应光照 if (child.material.type === 'MeshBasicMaterial') { // 如果是基础材质,替换为标准材质 child.material = new THREE.MeshStandardMaterial({ color: child.material.color || 0xffffff, map: child.material.map, metalness: 0.1, roughness: 0.6, emissive: new THREE.Color(0x333333), // 添加自发光 emissiveIntensity: 0.3 }); } else if (child.material.type === 'MeshStandardMaterial') { // 调整标准材质参数使其更亮 child.material.metalness = Math.max(0.05, child.material.metalness || 0.1); child.material.roughness = Math.min(0.8, child.material.roughness || 0.6); child.material.emissive = new THREE.Color(0x333333); child.material.emissiveIntensity = 0.3; // 添加自发光强度 } else if (child.material.type === 'MeshLambertMaterial') { // 对于Lambert材质也添加自发光 child.material.emissive = new THREE.Color(0x333333); } } } }); // 添加到场景和数组 scene.add(model); windTurbineModels.push(model); loadedCount++; console.log(`风电场进度: ${loadedCount}/${totalCount} 个风电机组已加载`); if (loadedCount === totalCount) { console.log('海上风电场加载完成!'); } }, function (progress) { if (progress.total > 0) { const percent = (progress.loaded / progress.total * 100).toFixed(1); console.log(`风电机组 ${index + 1} 加载进度: ${percent}%`); } }, function (error) { console.error(`风电机组 ${index + 1} 加载失败:`, error); // 如果单个模型加载失败,创建备用模型(同样应用旋转变换) createFallbackWindTurbine(rotatedX, rotatedZ, index); loadedCount++; } ); }); } // 修改备用风机创建函数,也应用旋转变换 function createFallbackWindTurbine(x = 0, z = 0, index = 0) { console.log(`创建备用风电机组模型 ${index + 1}`); // 创建风电机组主体(塔筒) const towerGeometry = new THREE.CylinderGeometry(1.6, 2.4, 24, 8); // 缩小尺寸 const towerMaterial = new THREE.MeshLambertMaterial({ color: 0xcccccc }); const tower = new THREE.Mesh(towerGeometry, towerMaterial); tower.position.set(0, 12, 0); tower.castShadow = true; tower.receiveShadow = true; tower.frustumCulled = false; // 禁用视锥体剔除 // 创建机舱 const nacelleGeometry = new THREE.BoxGeometry(6.4, 3.2, 3.2); // 缩小尺寸 const nacelleMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff }); const nacelle = new THREE.Mesh(nacelleGeometry, nacelleMaterial); nacelle.position.set(0, 24, 0); nacelle.castShadow = true; nacelle.frustumCulled = false; // 禁用视锥体剔除 // 创建叶片轮毂组(用于旋转) const rotorGroup = new THREE.Group(); // 创建叶片轮毂 const hubGeometry = new THREE.SphereGeometry(1.2, 8, 8); // 缩小尺寸 const hubMaterial = new THREE.MeshLambertMaterial({ color: 0x666666 }); const hub = new THREE.Mesh(hubGeometry, hubMaterial); hub.position.set(0, 0, 0); // 相对于rotorGroup的位置 hub.castShadow = true; hub.frustumCulled = false; // 禁用视锥体剔除 // 创建叶片 const bladeGeometry = new THREE.BoxGeometry(0.4, 12, 0.8); // 缩小尺寸 const bladeMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff }); const blade1 = new THREE.Mesh(bladeGeometry, bladeMaterial); blade1.position.set(0, 6, 0); // 相对于rotorGroup的位置 blade1.castShadow = true; blade1.frustumCulled = false; // 禁用视锥体剔除 const blade2 = new THREE.Mesh(bladeGeometry, bladeMaterial); blade2.position.set(0, 0, 6); blade2.rotation.z = Math.PI * 2 / 3; blade2.castShadow = true; blade2.frustumCulled = false; // 禁用视锥体剔除 const blade3 = new THREE.Mesh(bladeGeometry, bladeMaterial); blade3.position.set(0, 0, -6); blade3.rotation.z = Math.PI * 4 / 3; blade3.castShadow = true; blade3.frustumCulled = false; // 禁用视锥体剔除 // 将轮毂和叶片添加到旋转组 rotorGroup.add(hub); rotorGroup.add(blade1); rotorGroup.add(blade2); rotorGroup.add(blade3); // 设置旋转组的位置 rotorGroup.position.set(3.2, 24, 0); // 给旋转组添加一个标识,方便动画识别 rotorGroup.name = 'rotor_group'; // 组合风电机组 const windTurbine = new THREE.Group(); windTurbine.add(tower); windTurbine.add(nacelle); windTurbine.add(rotorGroup); // 将风机放置在水面上(y=0) windTurbine.position.set(x, 0, z); windTurbine.scale.set(0.8, 0.8, 0.8); // 整体缩放 // 应用旋转(与主风电场一致) const rotationAngle = THREE.MathUtils.degToRad(50); windTurbine.rotation.y = -rotationAngle; // 禁用整个组的视锥体剔除 windTurbine.traverse(function (child) { child.frustumCulled = false; }); scene.add(windTurbine); windTurbineModels.push(windTurbine); console.log(`备用风电机组模型 ${index + 1} 创建完成`); } // 动画循环 function animate() { requestAnimationFrame(animate); const time = clock.getElapsedTime(); // 漫游控制逻辑 const delta = Math.min(0.1, (time - prevTime)); // 如果使用指针锁定控制器且已锁定 if (pointerLockControls && pointerLockControls.isLocked) { // 计算移动方向 direction.z = Number(moveForward) - Number(moveBackward); direction.x = Number(moveRight) - Number(moveLeft); direction.y = Number(moveUp) - Number(moveDown); direction.normalize(); // 设置移动速度 const speed = 100.0; // 根据方向和速度更新速度向量 if (moveForward || moveBackward) velocity.z -= direction.z * speed * delta; if (moveLeft || moveRight) velocity.x -= direction.x * speed * delta; if (moveUp || moveDown) velocity.y -= direction.y * speed * delta; // 应用阻尼(摩擦力) velocity.x -= velocity.x * 10.0 * delta; velocity.y -= velocity.y * 10.0 * delta; velocity.z -= velocity.z * 10.0 * delta; // 移动相机 pointerLockControls.moveRight(-velocity.x * delta); pointerLockControls.moveForward(-velocity.z * delta); // 垂直移动 camera.position.y -= velocity.y * delta; // 简单的高度限制 if (camera.position.y < 5) { camera.position.y = 5; velocity.y = 0; } if (camera.position.y > 500) { camera.position.y = 500; velocity.y = 0; } } // 如果使用OrbitControls else if (controls) { controls.update(); } prevTime = time; // 在前几秒强制更新材质(解决材质加载延迟问题) if (time < 3 && windTurbineModels.length > 0) { windTurbineModels.forEach(model => { model.traverse(function (child) { if (child.isMesh && child.material) { if (child.material.needsUpdate !== undefined) { child.material.needsUpdate = true; } // 持续调整材质亮度 if (child.material.emissive) { child.material.emissiveIntensity = 0.3; } } }); }); } // 更新水面动画 - 增强水面波动效果 if (water && water.material.uniforms) { // 通过改变time值来控制水面波动动画 water.material.uniforms['time'].value += 1.0 / 60.0; // 可选:增加波动速度和强度 // water.material.uniforms['time'].value += 1.0 / 30.0; } // 风电机组动画 if (windTurbineModels.length > 0) { windTurbineModels.forEach((model, index) => { // 每个风电机组有轻微的相位差,创造更自然的效果 const phaseOffset = index * 0.2; // model.position.y = -3 + Math.sin(time * 0.5 + phaseOffset) * 1.5; // 叶片旋转动画 // 如果还没有缓存旋转中心和初始偏移,先进行初始化 if (!model.userData.rotorInitialized) { let rotorCenter = null; // 找到186部件作为旋转中心 model.traverse((child) => { if (child.name && child.name.toLowerCase().includes('186')) { rotorCenter = child; } }); // 缓存旋转中心和叶片的初始偏移 if (rotorCenter) { model.userData.rotorCenter = rotorCenter; model.userData.rotorCenterPosition = { x: rotorCenter.position.x, y: rotorCenter.position.y, z: rotorCenter.position.z }; // 为每个叶片计算并缓存初始偏移 model.traverse((child) => { if (child.name && (child.name.toLowerCase().includes('200') || child.name.toLowerCase().includes('214') || child.name.toLowerCase().includes('228') || child.name.toLowerCase().includes('风轮'))) { child.userData.initialOffset = { x: child.position.x - rotorCenter.position.x, y: child.position.y - rotorCenter.position.y, z: child.position.z - rotorCenter.position.z }; } }); } model.userData.rotorInitialized = true; } // 执行旋转动画 model.traverse((child) => { // 如果是备用模型的旋转组 if (child.name === 'rotor_group') { child.rotation.x = time * 2.0; // 绕X轴旋转 } // 如果是GLB模型的叶片部件 else if (child.name && (child.name.toLowerCase().includes('200') || child.name.toLowerCase().includes('214') || child.name.toLowerCase().includes('228') || child.name.toLowerCase().includes('风轮'))) { if (model.userData.rotorCenter && child.userData.initialOffset) { // 使用缓存的旋转中心位置(固定不变) const centerPos = model.userData.rotorCenterPosition; // 输出第一个风电机组的centerPos到控制台 // if (index === 0 && child.name.toLowerCase().includes('200')) { // console.log('第一个风电机组的centerPos:', centerPos); // } const offset = child.userData.initialOffset; // 围绕固定的旋转中心做圆周运动 const angle = time * 2.0; const cosAngle = Math.cos(angle); const sinAngle = Math.sin(angle); child.position.x = centerPos.x + (offset.x * cosAngle - offset.y * sinAngle); child.position.y = centerPos.y + (offset.x * sinAngle + offset.y * cosAngle) + 4; child.position.z = centerPos.z + offset.z - 4; // 同时让叶片自身也旋转 child.rotation.z = angle; } else { // 如果没有找到186部件,使用原来的旋转方式 child.rotation.z = time * 2.0; } } }); }); } // 渲染场景 if (scene && camera && renderer) { renderer.render(scene, camera); // 每隔一段时间输出渲染信息 if (Math.floor(time) % 5 === 0 && time % 1 < 0.1) { console.log('正在渲染场景,时间:', Math.floor(time), '场景对象数量:', scene.children.length); } } else { console.warn('场景、相机或渲染器未初始化'); } } // 窗口大小变化处理 function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } // 页面加载完成后初始化 window.addEventListener('DOMContentLoaded', function () { console.log('DOM加载完成,开始初始化Three.js场景'); // 检查Three.js是否加载 if (typeof THREE === 'undefined') { console.error('Three.js未加载!'); document.getElementById('loading').innerHTML = '错误:Three.js库未加载'; return; } console.log('Three.js版本:', THREE.REVISION); // 隐藏加载提示 const loadingElement = document.getElementById('loading'); if (loadingElement) { loadingElement.style.display = 'none'; } init(); animate(); }); // 添加一个切换控制模式的函数 function toggleControls() { if (pointerLockControls) { if (pointerLockControls.isLocked) { pointerLockControls.unlock(); } else { pointerLockControls.lock(); } } } // 键盘事件处理函数 function onKeyDown(event) { switch (event.code) { case 'ArrowUp': case 'KeyW': moveForward = true; break; case 'ArrowLeft': case 'KeyA': moveLeft = true; break; case 'ArrowDown': case 'KeyS': moveBackward = true; break; case 'ArrowRight': case 'KeyD': moveRight = true; break; case 'KeyQ': moveUp = true; break; case 'KeyE': moveDown = true; break; } } function onKeyUp(event) { switch (event.code) { case 'ArrowUp': case 'KeyW': moveForward = false; break; case 'ArrowLeft': case 'KeyA': moveLeft = false; break; case 'ArrowDown': case 'KeyS': moveBackward = false; break; case 'ArrowRight': case 'KeyD': moveRight = false; break; case 'KeyQ': moveUp = false; break; case 'KeyE': moveDown = false; break; } }