Added World to the API. Can be used to check world dimensions and offsets. Cleaned up and added some comment in Viewer. After removing the reference to a lot of issues arose. The frontend and preview-service seems to use it extensively. Changed the calls referencing the interactions to the ones in the API where it was aplicable, and commented out with a note added for the ones that were not aplicable. We proably need to expose a generic way to manipulate the camera from the API

This commit is contained in:
AlexandruPopovici
2022-08-24 18:24:43 +03:00
parent 25c74556d0
commit 632ad53152
14 changed files with 165 additions and 332 deletions
@@ -53,7 +53,7 @@ export default defineComponent({
},
methods: {
setView(view: string) {
this.viewer.interactions.rotateTo(view.toLowerCase())
this.viewer.rotateTo(view.toLowerCase())
}
}
})
@@ -405,7 +405,8 @@ export default {
sectionBox: this.viewer.sectionBox.getCurrentBox(),
selection: null // TODO for later, lazy now
},
screenshot: this.viewer.interactions.screenshot()
//@Dim: Changed this to use the API
screenshot: this.viewer.screenshot()
}
if (this.$route.query.overlay) {
commentInput.resources.push(
@@ -445,7 +446,8 @@ export default {
this.visible = false
this.commentValue = { doc: null, attachments: [] }
setIsAddingComment(false)
this.viewer.interactions.deselectObjects()
//@Dim: Changed this to use the API
this.viewer.resetSelection()
},
sendStatusUpdate() {
// TODO: typing or not
@@ -516,10 +516,11 @@ export default {
if (camToSet[6] === 1) {
this.viewer.toggleCameraProjection()
}
this.viewer.interactions.setLookAt(
{ x: camToSet[0], y: camToSet[1], z: camToSet[2] }, // position
{ x: camToSet[3], y: camToSet[4], z: camToSet[5] } // target
)
//@Dim: This needs to use the API.
// this.viewer.interactions.setLookAt(
// { x: camToSet[0], y: camToSet[1], z: camToSet[2] }, // position
// { x: camToSet[3], y: camToSet[4], z: camToSet[5] } // target
// )
if (camToSet[6] === 1) {
this.viewer.cameraHandler.activeCam.controls.zoom(camToSet[7], true)
}
@@ -254,10 +254,11 @@ export default {
if (camToSet[6] === 1) {
this.viewer.toggleCameraProjection()
}
this.viewer.interactions.setLookAt(
{ x: camToSet[0], y: camToSet[1], z: camToSet[2] }, // position
{ x: camToSet[3], y: camToSet[4], z: camToSet[5] } // target
)
//@Dim: This needs to use the API
// this.viewer.interactions.setLookAt(
// { x: camToSet[0], y: camToSet[1], z: camToSet[2] }, // position
// { x: camToSet[3], y: camToSet[4], z: camToSet[5] } // target
// )
if (camToSet[6] === 1) {
this.viewer.cameraHandler.activeCam.controls.zoom(camToSet[7], true)
}
@@ -466,8 +467,8 @@ export default {
uArrowEl.style.transform = `translate(${newTarget.x}px,${newTarget.y}px) rotate(${angle}rad)`
uArrowEl.style.opacity = user.clipped ? '0' : '1'
}
this.viewer.interactions.overlayObjects(selectedObjects)
//@Dim: This shouldn't be needed anymore, right?
// this.viewer.interactions.overlayObjects(selectedObjects)
}
}
}
@@ -727,6 +727,6 @@ export async function resetFilter() {
currentFilterState: null
})
await viewer.reset()
await viewer.resetFilters()
viewer.applyFilter(null)
}
@@ -269,6 +269,7 @@ import { Nullable } from '@/helpers/typeHelpers'
import { getCamArray } from '@/main/lib/viewer/core/helpers/cameraHelper'
import CommitObjectViewerScope from '@/main/components/viewer/CommitObjectViewerScope.vue'
import PrioritizedPortal from '@/main/components/common/utility/PrioritizedPortal.vue'
import { ViewerEvent } from '@speckle/viewer'
type ErroredResourceData = {
error: boolean
@@ -515,7 +516,7 @@ export default defineComponent({
}
}
this.viewer.on('busy', (val: boolean) => {
this.viewer.on(ViewerEvent.Busy, (val: boolean) => {
setIsViewerBusy(!!val)
this.viewerBusy = val
if (!val && this.camToSet) {
@@ -525,12 +526,14 @@ export default defineComponent({
if (this.camToSet[6] === 1) {
this.viewer.toggleCameraProjection()
}
this.viewer.interactions.setLookAt(
{ x: this.camToSet[0], y: this.camToSet[1], z: this.camToSet[2] }, // position
{ x: this.camToSet[3], y: this.camToSet[4], z: this.camToSet[5] } // target
)
//@Dim: This needs to be replaced with a call from the API.
// this.viewer.interactions.setLookAt(
// { x: this.camToSet[0], y: this.camToSet[1], z: this.camToSet[2] }, // position
// { x: this.camToSet[3], y: this.camToSet[4], z: this.camToSet[5] } // target
// )
if (this.camToSet[6] === 1) {
this.viewer.cameraHandler.activeCam.controls.zoom(this.camToSet[7], true)
//@Dim: This needs to be replaced with a call from the API.
// this.viewer.cameraHandler.activeCam.controls.zoom(this.camToSet[7], true)
}
this.camToSet = null
}, 200)
@@ -726,7 +729,7 @@ export default defineComponent({
async setFilters() {
try {
// repopulate object props
this.objectProperties = await this.viewer.getObjectsProperties()
this.objectProperties = this.viewer.getObjectProperties()
} catch (e) {
this.$eventHub.$emit('notification', {
text: 'Failed to get object properties from viewer.'
+6 -4
View File
@@ -26,15 +26,17 @@ async function pageFunction(objectUrl) {
// Main call failed. Wait some time for other objects to load inside the viewer and generate the preview anyway
await waitForAnimation(1000)
}
v.interactions.zoomExtents(0.95, false)
//@Dim: This needs to use the API
// v.interactions.zoomExtents(0.95, false)
await waitForAnimation(100)
// full 360
for (let i = 0; i < 24; i++) {
v.interactions.rotateCamera(undefined, undefined, false)
//@Dim: This needs to use the API
// v.interactions.rotateCamera(undefined, undefined, false)
await waitForAnimation()
ret.scr[i + ''] = v.interactions.screenshot()
//@Dim: Changed this to use the API
ret.scr[i + ''] = v.screenshot()
}
/*
+4 -11
View File
@@ -7,6 +7,7 @@ import {
import './style.css'
import Sandbox from './Sandbox'
import { IViewer } from '@speckle/viewer'
const container = document.querySelector<HTMLElement>('#renderer')
if (!container) {
@@ -20,7 +21,7 @@ params.showStats = true
// 'https://speckle-xyz-assets.ams3.digitaloceanspaces.com/studio010.hdr'
// 'http://localhost:3033/sample-hdri.exr'
const viewer = new Viewer(container, params)
const viewer: IViewer = new Viewer(container, params)
await viewer.init()
const sandbox = new Sandbox(viewer)
@@ -39,8 +40,8 @@ viewer.on(
)
viewer.on(ViewerEvent.LoadComplete, () => {
Object.assign(Sandbox.sceneParams.worldSize, viewer.worldSize)
Object.assign(Sandbox.sceneParams.worldOrigin, viewer.worldOrigin)
Object.assign(Sandbox.sceneParams.worldSize, viewer.World.worldSize)
Object.assign(Sandbox.sceneParams.worldOrigin, viewer.World.worldOrigin)
sandbox.refresh()
})
@@ -75,11 +76,3 @@ await sandbox.loadUrl(
// 'https://latest.speckle.dev/streams/444bfbd6e4/commits/e22f696b08'
// 'https://latest.speckle.dev/streams/92b620fb17/commits/af6098915b?c=%5B0.02144,-0.0377,0.05554,0.00566,0.00236,0,0,1%5D'
)
// const dataTree: DataTree = viewer.getDataTree()
// console.log(`Built data tree `, dataTree)
// console.log(
// dataTree.findAll((obj: SpeckleObject) => {
// return obj.speckle_type === 'Objects.Geometry.Mesh'
// })
// )
+4 -2
View File
@@ -3,6 +3,7 @@ import sampleHdri from './assets/sample-hdri.png'
import { FilteringState } from './modules/filtering/FilteringManager'
import { PropertyInfo } from './modules/filtering/PropertyManager'
import { DataTree } from './modules/tree/DataTree'
import { World } from './modules/World'
export interface ViewerParams {
postprocessing: boolean
@@ -48,7 +49,8 @@ export enum ViewerEvent {
LoadComplete = 'load-complete',
LoadProgress = 'load-progress',
UnloadComplete = 'unload-complete',
UnloadAllComplete = 'unload-all-complete'
UnloadAllComplete = 'unload-all-complete',
Busy = 'busy'
}
export type SelectionEvent = {
@@ -86,7 +88,6 @@ export const DefaultLightConfiguration: SunLightConfiguration = {
*/
export interface IViewer {
init(): Promise<void>
onWindowResize(): void
on(eventType: ViewerEvent, handler: (arg) => void)
toggleSectionBox(): void
sectionBoxOff(): void
@@ -144,6 +145,7 @@ export interface IViewer {
/** Data ops */
getDataTree(): DataTree
get World(): World
dispose(): void
}
+2 -1
View File
@@ -15,8 +15,9 @@ import {
import { SunLightConfiguration } from './IViewer'
import { DataTree, ObjectPredicate, SpeckleObject } from './modules/tree/DataTree'
import { World } from './modules/World'
export { Viewer, DefaultViewerParams, ViewerEvent, DefaultLightConfiguration }
export { Viewer, DefaultViewerParams, ViewerEvent, DefaultLightConfiguration, World }
export type {
IViewer,
+6 -3
View File
@@ -133,12 +133,14 @@ export default class SectionBox {
const val = !!event.value
if (val) {
this.dragging = val
this.viewer.interactions.preventSelection = val
//@Dim: Not sure what this needs to do in the new viewer
// this.viewer.interactions.preventSelection = val
this.viewer.cameraHandler.enabled = !val
} else {
setTimeout(() => {
this.dragging = val
this.viewer.interactions.preventSelection = val
//@Dim: Not sure what this needs to do in the new viewer
// this.viewer.interactions.preventSelection = val
this.viewer.cameraHandler.enabled = !val
}, 100)
}
@@ -351,9 +353,10 @@ export default class SectionBox {
if (targetBox) box = targetBox
else {
/* //@Dim: Not sure what this needs to do in the new viewer
if (this.viewer.interactions.selectedObjects.children.length !== 0) {
box = new THREE.Box3().setFromObject(this.viewer.interactions.selectedObjects)
} else if (this.viewer.speckleRenderer.allObjects.children.length !== 0) {
} else*/ if (this.viewer.speckleRenderer.allObjects.children.length !== 0) {
box = new THREE.Box3().setFromObject(this.viewer.speckleRenderer.allObjects)
} else {
box = new Box3(new THREE.Vector3(-1, -1, -1), new THREE.Vector3(1, 1, 1))
+95 -287
View File
@@ -3,11 +3,10 @@ import Stats from 'three/examples/jsm/libs/stats.module'
import ViewerObjectLoader from './ViewerObjectLoader'
import EventEmitter from './EventEmitter'
import InteractionHandler from './legacy/InteractionHandler'
import CameraHandler from './context/CameraHanlder'
import SectionBox from './SectionBox'
import { Clock, Color, MathUtils, Texture, Vector3 } from 'three'
import { Clock, Texture } from 'three'
import { Assets } from './Assets'
import { Optional } from '../helpers/typeHelper'
import {
@@ -21,32 +20,34 @@ import {
import { World } from './World'
import { TreeNode, WorldTree } from './tree/WorldTree'
import SpeckleRenderer from './SpeckleRenderer'
import {
FilterMaterialType,
FilteringManager,
FilteringState
} from './filtering/FilteringManager'
import { FilteringManager, FilteringState } from './filtering/FilteringManager'
import { PropertyInfo, PropertyManager } from './filtering/PropertyManager'
import { SpeckleType } from './converter/GeometryConverter'
import { DataTree } from './tree/DataTree'
export class Viewer extends EventEmitter implements IViewer {
public speckleRenderer: SpeckleRenderer
private clock: Clock
/** Container and optional stats element */
private container: HTMLElement
private stats: Optional<Stats>
private loaders: { [id: string]: ViewerObjectLoader } = {}
private _needsRender: boolean
private inProgressOperations: number
public sectionBox: SectionBox
public interactions: InteractionHandler
public cameraHandler: CameraHandler
/** Viewer params used at init time */
private startupParams: ViewerParams
/** Viewer components */
public static Assets: Assets
private speckleRenderer: SpeckleRenderer
private filteringManager: FilteringManager
/** Legacy viewer components (will revisit soon) */
public sectionBox: SectionBox
public cameraHandler: CameraHandler
/** Render flag for on-demand rendering */
private _needsRender: boolean
/** Misc members */
private inProgressOperations: number
private clock: Clock
private loaders: { [id: string]: ViewerObjectLoader } = {}
public get needsRender(): boolean {
return this._needsRender
@@ -56,19 +57,9 @@ export class Viewer extends EventEmitter implements IViewer {
this._needsRender = value || this._needsRender
}
private _worldOrigin: Vector3 = new Vector3()
public get worldSize() {
World.worldBox.getCenter(this._worldOrigin)
const size = new Vector3().subVectors(World.worldBox.max, World.worldBox.min)
return {
x: size.x,
y: size.y,
z: size.z
}
}
public get worldOrigin() {
return this._worldOrigin
/** Gets the World object. Currently it's used for statistics mostly */
public get World(): World {
return World
}
public constructor(
@@ -77,54 +68,84 @@ export class Viewer extends EventEmitter implements IViewer {
) {
super()
window.THREE = THREE // Do we really need this?
this.startupParams = params
this.clock = new THREE.Clock()
this.container = container || document.getElementById('renderer')
this.speckleRenderer = new SpeckleRenderer(this)
this.speckleRenderer.create(this.container)
new Assets(this.speckleRenderer.renderer)
this.cameraHandler = new CameraHandler(this)
if (params.showStats) {
this.stats = Stats()
this.container.appendChild(this.stats.dom)
}
this.loaders = {}
this.startupParams = params
this.clock = new THREE.Clock()
this.inProgressOperations = 0
this.speckleRenderer = new SpeckleRenderer(this)
this.speckleRenderer.create(this.container)
window.addEventListener('resize', this.onWindowResize.bind(this), false)
this.loaders = {}
new Assets(this.speckleRenderer.renderer)
this.filteringManager = new FilteringManager(this.speckleRenderer)
this.cameraHandler = new CameraHandler(this)
this.sectionBox = new SectionBox(this)
this.sectionBox.off()
this.sectionBox.controls.addEventListener('change', () => {
this.speckleRenderer.updateClippingPlanes(this.sectionBox.planes)
})
this.interactions = new InteractionHandler(this)
this.frame()
this.onWindowResize()
this.needsRender = true
this.inProgressOperations = 0
this.on(ViewerEvent.LoadComplete, (url) => {
WorldTree.getRenderTree(url).buildRenderTree()
this.speckleRenderer.addRenderTree(url)
this.zoomExtents()
})
}
this.filteringManager = new FilteringManager(this.speckleRenderer)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// ;(window as any).WT = WorldTree
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// ;(window as any).FM = this.filteringManager
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// ;(window as any).V = this
private onWindowResize() {
this.speckleRenderer.renderer.setSize(
this.container.offsetWidth,
this.container.offsetHeight
)
this.needsRender = true
}
private frame() {
this.update()
this.render()
}
private update() {
const delta = this.clock.getDelta()
this.needsRender = this.cameraHandler.controls.update(delta)
this.speckleRenderer.update(delta)
this.stats?.update()
requestAnimationFrame(this.frame.bind(this))
}
private render() {
if (this.needsRender) {
this.speckleRenderer.render(this.cameraHandler.activeCam.camera)
this._needsRender = false
}
}
public async init(): Promise<void> {
if (this.startupParams.environmentSrc) {
Assets.getEnvironment(this.startupParams.environmentSrc)
.then((value: Texture) => {
this.speckleRenderer.indirectIBL = value
})
.catch((reason) => {
console.warn(reason)
console.warn('Fallback to null environment!')
})
}
}
public on(eventType: ViewerEvent, listener: (arg) => void): void {
super.on(eventType, listener)
}
public getObjectProperties(resourceURL: string = null): PropertyInfo[] {
@@ -225,54 +246,19 @@ export class Viewer extends EventEmitter implements IViewer {
})
}
/**
* LEGACY: Handles (or tries to handle) old viewer filtering.
* @param args legacy filter object
*/
public async applyFilter(filter: unknown) {
filter
// return this.FilteringManager.handleLegacyFilter(filter)
}
public getDataTree(): DataTree {
return WorldTree.getDataTree()
}
public async init(): Promise<void> {
if (this.startupParams.environmentSrc) {
Assets.getEnvironment(this.startupParams.environmentSrc)
.then((value: Texture) => {
this.speckleRenderer.indirectIBL = value
})
.catch((reason) => {
console.warn(reason)
console.warn('Fallback to null environment!')
})
}
}
public on(eventType: ViewerEvent, listener: (arg) => void): void {
super.on(eventType, listener)
}
public onWindowResize() {
this.speckleRenderer.renderer.setSize(
this.container.offsetWidth,
this.container.offsetHeight
)
this.needsRender = true
}
private frame() {
this.update()
this.render()
}
private update() {
const delta = this.clock.getDelta()
this.needsRender = this.cameraHandler.controls.update(delta)
this.speckleRenderer.update(delta)
this.stats?.update()
requestAnimationFrame(this.frame.bind(this))
}
private render() {
if (this.needsRender) {
this.speckleRenderer.render(this.cameraHandler.activeCam.camera)
}
}
public toggleSectionBox() {
this.sectionBox.toggle()
}
@@ -342,15 +328,20 @@ export class Viewer extends EventEmitter implements IViewer {
})
}
/**
* OBJECT LOADING/UNLOADING
*/
public async loadObject(url: string, token: string = null, enableCaching = true) {
try {
if (++this.inProgressOperations === 1) (this as EventEmitter).emit('busy', true)
if (++this.inProgressOperations === 1)
(this as EventEmitter).emit(ViewerEvent.Busy, true)
const loader = new ViewerObjectLoader(this, url, token, enableCaching)
this.loaders[url] = loader
await loader.load()
} finally {
if (--this.inProgressOperations === 0) (this as EventEmitter).emit('busy', false)
if (--this.inProgressOperations === 0)
(this as EventEmitter).emit(ViewerEvent.Busy, false)
}
}
@@ -364,14 +355,15 @@ export class Viewer extends EventEmitter implements IViewer {
public async unloadObject(url: string) {
try {
if (++this.inProgressOperations === 1) (this as EventEmitter).emit('busy', true)
if (++this.inProgressOperations === 1)
(this as EventEmitter).emit(ViewerEvent.Busy, true)
delete this.loaders[url]
this.speckleRenderer.removeRenderTree(url)
WorldTree.getRenderTree(url).purge()
WorldTree.getInstance().purge(url)
} finally {
if (--this.inProgressOperations === 0) {
;(this as EventEmitter).emit('busy', false)
;(this as EventEmitter).emit(ViewerEvent.Busy, false)
console.warn(`Removed subtree ${url}`)
;(this as EventEmitter).emit(ViewerEvent.UnloadComplete, url)
}
@@ -380,7 +372,8 @@ export class Viewer extends EventEmitter implements IViewer {
public async unloadAll() {
try {
if (++this.inProgressOperations === 1) (this as EventEmitter).emit('busy', true)
if (++this.inProgressOperations === 1)
(this as EventEmitter).emit(ViewerEvent.Busy, true)
for (const key of Object.keys(this.loaders)) {
delete this.loaders[key]
}
@@ -393,198 +386,13 @@ export class Viewer extends EventEmitter implements IViewer {
WorldTree.getInstance().purge()
} finally {
if (--this.inProgressOperations === 0) {
;(this as EventEmitter).emit('busy', false)
;(this as EventEmitter).emit(ViewerEvent.Busy, false)
console.warn(`Removed all subtrees`)
;(this as EventEmitter).emit(ViewerEvent.UnloadAllComplete)
}
}
}
/**
* LEGACY: Handles (or tries to handle) old viewer filtering.
* @param args legacy filter object
*/
public async applyFilter(filter: unknown) {
filter
// return this.FilteringManager.handleLegacyFilter(filter)
}
public debugGetFilterByNumericPropetyData(propertyName: string): {
min: number
max: number
nodes: TreeNode[]
} {
const volumeNodes = []
let min = Infinity
let max = 0
WorldTree.getInstance().walk((node: TreeNode) => {
const params = node.model.raw.parameters
if (params) {
for (const k in params) {
if (!(params[k] instanceof Object)) continue
if (params[k].name === propertyName) {
min = Math.min(min, params[k].value)
max = Math.max(max, params[k].value)
volumeNodes.push(node)
}
}
}
return true
})
return {
min,
max,
nodes: volumeNodes
}
}
public debugApplyByNumericPropetyFilter(
data: { min: number; max: number; nodes: TreeNode[] },
propertyName: string,
min?: number,
max?: number
) {
const start = performance.now()
const nodesGradient = []
const nodesGhost = []
const values = []
/** This is the lazy approach */
WorldTree.getInstance().walk((node: TreeNode) => {
const params = node.model.raw.parameters
if (params) {
for (const k in params) {
if (!(params[k] instanceof Object)) continue
if (params[k].name === propertyName) {
const propertyValue = params[k].value
const passMin = min !== undefined ? propertyValue >= min : true
const passMax = max !== undefined ? propertyValue <= max : true
if (
data.nodes.includes(node) &&
passMin &&
passMax &&
!nodesGradient.includes(node)
) {
nodesGradient.push(node)
values.push(propertyValue)
}
} else {
if (!nodesGhost.includes(node)) nodesGhost.push(node)
}
}
}
return true
})
this.speckleRenderer.clearFilter()
this.speckleRenderer.beginFilter()
const ghostRvs = []
for (let k = 0; k < nodesGhost.length; k++) {
ghostRvs.push(
...WorldTree.getRenderTree().getRenderViewsForNode(nodesGhost[k], nodesGhost[k])
)
}
this.speckleRenderer.applyFilter(ghostRvs, {
filterType: FilterMaterialType.GHOST
})
for (let k = 0; k < nodesGradient.length; k++) {
const rvs = WorldTree.getRenderTree().getRenderViewsForNode(
nodesGradient[k],
nodesGradient[k]
)
// .map((value) => value.renderData.id)
const t = (values[k] - data.min) / (data.max - data.min)
this.speckleRenderer.applyFilter(rvs, {
filterType: FilterMaterialType.GRADIENT,
rampIndex: t
})
}
this.speckleRenderer.endFilter()
console.warn(`Filter time: ${performance.now() - start}`)
}
public debugGetFilterByNonNumericPropetyData(propertyName: string): {
color?: { name: string; color: string; colorIndex: number; nodes: [] }
} {
// OG implementation
const getColorHash = (objValue) => {
const objValueAsString = '' + objValue
let hash = 0
for (let i = 0; i < objValueAsString.length; i++) {
const chr = objValueAsString.charCodeAt(i)
hash = (hash << 5) - hash + chr
hash |= 0 // Convert to 32bit integer
}
hash = Math.abs(hash)
const colorHue = hash % 360
const rgb = new Color(`hsl(${colorHue}, 50%, 30%)`)
return rgb.getHex()
}
const data: {
color?: { name: string; color: string; colorIndex: number; nodes: [] }
} = {}
let colorCount = 0
/** This is the lazy approach */
WorldTree.getInstance().walk((node: TreeNode) => {
if (!node.model.atomic) return true
const propertyValue = node.model.raw[propertyName]
if (propertyValue !== null && propertyValue !== undefined) {
const color = getColorHash(propertyValue.split('.').reverse()[0])
if (data[color] === undefined) {
data[color] = {
name: propertyValue.split('.').reverse()[0],
color: new Color(MathUtils.randInt(0, 0xffffff)).getHex(),
colorIndex: colorCount,
nodes: []
}
colorCount++
}
if (!data[color].nodes.includes(node)) data[color].nodes.push(node)
}
return true
})
return data
}
public debugApplyByNonNumericPropetyFilter(data: {
color?: { name: string; color: number; colorIndex: number; nodes: [] }
}) {
const start = performance.now()
const colors = Object.values(data)
colors.sort((a, b) => a.colorIndex - b.colorIndex)
const rampTexture = Assets.generateDiscreetRampTexture(
colors.map((val) => val.color)
)
this.speckleRenderer.clearFilter()
this.speckleRenderer.beginFilter()
for (let k = 0; k < colors.length; k++) {
const nodes = colors[k].nodes
let rvs = []
for (let i = 0; i < nodes.length; i++) {
rvs = rvs.concat(
WorldTree.getRenderTree().getRenderViewsForNode(nodes[i], nodes[i])
)
}
this.speckleRenderer.applyFilter(rvs, {
filterType: FilterMaterialType.COLORED,
rampIndex: colors[k].colorIndex / colors.length,
rampIndexColor: new Color(colors[k].color),
rampTexture
})
}
this.speckleRenderer.endFilter()
console.warn(`Filter time: ${performance.now() - start}`)
}
public dispose() {
// TODO: currently it's easier to simply refresh the page :)
}
+16 -1
View File
@@ -1,10 +1,25 @@
import { Box3 } from 'three'
import { Box3, Vector3 } from 'three'
export class World {
/* This will no longer exist when we have a scene tree */
private static readonly boxes: Array<Box3> = new Array<Box3>()
public static readonly worldBox: Box3 = new Box3()
private static _worldOrigin: Vector3 = new Vector3()
public static get worldSize() {
World.worldBox.getCenter(this._worldOrigin)
const size = new Vector3().subVectors(World.worldBox.max, World.worldBox.min)
return {
x: size.x,
y: size.y,
z: size.z
}
}
public static get worldOrigin() {
return World._worldOrigin
}
public static expandWorld(box: Box3) {
World.boxes.push(box)
World.updateWorld()
@@ -52,7 +52,8 @@ v.on('section-box', (status) => {
})
window.viewerScreenshot = function () {
let data = v.interactions.screenshot() // transparent png.
//@Dim: Changed this to use the API
let data = v.screenshot() // transparent png.
let pop = window.open()
pop.document.title = 'super screenshot'
@@ -64,5 +65,6 @@ window.viewerScreenshot = function () {
}
window.zoomFast = function () {
v.interactions.zoomExtents(0.95, false)
//@Dim: This needs to use the API
// v.interactions.zoomExtents(0.95, false)
}