You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Three.js实现六边形体素地图的问题求助

六边形体素地图适配方案(Three.js)

针对第一种方案的修复(生成六边形体素并定位)

你提到第一种方案仅生成网格定位,核心问题是没把六边形体素与网格坐标绑定。可以按以下步骤修改:

  1. 创建六边形柱体几何:用CylinderGeometry生成标准六边形,调整参数适配体素尺寸,再旋转使其垂直于地面:
    // 生成六边形柱体(外接圆半径1,高度2,6段边)
    const hexVoxelGeo = new THREE.CylinderGeometry(1, 1, 2, 6);
    // 旋转90度让柱体立在XY平面上
    hexVoxelGeo.rotateX(Math.PI / 2);
    
  2. 绑定网格坐标与体素位置:遍历HexGrid的每个网格,用getCenter或hexToWorld获取世界坐标,创建并放置六边形体素:
    const hexGrid = new THREE.HexGrid(2); // 网格间距2
    // 遍历目标范围内的六边形坐标
    for (let q = -5; q <= 5; q++) {
      for (let r = -5; r <= 5; r++) {
        const hex = new THREE.HexGrid.Hex(q, r);
        const worldPos = hexGrid.hexToWorld(hex);
        // 生成体素网格并设置位置
        const voxel = new THREE.Mesh(hexVoxelGeo, yourMaterial);
        voxel.position.set(worldPos.x, 0, worldPos.y); // y轴作为高度可后续调整
        scene.add(voxel);
      }
    }
    
  3. 性能优化:如果体素数量多,改用InstancedMesh批量渲染,减少Draw Call。

针对第二种方案的VoxelWorld类适配

第二种方案生成了六边形但不兼容自定义VoxelWorld,核心是要重构VoxelWorld的坐标系统和体素管理逻辑:

  1. 重构坐标存储:把原立方体的笛卡尔坐标(x,y,z)替换为六边形轴向坐标(q,r)+ 高度y,用Map存储体素:
    class VoxelWorld {
      private voxels = new Map<string, THREE.Mesh>();
      private hexGrid = new THREE.HexGrid(2); // 网格间距与体素尺寸匹配
    
      // 添加体素:传入六边形坐标(q,r)和高度y
      addVoxel(q: number, r: number, y: number) {
        const key = `${q},${r},${y}`;
        if (this.voxels.has(key)) return;
        
        const hex = new THREE.HexGrid.Hex(q, r);
        const worldPos = this.hexGrid.hexToWorld(hex);
        worldPos.y = y * 2; // 体素高度2,按层堆叠
    
        const voxel = new THREE.Mesh(hexVoxelGeo, yourMaterial);
        voxel.position.copy(worldPos);
        this.scene.add(voxel);
        this.voxels.set(key, voxel);
      }
    
      // 获取体素:通过六边形坐标查询
      getVoxel(q: number, r: number, y: number) {
        return this.voxels.get(`${q},${r},${y}`);
      }
    }
    
  2. 适配拾取与交互:原立方体的射线检测逻辑要修改,先用worldToHex把鼠标射线交点转换成六边形坐标,再查询对应体素:
    function onMouseClick(event: MouseEvent) {
      const raycaster = new THREE.Raycaster();
      const mouse = new THREE.Vector2(
        (event.clientX / window.innerWidth) * 2 - 1,
        -(event.clientY / window.innerHeight) * 2 + 1
      );
      raycaster.setFromCamera(mouse, camera);
    
      // 先获取地面交点,转换为六边形坐标
      const groundPlane = new THREE.Plane(new THREE.Vector3(0,1,0), 0);
      const intersectionPoint = new THREE.Vector3();
      raycaster.ray.intersectPlane(groundPlane, intersectionPoint);
      const hex = hexGrid.worldToHex(new THREE.HexGrid.Hex(), intersectionPoint.x, intersectionPoint.z);
    
      // 查询该坐标下的体素
      const voxel = voxelWorld.getVoxel(hex.q, hex.r, 0);
      // 后续交互逻辑...
    }
    
  3. 邻接逻辑调整:如果需要实现体素的相邻检测(比如自动合并、挖除),要适配六边形的6个邻接方向,替换原立方体的上下左右前后逻辑。

内容的提问来源于stack exchange,提问作者drPapus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 19:48:05