First draft of DUI3 instancing
This commit is contained in:
Родитель
bf7eafeceb
Коммит
18ab05b140
|
@ -391,7 +391,12 @@ const getStream = () => {
|
|||
// Rhino sRGB vertex colors
|
||||
// 'https://app.speckle.systems/projects/47bbaf594f/models/ef78e94f72'
|
||||
// qGIS sRGB vertex colors
|
||||
'https://latest.speckle.systems/projects/5a6609a4b9/models/10f4931e8c'
|
||||
// 'https://latest.speckle.systems/projects/5a6609a4b9/models/10f4931e8c'
|
||||
// DUI3 blocks
|
||||
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/c6f3f309a2'
|
||||
'https://latest.speckle.systems/projects/126cd4b7bb/models/6b62c61a22'
|
||||
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/0a6a715a0a'
|
||||
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/4dc5265453'
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ export type SpeckleObject = {
|
|||
name?: string
|
||||
referencedId?: string
|
||||
units?: string
|
||||
applicationId?: string
|
||||
}
|
||||
|
||||
export interface ViewerParams {
|
||||
|
|
|
@ -19,6 +19,7 @@ export enum SpeckleType {
|
|||
RevitInstance = 'RevitInstance',
|
||||
Text = 'Text',
|
||||
Transform = 'Transform',
|
||||
InstanceProxy = 'InstanceProxy',
|
||||
Unknown = 'Unknown'
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { MathUtils } from 'three'
|
||||
import { MathUtils, Matrix4 } from 'three'
|
||||
import { type TreeNode, WorldTree } from '../../tree/WorldTree.js'
|
||||
import { NodeMap } from '../../tree/NodeMap.js'
|
||||
import type { SpeckleObject } from '../../../index.js'
|
||||
import { SpeckleType, type SpeckleObject } from '../../../index.js'
|
||||
import type ObjectLoader from '@speckle/objectloader'
|
||||
import Logger from '../../utils/Logger.js'
|
||||
|
||||
|
@ -22,6 +22,8 @@ export default class SpeckleConverter {
|
|||
private spoofIDs = false
|
||||
private tree: WorldTree
|
||||
private typeLookupTable: { [type: string]: string } = {}
|
||||
private instanceDefinitionLookupTable: { [id: string]: TreeNode } = {}
|
||||
private instancedObjectsLookupTable: { [id: string]: SpeckleObject } = {}
|
||||
private instanceCounter = 0
|
||||
|
||||
private readonly NodeConverterMapping: {
|
||||
|
@ -44,6 +46,8 @@ export default class SpeckleConverter {
|
|||
RevitInstance: this.RevitInstanceToNode.bind(this),
|
||||
Text: this.TextToNode.bind(this),
|
||||
Dimension: this.DimensionToNode.bind(this),
|
||||
InstanceDefinitionProxy: this.InstanceDefinitionProxyToNode.bind(this),
|
||||
InstanceProxy: this.InstanceProxyToNode.bind(this),
|
||||
Parameter: null
|
||||
}
|
||||
|
||||
|
@ -521,6 +525,105 @@ export default class SpeckleConverter {
|
|||
}
|
||||
}
|
||||
|
||||
private async InstanceDefinitionProxyToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
if (!obj.applicationId) {
|
||||
Logger.warn(`Instance Definition Proxy ${obj.id} has no applicationId`)
|
||||
return
|
||||
}
|
||||
this.instanceDefinitionLookupTable[obj.applicationId] = node
|
||||
}
|
||||
|
||||
private getInstanceProxyDefinitionId(obj: SpeckleObject): string {
|
||||
return (obj.DefinitionId || obj.definitionId) as string
|
||||
}
|
||||
|
||||
private getInstanceProxyTransform(obj: SpeckleObject): Array<number> {
|
||||
if (!(obj.transform || obj.Transform)) {
|
||||
return new Matrix4().toArray()
|
||||
}
|
||||
return (obj.transform || obj.Transform) as Array<number>
|
||||
}
|
||||
|
||||
private createTransformNode(obj: SpeckleObject) {
|
||||
const transformNodeId = MathUtils.generateUUID()
|
||||
const transformData = this.getEmptyTransformData(transformNodeId)
|
||||
transformData.units = obj.units as string
|
||||
transformData.matrix = this.getInstanceProxyTransform(obj)
|
||||
return this.tree.parse({
|
||||
id: transformNodeId,
|
||||
raw: transformData,
|
||||
atomic: false,
|
||||
children: []
|
||||
})
|
||||
}
|
||||
|
||||
private async InstanceProxyToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
return
|
||||
}
|
||||
|
||||
private async ConvertInstanceProxyToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
const definitionId = this.getInstanceProxyDefinitionId(obj)
|
||||
if (!definitionId) {
|
||||
Logger.warn(`Instance Proxy ${obj.id} has no definitionId`)
|
||||
return
|
||||
}
|
||||
const definition = this.instanceDefinitionLookupTable[definitionId]
|
||||
const transformNode = this.createTransformNode(obj)
|
||||
|
||||
this.tree.addNode(transformNode, node)
|
||||
const objectApplicationIds = definition.model.raw.Objects
|
||||
for (const objectApplicationId of objectApplicationIds) {
|
||||
const speckleData = this.instancedObjectsLookupTable[objectApplicationId]
|
||||
const instancedNode = this.tree.parse({
|
||||
id: this.getCompoundId(speckleData.id, this.instanceCounter++),
|
||||
raw: speckleData,
|
||||
atomic: false,
|
||||
children: [],
|
||||
instanced: true
|
||||
})
|
||||
this.tree.addNode(instancedNode, transformNode)
|
||||
await this.convertToNode(speckleData, instancedNode)
|
||||
}
|
||||
}
|
||||
|
||||
public async convertInstances() {
|
||||
// uh, oh
|
||||
this.NodeConverterMapping.InstanceProxy = this.ConvertInstanceProxyToNode.bind(this)
|
||||
for (const k in this.instanceDefinitionLookupTable) {
|
||||
const definition = this.instanceDefinitionLookupTable[k]
|
||||
const objectApplicationIds = definition.model.raw.Objects
|
||||
for (const objectApplicationId of objectApplicationIds) {
|
||||
const objectNodes = this.tree.findAll((node: TreeNode) => {
|
||||
// String vs int
|
||||
return (
|
||||
node.model.raw.applicationId === Number.parseInt(objectApplicationId) ||
|
||||
node.model.raw.applicationId === objectApplicationId
|
||||
)
|
||||
})
|
||||
const objectNode = objectNodes[0]
|
||||
this.instancedObjectsLookupTable[objectApplicationId] = objectNode.model.raw
|
||||
|
||||
this.tree.removeNode(objectNode, true)
|
||||
}
|
||||
}
|
||||
const plm: TreeNode[] = []
|
||||
await this.tree.walkAsync((node: TreeNode) => {
|
||||
const type = this.getSpeckleType(node.model.raw)
|
||||
if (type !== SpeckleType.InstanceProxy) {
|
||||
return true
|
||||
}
|
||||
plm.push(node)
|
||||
return true
|
||||
})
|
||||
for (let i = 0; i < plm.length; i++) {
|
||||
await this.convertToNode(plm[i].model.raw, plm[i])
|
||||
}
|
||||
// for (let k = 0; k < this.instanceProxies.length; k++) {
|
||||
// const node = this.instanceProxies[k]
|
||||
// await this.convertToNode(node.model.raw, node)
|
||||
// }
|
||||
}
|
||||
|
||||
private async PointcloudToNode(obj: SpeckleObject, node: TreeNode) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
|
|
|
@ -70,6 +70,8 @@ export class SpeckleGeometryConverter extends GeometryConverter {
|
|||
return this.TextToGeometryData(node)
|
||||
case SpeckleType.Transform:
|
||||
return this.TransformToGeometryData(node)
|
||||
case SpeckleType.InstanceProxy:
|
||||
return this.InstanceProxyToGeometyData(node)
|
||||
case SpeckleType.Unknown:
|
||||
// console.warn(`Skipping geometry conversion for ${type}`)
|
||||
return null
|
||||
|
@ -176,6 +178,11 @@ export class SpeckleGeometryConverter extends GeometryConverter {
|
|||
return null
|
||||
}
|
||||
|
||||
private InstanceProxyToGeometyData(node: NodeData): GeometryData | null {
|
||||
node
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* POINT CLOUD
|
||||
*/
|
||||
|
|
|
@ -128,6 +128,8 @@ export class SpeckleLoader extends Loader {
|
|||
return Promise.resolve(false)
|
||||
}
|
||||
|
||||
await this.converter.convertInstances()
|
||||
|
||||
const t0 = performance.now()
|
||||
const geometryConverter = new SpeckleGeometryConverter()
|
||||
|
||||
|
|
|
@ -108,8 +108,14 @@ export class WorldTree {
|
|||
if (this.nodeMaps[parent.model.subtreeId]?.addNode(node)) parent.addChild(node)
|
||||
}
|
||||
|
||||
public removeNode(node: TreeNode): void {
|
||||
public removeNode(node: TreeNode, removeChildren: boolean): void {
|
||||
const children = node.children
|
||||
this.nodeMaps[node.model.subtreeId]?.removeNode(node)
|
||||
node.drop()
|
||||
if (!removeChildren || !children) return
|
||||
for (let k = 0; k < children.length; k++) {
|
||||
this.removeNode(children[k], removeChildren)
|
||||
}
|
||||
}
|
||||
|
||||
public findAll(predicate: SearchPredicate, node?: TreeNode): Array<TreeNode> {
|
||||
|
|
Загрузка…
Ссылка в новой задаче