Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Z scaling #937

Merged
merged 25 commits into from Mar 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2a001a6
modify model transform keyin to take scaling
MarcNeely Feb 11, 2021
581a421
test
MarcNeely Mar 10, 2021
5a41d6b
fix instancing
MarcNeely Mar 10, 2021
17374c1
Compare forceNoInstancing
pmconne Mar 10, 2021
26f9e49
restore deleted property.
pmconne Mar 10, 2021
48e2f41
Remove unnecessary invalidateScene and requestRedraw calls.
pmconne Mar 10, 2021
e4c3ac1
Cleanup & make work nicer with Z offset
MarcNeely Mar 12, 2021
5a5b2d9
fix rgb axes in measure distance tool
MarcNeely Mar 12, 2021
a742f67
Merge branch 'z-scaling' of https://github.com/imodeljs/imodeljs into…
MarcNeely Mar 12, 2021
023c1fc
Remove debug
MarcNeely Mar 15, 2021
8e2638d
lint & typo
MarcNeely Mar 18, 2021
567b7fe
Merge branch 'master' into z-scaling
MarcNeely Mar 22, 2021
f09107e
Merge branch 'master' into z-scaling
mergify[bot] Mar 22, 2021
1aa841e
Modify tessellation for nonuniform scaling
MarcNeely Mar 22, 2021
9d3b718
Merge branch 'z-scaling' of https://github.com/imodeljs/imodeljs into…
MarcNeely Mar 22, 2021
dbc6969
rush change
MarcNeely Mar 22, 2021
325b952
extract-api
MarcNeely Mar 22, 2021
dbce0b4
Replace use of System.instance with IModelApp.rSys
MarcNeely Mar 23, 2021
2609c68
move scaleFactor calc to TileDrawArgs constructor
MarcNeely Mar 23, 2021
1e78608
Merge branch 'master' into z-scaling
pmconne Mar 25, 2021
a8b328c
Merge branch 'master' into z-scaling
mergify[bot] Mar 25, 2021
b033c23
Merge branch 'master' into z-scaling
mergify[bot] Mar 25, 2021
ba5928b
Merge branch 'master' into z-scaling
mergify[bot] Mar 25, 2021
d071d13
Merge branch 'master' into z-scaling
mergify[bot] Mar 25, 2021
015c99d
Merge branch 'master' into z-scaling
mergify[bot] Mar 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 15 additions & 14 deletions common/api/imodeljs-frontend.api.md
Expand Up @@ -5930,15 +5930,7 @@ export class MeasureAreaTool extends MeasureElementTool {
// @alpha (undocumented)
export class MeasureDistanceTool extends PrimitiveTool {
// (undocumented)
protected readonly _acceptedSegments: {
distance: number;
slope: number;
start: Point3d;
end: Point3d;
delta: Vector3d;
refAxes: Matrix3d;
marker: MeasureMarker;
}[];
protected readonly _acceptedSegments: Segment[];
// (undocumented)
protected acceptNewSegments(): Promise<void>;
// (undocumented)
Expand All @@ -5952,7 +5944,7 @@ export class MeasureDistanceTool extends PrimitiveTool {
// (undocumented)
protected displayDelta(context: DecorateContext, seg: any): void;
// (undocumented)
protected displayDynamicDistance(context: DecorateContext, points: Point3d[]): void;
protected displayDynamicDistance(context: DecorateContext, points: Point3d[], adjustedPoints: Point3d[]): void;
// (undocumented)
getDecorationGeometry(_hit: HitDetail): GeometryStreamProps | undefined;
// (undocumented)
Expand All @@ -5968,12 +5960,11 @@ export class MeasureDistanceTool extends PrimitiveTool {
// (undocumented)
isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean;
// (undocumented)
protected _lastMotionAdjustedPt?: Point3d;
// (undocumented)
protected _lastMotionPt?: Point3d;
// (undocumented)
protected readonly _locationData: {
point: Point3d;
refAxes: Matrix3d;
}[];
protected readonly _locationData: Location[];
// (undocumented)
onDataButtonDown(ev: BeButtonEvent): Promise<EventHandled>;
// (undocumented)
Expand Down Expand Up @@ -8114,6 +8105,8 @@ export abstract class RenderSystem implements IDisposable {
get supportsInstancing(): boolean;
// @internal (undocumented)
get supportsLogZBuffer(): boolean;
// @internal (undocumented)
get supportsNonuniformScaledInstancing(): boolean;
}

// @public
Expand Down Expand Up @@ -8509,6 +8502,8 @@ export class ScreenViewport extends Viewport {
source: DepthPointSource;
sourceId?: string;
};
// @internal (undocumented)
picker: ElementPicker;
pickNearestVisibleGeometry(pickPoint: Point3d, radius?: number, allowNonLocatable?: boolean, out?: Point3d): Point3d | undefined;
// @internal
static removeAllChildren(el: HTMLDivElement): void;
Expand Down Expand Up @@ -10199,6 +10194,8 @@ export class TileDrawArgs {
// @internal (undocumented)
parentsAndChildrenExclusive: boolean;
// @internal (undocumented)
readonly pixelSizeScaleFactor: number;
// @internal (undocumented)
planarClassifier?: RenderPlanarClassifier;
// @internal
processSelectedTiles(_tiles: Tile[]): void;
Expand Down Expand Up @@ -12675,6 +12672,10 @@ export abstract class ViewState extends ElementState {
// (undocumented)
toJSON(): ViewDefinitionProps;
toProps(): ViewStateProps;
// @internal (undocumented)
transformNormalByModelDisplayTransform(modelId: string | undefined, normal: Vector3d): void;
// @internal (undocumented)
transformPointByModelDisplayTransform(modelId: string | undefined, pnt: Point3d, inverse: boolean): void;
// (undocumented)
protected _updateMaxGlobalScopeFactor(): void;
get viewFlags(): ViewFlags;
Expand Down
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@bentley/imodeljs-frontend",
"comment": "Added capability to scale the model display transform nonuniformly and have still Accusnap properly.",
"type": "none"
}
],
"packageName": "@bentley/imodeljs-frontend",
"email": "36053767+MarcNeely@users.noreply.github.com"
}
21 changes: 16 additions & 5 deletions core/frontend/src/AccuSnap.ts
Expand Up @@ -705,28 +705,39 @@ export class AccuSnap implements Decorator {
};

// If this hit is from a plan projection model, apply the model's elevation to the snap point for display.
// Likewise, if it is a hit on a model with a display transform, apply the model's transform to the snap point.
let snapPoint = result.snapPoint!;
const elevation = undefined !== thisHit.modelId ? thisHit.viewport.view.getModelElevation(thisHit.modelId) : 0;
if (0 !== elevation) {
if (0 !== elevation || undefined !== thisHit.viewport.view.modelDisplayTransformProvider) {
const adjustedSnapPoint = Point3d.fromJSON(snapPoint);
thisHit.viewport.view.transformPointByModelDisplayTransform(thisHit.modelId, adjustedSnapPoint, false);
adjustedSnapPoint.z += elevation;
snapPoint = adjustedSnapPoint;
}

const snap = new SnapDetail(thisHit, result.snapMode, result.heat, snapPoint);

// Apply model's elevation to curve for display.
// Apply model's elevation and display transform to curve for display.
let transform;
if (0 !== elevation)
if (undefined !== thisHit.modelId && undefined !== thisHit.viewport.view.modelDisplayTransformProvider) {
transform = thisHit.viewport.view.getModelDisplayTransform(thisHit.modelId, Transform.createIdentity());
if (0 !== elevation)
transform.origin.set(0, 0, elevation);
} else if (0 !== elevation) {
transform = Transform.createTranslationXYZ(0, 0, elevation);
}

snap.setCurvePrimitive(parseCurve(result.curve), transform, result.geomType);
if (undefined !== result.parentGeomType)
snap.parentGeomType = result.parentGeomType;
if (undefined !== result.hitPoint)
if (undefined !== result.hitPoint) {
snap.hitPoint.setFromJSON(result.hitPoint); // Update hitPoint from readPixels with exact point location corrected to surface/edge geometry...
if (undefined !== result.normal)
thisHit.viewport.view.transformPointByModelDisplayTransform(thisHit.modelId, snap.hitPoint, false);
}
if (undefined !== result.normal) {
snap.normal = Vector3d.fromJSON(result.normal);
thisHit.viewport.view.transformNormalByModelDisplayTransform(thisHit.modelId, snap.normal);
}

if (SnapMode.Intersection !== snap.snapMode)
return snap;
Expand Down
22 changes: 22 additions & 0 deletions core/frontend/src/ViewState.ts
Expand Up @@ -1034,6 +1034,28 @@ export abstract class ViewState extends ElementState {
return this.modelDisplayTransformProvider ? this.modelDisplayTransformProvider.getModelDisplayTransform(modelId, baseTransform) : baseTransform;
}

/** @internal */
public transformPointByModelDisplayTransform(modelId: string | undefined, pnt: Point3d, inverse: boolean): void {
if (undefined !== modelId && undefined !== this.modelDisplayTransformProvider) {
const transform = this.modelDisplayTransformProvider.getModelDisplayTransform(modelId, Transform.createIdentity());
const newPnt = inverse ? transform.multiplyInversePoint3d(pnt) : transform.multiplyPoint3d(pnt);
if (undefined !== newPnt)
pnt.set(newPnt.x, newPnt.y, newPnt.z);
}
}

/** @internal */
public transformNormalByModelDisplayTransform(modelId: string | undefined, normal: Vector3d): void {
if (undefined !== modelId && undefined !== this.modelDisplayTransformProvider) {
const transform = this.modelDisplayTransformProvider.getModelDisplayTransform(modelId, Transform.createIdentity());
const newVec = transform.matrix.multiplyInverse(normal);
if (undefined !== newVec) {
newVec.normalizeInPlace();
normal.set(newVec.x, newVec.y, newVec.z);
}
}
}

/** Invoked when this view becomes the view displayed by the specified [[Viewport]].
* A ViewState can be attached to at most **one** Viewport.
* @note If you override this method you **must** call `super.attachToViewport`.
Expand Down
14 changes: 10 additions & 4 deletions core/frontend/src/Viewport.ts
Expand Up @@ -2366,9 +2366,12 @@ export abstract class Viewport implements IDisposable {
this.npcToWorld(npc, npc);

// If this is a plan projection model, invert the elevation applied to its display transform.
// Likewise, if it is a hit on a model with a display transform, reverse the display transform.
const modelId = pixels.getPixel(x, y).featureTable?.modelId;
if (undefined !== modelId)
if (undefined !== modelId) {
npc.z -= this.view.getModelElevation(modelId);
this.view.transformPointByModelDisplayTransform(modelId, npc, true);
}
}

return npc;
Expand Down Expand Up @@ -2765,6 +2768,9 @@ export class ScreenViewport extends Viewport {
return result;
}

/** @internal */
public picker = new ElementPicker(); // Picker used in pickDepthPoint below so it hangs around and can be querried later.

/** Find a point on geometry visible in this Viewport, within a radius of supplied pick point.
* If no geometry is selected, return the point projected to the most appropriate reference plane.
* @param pickPoint Point to search about, in world coordinates
Expand All @@ -2781,14 +2787,14 @@ export class ScreenViewport extends Viewport {
if (undefined === radius)
radius = this.pixelsFromInches(ToolSettings.viewToolPickRadiusInches);

const picker = new ElementPicker();
this.picker.empty();
const locateOpts = new LocateOptions();
locateOpts.allowNonLocatable = (undefined === options || !options.excludeNonLocatable);
locateOpts.allowDecorations = (undefined === options || !options.excludeDecorations);
locateOpts.allowExternalIModels = (undefined === options || !options.excludeExternalIModels);

if (0 !== picker.doPick(this, pickPoint, radius, locateOpts)) {
const hitDetail = picker.getHit(0)!;
if (0 !== this.picker.doPick(this, pickPoint, radius, locateOpts)) {
const hitDetail = this.picker.getHit(0)!;
const hitPoint = hitDetail.getPoint();
if (hitDetail.isModelHit)
return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, source: DepthPointSource.Model, sourceId: hitDetail.sourceId };
Expand Down
3 changes: 3 additions & 0 deletions core/frontend/src/render/RenderSystem.ts
Expand Up @@ -191,6 +191,9 @@ export abstract class RenderSystem implements IDisposable {
/** @internal */
public get supportsInstancing(): boolean { return true; }

/** @internal */
public get supportsNonuniformScaledInstancing(): boolean { return true; }

/** @internal */
public get dpiAwareLOD(): boolean { return true === this.options.dpiAwareLOD; }

Expand Down
12 changes: 12 additions & 0 deletions core/frontend/src/render/webgl/BranchUniforms.ts
Expand Up @@ -61,6 +61,7 @@ export class BranchUniforms {
private readonly _mvp32 = new Matrix4();
private readonly _m32 = new Matrix4();
private readonly _v32 = new Matrix3();
private readonly _mvn32 = new Matrix3();

// Working state
private readonly _scratchTransform = Transform.createIdentity();
Expand Down Expand Up @@ -169,6 +170,11 @@ export class BranchUniforms {
uniform.setMatrix3(this._v32);
}

public bindModelViewNTransform(uniform: UniformHandle, geom: CachedGeometry, isViewCoords: boolean) {
if (this.update(uniform, geom, isViewCoords))
uniform.setMatrix3(this._mvn32);
}

private update(uniform: UniformHandle, geometry: CachedGeometry, isViewCoords: boolean): boolean {
const uniforms = this._target.uniforms[isViewCoords ? "viewRect" : "frustum"];
if (!sync(uniforms, this))
Expand Down Expand Up @@ -230,6 +236,12 @@ export class BranchUniforms {
Matrix4d.createTransform(mv, this._mv);
this._mv32.initFromTransform(mv);

const inv = this._mv.createInverse();
if (undefined !== inv) {
const invTr = inv.cloneTransposed();
this._mvn32.initFromMatrix3d(invTr.matrixPart());
}

// Don't bother computing mvp for instanced geometry - it's not used.
if (!this._isInstanced) {
uniforms.projectionMatrix.multiplyMatrixMatrix(this._mv, this._mvp);
Expand Down
1 change: 1 addition & 0 deletions core/frontend/src/render/webgl/System.ts
Expand Up @@ -391,6 +391,7 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re

public get maxTextureSize(): number { return this.capabilities.maxTextureSize; }
public get supportsInstancing(): boolean { return this.capabilities.supportsInstancing; }
public get supportsNonuniformScaledInstancing(): boolean { return this.capabilities.isWebGL2; }
public get isWebGL2(): boolean { return this.capabilities.isWebGL2; }
public get isMobile(): boolean { return this.capabilities.isMobile; }

Expand Down
20 changes: 18 additions & 2 deletions core/frontend/src/render/webgl/glsl/Vertex.ts
Expand Up @@ -12,6 +12,7 @@ import { UniformHandle } from "../UniformHandle";
import { Matrix4 } from "../Matrix";
import { RenderPass, TextureUnit } from "../RenderFlags";
import { VariableType, VertexShaderBuilder } from "../ShaderBuilder";
import { System } from "../System";
import { decodeUint16, decodeUint24 } from "./Decode";
import { addInstanceOverrides } from "./Instancing";
import { addLookupTable } from "./LookupTable";
Expand Down Expand Up @@ -113,7 +114,13 @@ export function addModelViewMatrix(vert: VertexShaderBuilder): void {
}

const computeNormalMatrix = `
g_nmx = mat3(MAT_MV);
g_nmx = mat3(u_modelViewN);
g_nmx[0][0] *= u_frustumScale.x;
g_nmx[1][1] *= u_frustumScale.y;
`;

const computeNormalMatrix2 = `
g_nmx = transpose(inverse(mat3(MAT_MV)));
g_nmx[0][0] *= u_frustumScale.x;
g_nmx[1][1] *= u_frustumScale.y;
`;
Expand All @@ -128,7 +135,16 @@ export function addNormalMatrix(vert: VertexShaderBuilder) {
});
});

vert.addInitializer(computeNormalMatrix);
if (System.instance.capabilities.isWebGL2)
vert.addInitializer(computeNormalMatrix2);
else {
vert.addUniform("u_modelViewN", VariableType.Mat3, (prog) => {
prog.addGraphicUniform("u_modelViewN", (uniform, params) => {
params.target.uniforms.branch.bindModelViewNTransform(uniform, params.geometry, false);
});
});
vert.addInitializer(computeNormalMatrix);
}
}

const scratchLutParams = new Float32Array(4);
Expand Down