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:
AlexandruPopovici
2022-06-10 00:08:03 +03:00
parent f2c11abb23
commit 757cc7e666
6 changed files with 125 additions and 23 deletions
+64 -4
View File
@@ -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)
}
}
+12
View File
@@ -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
}
}
+18 -3
View File
@@ -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) {
+4 -5
View File
@@ -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]
}
}