|
@@ -11,6 +11,8 @@ import { addSphere } from '../../mol-geo/geometry/mesh/builder/sphere';
|
|
import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
|
|
import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
|
|
import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder';
|
|
import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder';
|
|
import { PickingId } from '../../mol-geo/geometry/picking';
|
|
import { PickingId } from '../../mol-geo/geometry/picking';
|
|
|
|
+import { Text } from '../../mol-geo/geometry/text/text';
|
|
|
|
+import { TextBuilder } from '../../mol-geo/geometry/text/text-builder';
|
|
import { GraphicsRenderObject } from '../../mol-gl/render-object';
|
|
import { GraphicsRenderObject } from '../../mol-gl/render-object';
|
|
import { Scene } from '../../mol-gl/scene';
|
|
import { Scene } from '../../mol-gl/scene';
|
|
import { WebGLContext } from '../../mol-gl/webgl/context';
|
|
import { WebGLContext } from '../../mol-gl/webgl/context';
|
|
@@ -23,19 +25,34 @@ import { Visual } from '../../mol-repr/visual';
|
|
import { ColorNames } from '../../mol-util/color/names';
|
|
import { ColorNames } from '../../mol-util/color/names';
|
|
import { MarkerAction, MarkerActions } from '../../mol-util/marker-action';
|
|
import { MarkerAction, MarkerActions } from '../../mol-util/marker-action';
|
|
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
|
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
|
|
|
+import { assertUnreachable } from '../../mol-util/type-helpers';
|
|
import { Camera, ICamera } from '../camera';
|
|
import { Camera, ICamera } from '../camera';
|
|
import { Viewport } from '../camera/util';
|
|
import { Viewport } from '../camera/util';
|
|
|
|
|
|
// TODO add scale line/grid
|
|
// TODO add scale line/grid
|
|
|
|
|
|
const AxesParams = {
|
|
const AxesParams = {
|
|
- ...Mesh.Params,
|
|
|
|
- alpha: { ...Mesh.Params.alpha, defaultValue: 0.51 },
|
|
|
|
- ignoreLight: { ...Mesh.Params.ignoreLight, defaultValue: true },
|
|
|
|
|
|
+ alpha: PD.Numeric(0.51, { min: 0, max: 1, step: 0.01 }, { isEssential: true, label: 'Opacity' }),
|
|
colorX: PD.Color(ColorNames.red, { isEssential: true }),
|
|
colorX: PD.Color(ColorNames.red, { isEssential: true }),
|
|
colorY: PD.Color(ColorNames.green, { isEssential: true }),
|
|
colorY: PD.Color(ColorNames.green, { isEssential: true }),
|
|
colorZ: PD.Color(ColorNames.blue, { isEssential: true }),
|
|
colorZ: PD.Color(ColorNames.blue, { isEssential: true }),
|
|
scale: PD.Numeric(0.33, { min: 0.1, max: 2, step: 0.1 }, { isEssential: true }),
|
|
scale: PD.Numeric(0.33, { min: 0.1, max: 2, step: 0.1 }, { isEssential: true }),
|
|
|
|
+ location: PD.Select('bottom-left', PD.arrayToOptions(['bottom-left', 'bottom-right', 'top-left', 'top-right'] as const)),
|
|
|
|
+ originColor: PD.Color(ColorNames.grey),
|
|
|
|
+ radiusScale: PD.Numeric(0.075, { min: 0.01, max: 0.3, step: 0.001 }),
|
|
|
|
+ showPlanes: PD.Boolean(true),
|
|
|
|
+ planeColorXY: PD.Color(ColorNames.grey, { label: 'Plane Color XY' }),
|
|
|
|
+ planeColorXZ: PD.Color(ColorNames.grey, { label: 'Plane Color XZ' }),
|
|
|
|
+ planeColorYZ: PD.Color(ColorNames.grey, { label: 'Plane Color YZ' }),
|
|
|
|
+ showLabels: PD.Boolean(false),
|
|
|
|
+ labelX: PD.Text('X'),
|
|
|
|
+ labelY: PD.Text('Y'),
|
|
|
|
+ labelZ: PD.Text('Z'),
|
|
|
|
+ labelColorX: PD.Color(ColorNames.grey),
|
|
|
|
+ labelColorY: PD.Color(ColorNames.grey),
|
|
|
|
+ labelColorZ: PD.Color(ColorNames.grey),
|
|
|
|
+ labelOpacity: PD.Numeric(1, { min: 0, max: 1, step: 0.01 }),
|
|
|
|
+ labelScale: PD.Numeric(0.25, { min: 0.1, max: 1.0, step: 0.01 }),
|
|
};
|
|
};
|
|
type AxesParams = typeof AxesParams
|
|
type AxesParams = typeof AxesParams
|
|
type AxesProps = PD.Values<AxesParams>
|
|
type AxesProps = PD.Values<AxesParams>
|
|
@@ -56,7 +73,8 @@ export class CameraHelper {
|
|
axes: { name: 'off', params: {} }
|
|
axes: { name: 'off', params: {} }
|
|
};
|
|
};
|
|
|
|
|
|
- private renderObject: GraphicsRenderObject | undefined;
|
|
|
|
|
|
+ private meshRenderObject: GraphicsRenderObject | undefined;
|
|
|
|
+ private textRenderObject: GraphicsRenderObject | undefined;
|
|
private pixelRatio = 1;
|
|
private pixelRatio = 1;
|
|
|
|
|
|
constructor(private webgl: WebGLContext, props: Partial<CameraHelperProps> = {}) {
|
|
constructor(private webgl: WebGLContext, props: Partial<CameraHelperProps> = {}) {
|
|
@@ -80,8 +98,14 @@ export class CameraHelper {
|
|
...props.axes.params,
|
|
...props.axes.params,
|
|
scale: props.axes.params.scale * this.webgl.pixelRatio
|
|
scale: props.axes.params.scale * this.webgl.pixelRatio
|
|
};
|
|
};
|
|
- this.renderObject = createAxesRenderObject(params);
|
|
|
|
- this.scene.add(this.renderObject);
|
|
|
|
|
|
+ this.meshRenderObject = createMeshRenderObject(params);
|
|
|
|
+ this.scene.add(this.meshRenderObject);
|
|
|
|
+ if (props.axes.params.showLabels) {
|
|
|
|
+ this.textRenderObject = createTextRenderObject(params);
|
|
|
|
+ this.scene.add(this.textRenderObject);
|
|
|
|
+ } else {
|
|
|
|
+ this.textRenderObject = undefined;
|
|
|
|
+ }
|
|
this.scene.commit();
|
|
this.scene.commit();
|
|
|
|
|
|
Vec3.set(this.camera.position, 0, 0, params.scale * 200);
|
|
Vec3.set(this.camera.position, 0, 0, params.scale * 200);
|
|
@@ -99,19 +123,29 @@ export class CameraHelper {
|
|
|
|
|
|
getLoci(pickingId: PickingId) {
|
|
getLoci(pickingId: PickingId) {
|
|
const { objectId, groupId, instanceId } = pickingId;
|
|
const { objectId, groupId, instanceId } = pickingId;
|
|
- if (!this.renderObject || objectId !== this.renderObject.id || groupId === CameraHelperAxis.None) return EmptyLoci;
|
|
|
|
|
|
+ if ((
|
|
|
|
+ (!this.meshRenderObject || objectId !== this.meshRenderObject.id) &&
|
|
|
|
+ (!this.textRenderObject || objectId !== this.textRenderObject.id)
|
|
|
|
+ ) || groupId === CameraHelperAxis.None) return EmptyLoci;
|
|
return CameraAxesLoci(this, groupId, instanceId);
|
|
return CameraAxesLoci(this, groupId, instanceId);
|
|
}
|
|
}
|
|
|
|
|
|
private eachGroup = (loci: Loci, apply: (interval: Interval) => boolean): boolean => {
|
|
private eachGroup = (loci: Loci, apply: (interval: Interval) => boolean): boolean => {
|
|
- if (!this.renderObject) return false;
|
|
|
|
if (!isCameraAxesLoci(loci)) return false;
|
|
if (!isCameraAxesLoci(loci)) return false;
|
|
let changed = false;
|
|
let changed = false;
|
|
- const groupCount = this.renderObject.values.uGroupCount.ref.value;
|
|
|
|
- const { elements } = loci;
|
|
|
|
- for (const { groupId, instanceId } of elements) {
|
|
|
|
- const idx = instanceId * groupCount + groupId;
|
|
|
|
- if (apply(Interval.ofSingleton(idx))) changed = true;
|
|
|
|
|
|
+ if (this.meshRenderObject) {
|
|
|
|
+ const groupCount = this.meshRenderObject.values.uGroupCount.ref.value;
|
|
|
|
+ for (const { groupId, instanceId } of loci.elements) {
|
|
|
|
+ const idx = instanceId * groupCount + groupId;
|
|
|
|
+ if (apply(Interval.ofSingleton(idx))) changed = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (this.textRenderObject) {
|
|
|
|
+ const groupCount = this.textRenderObject.values.uGroupCount.ref.value;
|
|
|
|
+ for (const { groupId, instanceId } of loci.elements) {
|
|
|
|
+ const idx = instanceId * groupCount + groupId;
|
|
|
|
+ if (apply(Interval.ofSingleton(idx))) changed = true;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
return changed;
|
|
return changed;
|
|
};
|
|
};
|
|
@@ -122,11 +156,14 @@ export class CameraHelper {
|
|
if (!isCameraAxesLoci(loci)) return false;
|
|
if (!isCameraAxesLoci(loci)) return false;
|
|
if (loci.data !== this) return false;
|
|
if (loci.data !== this) return false;
|
|
}
|
|
}
|
|
- return Visual.mark(this.renderObject, loci, action, this.eachGroup);
|
|
|
|
|
|
+ return (
|
|
|
|
+ Visual.mark(this.meshRenderObject, loci, action, this.eachGroup) ||
|
|
|
|
+ Visual.mark(this.textRenderObject, loci, action, this.eachGroup)
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
|
|
update(camera: ICamera) {
|
|
update(camera: ICamera) {
|
|
- if (!this.renderObject) return;
|
|
|
|
|
|
+ if (!this.meshRenderObject || this.props.axes.name === 'off') return;
|
|
|
|
|
|
if (this.pixelRatio !== this.webgl.pixelRatio) {
|
|
if (this.pixelRatio !== this.webgl.pixelRatio) {
|
|
this.setProps(this.props);
|
|
this.setProps(this.props);
|
|
@@ -135,12 +172,37 @@ export class CameraHelper {
|
|
updateCamera(this.camera, camera.viewport, camera.viewOffset);
|
|
updateCamera(this.camera, camera.viewport, camera.viewOffset);
|
|
Mat4.extractRotation(this.scene.view, camera.view);
|
|
Mat4.extractRotation(this.scene.view, camera.view);
|
|
|
|
|
|
- const r = this.renderObject.values.boundingSphere.ref.value.radius;
|
|
|
|
- Mat4.setTranslation(this.scene.view, Vec3.create(
|
|
|
|
- -camera.viewport.width / 2 + r,
|
|
|
|
- -camera.viewport.height / 2 + r,
|
|
|
|
- 0
|
|
|
|
- ));
|
|
|
|
|
|
+ const r = this.textRenderObject
|
|
|
|
+ ? this.textRenderObject.values.boundingSphere.ref.value.radius
|
|
|
|
+ : this.meshRenderObject.values.boundingSphere.ref.value.radius;
|
|
|
|
+ const l = this.props.axes.params.location;
|
|
|
|
+ if (l === 'bottom-left') {
|
|
|
|
+ Mat4.setTranslation(this.scene.view, Vec3.create(
|
|
|
|
+ -camera.viewport.width / 2 + r,
|
|
|
|
+ -camera.viewport.height / 2 + r,
|
|
|
|
+ 0
|
|
|
|
+ ));
|
|
|
|
+ } else if (l === 'bottom-right') {
|
|
|
|
+ Mat4.setTranslation(this.scene.view, Vec3.create(
|
|
|
|
+ camera.viewport.width / 2 - r,
|
|
|
|
+ -camera.viewport.height / 2 + r,
|
|
|
|
+ 0
|
|
|
|
+ ));
|
|
|
|
+ } else if (l === 'top-left') {
|
|
|
|
+ Mat4.setTranslation(this.scene.view, Vec3.create(
|
|
|
|
+ -camera.viewport.width / 2 + r,
|
|
|
|
+ camera.viewport.height / 2 - r,
|
|
|
|
+ 0
|
|
|
|
+ ));
|
|
|
|
+ } else if (l === 'top-right') {
|
|
|
|
+ Mat4.setTranslation(this.scene.view, Vec3.create(
|
|
|
|
+ camera.viewport.width / 2 - r,
|
|
|
|
+ camera.viewport.height / 2 - r,
|
|
|
|
+ 0
|
|
|
|
+ ));
|
|
|
|
+ } else {
|
|
|
|
+ assertUnreachable(l);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -151,17 +213,23 @@ export enum CameraHelperAxis {
|
|
Z,
|
|
Z,
|
|
XY,
|
|
XY,
|
|
XZ,
|
|
XZ,
|
|
- YZ
|
|
|
|
|
|
+ YZ,
|
|
|
|
+ Origin
|
|
}
|
|
}
|
|
|
|
|
|
-function getAxisLabel(axis: number) {
|
|
|
|
|
|
+function getAxisLabel(axis: number, cameraHelper: CameraHelper) {
|
|
|
|
+ const a = cameraHelper.props.axes;
|
|
|
|
+ const x = a.name === 'on' ? a.params.labelX : 'X';
|
|
|
|
+ const y = a.name === 'on' ? a.params.labelY : 'Y';
|
|
|
|
+ const z = a.name === 'on' ? a.params.labelZ : 'Z';
|
|
switch (axis) {
|
|
switch (axis) {
|
|
- case CameraHelperAxis.X: return 'X Axis';
|
|
|
|
- case CameraHelperAxis.Y: return 'Y Axis';
|
|
|
|
- case CameraHelperAxis.Z: return 'Z Axis';
|
|
|
|
- case CameraHelperAxis.XY: return 'XY Plane';
|
|
|
|
- case CameraHelperAxis.XZ: return 'XZ Plane';
|
|
|
|
- case CameraHelperAxis.YZ: return 'YZ Plane';
|
|
|
|
|
|
+ case CameraHelperAxis.X: return `${x} Axis`;
|
|
|
|
+ case CameraHelperAxis.Y: return `${y} Axis`;
|
|
|
|
+ case CameraHelperAxis.Z: return `${z} Axis`;
|
|
|
|
+ case CameraHelperAxis.XY: return `${x}${y} Plane`;
|
|
|
|
+ case CameraHelperAxis.XZ: return `${x}${z} Plane`;
|
|
|
|
+ case CameraHelperAxis.YZ: return `${y}${z} Plane`;
|
|
|
|
+ case CameraHelperAxis.Origin: return 'Origin';
|
|
default: return 'Axes';
|
|
default: return 'Axes';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -169,7 +237,7 @@ function getAxisLabel(axis: number) {
|
|
function CameraAxesLoci(cameraHelper: CameraHelper, groupId: number, instanceId: number) {
|
|
function CameraAxesLoci(cameraHelper: CameraHelper, groupId: number, instanceId: number) {
|
|
return DataLoci('camera-axes', cameraHelper, [{ groupId, instanceId }],
|
|
return DataLoci('camera-axes', cameraHelper, [{ groupId, instanceId }],
|
|
void 0 /** bounding sphere */,
|
|
void 0 /** bounding sphere */,
|
|
- () => getAxisLabel(groupId));
|
|
|
|
|
|
+ () => getAxisLabel(groupId, cameraHelper));
|
|
}
|
|
}
|
|
export type CameraAxesLoci = ReturnType<typeof CameraAxesLoci>
|
|
export type CameraAxesLoci = ReturnType<typeof CameraAxesLoci>
|
|
export function isCameraAxesLoci(x: Loci): x is CameraAxesLoci {
|
|
export function isCameraAxesLoci(x: Loci): x is CameraAxesLoci {
|
|
@@ -206,15 +274,17 @@ function updateCamera(camera: Camera, viewport: Viewport, viewOffset: Camera.Vie
|
|
Mat4.ortho(camera.projection, left, right, top, bottom, near, far);
|
|
Mat4.ortho(camera.projection, left, right, top, bottom, near, far);
|
|
}
|
|
}
|
|
|
|
|
|
-function createAxesMesh(scale: number, mesh?: Mesh) {
|
|
|
|
|
|
+function createAxesMesh(props: AxesProps, mesh?: Mesh) {
|
|
const state = MeshBuilder.createState(512, 256, mesh);
|
|
const state = MeshBuilder.createState(512, 256, mesh);
|
|
- const radius = 0.075 * scale;
|
|
|
|
- const x = Vec3.scale(Vec3(), Vec3.unitX, scale);
|
|
|
|
- const y = Vec3.scale(Vec3(), Vec3.unitY, scale);
|
|
|
|
- const z = Vec3.scale(Vec3(), Vec3.unitZ, scale);
|
|
|
|
|
|
+ const scale = 100 * props.scale;
|
|
|
|
+ const radius = props.radiusScale * scale;
|
|
|
|
+ const textScale = props.showLabels ? 100 * props.labelScale / 3 : 0;
|
|
|
|
+ const x = Vec3.scale(Vec3(), Vec3.unitX, scale - textScale);
|
|
|
|
+ const y = Vec3.scale(Vec3(), Vec3.unitY, scale - textScale);
|
|
|
|
+ const z = Vec3.scale(Vec3(), Vec3.unitZ, scale - textScale);
|
|
const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments: 32 };
|
|
const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments: 32 };
|
|
|
|
|
|
- state.currentGroup = CameraHelperAxis.None;
|
|
|
|
|
|
+ state.currentGroup = CameraHelperAxis.Origin;
|
|
addSphere(state, Vec3.origin, radius, 2);
|
|
addSphere(state, Vec3.origin, radius, 2);
|
|
|
|
|
|
state.currentGroup = CameraHelperAxis.X;
|
|
state.currentGroup = CameraHelperAxis.X;
|
|
@@ -229,50 +299,102 @@ function createAxesMesh(scale: number, mesh?: Mesh) {
|
|
addSphere(state, z, radius, 2);
|
|
addSphere(state, z, radius, 2);
|
|
addCylinder(state, Vec3.origin, z, 1, cylinderProps);
|
|
addCylinder(state, Vec3.origin, z, 1, cylinderProps);
|
|
|
|
|
|
- Vec3.scale(x, x, 0.5);
|
|
|
|
- Vec3.scale(y, y, 0.5);
|
|
|
|
- Vec3.scale(z, z, 0.5);
|
|
|
|
-
|
|
|
|
- state.currentGroup = CameraHelperAxis.XY;
|
|
|
|
- MeshBuilder.addTriangle(state, Vec3.origin, x, y);
|
|
|
|
- MeshBuilder.addTriangle(state, Vec3.origin, y, x);
|
|
|
|
- const xy = Vec3.add(Vec3(), x, y);
|
|
|
|
- MeshBuilder.addTriangle(state, xy, x, y);
|
|
|
|
- MeshBuilder.addTriangle(state, xy, y, x);
|
|
|
|
-
|
|
|
|
- state.currentGroup = CameraHelperAxis.XZ;
|
|
|
|
- MeshBuilder.addTriangle(state, Vec3.origin, x, z);
|
|
|
|
- MeshBuilder.addTriangle(state, Vec3.origin, z, x);
|
|
|
|
- const xz = Vec3.add(Vec3(), x, z);
|
|
|
|
- MeshBuilder.addTriangle(state, xz, x, z);
|
|
|
|
- MeshBuilder.addTriangle(state, xz, z, x);
|
|
|
|
-
|
|
|
|
- state.currentGroup = CameraHelperAxis.YZ;
|
|
|
|
- MeshBuilder.addTriangle(state, Vec3.origin, y, z);
|
|
|
|
- MeshBuilder.addTriangle(state, Vec3.origin, z, y);
|
|
|
|
- const yz = Vec3.add(Vec3(), y, z);
|
|
|
|
- MeshBuilder.addTriangle(state, yz, y, z);
|
|
|
|
- MeshBuilder.addTriangle(state, yz, z, y);
|
|
|
|
|
|
+ if (props.showPlanes) {
|
|
|
|
+ Vec3.scale(x, x, 0.5);
|
|
|
|
+ Vec3.scale(y, y, 0.5);
|
|
|
|
+ Vec3.scale(z, z, 0.5);
|
|
|
|
+
|
|
|
|
+ state.currentGroup = CameraHelperAxis.XY;
|
|
|
|
+ MeshBuilder.addTriangle(state, Vec3.origin, x, y);
|
|
|
|
+ MeshBuilder.addTriangle(state, Vec3.origin, y, x);
|
|
|
|
+ const xy = Vec3.add(Vec3(), x, y);
|
|
|
|
+ MeshBuilder.addTriangle(state, xy, x, y);
|
|
|
|
+ MeshBuilder.addTriangle(state, xy, y, x);
|
|
|
|
+
|
|
|
|
+ state.currentGroup = CameraHelperAxis.XZ;
|
|
|
|
+ MeshBuilder.addTriangle(state, Vec3.origin, x, z);
|
|
|
|
+ MeshBuilder.addTriangle(state, Vec3.origin, z, x);
|
|
|
|
+ const xz = Vec3.add(Vec3(), x, z);
|
|
|
|
+ MeshBuilder.addTriangle(state, xz, x, z);
|
|
|
|
+ MeshBuilder.addTriangle(state, xz, z, x);
|
|
|
|
+
|
|
|
|
+ state.currentGroup = CameraHelperAxis.YZ;
|
|
|
|
+ MeshBuilder.addTriangle(state, Vec3.origin, y, z);
|
|
|
|
+ MeshBuilder.addTriangle(state, Vec3.origin, z, y);
|
|
|
|
+ const yz = Vec3.add(Vec3(), y, z);
|
|
|
|
+ MeshBuilder.addTriangle(state, yz, y, z);
|
|
|
|
+ MeshBuilder.addTriangle(state, yz, z, y);
|
|
|
|
+ }
|
|
|
|
|
|
return MeshBuilder.getMesh(state);
|
|
return MeshBuilder.getMesh(state);
|
|
}
|
|
}
|
|
|
|
|
|
-function getAxesShape(props: AxesProps, shape?: Shape<Mesh>) {
|
|
|
|
|
|
+function getAxesMeshShape(props: AxesProps, shape?: Shape<Mesh>) {
|
|
const scale = 100 * props.scale;
|
|
const scale = 100 * props.scale;
|
|
- const mesh = createAxesMesh(scale, shape?.geometry);
|
|
|
|
|
|
+ const mesh = createAxesMesh(props, shape?.geometry);
|
|
mesh.setBoundingSphere(Sphere3D.create(Vec3.create(scale / 2, scale / 2, scale / 2), scale + scale / 4));
|
|
mesh.setBoundingSphere(Sphere3D.create(Vec3.create(scale / 2, scale / 2, scale / 2), scale + scale / 4));
|
|
const getColor = (groupId: number) => {
|
|
const getColor = (groupId: number) => {
|
|
switch (groupId) {
|
|
switch (groupId) {
|
|
- case 1: return props.colorX;
|
|
|
|
- case 2: return props.colorY;
|
|
|
|
- case 3: return props.colorZ;
|
|
|
|
|
|
+ case CameraHelperAxis.X: return props.colorX;
|
|
|
|
+ case CameraHelperAxis.Y: return props.colorY;
|
|
|
|
+ case CameraHelperAxis.Z: return props.colorZ;
|
|
|
|
+ case CameraHelperAxis.XY: return props.planeColorXY;
|
|
|
|
+ case CameraHelperAxis.XZ: return props.planeColorXZ;
|
|
|
|
+ case CameraHelperAxis.YZ: return props.planeColorYZ;
|
|
|
|
+ case CameraHelperAxis.Origin: return props.originColor;
|
|
|
|
+ default: return ColorNames.grey;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ return Shape.create('axes-mesh', {}, mesh, getColor, () => 1, () => '');
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function createMeshRenderObject(props: AxesProps) {
|
|
|
|
+ const shape = getAxesMeshShape(props);
|
|
|
|
+ return Shape.createRenderObject(shape, {
|
|
|
|
+ ...PD.getDefaultValues(Mesh.Params),
|
|
|
|
+ ...props,
|
|
|
|
+ ignoreLight: true,
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//
|
|
|
|
+
|
|
|
|
+function createAxesText(props: AxesProps, text?: Text) {
|
|
|
|
+ const builder = TextBuilder.create(props, 8, 8, text);
|
|
|
|
+ const scale = 100 * props.scale;
|
|
|
|
+
|
|
|
|
+ const x = Vec3.scale(Vec3(), Vec3.unitX, scale);
|
|
|
|
+ const y = Vec3.scale(Vec3(), Vec3.unitY, scale);
|
|
|
|
+ const z = Vec3.scale(Vec3(), Vec3.unitZ, scale);
|
|
|
|
+
|
|
|
|
+ const textScale = 100 * props.labelScale;
|
|
|
|
+ builder.add(props.labelX, x[0], x[1], x[2], 0.0, textScale, CameraHelperAxis.X);
|
|
|
|
+ builder.add(props.labelY, y[0], y[1], y[2], 0.0, textScale, CameraHelperAxis.Y);
|
|
|
|
+ builder.add(props.labelZ, z[0], z[1], z[2], 0.0, textScale, CameraHelperAxis.Z);
|
|
|
|
+
|
|
|
|
+ return builder.getText();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getAxesTextShape(props: AxesProps, shape?: Shape<Text>) {
|
|
|
|
+ const scale = 100 * props.scale;
|
|
|
|
+ const text = createAxesText(props, shape?.geometry);
|
|
|
|
+ text.setBoundingSphere(Sphere3D.create(Vec3.create(scale / 2, scale / 2, scale / 2), scale));
|
|
|
|
+ const getColor = (groupId: number) => {
|
|
|
|
+ switch (groupId) {
|
|
|
|
+ case CameraHelperAxis.X: return props.labelColorX;
|
|
|
|
+ case CameraHelperAxis.Y: return props.labelColorY;
|
|
|
|
+ case CameraHelperAxis.Z: return props.labelColorZ;
|
|
default: return ColorNames.grey;
|
|
default: return ColorNames.grey;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
- return Shape.create('axes', {}, mesh, getColor, () => 1, () => '');
|
|
|
|
|
|
+ return Shape.create('axes-text', {}, text, getColor, () => 1, () => '');
|
|
}
|
|
}
|
|
|
|
|
|
-function createAxesRenderObject(props: AxesProps) {
|
|
|
|
- const shape = getAxesShape(props);
|
|
|
|
- return Shape.createRenderObject(shape, props);
|
|
|
|
-}
|
|
|
|
|
|
+function createTextRenderObject(props: AxesProps) {
|
|
|
|
+ const shape = getAxesTextShape(props);
|
|
|
|
+ return Shape.createRenderObject(shape, {
|
|
|
|
+ ...PD.getDefaultValues(Text.Params),
|
|
|
|
+ ...props,
|
|
|
|
+ alpha: props.labelOpacity,
|
|
|
|
+ });
|
|
|
|
+}
|