You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

827 lines
31 KiB
JavaScript

// 全局变量
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;
}
}