Model
基于Three.js的3D模型管理模块,用于管理3D场景中的对象。作为3D场景的核心容器,组织和管理实例化对象、合并对象和单一对象。
类定义
class NodeIndex
class Model extends Group静态属性
GROUP_TYPE
NIVIOBIM组的类型枚举,定义支持的组类型。
类型: {Object}
静态: true
只读: true
属性:
INSTANCED{string} - 实例化组类型MERGED{string} - 合并组类型SINGLE{string} - 单一组类型MODEL{string} - 模型类型
示例:
// 检查组类型
if (groupType === GROUP_TYPE.INSTANCED) {
console.log('这是实例化组');
}OBJECT3D_TYPE
NIVIOBIM 3D对象的类型枚举,定义支持的3D对象类型。
类型: {Object}
静态: true
只读: true
属性:
MESH{string} - 网格对象类型LINE{string} - 线条对象类型LINE_SEGMENTS{string} - 线段对象类型LINE_LOOP{string} - 闭合线条对象类型
示例:
// 检查对象类型
if (object.type === OBJECT3D_TYPE.MESH) {
console.log('这是网格对象');
}构造函数
constructor()
创建模型实例,初始化模型对象,创建三个子组:实例化组、合并组和独立组。设置用户数据,包括材质管理、节点索引、包围盒等。
示例:
// 创建模型实例
const model = new Model();
// 访问子组
const instancedGroup = model.instancedGroup;
const mergedGroup = model.mergedGroup;
const singleGroup = model.singleGroup;属性
allMaterials
获取所有材质,返回模型中所有类型的材质数组,包括实例化、合并和单一对象的材质。
类型: {Array<Material>}
只读: true
示例:
// 获取所有材质
const materials = model.allMaterials;
console.log(`模型包含 ${materials.length} 个材质`);instancedGroup
获取实例化组,返回包含所有实例化对象的组,用于管理具有相同几何体和材质的多个实例。
类型: {Group}
只读: true
示例:
// 获取实例化组
const instancedGroup = model.instancedGroup;
console.log(`实例化组包含 ${instancedGroup.children.length} 个对象`);mergedGroup
获取合并组,返回包含所有合并对象的组,用于管理具有相同材质但不同几何体的对象。
类型: {Group}
只读: true
示例:
// 获取合并组
const mergedGroup = model.mergedGroup;
console.log(`合并组包含 ${mergedGroup.children.length} 个对象`);singleGroup
获取独立组,返回包含所有独立对象的组,用于管理具有独特几何体和材质的单个对象。
类型: {Group}
只读: true
示例:
// 获取独立组
const singleGroup = model.singleGroup;
console.log(`独立组包含 ${singleGroup.children.length} 个对象`);count
获取模型几何元素个数,返回模型中所有几何元素的总数,包括实例化、合并和独立对象的数量。
类型: {number}
只读: true
示例:
// 获取几何元素个数
const count = model.count;
console.log(`模型包含 ${count} 个几何元素`);方法
add(NWYDObject)
添加NWYD对象到模型,将逆维悦动数据对象添加到模型中,自动处理材质管理和对象分组。支持实例化对象、合并对象和单一对象的添加。
参数:
NWYDObject{Object3D} - 逆维悦动数据对象,必须是支持的NWYD对象类型
返回值:
- {Object3D|Error} 添加的对象或错误信息
示例:
// 添加实例化网格
const result = model.add(instancedMesh);
if (result instanceof Error) {
console.error('添加失败:', result.message);
} else {
console.log('添加成功');
}addNodeIndex(uniqueId, userData)
添加节点索引,为指定的唯一标识符添加节点索引信息,用于建立对象的层级关系。
参数:
uniqueId{string} - 唯一标识符userData{Object} - 用户数据,包含Database_ID、Revit_ID、name等属性
示例:
// 添加节点索引
const userData = {
Database_ID: 123,
Revit_ID: 'abc-123',
name: 'Building A'
};
model.addNodeIndex('unique-id-123', userData);computeBVHTree()
计算模型的BVH树,构建模型的包围盒层次结构(BVH)树,用于加速射线检测和视锥体剔除。BVH树使用世界坐标系下的包围盒进行计算。
抛出:
- {Error} 当场景包围盒未定义时抛出错误
示例:
// 计算BVH树
try {
model.computeBVHTree();
console.log('BVH树构建成功');
} catch (error) {
console.error('BVH树构建失败:', error.message);
}getInstance(uniqueId, overrideMaterial, edgesLineMaterial)
根据唯一ID获取几何实例,根据唯一标识符获取指定的几何实例,支持材质覆盖和边缘线材质设置。返回包含节点组和包围球的对象。
参数:
uniqueId{string} - 模型的唯一标识符overrideMaterial{Material} [可选] - 替换图形的材质,可选edgesLineMaterial{Material} [可选] - 边缘线材质,可选
返回值:
- {Object|null} 几何实例对象,包含node(节点组)和boundingSphere(包围球),如果未找到则返回null
示例:
// 获取几何实例
const instance = model.getInstance('unique-id-123');
if (instance) {
console.log('找到实例:', instance.node);
console.log('包围球:', instance.boundingSphere);
}setVisibleByUniqueId(uniqueId, boolean)
通过唯一ID设置实例可见性,根据唯一标识符设置对应实例的可见性,支持实例化、合并和单一对象。
参数:
uniqueId{string} - 模型的唯一标识符boolean{boolean} - 是否可见,true为可见,false为隐藏
示例:
// 隐藏实例
model.setVisibleByUniqueId('unique-id-123', false);
// 显示实例
model.setVisibleByUniqueId('unique-id-123', true);getBVHTreeFromJson(json)
从JSON数据构造BVH树,从BVHNode的序列化数据中重新构造BVH树,用于恢复之前保存的BVH结构。
参数:
json{Object} - BVH树序列化数据
示例:
// 从JSON构造BVH树
const bvhJson = { box3: {}, children: [] };
model.getBVHTreeFromJson(bvhJson);renderSort()
渲染排序,对组内的逆维悦动数据对象进行排序,按照renderId进行升序排列。这有助于优化渲染性能和确保渲染顺序的一致性。
示例:
// 对模型进行渲染排序
model.renderSort();getOptimumRadio()
获取优化比率,计算模型的优化比率,比较优化前后的对象数量,显示优化效果。
返回值:
- {Object} 优化比率信息,包含merged(优化后数量)、old(优化前数量)、radio(优化比率百分比)
示例:
// 获取优化比率
const ratio = model.getOptimumRadio();
console.log(`优化前: ${ratio.old} 个对象`);
console.log(`优化后: ${ratio.merged} 个对象`);
console.log(`优化比率: ${ratio.radio}`);getNodeIndexByUniqueId(uniqueId)
根据唯一ID获取节点索引,根据唯一标识符获取对应的节点索引信息,包含子节点、数据库ID、Revit ID等。
参数:
uniqueId{string} - 唯一标识符
返回值:
- {NodeIndex} 节点索引信息,如果未找到则返回undefined
示例:
// 获取节点索引
const nodeIndex = model.getNodeIndexByUniqueId('unique-id-123');
if (nodeIndex) {
console.log('节点名称:', nodeIndex.name);
console.log('数据库ID:', nodeIndex.databaseId);
console.log('子节点数量:', nodeIndex.children.length);
}raycast(raycaster, intersection)
射线检测,对模型进行射线检测,如果存在BVH树则使用BVH加速,否则使用传统方法。
参数:
raycaster{Raycaster} - 射线投射器intersection{Array} [可选] - 相交结果数组,可选参数
示例:
// 射线检测
const raycaster = new THREE.Raycaster();
const intersections = [];
model.raycast(raycaster, intersections);
console.log('相交对象数量:', intersections.length);bvhRayCaster(ray)
BVH射线检测,使用BVH树进行高效的射线检测,返回与射线相交的对象数组。
参数:
ray{Ray} - 射线对象
返回值:
- {Array} 相交对象数组
示例:
// BVH射线检测
const ray = new THREE.Ray(origin, direction);
const objects = model.bvhRayCaster(ray);
console.log('相交对象数量:', objects.length);getRenderInstanceByBVHNodes(model, bvhNodes, objectsArray)
根据BVH节点获取渲染实例,根据BVH节点数组获取对应的渲染实例对象,用于射线检测后的对象获取。
参数:
model{Model} - 模型对象bvhNodes{Array} - BVH节点数组objectsArray{Array} - 对象数组,用于存储结果
示例:
// 根据BVH节点获取渲染实例
const objects = [];
model.getRenderInstanceByBVHNodes(model, bvhNodes, objects);
console.log('获取到的对象数量:', objects.length);使用场景
3D场景处理
- 将大量相似对象进行实例化处理,减少绘制调用
- 合并相同材质的对象,减少绘制调用
- 使用BVH树支持射线检测和视锥体剔除
- 自动选择相应的处理策略
模型管理
- 统一管理3D模型的各种对象组
- 提供模型的层级结构管理
- 支持模型的序列化和反序列化
- 建立对象的索引映射关系
渲染处理
- 通过实例化对象减少绘制调用
- 通过合并对象减少绘制调用
- 使用BVH树支持碰撞检测
- 材质共享,减少内存使用
边界计算
- 自动计算模型的包围盒和包围球
- 为相机定位提供参考
- 支持模型的自动适配
- 世界坐标系下的包围盒计算
数据结构
- 提供模型的标准数据结构
- 支持模型的元数据存储
- 便于模型的扩展和定制
- 支持外部系统数据映射
相关链接
- InstancedObjects - 实例化对象
- MergedObjects - 合并对象
- SingleObjects - 单对象