简介:这份压缩包是面向Blender用户的BlenderGIS插件,用于在三维建模环境与地理空间数据之间建立衔接,适合需要将地图、地形或带坐标信息的空间数据转化为可编辑三维场景的建模师、GIS可视化学习者及技术美术。插件以Python脚本为核心,配合界面定义、图标与示例图片、说明文档和授权文件,构成可直接部署研究的插件目录。包内共131个文件,包含78个py脚本、32个svg矢量图标、13个png图像,以及md说明、ui界面、json配置、version版本标记和license授权等,压缩包约402KB,体量轻便,便于阅读源码与按需替换资源。目前已有6859人学习下载,说明其在Blender地理数据工作流中具有较高关注度。读者可从中了解插件如何组织坐标转换、地图图层与三维视图的交互逻辑,借鉴脚本与界面资源的配合方式,并据此搭建自己的地理建模实验环境,减少从零摸索插件结构的成本。
1. 把 zip 拖进偏好设置,然后 Import 菜单里什么都没有
这是 3D-BlenderGIS 插件最典型的开局翻车现场:下载完3D-BlenderGIS.zip,打开 Blender 偏好设置,点安装、选文件、勾上复选框,重启,接着打开 Object → Import 菜单,结果干干净净,没有任何 GIS 相关条目。更糟的是另一种情况——条目出来了,点一下直接弹 Python 异常,控制台刷一大片红字。
它和常见的 3D 插件根本不是一类东西:不是单个.py文件丢进目录就能用,而是带了一整套自己的模块目录、EPSG 坐标定义表和模块加载逻辑。装错层级、Blender 主版本不对、内置 Python 版本对不上,这三种情况报出来的错还各不相同,光看界面提示基本猜不到原因。需要这套东西的人很明确:手上有 shapefile、GeoTIFF、DEM 这类地理数据,想把它们立起来做地形、做城市体块、做地形渲染。装不对,一天时间就耗在找一个根本不会出现的按钮上。
2. 环境清点:Blender 主版本、内置 Python 和 BlenderGIS 分支的对应关系
动手之前先把三件事定下来:用哪个 Blender、这个 Blender 内置的 Python 是几点几、BlenderGIS 拿哪个分支。这三项没对齐,后面所有安装动作都是白费。我见过太多人卡在「插件能勾上但一用就报错」,回头一查,是 Blender 4.x 配了一个为 2.9 时代写的插件版本。
2.1 Blender 主版本决定插件能不能加载
Blender 从 2.80 开始把 Python API 大改了一轮,插件的注册方式、操作符定义、面板绘制全变了;到 4.x 又移除了若干旧接口。BlenderGIS 的 2.2.x 分支声明支持 2.8 以上,但实际使用中,Blender 3.3 LTS 和 3.6 LTS 是最稳的两档,2.2.x 的多数功能在这两个版本上验证得最充分。Blender 4.0 之后能跑,但需要相对较新的 2.2.x 构建,老一点的构建会在注册阶段就抛属性错误。
内置 Python 版本必须一起看,因为 Blender 用的是自己打包的解释器,不是你系统里那个。系统 Python 是 3.12,不代表 Blender 里也是 3.12。
| Blender 版本 | 内置 Python | BlenderGIS 2.2.x 表现 | 建议 |
|---|---|---|---|
| 2.93 LTS | 3.9 | 可用,部分新功能缺失 | 不推荐新项目 |
| 3.3 LTS | 3.10 | 稳定 | 老机器、老工程续用 |
| 3.6 LTS | 3.10 | 最稳,兼容性最好 | 首选 |
| 4.0 – 4.2 LTS | 3.11 | 可用,需较新构建 | 可用,注意安装入口变化 |
| 4.3 及以上 | 3.11 | 多数可用,个别操作符告警 | 接受少量告警再用 |
我的习惯是:新机器上装 Blender 3.6 LTS 专门跑 GIS 相关的活儿,4.x 留给建模和渲染。同一台机器装多个 Blender 版本互不干扰,插件的用户目录按版本号分开,这点后面会讲。
2.2 先解压看一眼 zip 里的层级,别急着装
这一步很多人跳过,但它是后面一半问题的根源。Blender 识别一个插件,判断依据是某个目录下直接存在__init__.py,并且这个文件里有bl_info字典。如果 zip 打包时多套了一层文件夹,装进去就变成addons/xxx/xxx/__init__.py,Blender 会认为外层目录不是插件,里层又扫不到。
先列一下压缩包的顶层结构:
# 只看前 20 行,确认顶层是文件还是文件夹,以及文件夹叫什么名字 unzip -l 3D-BlenderGIS.zip | head -n 20 # 想更准确一点,直接找 __init__.py 在第几层 unzip -l 3D-BlenderGIS.zip | grep "__init__.py"unzip -l只列内容不解压,用来判断层级最省事。关键在于__init__.py前面有几段路径:如果输出是BlenderGIS/__init__.py,说明压缩包内只有一层目录,直接装没问题;如果是3D-BlenderGIS/BlenderGIS/__init__.py,那就多了一层,从偏好设置装进去大概率会出现「勾得上但不工作」的情况。
Windows 上没有unzip就用 PowerShell,效果一样:
# 列出压缩包内的条目,观察层级 Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::OpenRead("D:\dl\3D-BlenderGIS.zip").Entries | Select-Object -First 20 -ExpandProperty FullName2.3 三条语句把本机环境摸清楚
不确定自己的 Blender 内置的是哪个 Python,不用去翻安装目录,直接在 Blender 里问它。切到 Scripting 工作区,新建一个文本块,粘进去运行:
import bpy, sys, addon_utils print("Blender:", bpy.app.version_string) # 主版本号,决定插件兼容性 print("Python :", sys.version.split()[0]) # 内置解释器版本,不是你系统的 print("Paths :", bpy.utils.script_paths()) # addons 搜索路径,最后一条通常是用户目录 print("Addons :", [m.__name__ for m in addon_utils.modules() if 'gis' in m.__name__.lower()])四行的作用分别是:确认 Blender 主版本、确认内置 Python 版本、确认插件应该往哪个目录放、确认当前有没有被识别到的 GIS 相关插件。第四行如果输出空列表,说明 Blender 压根没扫到插件目录,问题在路径而不是插件本身。
bpy.utils.script_paths()返回的是一个列表,包含系统级目录和用户级目录。装插件优先放用户级,也就是列表里形如.../scripts/addons且位于个人配置目录下的那一条。系统级目录在 Linux 上往往需要 root 权限,改起来麻烦,升级 Blender 时还容易被覆盖。
注意:Blender 4.2 之后引入了扩展(Extension)机制,带
blender_manifest.toml的包走扩展通道,BlenderGIS 这类老式插件仍然走scripts/addons。这两套目录不是一回事,装错通道会提示包格式不合法。
3. 安装落地:从偏好设置装 zip 和手动解压到 addons 目录两条路
路径有两条,官方入口省事但有版本陷阱,手动解压可控但要求你把目录层级摆对。我一般是先试官方入口,一分钟内搞不定就转手动,别在界面上反复点。
3.1 走偏好设置装 zip:能做与不能做
标准流程是:Edit → Preferences → Add-ons,右上角安装按钮,选中3D-BlenderGIS.zip,确认,然后在列表里找到条目勾选启用。插件条目的名字通常以 GIS 开头,搜索框里直接输gis比翻列表快。
Blender 4.2 之后这个入口有个变化要注意:右上角的安装按钮默认走的是扩展安装,如果直接选一个老式插件的 zip,可能提示缺少清单文件或者包格式不合法。这时要展开按钮旁的下拉,选「Install Legacy Add-on」这类专门给老式插件留的入口,再选 zip。界面上两个入口长得像,选错了会以为文件坏了。
官方入口的局限在于它完全按 zip 内的层级来放文件。压缩包内如果多一层目录,它照搬不误,装完就是双层嵌套。所以装之前 2.2 节那一步不能省。
还有一点:装完必须手动勾选启用。Blender 装完不会自动启用插件,列表里条目存在但复选框是空的,这时候 Import 菜单当然没有东西。
3.2 手动解压:三个平台的目标路径
手动安装的核心是找到正确的scripts/addons目录,把「包含__init__.py的那一层目录」整体拷进去。三个平台的用户级路径如下,其中<版本号>换成你的 Blender 主次版本,比如3.6或4.2:
| 平台 | 用户级 addons 路径 |
|---|---|
| Linux | ~/.config/blender/<版本号>/scripts/addons/ |
| Windows | %APPDATA%\Blender Foundation\Blender\<版本号>\scripts\addons\ |
| macOS | ~/Library/Application Support/Blender/<版本号>/scripts/addons/ |
Linux 下的完整操作:
# 1. 先解压到一个临时目录,不要直接往 addons 里解 mkdir -p /tmp/gis_unpack unzip -q 3D-BlenderGIS.zip -d /tmp/gis_unpack # 2. 找出 __init__.py 所在的那一层,那一层的目录名就是插件目录名 find /tmp/gis_unpack -maxdepth 3 -name "__init__.py" # 3. 建好目标目录,把插件目录整体拷进去 ADDON_DIR="$HOME/.config/blender/3.6/scripts/addons" mkdir -p "$ADDON_DIR" cp -r /tmp/gis_unpack/BlenderGIS "$ADDON_DIR/" # 4. 验证层级:这一条必须能打印出文件路径,否则层级错了 ls "$ADDON_DIR/BlenderGIS/__init__.py"第 2 步的find是关键,-maxdepth 3限制搜索深度避免翻遍整个磁盘,输出结果里__init__.py的父目录就是你要拷的东西。第 4 步的验证不能省:如果ls报「No such file」,说明拷贝时多带或少带了一层。
Windows 用 PowerShell 做同样的事:
$src = "D:\dl\3D-BlenderGIS.zip" $tmp = "$env:TEMP\gis_unpack" $dst = "$env:APPDATA\Blender Foundation\Blender\3.6\scripts\addons" # 解压到临时目录 Expand-Archive -Path $src -DestinationPath $tmp -Force # 找出含 __init__.py 的目录 Get-ChildItem -Path $tmp -Recurse -Depth 3 -Filter "__init__.py" | Select-Object -ExpandProperty DirectoryName # 把上一步打印出来的目录整体拷进 addons New-Item -ItemType Directory -Force -Path $dst | Out-Null Copy-Item -Path "$tmp\BlenderGIS" -Destination $dst -Recurse -Force # 验证 Test-Path "$dst\BlenderGIS\__init__.py"-Depth 3对应 Linux 的-maxdepth 3,Test-Path返回True才算放对位置。Windows 上路径里有空格,所有变量都要加引号,这点比 Linux 容易翻车。
3.3 启用插件并确认它真的被加载了
文件放对位置只是第一步,还得让 Blender 重新扫描并启用。重启 Blender 是最省事的刷新方式,或者在 Scripting 里直接用代码启用:
import addon_utils, bpy # 先看 Blender 扫到了哪些含 gis 的模块,输出即模块名 candidates = [m.__name__ for m in addon_utils.modules() if 'gis' in m.__name__.lower()] print("扫到的模块:", candidates) # 用上一步打印的模块名启用,注意不是文件名而是模块名 for name in candidates: addon_utils.enable(name, default_set=True, persistent=True) print(name, "已启用") # 确认启用状态,True 才算成功 for name in candidates: print(name, addon_utils.check(name))default_set=True表示写入用户偏好,下次启动自动启用;persistent=True让插件在加载后保持启用状态,不会因为文件切换被临时禁用。addon_utils.check返回一个二元组,第二位是当前启用状态。
如果candidates是空列表,问题一定在目录层级或路径,回到 3.2 节重查。如果模块扫到了但启用时报异常,那就是插件代码和 Blender 版本不匹配,回到第 2 章的版本对照表选一个更合适的组合。
4. 首次配置:坐标参考、单位比例和 Georender 三个开关
插件启用了不等于能用。地理数据进 Blender 要过一道投影转换,转换参数填错,模型要么缩成一个点,要么飘到视口外面找不着。这一段是整个流程里最容易含糊过去、也最容易在后期返工的地方。
4.1 SRC 和 DST:源坐标参考和目标坐标参考
导入 shapefile 或 GeoJSON 的时候,会弹出一个参数面板,里面有两个坐标参考输入框:SRC 是数据本身用的坐标系,DST 是转换到 Blender 场景里用的平面坐标系。常见做法是 SRC 填EPSG:4326(经纬度),DST 填EPSG:3857(Web 墨卡托,单位为米),这样导入后场景单位就是米,模型尺寸和真实世界的对应关系直观。
EPSG:4326的单位是度,直接进 Blender 会得到一堆 0.0x 量级的坐标,视图里几乎看不见;EPSG:3857的单位是米,投影后数值在几百万量级,需要靠视图裁剪范围才能看到全貌。两种极端都会让人以为导入失败,其实数据好好地在场景里。
如果数据自带.prj文件或者 GeoJSON 里有 CRS 声明,SRC 可以留空让插件自己读;没有的话必须手填,填错的表现是模型位置偏移几公里甚至几十公里。拿不准源坐标系时,先看一下数据附带的元信息,别靠猜。
提示:DST 不一定要用 3857。做小范围场地的时候,用一个以场地中心为原点的本地平面坐标系,模型坐标会小很多,后续做相机动画和粒子分布都更省心。
4.2 单位与比例:经纬度不是米
Blender 场景默认单位是米,但场景比例因子默认是 1.0。对大多数地理数据来说这个设置是对的,不要去动它。真正要动的是视图裁剪范围,因为投影后的坐标可能是几十万到几百万米量级,超出默认裁剪距离就会被裁掉,表现出来就是「导入成功但视口里什么都没有」。
用代码统一设置,比在界面上一项项点更可靠:
import bpy scene = bpy.context.scene # 单位系统设为公制,长度单位显示为米 scene.unit_settings.system = 'METRIC' scene.unit_settings.length_unit = 'METERS' # 比例因子保持 1.0,表示 1 Blender 单位 = 1 米,地理数据不要改这个值 scene.unit_settings.scale_length = 1.0 # 放大视口裁剪范围,避免大坐标模型被裁掉 for area in bpy.context.screen.areas: if area.type == 'VIEW_3D': for space in area.spaces: if space.type == 'VIEW_3D': space.clip_start = 0.1 space.clip_end = 100000.0 # 单位米,覆盖大部分城市级范围scale_length是全局比例因子,改动它会让场景里所有已存在的物体按比例缩放,地理数据场景里保持 1.0 最安全。clip_end是视口远裁剪面,默认值只有 1000 米,城市级或省级范围的数据必然被裁;设成 10 万米能覆盖大部分场景,数值再大精度会下降,不要无脑加零。
clip_start保持 0.1 左右就行,设得太小会出现深度精度问题,近距离观察时面片闪烁。
4.3 Georender 开关和场景组织
Georender 是这套插件里比较特别的一个能力:打开之后,物体除了自身的变换,还会记录一份地理坐标信息,导出或者做地理对齐时用得上。首次导入数据后建议把它打开,位置在场景属性里,跟地理参考相关的那一组。
打开之后有个副作用要提前知道:物体的location不再是你熟悉的局部坐标含义,直接改数值会出现「改了没反应」或者「跳到别处」的情况。调位置的时候优先用 3D 游标配合吸附,或者临时关掉 Georender 调完再打开。
场景组织上我一般分三层:地理参考层放导入的原始数据,处理层放切割、简化后的中间结果,出图层放最终要渲染或导出的对象。三个集合分开,好处是后面替换数据源的时候不用重新调材质和灯光。
4.4 底图与离线数据的取舍
插件里带在线底图抓取的功能,能从公开的地图服务拉影像或矢量贴到场景里。这一项在能访问对应服务的机器上很方便,但有两件事要注意:一是内网机器和离线机器上这个功能直接用不了,别在界面上反复试点;二是抓下来的影像分辨率和坐标精度受服务端限制,做精确对齐的时候不要拿它当基准。
离线场景的替代方案是本地 GeoTIFF 或 DEM。把影像文件放本地,用导入影像的功能把它铺到地形上,坐标参考跟矢量数据填同一套,对齐精度反而比在线底图更可控。我的习惯是:底图只用来做视觉参考和快速定位,真要对齐,一律用本地数据加明确的坐标系参数。
5. 排查:BlenderGIS 装完导入失败的四类现象
下面四条是我自己在不同机器上真踩过的,按出现频率从高到低排。每条都按现象、原因、解决三段来写,对不上现象的别硬套。
5.1 现象一:偏好设置里勾不上,或者勾上重启后自动消失
现象:列表里能搜到条目,勾选后没报错,但重启 Blender 再打开偏好设置,复选框又变回空的。
原因有两层。表层是插件在启用阶段抛了异常,Blender 捕获后静默回滚了启用状态,界面上不显示红字;深层是bl_info里声明的 Blender 最低版本与当前版本不匹配,或者插件模块内部的相对导入路径断了——后者通常就是 2.2 节说的双层目录嵌套造成的。
解决:先看控制台。Windows 上开 Window → Toggle System Console,Linux 和 macOS 从终端启动 Blender 就能看到标准输出。控制台里搜Traceback,第一行报错往往就写着哪个模块导入失败。确认是ModuleNotFoundError且路径里出现重复的插件目录名,就是层级问题,按 3.2 节重新摆一遍目录。如果是属性不存在(AttributeError),那是版本不匹配,换 Blender 版本或换插件构建。
5.2 现象二:Import 菜单里根本没有 GIS 条目
现象:插件勾选状态是启用的,但 Object → Import 或者 File → Import 里找不到任何 GIS 相关项。
原因:插件的操作符注册失败。每个导入项背后是一个操作符类,注册阶段出错,操作符就不会出现在菜单里,而插件的启用状态可能仍然是 True。另一个常见原因是菜单是上下文相关的,切到了错误的编辑器模式或选中了不合适的对象类型。
解决:在 Scripting 里跑一段代码,直接列出已注册的操作符:
import bpy # 列出所有与 gis 相关的已注册操作符,有输出说明注册成功 ops = [op for op in dir(bpy.ops) if 'gis' in op.lower()] print("操作符模块:", ops) # 进一步列出每个模块下的具体操作符 for mod in ops: sub = [o for o in dir(getattr(bpy.ops, mod)) if not o.startswith('_')] print(mod, "->", sub[:10])如果输出是空列表,说明操作符压根没注册成功,回去看控制台报错;如果输出了具体操作符但菜单里没有,那多半是界面上下文问题,切回 3D 视图、清空选中对象再试。
5.3 现象三:一点导入就抛 Python 异常
现象:菜单项能点,点完弹出错误提示,控制台刷出一屏堆栈。
原因:按频率排,一是数据文件本身有问题,比如 shapefile 缺少配套的.dbf或.shx,单独的.shp是读不出属性表的;二是字符编码,属性表里带非 ASCII 字符时默认编码读不动;三是文件路径里有中文或空格,某些内部调用没做转义。
解决:先查文件完整性,一个 shapefile 至少要有.shp、.shx、.dbf三个同名文件。再查路径,把数据挪到一个纯英文无空格的短路径下重试,这一步能排除掉相当一部分莫名其妙的报错。编码问题在导入参数面板里通常有编码选项,改成GBK或UTF-8试一遍,属性表能正常显示就说明是编码问题。
注意:不要把所有导入报错都当成插件坏了。堆栈的最后一行往往指向具体文件和数据行号,先读那行再决定要不要重装。
5.4 现象四:模型进来了,但位置离谱或者比例不对
现象:导入后场景里确实多了东西,但要么缩成一个点看不见,要么跑到视口几百公里外,要么整体大了或小了几百倍。
原因:三个可能。坐标参考填错,把经纬度当米或者反过来;视口裁剪范围没调,模型在视野外被裁掉;场景比例因子被改过,导入的对象按缩放后的单位计算位置。
解决:先按 4.2 节的代码重置单位设置和裁剪范围,排除后两项。还在原地打转的话,选中导入的对象,按小键盘的.键聚焦到它身上,看它的实际坐标量级:坐标在个位数到几十,说明用的是度为单位;在几万到几百万,说明是投影后的米。对着量级反推坐标参考填得对不对,比盲试参数快得多。
6. 验证跑通:用一份小范围数据把「坐标、比例、贴图」三件事验一遍
插件装完、参数配好,最后一步是验证。不要拿一份几百万要素的全省数据来试,那玩意儿出错时你根本分不清是数据问题还是配置问题。找一份范围小、自带坐标声明、要素数量在几十到几百之间的数据,跑一遍三点验证:
| 验证项 | 期望结果 | 判断依据 |
|---|---|---|
| 坐标量级 | 物体location在万级到百万级(米) | 个位数说明还是经纬度 |
| 尺寸比例 | 量一个已知长度的地物,数值与实地接近 | 差几十倍说明投影或比例错了 |
| 贴图对齐 | 影像与矢量边界重合 | 明显错位说明 SRC/DST 不一致 |
验证坐标量级,选中对象后在右侧变换面板看Location,或者用一行代码打印:
import bpy for obj in bpy.context.selected_objects: loc = obj.matrix_world.translation print(obj.name, round(loc.x, 2), round(loc.y, 2), round(loc.z, 2))matrix_world.translation拿的是世界坐标,比直接读obj.location可靠,因为后者受父子关系和 Georender 影响。数值量级对上了,前两项基本就过了。
贴图对齐这一项最容易被忽略,也最能暴露坐标参考填错。做法是先导入矢量边界,再导入同范围的影像,两层叠在一起看边界和影像上的地物是否吻合。错位但不缩放,通常是 SRC 和 DST 用了不同基准;既错位又缩放,通常是源坐标参考填错了。
我自己的习惯是每次新装环境都拿同一份小样数据跑一遍这三点,不管这次装得多顺利。血泪经验是有一回省了这一步,直接上了一份大范围数据,渲染了四个小时才发现整体偏了三百米,返工重来的时间够我把这套流程走上十遍。那份小样数据我现在还留着,跟着插件安装包放一起,装完就验,验完再动真数据。
希望帮到你。
本文还有配套的精品资源,点击获取