Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
/** @internal */
export class InstanceBuffers implements WebGlDisposable {
public readonly numInstances: number;
public readonly transforms: BufferHandle;
public readonly featureIds?: BufferHandle;
public readonly hasFeatures: boolean;
public readonly symbology?: BufferHandle;
public readonly shared: boolean;
// The center of the range of the instances' translations.
private readonly _rtcCenter: Point3d;
// A transform including only rtcCenter.
private readonly _rtcOnlyTransform: Transform;
// A transform from _rtcCenter including model matrix
private readonly _rtcModelTransform: Transform;
// The model matrix from which _rtcModelTransform was previously computed. If it changes, _rtcModelTransform must be recomputed.
private readonly _modelMatrix = Transform.createIdentity();
// Holds the instance transforms for computing range. Set to undefined after range computed (immediately after construction)
private _transforms?: Float32Array;
// Holds the range computed from the above transforms
private _range?: Range3d;
private constructor(shared: boolean, count: number, transforms: BufferHandle, rtcCenter: Point3d, transformsData: Float32Array, symbology?: BufferHandle, featureIds?: BufferHandle) {
this.shared = shared;
this.numInstances = count;
this.transforms = transforms;
this.featureIds = featureIds;
this.hasFeatures = undefined !== featureIds;
this.symbology = symbology;
this._rtcCenter = rtcCenter;
this._rtcOnlyTransform = Transform.createTranslation(this._rtcCenter);
this._rtcModelTransform = this._rtcOnlyTransform.clone();
this._transforms = transformsData;
public static rangeFromJson(json: any): AxisAlignedBox3d {
if (undefined !== json.root.boundingVolume.region) {
const region = JsonUtils.asArray(json.root.boundingVolume.region);
if (undefined === region)
throw new TypeError("Unable to determine GeoLocation - no root Transform or Region on root.");
const ecefLow = (new Cartographic(region[0], region[1], region[4])).toEcef();
const ecefHigh = (new Cartographic(region[2], region[3], region[5])).toEcef();
return Range3d.create(ecefLow, ecefHigh);
} else {
let rootTransform = RealityModelTileUtils.transformFromJson(json.root.transform);
const range = RealityModelTileUtils.rangeFromBoundingVolume(json.root.boundingVolume)!;
if (undefined === rootTransform)
rootTransform = Transform.createIdentity();
return rootTransform.multiplyRange(range);
}
return Range3d.createNull();
}
public static async rangeFromUrl(url: string): Promise {
if (undefined !== this._range)
return this._range.clone(out);
this._range = new Range3d();
const tfs = this._transforms;
if (undefined === tfs) {
assert(false);
return this._range.clone(out);
}
this._transforms = undefined;
const numFloatsPerTransform = 3 * 4;
assert(0 === tfs.length % (3 * 4));
const tf = Transform.createIdentity();
const r = new Range3d();
for (let i = 0; i < tfs.length; i += numFloatsPerTransform) {
tf.setFromJSON({
origin: [tfs[i + 3], tfs[i + 7], tfs[i + 11]],
matrix: [
[tfs[i + 0], tfs[i + 1], tfs[i + 2]],
[tfs[i + 4], tfs[i + 5], tfs[i + 6]],
[tfs[i + 8], tfs[i + 9], tfs[i + 10]],
],
});
reprRange.clone(r);
tf.multiplyRange(r, r);
this._range.extendRange(r);
}
public reset(transform: Transform = Transform.createIdentity(), surfacesOnly: boolean = false) {
this.clear();
this._transform = transform;
this._surfacesOnly = surfacesOnly;
}
async function getTileTreeProps(url: string, tilesetToDbJson: any, iModel: IModelConnection): Promise {
if (!url)
throw new IModelError(BentleyStatus.ERROR, "Unable to read reality data");
const accessToken = await getAccessToken();
const tileClient = new RealityModelTileClient(url, accessToken);
const json = await tileClient.getRootDocument(url);
const ecefLocation = iModel.ecefLocation;
let rootTransform = ecefLocation ? ecefLocation.getTransform().inverse()! : Transform.createIdentity();
if (json.root.transform)
rootTransform = rootTransform.multiplyTransformTransform(RealityModelTileUtils.transformFromJson(json.root.transform));
else if (json.root.boundingVolume && Array.isArray(json.root.boundingVolume.region))
rootTransform = Transform.createTranslationXYZ(0, 0, (json.root.boundingVolume.region[4] + json.root.boundingVolume.region[5]) / 2.0).multiplyTransformTransform(rootTransform);
if (undefined !== tilesetToDbJson)
rootTransform = Transform.fromJSON(tilesetToDbJson).multiplyTransformTransform(rootTransform);
return new RealityModelTileTreeProps(json, tileClient, rootTransform);
}
}
public getAnimationTransform(time: number, interval: Interval): Transform | undefined {
if (!ElementTimeline.findTimelineInterval(interval, time, this.transformTimeline) || this.transformTimeline![interval.index0].value === null)
return undefined;
if (interval.index0 < 0)
return Transform.createIdentity();
const timeline = this.transformTimeline!;
const value = timeline[interval.index0].value;
const transform = Transform.fromJSON(value.transform);
if (interval.fraction > 0.0) {
const value1 = timeline[interval.index1].value;
if (value1.pivot !== null && value1.orientation !== null && value1.position !== null) {
const q0 = Point4d.fromJSON(value.orientation), q1 = Point4d.fromJSON(value1.orientation);
const sum = Point4d.interpolateQuaternions(q0, interval.fraction, q1);
const interpolatedMatrix = Matrix3d.createFromQuaternion(sum);
const position0 = Vector3d.fromJSON(value.position), position1 = Vector3d.fromJSON(value1.position);
const pivot = Vector3d.fromJSON(value.pivot);
const pre = Transform.createTranslation(pivot);
const post = Transform.createTranslation(position0.interpolate(interval.fraction, position1));
const product = post.multiplyTransformMatrix3d(interpolatedMatrix);
transform.setFromJSON(product.multiplyTransformTransform(pre));
public getLocationTransform(settings?: TerrainSettings): Transform {
if (settings === undefined)
return Transform.createIdentity();
const matrix = Matrix3d.createScale(1.0, 1.0, this.settings ? this.settings.exaggeration : 1.0);
const origin = Matrix3d.xyzMinusMatrixTimesXYZ(this._fixedPoint, matrix, this._fixedPoint);
return Transform.createRefs(origin, matrix);
}
if ("Node_Root" === nodeKey) {
for (const primitive of primitives) {
const graphic = this.readMeshGraphic(primitive);
if (undefined !== graphic)
graphics.push(graphic);
}
} else {
const branch = new GraphicBranch(true);
branch.animationId = this._modelId + "_" + nodeKey;
for (const primitive of primitives) {
const graphic = this.readMeshGraphic(primitive);
if (undefined !== graphic)
branch.add(graphic);
}
if (!branch.isEmpty)
graphics.push(this._system.createBranch(branch, Transform.createIdentity()));
}
}
}
let tileGraphic: RenderGraphic | undefined;
switch (graphics.length) {
case 0:
break;
case 1:
tileGraphic = graphics[0];
break;
default:
tileGraphic = this._system.createGraphicList(graphics);
break;
}