map3d 建筑建模原理THREE.Shape 与 ExtrudeGeometry 拉伸立体城市的完整实现【免费下载链接】map3d️ Generate City 3D map with R3F. Include building and road information.项目地址: https://gitcode.com/gh_mirrors/map/map3dmap3d是一个基于 React-Three-FiberR3F的 3D 城市地图生成工具核心思路是从 OpenStreetMap 抓取真实世界的建筑轮廓与高度数据用THREE.Shape勾勒每栋楼的平面轮廓再通过ExtrudeGeometry 拉伸把二维轮廓站起来最终在浏览器里渲染出一座可旋转、可点击、可导出 GLB 的立体城市。本文面向新手完整拆解这套建筑建模原理。一、先看懂效果一座数据驱动的立体城市 ️从上面的效果图可以看到灰色体块是建筑绿色线条是道路。这些不是手工建模的结果而是由地图数据自动生成的建筑体块OpenStreetMap 中building标签的轮廓 高度数据道路线条highway标签的折线数据交互能力悬停任意建筑可查看名称、高度、层数、地址等真实标签信息二、数据准备在地图上画个框圈出你的城市区域整个流程的起点是一个 Leaflet 二维地图。用户拖拽画一个矩形框系统就会记录这个区域的东北角和西南角两个坐标点存入全局状态区域选择与矩形绘制SelectMap.tsx状态存储建筑列表 区域中心点areaStore.ts拿到框选区域后项目通过 Overpass API 向 OpenStreetMap 发起查询拉取区域内所有建筑的完整几何轮廓建筑数据查询way[building]与relation[building]带out body geom返回完整顶点App.tsx加载过程与数据预览组件Processing.tsx 每个建筑返回的geometry是一串经纬度顶点tags则包含名称、高度、楼层数等元信息——这正是后面建模的全部原料。三、坐标投影把经纬度换算成三维空间坐标 经纬度是球面坐标不能直接用于 3D 场景。map3d 用了一个轻量级的局部平面投影以选区中心为原点把每个顶点换算成 X/Y 坐标其中经度差会乘以参考纬度的余弦值来修正赤道到极度的尺度差异投影函数projectSpace.tsx全局缩放系数scale 51000Space.tsx投影后的顶点是THREE.Vector2为下一步绘制轮廓做好了准备。四、核心建模第一步THREE.Shape 勾勒建筑轮廓 ✏️建模的关键代码集中在 Space.tsx 的areaData函数中流程只有四步过滤无效数据轮廓少于 3 个顶点的建筑直接跳过投影顶点把经纬度顶点逐个转为平面坐标闭合轮廓若首尾顶点不重合手动补上第一个点Shape 要求封闭轮廓创建 Shapenew THREE.Shape(shapePoints)生成二维轮廓对象这里的细节很值得新手注意Space.tsx 中的shapePoints[0].equals(...)判重逻辑就是用来保证轮廓闭合的——轮廓不闭合后续拉伸会得到一个有洞的畸形网格。五、核心建模第二步ExtrudeGeometry 让建筑站起来 ️轮廓只是纸上的线稿真正让建筑拥有体积的是ExtrudeGeometry挤出几何体。map3d 为每栋楼配置的拉伸参数Space.tsx非常简洁只有三项depth深度建筑的高度来自数据标签steps: 1只分 1 段拉伸避免产生多余的水平分面bevelEnabled: false关闭斜角保证建筑边缘笔直方正而高度的取值策略也很有意思Space.tsx优先读取height标签单位米没有高度但有楼层数building:levels时按每层 2.2 米估算两者都缺失则回退为默认 10 米。这解释了为什么有些楼看起来特别高——因为数据缺失时用了兜底值。最终在 Building 组件 中Shape 和参数交给extrudeGeometry配合rotation{[-Math.PI / 2, 0, 0]}把挤出方向从水平扳成竖直建筑便垂直站立在平地上。六、道路、交互与场景氛围从灰色体块到活的城市 建筑立起来后项目又叠加了三层城市感道路网络同样从 Overpass 拉取highway折线转成THREE.BufferGeometry后用 drei 的Line渲染成绿色路网Space.tsx悬停信息卡片onPointerOver触发高亮变色并在建筑顶部弹出毛玻璃卡片展示名称、高度、楼层、地址等 OSM 标签Space.tsx场景氛围drei 提供的Sky程序化天空、Environment presetcity城市环境贴图与多光源让灰白色块不再寡淡Space.tsx七、导出 GLB把立体城市带出浏览器 map3d 的建模不是看完即止。项目用一个标记机制区分可导出的对象参与导出的建筑与道路都带有userData.exportToGLB true导出时遍历场景、克隆这些节点交给 three.js 自带的GLTFExporter打包成标准 GLB 模型文件Space.tsx。这意味着你拉伸出来的整座城市可以直接导入 Unity、Blender 或数字孪生平台继续加工——这正是 README 中提到的数字孪生、无人机测量、GPS 标记等扩展能力的技术基础。八、总结这套建模原理为什么值得学习环节技术点源码位置区域选择Leaflet 矩形框选SelectMap.tsx数据获取Overpass API 查询建筑轮廓App.tsx坐标投影经纬度 → 局部平面坐标Space.tsx轮廓建模THREE.Shape 闭合轮廓Space.tsx立体拉伸ExtrudeGeometry depth 参数Space.tsx模型导出GLTFExporter 输出 GLBSpace.tsx一句话总结map3d 证明了3D 城市并不神秘——轮廓Shape 高度Extrude 的 depth 真实地图数据三样东西组合起来就能把整座城市从平面的经纬度里挤成一座可以导出的立体城市。理解了这套原理你就能把它迁移到数字孪生、仿真、游戏场景搭建等大量实际项目中。【免费下载链接】map3d️ Generate City 3D map with R3F. Include building and road information.项目地址: https://gitcode.com/gh_mirrors/map/map3d创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?