diff --git a/src/buffer/point-buffer.ts b/src/buffer/point-buffer.ts index c63cbb396..0374c1ed5 100644 --- a/src/buffer/point-buffer.ts +++ b/src/buffer/point-buffer.ts @@ -9,6 +9,7 @@ import { DataTexture } from 'three' import '../shader/Point.vert' import '../shader/Point.frag' +import { BufferRegistry } from '../globals' import { defaults } from '../utils' import { smoothstep } from '../math/math-utils' import Buffer, { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferTypes } from './buffer' @@ -175,4 +176,6 @@ class PointBuffer extends Buffer { } } +BufferRegistry.add('point', PointBuffer) + export default PointBuffer diff --git a/src/buffer/wideline-buffer.ts b/src/buffer/wideline-buffer.ts index 8174a65ba..13a09f5db 100644 --- a/src/buffer/wideline-buffer.ts +++ b/src/buffer/wideline-buffer.ts @@ -9,6 +9,7 @@ import { Vector2, Matrix4 } from 'three' import '../shader/WideLine.vert' import '../shader/WideLine.frag' +import { BufferRegistry } from '../globals' import MappedQuadBuffer from './mappedquad-buffer' import { BufferDefaultParameters, BufferParameterTypes, BufferData } from './buffer' @@ -49,6 +50,8 @@ class WideLineBuffer extends MappedQuadBuffer { constructor (data: WideLineBufferData, params: Partial = {}) { super(data, params) + if (!data.color2 && data.color) data.color2 = data.color + this.addUniforms({ 'linewidth': { value: this.parameters.linewidth }, 'resolution': { value: new Vector2() }, @@ -66,4 +69,6 @@ class WideLineBuffer extends MappedQuadBuffer { } } +BufferRegistry.add('wideline', WideLineBuffer) + export default WideLineBuffer diff --git a/src/controls/picking-proxy.ts b/src/controls/picking-proxy.ts index 126d3dd3b..66d08889a 100644 --- a/src/controls/picking-proxy.ts +++ b/src/controls/picking-proxy.ts @@ -243,6 +243,10 @@ class PickingProxy { * @type {Object} */ get octahedron () { return this._objectIfType('octahedron') as ShapePrimitive } + /** + * @type {Object} + */ + get point () { return this._objectIfType('point') as ShapePrimitive } /** * @type {Object} */ @@ -279,6 +283,10 @@ class PickingProxy { * @type {Object} */ get volume () { return this._objectIfType('volume') as { volume: Volume, value: number } } + /** + * @type {Object} + */ + get wideline () { return this._objectIfType('wideline') as ShapePrimitive } _objectIfType (type: string) { return this.type === type ? this.object : undefined @@ -311,6 +319,8 @@ class PickingProxy { msg = this.ellipsoid.name } else if (this.octahedron) { msg = this.octahedron.name + } else if (this.point) { + msg = this.point.name } else if (this.mesh) { msg = `mesh: ${this.mesh.name || this.mesh.serial} (${this.mesh.shape.name})` } else if (this.slice) { @@ -329,6 +339,8 @@ class PickingProxy { msg = 'unknown' } else if (this.volume) { msg = `volume: ${this.volume.value.toPrecision(3)} (${this.volume.volume.name})` + } else if (this.wideline) { + msg = this.wideline.name } return msg } diff --git a/src/geometry/primitive.ts b/src/geometry/primitive.ts index 345dea265..80e3ef729 100644 --- a/src/geometry/primitive.ts +++ b/src/geometry/primitive.ts @@ -271,3 +271,47 @@ export class TextPrimitive extends Primitive { box.expandByPoint(tmpVec.fromArray(data.position)) } } + +/** + * Point primitive + */ +export class PointPrimitive extends Primitive { + static type = 'point' + + static fields = { + position: 'v3', + color: 'c', + } + + static positionFromShape (shape: Shape, pid: number) { + return this.valueFromShape(shape, pid, 'position') + } + + static expandBoundingBox (box: Box3, data: any) { + box.expandByPoint(tmpVec.fromArray(data.position)) + } +} + +/** + * Wideline geometry primitive + */ +export class WidelinePrimitive extends Primitive { + static type = 'wideline' + + static fields = { + position1: 'v3', + position2: 'v3', + color: 'c' + } + + static positionFromShape (shape: Shape, pid: number) { + const p1 = this.valueFromShape(shape, pid, 'position1') + const p2 = this.valueFromShape(shape, pid, 'position2') + return p1.add(p2).multiplyScalar(0.5) + } + + static expandBoundingBox (box: Box3, data: any) { + box.expandByPoint(tmpVec.fromArray(data.position1)) + box.expandByPoint(tmpVec.fromArray(data.position2)) + } +} diff --git a/src/geometry/shape.ts b/src/geometry/shape.ts index ef856f351..a4dc1062e 100644 --- a/src/geometry/shape.ts +++ b/src/geometry/shape.ts @@ -8,9 +8,9 @@ import { Box3, Vector3, Color } from 'three' import { createParams, ensureFloat32Array, getUintArray } from '../utils' import { - ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, - EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, - TetrahedronPrimitive, TextPrimitive, TorusPrimitive + ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, EllipsoidPrimitive, + OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, TextPrimitive, + TorusPrimitive, PointPrimitive, WidelinePrimitive } from './primitive' import { MeshPicker } from '../utils/picker' import Buffer from '../buffer/buffer' @@ -21,8 +21,8 @@ const tmpBox = new Box3() const Primitives = [ ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, - EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, - TetrahedronPrimitive, TextPrimitive, TorusPrimitive + EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, + TextPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive ] const ShapeDefaultParameters = { @@ -32,7 +32,11 @@ const ShapeDefaultParameters = { disableImpostor: false, openEnded: false, dashedCylinder: false, - labelParams: {} as Partial + labelParams: {} as Partial, + pointSize: 2, + sizeAttenuation: false, + useTexture: true, + lineWidth: 2 } type ShapeParameters = typeof ShapeDefaultParameters @@ -322,7 +326,7 @@ class Shape { * @example * shape.addText([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ], 0.5, "Hello"); * - * @param {Vector3|Array} position - from position vector or array + * @param {Vector3|Array} position - position vector or array * @param {Color|Array} color - color object or array * @param {Float} size - size value * @param {String} text - text value @@ -335,6 +339,41 @@ class Shape { return this } + /** + * Add point + * @example + * shape.addPoint([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ]); + * + * @param {Vector3|Array} position - position vector or array + * @param {Color|Array} color - color object or array + * @param {String} [name] - text + * @return {Shape} this object + */ + addPoint (position: Vector3|[number, number, number], color: Color|[number, number, number], name: string) { + PointPrimitive.objectToShape( + this, { position, color, name } + ) + return this + } + + /** + * Add a wideline + * @example + * shape.addWideline([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ]); + * + * @param {Vector3|Array} position1 - from position vector or array + * @param {Vector3|Array} position2 - to position vector or array + * @param {Color|Array} color - color object or array + * @param {String} [name] - text + * @return {Shape} this object + */ + addWideline (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], name: string) { + WidelinePrimitive.objectToShape( + this, { position1, position2, color, name } + ) + return this + } + /** * Deprecated, use `.addText` */ diff --git a/src/utils/picker.js b/src/utils/picker.js index a6784c68c..6917944e6 100644 --- a/src/utils/picker.js +++ b/src/utils/picker.js @@ -12,7 +12,7 @@ import Selection from '../selection/selection' import { ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, - TetrahedronPrimitive, TorusPrimitive + TetrahedronPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive } from '../geometry/primitive' import { contactTypeName } from '../chemistry/interactions/contact' @@ -393,6 +393,14 @@ class SlicePicker extends VolumePicker { get type () { return 'slice' } } +class PointPicker extends ShapePicker { + get primitive () { return PointPrimitive } +} + +class WidelinePicker extends ShapePicker { + get primitive () { return WidelinePrimitive } +} + PickerRegistry.add('arrow', ArrowPicker) PickerRegistry.add('box', BoxPicker) PickerRegistry.add('cone', ConePicker) @@ -402,6 +410,8 @@ PickerRegistry.add('octahedron', OctahedronPicker) PickerRegistry.add('sphere', SpherePicker) PickerRegistry.add('tetrahedron', TetrahedronPicker) PickerRegistry.add('torus', TorusPicker) +PickerRegistry.add('point', PointPicker) +PickerRegistry.add('wideline', WidelinePicker) export { Picker, @@ -427,5 +437,7 @@ export { TorusPicker, UnitcellPicker, UnknownPicker, - VolumePicker + VolumePicker, + PointPicker, + WidelinePicker }