783. Continued working on batching. Got first batches to render on the screen. A bit messed up, but it's something
This commit is contained in:
@@ -1,15 +1,75 @@
|
||||
import { BufferGeometry } from 'three'
|
||||
import {
|
||||
BufferGeometry,
|
||||
Float32BufferAttribute,
|
||||
Material,
|
||||
Mesh,
|
||||
Uint32BufferAttribute
|
||||
} from 'three'
|
||||
import { NodeRenderView } from './NodeRenderView'
|
||||
|
||||
export default class Batch {
|
||||
private id: string
|
||||
private renderViews: NodeRenderView[]
|
||||
private bufferGeometry: BufferGeometry
|
||||
private material: Material
|
||||
public mesh: Mesh
|
||||
|
||||
public constructor() {
|
||||
public constructor(id: string, renderViews: NodeRenderView[]) {
|
||||
this.id = id
|
||||
this.renderViews = renderViews
|
||||
this.bufferGeometry = new BufferGeometry()
|
||||
}
|
||||
|
||||
public addRenderView(renderView: NodeRenderView) {
|
||||
this.renderViews.push(renderView)
|
||||
public setMaterial(material: Material) {
|
||||
this.material = material
|
||||
|
||||
this.mesh
|
||||
this.material
|
||||
this.renderViews
|
||||
this.bufferGeometry
|
||||
}
|
||||
|
||||
public buildBatch() {
|
||||
const indicesCount = this.renderViews.flatMap(
|
||||
(val: NodeRenderView) => val.renderData.geometry.attributes.INDEX
|
||||
).length
|
||||
const attributeCount = this.renderViews.flatMap(
|
||||
(val: NodeRenderView) => val.renderData.geometry.attributes.POSITION
|
||||
).length
|
||||
const indices = new Int32Array(indicesCount)
|
||||
const position = new Float32Array(attributeCount)
|
||||
let offset = 0
|
||||
let arrayOffset = 0
|
||||
for (let k = 0; k < this.renderViews.length; k++) {
|
||||
const geometry = this.renderViews[k].renderData.geometry
|
||||
indices.set(
|
||||
geometry.attributes.INDEX.map((val) => val + offset),
|
||||
arrayOffset
|
||||
)
|
||||
position.set(geometry.attributes.POSITION, offset)
|
||||
this.renderViews[k].setBatchData(
|
||||
this.id,
|
||||
arrayOffset,
|
||||
geometry.attributes.INDEX.length
|
||||
)
|
||||
|
||||
offset += geometry.attributes.POSITION.length
|
||||
arrayOffset += geometry.attributes.INDEX.length
|
||||
}
|
||||
|
||||
this.bufferGeometry.setIndex(new Uint32BufferAttribute(indices, 1))
|
||||
|
||||
this.bufferGeometry.setAttribute(
|
||||
'position',
|
||||
new Float32BufferAttribute(position, 3)
|
||||
)
|
||||
|
||||
this.bufferGeometry.computeVertexNormals()
|
||||
this.bufferGeometry.computeBoundingSphere()
|
||||
this.bufferGeometry.computeBoundingBox()
|
||||
|
||||
// Geometry.updateRTEGeometry(this.bufferGeometry)
|
||||
|
||||
this.mesh = new Mesh(this.bufferGeometry, this.material)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { generateUUID } from 'three/src/math/MathUtils'
|
||||
import Batch from './Batch'
|
||||
import { SpeckleType } from './converter/GeometryConverter'
|
||||
import { WorldTree } from './converter/WorldTree'
|
||||
import Materials from './materials/Materials'
|
||||
|
||||
export default class Batcher {
|
||||
private materials: Materials
|
||||
public batches: { [id: string]: Batch } = {}
|
||||
|
||||
public constructor() {
|
||||
this.materials = new Materials()
|
||||
@@ -30,6 +33,15 @@ export default class Batcher {
|
||||
const batch = rendeViews.slice(batchStart, m)
|
||||
batches.push(batch)
|
||||
batchStart += batch.length
|
||||
|
||||
const material = this.materials.updateMaterialMap(
|
||||
materialHashes[k],
|
||||
batch[0].renderData.renderMaterial
|
||||
)
|
||||
const batchID = generateUUID()
|
||||
this.batches[batchID] = new Batch(batchID, batch)
|
||||
this.batches[batchID].setMaterial(material)
|
||||
this.batches[batchID].buildBatch()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,13 @@ export interface NodeRenderData {
|
||||
geometry: GeometryData
|
||||
renderMaterial: RenderMaterial
|
||||
displayStyle: DisplayStyle
|
||||
batchId: string
|
||||
batchIndexStart: number
|
||||
batchIndexCount: number
|
||||
}
|
||||
|
||||
export class NodeRenderView {
|
||||
private _batchId: string
|
||||
private _batchIndexStart: number
|
||||
private _batchIndexCount: number
|
||||
|
||||
private readonly _renderData: NodeRenderData
|
||||
private _materialHash: number
|
||||
|
||||
@@ -34,9 +35,23 @@ export class NodeRenderView {
|
||||
return this._materialHash
|
||||
}
|
||||
|
||||
public get hasGeometry() {
|
||||
return this._renderData.geometry && this._renderData.geometry.attributes
|
||||
}
|
||||
|
||||
public constructor(data: NodeRenderData) {
|
||||
this._renderData = data
|
||||
this._materialHash = this.getMaterialHash(data.renderMaterial)
|
||||
|
||||
this._batchId
|
||||
this._batchIndexCount
|
||||
this._batchIndexStart
|
||||
}
|
||||
|
||||
public setBatchData(id: string, start: number, count: number) {
|
||||
this._batchId = id
|
||||
this._batchIndexStart = start
|
||||
this._batchIndexCount = count
|
||||
}
|
||||
|
||||
private getMaterialHash(material: RenderMaterial) {
|
||||
|
||||
@@ -16,6 +16,8 @@ export class RenderTree {
|
||||
this.root.walk((node: TreeNode): boolean => {
|
||||
const rendeNode = this.buildRenderNode(node)
|
||||
node.model.renderView = rendeNode ? new NodeRenderView(rendeNode) : null
|
||||
if (node.model.renderView && node.model.renderView.hasGeometry)
|
||||
Geometry.transformGeometryData(rendeNode.geometry, this.computeTransform(node))
|
||||
return true
|
||||
})
|
||||
}
|
||||
@@ -33,10 +35,7 @@ export class RenderTree {
|
||||
Materials.renderMaterialFromNode(node.parent),
|
||||
displayStyle:
|
||||
Materials.displayStyleFromNode(node) ||
|
||||
Materials.displayStyleFromNode(node.parent),
|
||||
batchId: 'n/a',
|
||||
batchIndexStart: 0,
|
||||
batchIndexCount: 0
|
||||
Materials.displayStyleFromNode(node.parent)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
@@ -77,7 +76,7 @@ export class RenderTree {
|
||||
if (renderView) {
|
||||
const renderData = renderView.renderData
|
||||
if (renderData.speckleType === SpeckleType.BlockInstance) return true
|
||||
Geometry.transformGeometryData(renderData.geometry, this.computeTransform(node))
|
||||
// Geometry.transformGeometryData(renderData.geometry, this.computeTransform(node))
|
||||
let geometry = null
|
||||
let wrapperType = ''
|
||||
/** ULTA-TEMPORARY */
|
||||
|
||||
@@ -107,12 +107,17 @@ export default class ViewerObjectLoader {
|
||||
WorldTree.getRenderTree().buildRenderTree()
|
||||
|
||||
batcher.makeBatches()
|
||||
for (const k in batcher.batches) {
|
||||
this.viewer.scene.add(batcher.batches[k].mesh)
|
||||
}
|
||||
|
||||
parsedObjects = WorldTree.getRenderTree().getObjectWrappers()
|
||||
|
||||
for (let k = 0; k < parsedObjects.length; k++) {
|
||||
await this.converter.asyncPause()
|
||||
this.viewer.sceneManager.addObject(parsedObjects[k])
|
||||
}
|
||||
|
||||
await this.viewer.sceneManager.postLoadFunction()
|
||||
this.viewer.emit('load-complete')
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { DoubleSide, Material } from 'three'
|
||||
import { DoubleSide, Material, MeshStandardMaterial } from 'three'
|
||||
import { TreeNode } from '../converter/WorldTree'
|
||||
import { DisplayStyle, RenderMaterial } from '../NodeRenderView'
|
||||
import SpeckleStandardMaterial from './SpeckleStandardMaterial'
|
||||
|
||||
export default class Materials {
|
||||
private readonly materialMap: { [hash: number]: Material } = {}
|
||||
@@ -30,18 +29,30 @@ export default class Materials {
|
||||
return displayStyle
|
||||
}
|
||||
|
||||
public updateMaterialMap(hash: number, renderMaterial: RenderMaterial) {
|
||||
public updateMaterialMap(hash: number, renderMaterial: RenderMaterial): Material {
|
||||
if (this.materialMap[hash]) {
|
||||
console.warn(`Duplicate material hash found: ${hash}, overwritting`)
|
||||
}
|
||||
|
||||
this.materialMap[hash] = new SpeckleStandardMaterial({
|
||||
color: renderMaterial.color,
|
||||
emissive: 0x0,
|
||||
roughness: 1,
|
||||
metalness: 0,
|
||||
side: DoubleSide // TBD
|
||||
// clippingPlanes: this.viewer.sectionBox.planes
|
||||
})
|
||||
if (renderMaterial) {
|
||||
this.materialMap[hash] = new MeshStandardMaterial({
|
||||
color: renderMaterial.color,
|
||||
emissive: 0x0,
|
||||
roughness: 1,
|
||||
metalness: 0,
|
||||
side: DoubleSide // TBD
|
||||
// clippingPlanes: this.viewer.sectionBox.planes
|
||||
})
|
||||
} else {
|
||||
this.materialMap[hash] = new MeshStandardMaterial({
|
||||
color: 0xff00ff,
|
||||
emissive: 0x0,
|
||||
roughness: 1,
|
||||
metalness: 0,
|
||||
side: DoubleSide // TBD
|
||||
// clippingPlanes: this.viewer.sectionBox.planes
|
||||
})
|
||||
}
|
||||
return this.materialMap[hash]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user