3D 模型模块
脚本入口: eve.Model3D()
通过 medialoader/Assimp 载入模型数据,再交给图形模块渲染。
基本用法
读取材质并装配渲染对象
ModelData 可以直接读取材质参数(base color、metallic/roughness、贴图路径与内嵌贴图), 然后交给 createRenderable 一键装配成可渲染的 Renderable3D:
内嵌贴图(glTF/FBX 内嵌 PNG/JPEG)用 getEmbeddedTextureCount() 查询, getEmbeddedTextureImageData(idx) 解码为 ImageData(调用方负责释放)。
对象关系与调用时机
Model3D 只负责加载 ModelData;ModelData 包含 mesh/material 数据和统计信息。GPU mesh、材质实例、摄像机与实际 draw 属于 Graphics。
从碰撞点反查 UV 的同一套 ModelData 也可以**程序化改顶点法线**,再烘焙成法线贴图:
setVertexNormal(mesh, vertex, x, y, z) 写单个顶点。bakeNormalMap 的 space 为 "tangent"(PBR 采样)或 "object"。无 UV 的 mesh 会失败。 newModelDataFromFile 走共享缓存,不要在被多方持有的实例上改法线;从内存 newModelData 解码一份再改。
目标导向指南
载入并检查模型
用 newModelDataFromFile(path) 载入 glTF/FBX/OBJ 等支持格式;先读取 mesh/material/face/vertex 数量并检查法线、UV,失败时显示占位模型。资源应在初始化或加载阶段创建。
提交模型渲染
将 ModelData 转换为 Graphics 所需 mesh/renderable,设置材质、变换和光照标志,再在渲染阶段调用 3D 渲染入口。模型数据可复用,实例只保存不同变换。
从碰撞点反查 UV
用 getVertexPosition(meshIndex, vertexIndex, component) 和 getFaceVertexIndex(meshIndex, triangleIndex, corner) 按导入模型的原始拓扑构建三角形碰撞体。 射线命中后,将命中三角形索引与模型局部坐标传给 mapSurfacePointToUv(meshIndex, triangleIndex, localX, localY, localZ, channel)。返回的 SurfaceUv 提供 getU()、getV()、getBarycentricA()、getBarycentricB()、 getBarycentricC()、getTriangleIndex() 和 getUvChannel()。命中点必须是模型局部空间; 若渲染实例有变换,需先将世界命中点反变换到局部空间。
常见问题
- 在 render 中载入模型:I/O 和解析必须在加载阶段。
- 模型无 normals 仍启用光照:先检查
hasNormals()。 - 每个实例重复加载同一文件:共享 ModelData 和 GPU 资源。
API 快查
下列方法名来自当前 Squirrel 绑定;同一模块创建的辅助对象(例如 World、Body、Source)的方法也列在这里。
empty()、getFaceCount()、getMaterialCount()、getMeshCount()、getName()、getVertexCount()、hasNormals()、hasTexCoords()- 表面拓扑与 UV 反查:
getVertexPosition()、getFaceVertexIndex()、mapSurfacePointToUv();SurfaceUv.getU()、getV()、getBarycentricA()、getBarycentricB()、getBarycentricC()、getTriangleIndex()、getUvChannel() - 顶点流:
getTexCoordChannelCount()、hasTexCoordChannel()、getTexCoord()、hasTangents()、getTangent()、getBitangent()、getVertexColorChannelCount()、hasVertexColorChannel()、getVertexColor()、getVertexNormal()、setVertexNormal()、applyVertexNormals()、applyVertexNormalsFrom()、bakeNormalMap() - 材质:
getMaterialIndex()、getMaterialName()、getMaterialBaseColorR/G/B/A()、getMaterialMetallicFactor()、getMaterialRoughnessFactor()、getMaterialOpacity()、getMaterialTwoSided()、getMaterialAlphaMode()、getMaterialAlphaCutoff()、getMaterialTextureSlotCount()、getMaterialTexturePath()、getMaterialTextureEmbeddedIndex() - 内嵌贴图:
getEmbeddedTextureCount()、getEmbeddedTextureName()、getEmbeddedTextureWidth()、getEmbeddedTextureHeight()、getEmbeddedTextureImageData() - 蒙皮:
hasBones()、getBoneCount()、getBoneName()、getInverseBindMatrixElement()、getBoneWeightCount()、getBoneWeightVertex()、getBoneWeightValue() - 动画剪辑:
getAnimationCount()、getAnimationName() newModelData()、newModelDataFromFile()、createRenderable()- 离线封装:
bakeModel(sourcePath, destinationPath)将自包含 GLB/FBX 打包为.evmodel;部署时仍用newModelDataFromFile()透明加载。
.evmodel 是稳定的单文件传输封装,记录原始格式并避免部署时扩展名猜测;它不会自动收集 OBJ/MTL 的外部 sidecar,因此离线生产优先以 GLB 或内嵌贴图 FBX 为输入。GPU Mesh 会保留所有导入 UV、顶点色及 tangent/bitangent 流供自定义管线和后续烘焙使用;内置 PBR shader 当前仍以 UV0 采样。
createRenderable(gfx, modelData, meshIndex) 内部等价于 C++ 的 model3d::buildRenderable(节点世界变换烘焙进顶点,材质 tint / metallic / roughness 与 albedo、normal、height 贴图自动应用,内嵌/外部贴图均可解析)。
注意:Squirrel 绑定按完整参数个数校验,
getMaterialTexturePath/getMaterialTextureEmbeddedIndex需要显式传slot(默认 0)。
使用要点
- 模块对象和它创建的资源对象应保存在全局或实体状态中,不要在每帧重复创建。
- 带
update(dt)的系统应在eve_update调用;绘制方法应在eve_render调用。 - 参数约束、默认值和返回类型以对应模块头文件及
addFunc绑定为准;本文 API 快查与当前源码同步生成。
源码: src/modules/model3d/ 相关测试: 在 test/ 中搜索 model3d。
后台预加载
model3d.requestModelData(path) 返回 Result,将模型读取和解析提交给引擎线程池。 成功仅表示已排队或已缓存;之后 newModelDataFromFile(path) 等待同一个资源缓存条目, 不会重复解析,解析失败仍由该读取报告。预加载使用默认 ModelLoadOptions。 调用发生在游戏线程,后台任务只处理 CPU 数据,不访问脚本 VM 或上传 GPU。 ResourceManager 拥有任务和解析结果,复制路径;清理/卸载遵循其 epoch 与生命周期约定。 缺少线程执行器时返回 Unsupported,空路径返回 InvalidArgument,不默默改为同步加载。 Filesystem 必须先在游戏线程初始化;工作线程不会创建模块。
requestModelDataWithOptions(path, options) 返回提交 Result; loadModelDataWithOptions(path, options) 返回带 value 的读取 Result,value 借用自资源缓存。 options 是严格的布尔值表,可包含 triangulate、generateNormalsIfMissing、 joinIdenticalVertices、flipUVs、improveCacheLocality,省略字段默认 true; 未知字段和非布尔值均拒绝。选项参与缓存键,预加载和读取必须传相同选项。 对已经建立索引的导出网格,可显式关闭 joinIdenticalVertices 和 improveCacheLocality, 保留导出器的顶点/三角形顺序;这不会改变普通模型加载的默认选项。
静态植被变形
model3d.prepareFoliageDeformation(modelData, meshIndex, renderable) 返回 Result, 为由同一模型/网格创建的未蒙皮 Renderable 生成拥有自身存储的静止形态变形数据。 检查索引、顶点数量、有限坐标和正高度后一次提交;失败不替换原数据。 调用成本随顶点数线性增长,只在准备资产时执行,不能每帧重复。 在 main/render 线程同步调用,不保留 modelData 借用,不执行回调。 配合 Graphics 的 configureFoliageWind 与显式时间使用,保留导入 PBR 纹理。