-
Notifications
You must be signed in to change notification settings - Fork 208
/
GraphicBranch.ts
215 lines (193 loc) · 8.25 KB
/
GraphicBranch.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Rendering
*/
import { disposeArray, Id64String, IDisposable } from "@itwin/core-bentley";
import {
FeatureAppearanceProvider, HiddenLine, RealityModelDisplaySettings, RenderSchedule, ViewFlagOverrides, ViewFlags,
} from "@itwin/core-common";
import { IModelConnection } from "../IModelConnection";
import { IModelApp } from "../IModelApp";
import { FeatureSymbology } from "./FeatureSymbology";
import { RenderClipVolume } from "./RenderClipVolume";
import { RenderGraphic } from "./RenderGraphic";
import { RenderMemory } from "./RenderMemory";
import { RenderPlanarClassifier } from "./RenderPlanarClassifier";
import { RenderTextureDrape } from "./RenderSystem";
import { Range3d } from "@itwin/core-geometry";
import { AnimationNodeId } from "../common/render/AnimationNodeId";
/** Carries information in a GraphicBranchOptions about a GraphicBranch produced by drawing one view into the context of another.
* @internal
*/
export interface GraphicBranchFrustum {
is3d: boolean;
scale: {
x: number;
y: number;
};
}
/**
* A node in a scene graph. The branch itself is not renderable. Instead it contains a list of RenderGraphics,
* and a transform, symbology overrides, and clip volume which are to be applied when rendering them.
* Branches can be nested to build an arbitrarily-complex scene graph.
* @see [[RenderSystem.createBranch]]
* @public
* @extensions
*/
export class GraphicBranch implements IDisposable /* , RenderMemory.Consumer */ {
/** The child nodes of this branch */
public readonly entries: RenderGraphic[] = [];
/** If true, when the branch is disposed of, the RenderGraphics in its entries array will also be disposed */
public readonly ownsEntries: boolean;
/** Selectively overrides the view's [ViewFlags]($common) while drawing graphics within this branch. The default overrides nothing.
* @see [[setViewFlagOverrides]].
*/
public viewFlagOverrides: ViewFlagOverrides = {};
/** Controls how reality models are displayed within this branch.
* @beta
*/
public realityModelDisplaySettings?: RealityModelDisplaySettings;
/** @internal */
public realityModelRange?: Range3d;
/** Optional symbology overrides to be applied to all graphics in this branch */
public symbologyOverrides?: FeatureSymbology.Overrides;
/** Optional animation branch Id that incorporates the model Id and, for element timelines, the batch Id.
* @internal
*/
public animationId?: string;
/** Identifies the node in the [RenderSchedule.Script]($backend) with which this branch is associated.
* @internal
*/
public animationNodeId?: AnimationNodeId | number;
/** Identifies the "group" to which this branch belongs.
* Groups represent cross-cutting subsets of a tile tree's contents.
* For example, if a tile tree contains geometry from multiple models, each model (or smaller groups of multiple models) could be considered a group.
* The top-level branches containing graphics from multiple tiles will each specify the group they represent, and the child branches within each
* tile will likewise specify the group to which they belong.
* When drawing, only the graphics within a tile that correlate with the current group will be drawn.
* Groups cannot nest.
* @internal
*/
public groupNodeId?: number;
/** Constructor
* @param ownsEntries If true, when this branch is [[dispose]]d, all of the [[RenderGraphic]]s it contains will also be disposed.
*/
public constructor(ownsEntries: boolean = false) {
this.ownsEntries = ownsEntries;
}
/** Add a graphic to this branch. */
public add(graphic: RenderGraphic): void {
this.entries.push(graphic);
}
/** Compute the view flags that result from applying this branch's [[viewFlagOverrides]] to the input flags.
* @param flags The input view flags, e.g., from the view's [[DisplayStyleState]].
* @returns The result of applying [[viewFlagOverrides]] to `flags`.
*/
public getViewFlags(flags: ViewFlags): ViewFlags {
return flags.override(this.viewFlagOverrides);
}
/** Set [[viewFlagOverrides]] to override **all** ViewFlags as specified by `flags`. */
public setViewFlags(flags: ViewFlags): void {
this.viewFlagOverrides = { ...flags };
}
/** Change [[viewFlagOverrides]]. */
public setViewFlagOverrides(ovr: ViewFlagOverrides): void {
this.viewFlagOverrides = { ...ovr };
}
/** Disposes of all graphics in this branch, if and only if [[ownsEntries]] is true. */
public dispose() {
this.clear();
}
/** Returns true if this branch contains no graphics. */
public get isEmpty(): boolean {
return 0 === this.entries.length;
}
/** Empties the list of [[RenderGraphic]]s contained in this branch, and if the [[ownsEntries]] flag is set, also disposes of them. */
public clear(): void {
if (this.ownsEntries)
disposeArray(this.entries);
else
this.entries.length = 0;
}
/** @internal */
public collectStatistics(stats: RenderMemory.Statistics): void {
for (const entry of this.entries)
entry.collectStatistics(stats);
}
}
/** Options passed to [[RenderSystem.createGraphicBranch]].
* @public
* @extensions
*/
export interface GraphicBranchOptions {
/** Clip applied to the graphics in the branch. */
clipVolume?: RenderClipVolume;
/** @internal */
classifierOrDrape?: RenderPlanarClassifier | RenderTextureDrape;
/** Optionally replaces the view's hidden line settings when drawing the branch. */
hline?: HiddenLine.Settings;
/** The iModel from which the graphics originate, if different than that associated with the view. */
iModel?: IModelConnection;
/** @internal */
frustum?: GraphicBranchFrustum;
/** Supplements the view's [[FeatureSymbology.Overrides]] for graphics in the branch. */
appearanceProvider?: FeatureAppearanceProvider;
/** @internal Secondary planar classifiers (map layers) */
secondaryClassifiers?: Map<number, RenderPlanarClassifier>;
/** The Id of the [ViewAttachment]($backend) from which this branch's graphics originated.
* @internal
*/
viewAttachmentId?: Id64String;
}
/** Clip/Transform for a branch that are varied over time.
* @internal
*/
export interface AnimationBranchState {
readonly clip?: RenderClipVolume;
readonly omit?: boolean;
}
/** @internal */
export function formatAnimationBranchId(modelId: Id64String, branchId: number): string {
if (branchId < 0)
return modelId;
return `${modelId}_Node_${branchId.toString()}`;
}
function addAnimationBranch(modelId: Id64String, timeline: RenderSchedule.Timeline, branchId: number, branches: Map<string, AnimationBranchState>, time: number): void {
const clipVector = timeline.getClipVector(time);
const clip = clipVector ? IModelApp.renderSystem.createClipVolume(clipVector) : undefined;
if (clip)
branches.set(formatAnimationBranchId(modelId, branchId), { clip });
}
/** Mapping from node/branch IDs to animation branch state
* @internal
*/
export interface AnimationBranchStates {
/** Maps node Id to branch state. */
readonly branchStates: Map<string, AnimationBranchState>;
/** Ids of nodes that apply a transform. */
readonly transformNodeIds: ReadonlySet<number>;
}
/** @internal */
export namespace AnimationBranchStates {
export function fromScript(script: RenderSchedule.Script, time: number): AnimationBranchStates | undefined {
if (!script.containsModelClipping && !script.requiresBatching)
return undefined;
const branches = new Map<string, AnimationBranchState>();
for (const model of script.modelTimelines) {
addAnimationBranch(model.modelId, model, -1, branches, time);
for (const elem of model.elementTimelines) {
if (elem.getVisibility(time) <= 0)
branches.set(formatAnimationBranchId(model.modelId, elem.batchId), { omit: true });
else
addAnimationBranch(model.modelId, elem, elem.batchId, branches, time);
}
}
return {
branchStates: branches,
transformNodeIds: script.transformBatchIds,
};
}
}