Compare commits

..

1 Commits

Author SHA1 Message Date
Alexander Rose
1db0ada684 debugging 2022-08-20 16:50:39 -07:00
200 changed files with 2501 additions and 10479 deletions

View File

@@ -1,10 +0,0 @@
<!-- Thank you for contributing to Mol* -->
# Description
## Actions
- [ ] Added description of changes to the `[Unreleased]` section of `CHANGELOG.md`
- [ ] Updated headers of modified files
- [ ] Added my name to `package.json`'s `contributors`

View File

@@ -6,6 +6,7 @@
"recommendations": [
"dbaeumer.vscode-eslint",
"firsttris.vscode-jest-runner",
"msjsdiag.debugger-for-chrome",
"slevesque.shader",
"stpn.vscode-graphql",
"wayou.vscode-todo-highlight"

View File

@@ -6,88 +6,6 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased]
## [v3.25.1] - 2022-11-20
- Fix edge-case in `Structure.eachUnitPair` with single-element units
- Fix 'auto' structure-quality for coarse models
## [v3.25.0] - 2022-11-16
- Fix handling of gzipped assets (reverts #615)
## [v3.24.0] - 2022-11-13
- Make `PluginContext.initContainer` checkered canvas background optional
- Store URL of downloaded assets to detect zip/gzip based on extension (#615)
- Add optional `operator.key`; can be referenced in `IndexPairBonds`
- Add overpaint/transparency/substance theme strength to representations
- Fix viewport color for transparent background
## [v3.23.0] - 2022-10-19
- Add `PluginContext.initContainer/mount/unmount` methods; these should make it easier to reuse a plugin context with both custom and built-in UI
- Add `PluginContext.canvas3dInitialized`
- `createPluginUI` now resolves after the 3d canvas has been initialized
- Change EM Volume Streaming default from `Whole Structure` to `Auto`
## [v3.22.0] - 2022-10-17
- Replace `VolumeIsosurfaceParams.pickingGranularity` param with `Volume.PickingGranuality`
## [v3.21.0] - 2022-10-17
- Add `VolumeIsosurfaceParams.pickingGranularity` param
- Prevent component controls collapsing when option is selected
## [v3.20.0] - 2022-10-16
- [Breaking] Rename the ``model-index`` color theme to ``trajectory-index``
- Add a new ``model-index`` color theme that uniquely colors each loaded model
- Add the new ``model-index`` and ``structure-index`` color themes as an option for the carbon color in the ``element-symbol`` and ``ilustrative`` color themes
- Add ``structure-index`` color theme that uniquely colors each root structure
- Add ``nearest`` method to ``Lookup3D``
- Add mipmap-based blur for skybox backgrounds
## [v3.19.0] - 2022-10-01
- Fix "empty textures" error on empty canvas
- Optimize BinaryCIF integer packing encoder
- Fix dual depth peeling when post-processing is off or when rendering direct-volumes
- Add ``cameraClipping.minNear`` parameter
- Fix black artifacts on specular highlights with transparent background
## [v3.18.0] - 2022-09-17
- Integration of Dual depth peeling - OIT method
- Stereo camera improvements
- Fix param updates not applied
- Better param ranges and description
- Add timer.mark for left/right camera
## [v3.17.0] - 2022-09-11
- [Fix] Clone ``Canvas3DParams`` when creating a ``Canvas3D`` instance to prevent shared state between multiple instances
- Add ``includeResidueTest`` option to ``alignAndSuperposeWithSIFTSMapping``
- Add ``parentDisplay`` param for interactions representation.
- [Experimental] Add support for PyMOL, VMD, and Jmol atom expressions in selection scripts
- Support for ``failIfMajorPerformanceCaveat`` webgl attribute. Add ``PluginConfig.General.AllowMajorPerformanceCaveat`` and ``allow-major-performance-caveat`` Viewer GET param.
- Fix handling of PDB TER records (#549)
- Add support for getting multiple loci from a representation (``.getAllLoci()``)
- Add ``key`` property to intra- and inter-bonds for referencing source data
- Fix click event triggered after move
## [v3.16.0] - 2022-08-25
- Support ``globalColorParams`` and ``globalSymmetryParams`` in common representation params
- Support ``label`` parameter in ``Viewer.loadStructureFromUrl``
- Fix ``ViewportHelpContent`` Mouse Controls section
## [v3.15.0] - 2022-08-23
- Fix wboit in Safari >=15 (add missing depth renderbuffer to wboit pass)
- Add 'Around Camera' option to Volume streaming
- Avoid queuing more than one update in Volume streaming
## [v3.14.0] - 2022-08-20
- Expose inter-bonds compute params in structure

4297
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "molstar",
"version": "3.25.1",
"version": "3.14.0",
"description": "A comprehensive macromolecular library.",
"homepage": "https://github.com/molstar/molstar#readme",
"repository": {
@@ -89,74 +89,71 @@
"Ludovic Autin <autin@scripps.edu>",
"Michal Malý <michal.maly@ibt.cas.cz>",
"Jiří Černý <jiri.cerny@ibt.cas.cz>",
"Panagiotis Tourlas <panagiot_tourlov@hotmail.com>",
"Adam Midlik <midlik@gmail.com>",
"Koya Sakuma <koya.sakuma.work@gmail.com>",
"Gianluca Tomasello <giagitom@gmail.com>"
"Panagiotis Tourlas <panagiot_tourlov@hotmail.com>"
],
"license": "MIT",
"devDependencies": {
"@graphql-codegen/add": "^3.2.1",
"@graphql-codegen/cli": "^2.13.11",
"@graphql-codegen/cli": "^2.11.6",
"@graphql-codegen/time": "^3.2.1",
"@graphql-codegen/typescript": "^2.8.1",
"@graphql-codegen/typescript": "^2.7.3",
"@graphql-codegen/typescript-graphql-files-modules": "^2.2.1",
"@graphql-codegen/typescript-graphql-request": "^4.5.8",
"@graphql-codegen/typescript-operations": "^2.5.6",
"@graphql-codegen/typescript-graphql-request": "^4.5.3",
"@graphql-codegen/typescript-operations": "^2.5.3",
"@types/cors": "^2.8.12",
"@types/gl": "^6.0.1",
"@types/jest": "^29.2.2",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.8",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"@types/gl": "^4.1.1",
"@types/jest": "^28.1.7",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"benchmark": "^2.1.4",
"concurrently": "^7.5.0",
"concurrently": "^7.3.0",
"cpx2": "^4.2.0",
"crypto-browserify": "^3.12.0",
"css-loader": "^6.7.2",
"eslint": "^8.27.0",
"css-loader": "^6.7.1",
"eslint": "^8.22.0",
"extra-watch-webpack-plugin": "^1.0.3",
"file-loader": "^6.2.0",
"fs-extra": "^10.1.0",
"graphql": "^16.6.0",
"http-server": "^14.1.1",
"jest": "^29.3.1",
"jest": "^28.1.3",
"mini-css-extract-plugin": "^2.6.1",
"path-browserify": "^1.0.1",
"raw-loader": "^4.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"sass": "^1.56.1",
"sass-loader": "^13.2.0",
"simple-git": "^3.15.0",
"sass": "^1.54.5",
"sass-loader": "^13.0.2",
"simple-git": "^3.12.0",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.1",
"ts-jest": "^29.0.3",
"typescript": "^4.8.4",
"webpack": "^5.75.0",
"ts-jest": "^28.0.8",
"typescript": "^4.7.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
},
"dependencies": {
"@types/argparse": "^2.0.10",
"@types/benchmark": "^2.1.2",
"@types/benchmark": "^2.1.1",
"@types/compression": "1.7.2",
"@types/express": "^4.17.14",
"@types/node": "^16.18.3",
"@types/express": "^4.17.13",
"@types/node": "^16.11.51",
"@types/node-fetch": "^2.6.2",
"@types/swagger-ui-dist": "3.30.1",
"argparse": "^2.0.1",
"body-parser": "^1.20.1",
"body-parser": "^1.20.0",
"compression": "^1.7.4",
"cors": "^2.8.5",
"express": "^4.18.2",
"express": "^4.18.1",
"h264-mp4-encoder": "^1.0.12",
"immer": "^9.0.16",
"immer": "^9.0.15",
"immutable": "^4.1.0",
"node-fetch": "^2.6.7",
"rxjs": "^7.5.7",
"swagger-ui-dist": "^4.15.5",
"tslib": "^2.4.1",
"rxjs": "^7.5.6",
"swagger-ui-dist": "^4.14.0",
"tslib": "^2.4.0",
"util.promisify": "^1.1.1",
"xhr2": "^0.2.1"
},

View File

@@ -58,22 +58,20 @@ class Viewer {
}
static async create(elementOrId: string | HTMLElement, colors = [Color(0x992211), Color(0xDDDDDD)], showButtons = true) {
const o = {
...DefaultViewerOptions, ...{
layoutIsExpanded: false,
layoutShowControls: false,
layoutShowRemoteState: false,
layoutShowSequence: true,
layoutShowLog: false,
layoutShowLeftPanel: true,
const o = { ...DefaultViewerOptions, ...{
layoutIsExpanded: false,
layoutShowControls: false,
layoutShowRemoteState: false,
layoutShowSequence: true,
layoutShowLog: false,
layoutShowLeftPanel: true,
viewportShowExpand: true,
viewportShowControls: false,
viewportShowSettings: false,
viewportShowSelectionMode: false,
viewportShowAnimation: false,
}
};
viewportShowExpand: true,
viewportShowControls: false,
viewportShowSettings: false,
viewportShowSelectionMode: false,
viewportShowAnimation: false,
} };
const defaultSpec = DefaultPluginUISpec();
const spec: PluginUISpec = {
@@ -137,16 +135,18 @@ class Viewer {
}
};
PluginCommands.Canvas3D.SetSettings(plugin, {
settings: {
renderer: {
...plugin.canvas3d!.props.renderer,
backgroundColor: ColorNames.white,
},
camera: {
...plugin.canvas3d!.props.camera,
helper: { axes: { name: 'off', params: {} } }
}
plugin.behaviors.canvas3d.initialized.subscribe(v => {
if (v) {
PluginCommands.Canvas3D.SetSettings(plugin, { settings: {
renderer: {
...plugin.canvas3d!.props.renderer,
backgroundColor: ColorNames.white,
},
camera: {
...plugin.canvas3d!.props.camera,
helper: { axes: { name: 'off', params: {} } }
}
} });
}
});
@@ -166,7 +166,7 @@ class Viewer {
structures.push({ ref: structureProperties?.ref || structure.ref });
}
// remove current structures from hierarchy as they will be merged
// remove current structuresfrom hierarchy as they will be merged
// TODO only works with using loadStructuresFromUrlsAndMerge once
// need some more API metho to work with the hierarchy
this.plugin.managers.structure.hierarchy.updateCurrent(this.plugin.managers.structure.hierarchy.current.structures, 'remove');

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -202,14 +202,14 @@ const InteractionsPreset = StructureRepresentationPresetProvider({
const components = {
ligand: await presetStaticComponent(plugin, structureCell, 'ligand'),
surroundings: await plugin.builders.structure.tryCreateComponentFromSelection(structureCell, ligandSurroundings, `surroundings`),
interactions: await presetStaticComponent(plugin, structureCell, 'ligand'),
interactions: await plugin.builders.structure.tryCreateComponentFromSelection(structureCell, ligandPlusSurroundings, `interactions`)
};
const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, params);
const representations = {
ligand: builder.buildRepresentation(update, components.ligand, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.3 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ligand' }),
ballAndStick: builder.buildRepresentation(update, components.surroundings, { type: 'ball-and-stick', typeParams: { ...typeParams, material: CustomMaterial, sizeFactor: 0.1, sizeAspectRatio: 1 }, color: 'element-symbol', colorParams: { carbonColor: { name: 'element-symbol', params: {} } } }, { tag: 'ball-and-stick' }),
interactions: builder.buildRepresentation(update, components.interactions, { type: InteractionsRepresentationProvider, typeParams: { ...typeParams, material: CustomMaterial, includeParent: true, parentDisplay: 'between' }, color: InteractionTypeColorThemeProvider }, { tag: 'interactions' }),
interactions: builder.buildRepresentation(update, components.interactions, { type: InteractionsRepresentationProvider, typeParams: { ...typeParams, material: CustomMaterial }, color: InteractionTypeColorThemeProvider }, { tag: 'interactions' }),
label: builder.buildRepresentation(update, components.surroundings, { type: 'label', typeParams: { ...typeParams, material: CustomMaterial, background: false, borderWidth: 0.1 }, color: 'uniform', colorParams: { value: Color(0x000000) } }, { tag: 'label' }),
};

View File

@@ -88,9 +88,7 @@ const DefaultViewerOptions = {
pickScale: PluginConfig.General.PickScale.defaultValue,
pickPadding: PluginConfig.General.PickPadding.defaultValue,
enableWboit: PluginConfig.General.EnableWboit.defaultValue,
enableDpoit: PluginConfig.General.EnableDpoit.defaultValue,
preferWebgl1: PluginConfig.General.PreferWebGl1.defaultValue,
allowMajorPerformanceCaveat: PluginConfig.General.AllowMajorPerformanceCaveat.defaultValue,
viewportShowExpand: PluginConfig.Viewport.ShowExpand.defaultValue,
viewportShowControls: PluginConfig.Viewport.ShowControls.defaultValue,
@@ -160,9 +158,7 @@ export class Viewer {
[PluginConfig.General.PickScale, o.pickScale],
[PluginConfig.General.PickPadding, o.pickPadding],
[PluginConfig.General.EnableWboit, o.enableWboit],
[PluginConfig.General.EnableDpoit, o.enableDpoit],
[PluginConfig.General.PreferWebGl1, o.preferWebgl1],
[PluginConfig.General.AllowMajorPerformanceCaveat, o.allowMajorPerformanceCaveat],
[PluginConfig.Viewport.ShowExpand, o.viewportShowExpand],
[PluginConfig.Viewport.ShowControls, o.viewportShowControls],
[PluginConfig.Viewport.ShowSettings, o.viewportShowSettings],
@@ -203,7 +199,7 @@ export class Viewer {
return PluginCommands.State.Snapshots.OpenUrl(this.plugin, { url, type });
}
loadStructureFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false, options?: LoadStructureOptions & { label?: string }) {
loadStructureFromUrl(url: string, format: BuiltInTrajectoryFormat = 'mmcif', isBinary = false, options?: LoadStructureOptions) {
const params = DownloadStructure.createDefaultParams(this.plugin.state.data.root.obj!, this.plugin);
return this.plugin.runTask(this.plugin.state.data.applyAction(DownloadStructure, {
source: {
@@ -212,7 +208,6 @@ export class Viewer {
url: Asset.Url(url),
format: format as any,
isBinary,
label: options?.label,
options: { ...params.source.params.options, representationParams: options?.representationParams as any },
}
}
@@ -501,4 +496,4 @@ export const ViewerAutoPreset = StructureRepresentationPresetProvider({
return await PresetStructureRepresentations.auto.apply(ref, params, plugin);
}
}
});
});

View File

@@ -38,15 +38,6 @@
viewer.loadPdb('7bv2');
viewer.loadEmdb('EMD-30210', { detail: 6 });
// viewer.loadAllModelsOrAssemblyFromUrl('https://cs.litemol.org/5ire/full', 'mmcif', false, { representationParams: { theme: { globalName: 'operator-name' } } })
// viewer.loadStructureFromUrl('my url', 'pdb', false, {
// representationParams: {
// theme: {
// globalName: 'uniform',
// globalColorParams: { value: 0xff0000 }
// }
// },
// label: 'my structure'
// });
});
</script>
</body>

View File

@@ -60,9 +60,7 @@
var pickScale = getParam('pick-scale', '[^&]+').trim();
var pickPadding = getParam('pick-padding', '[^&]+').trim();
var disableWboit = getParam('disable-wboit', '[^&]+').trim() === '1';
var enableDpoit = getParam('enable-dpoit', '[^&]+').trim() === '1';
var preferWebgl1 = getParam('prefer-webgl1', '[^&]+').trim() === '1' || void 0;
var allowMajorPerformanceCaveat = getParam('allow-major-performance-caveat', '[^&]+').trim() === '1';
molstar.Viewer.create('app', {
layoutShowControls: !hideControls,
@@ -76,10 +74,8 @@
pixelScale: parseFloat(pixelScale) || 1,
pickScale: parseFloat(pickScale) || 0.25,
pickPadding: isNaN(parseFloat(pickPadding)) ? 1 : parseFloat(pickPadding),
enableWboit: (disableWboit || enableDpoit) ? false : void 0, // use default value if disable-wboit is not set
enableDpoit: enableDpoit ? true : void 0,
enableWboit: disableWboit ? false : void 0, // use default value if disable-wboit is not set
preferWebgl1: preferWebgl1,
allowMajorPerformanceCaveat: allowMajorPerformanceCaveat,
}).then(viewer => {
var snapshotId = getParam('snapshot-id', '[^&]+').trim();
if (snapshotId) viewer.setRemoteSnapshot(snapshotId);

View File

@@ -71,7 +71,6 @@ export function getFieldType(type: string, description: string, values?: string[
case 'ec-type':
case 'ucode-alphanum-csv':
case 'id_list':
case 'entity_id_list':
return ListCol('str', ',', description);
case 'id_list_spc':
return ListCol('str', ' ', description);

View File

@@ -4,16 +4,16 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { createRoot } from 'react-dom/client';
import * as ReactDOM from 'react-dom';
import { AlphaOrbitalsExample } from '.';
import { ParameterControls } from '../../mol-plugin-ui/controls/parameters';
import { useBehavior } from '../../mol-plugin-ui/hooks/use-behavior';
import { PluginContextContainer } from '../../mol-plugin-ui/plugin';
export function mountControls(orbitals: AlphaOrbitalsExample, parent: Element) {
createRoot(parent).render(<PluginContextContainer plugin={orbitals.plugin}>
ReactDOM.render(<PluginContextContainer plugin={orbitals.plugin}>
<Controls orbitals={orbitals} />
</PluginContextContainer>);
</PluginContextContainer>, parent);
}
function Controls({ orbitals }: { orbitals: AlphaOrbitalsExample }) {

View File

@@ -82,20 +82,24 @@ export class AlphaOrbitalsExample {
this.plugin.managers.interactivity.setProps({ granularity: 'element' });
if (!canComputeGrid3dOnGPU(this.plugin.canvas3d?.webgl)) {
PluginCommands.Toast.Show(this.plugin, {
title: 'Error',
message: `Browser/device does not support required WebGL extension (OES_texture_float).`
this.plugin.behaviors.canvas3d.initialized.subscribe(init => {
if (!init) return;
if (!canComputeGrid3dOnGPU(this.plugin.canvas3d?.webgl)) {
PluginCommands.Toast.Show(this.plugin, {
title: 'Error',
message: `Browser/device does not support required WebGL extension (OES_texture_float).`
});
return;
}
this.load({
moleculeSdf: DemoMoleculeSDF,
...DemoOrbitals
});
return;
}
this.load({
moleculeSdf: DemoMoleculeSDF,
...DemoOrbitals
mountControls(this, document.getElementById('controls')!);
});
mountControls(this, document.getElementById('controls')!);
}
readonly params = new BehaviorSubject<ParamDefinition.For<Params>>({} as any);

View File

@@ -72,7 +72,6 @@ export const Backgrounds = PluginBehavior.create<{ }>({
lightness: 0,
saturation: 0,
opacity: 1,
blur: 0.3,
}
}
}, 'Purple Nebula Skybox'],

View File

@@ -60,8 +60,6 @@ export class GeometryExporterUI extends CollapsableControls<{}, State> {
}
componentDidMount() {
if (!this.plugin.canvas3d) return;
const merged = merge(
this.controls.behaviors.params,
this.plugin.canvas3d!.reprCount

View File

@@ -118,13 +118,11 @@ export class Mp4Controls extends PluginComponent {
}
private init() {
if (!this.plugin.canvas3d) return;
this.subscribe(this.plugin.managers.animation.events.updated.pipe(debounceTime(16)), () => {
this.sync();
});
this.subscribe(this.plugin.canvas3d.resized, () => this.syncInfo());
this.subscribe(this.plugin.canvas3d?.resized!, () => this.syncInfo());
this.subscribe(this.plugin.helpers.viewportScreenshot?.events.previewed!, () => this.syncInfo());
this.subscribe(this.plugin.behaviors.state.isBusy, b => this.updateCanApply(b));

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -260,8 +260,7 @@ namespace Camera {
radius: 0,
radiusMax: 10,
fog: 50,
clipFar: true,
minNear: 5,
clipFar: true
};
}
@@ -277,7 +276,6 @@ namespace Camera {
radiusMax: number
fog: number
clipFar: boolean
minNear: number
}
export function copySnapshot(out: Snapshot, source?: Partial<Snapshot>) {
@@ -294,7 +292,6 @@ namespace Camera {
if (typeof source.radiusMax !== 'undefined') out.radiusMax = source.radiusMax;
if (typeof source.fog !== 'undefined') out.fog = source.fog;
if (typeof source.clipFar !== 'undefined') out.clipFar = source.clipFar;
if (typeof source.minNear !== 'undefined') out.minNear = source.minNear;
return out;
}
@@ -306,7 +303,6 @@ namespace Camera {
&& a.radiusMax === b.radiusMax
&& a.fog === b.fog
&& a.clipFar === b.clipFar
&& a.minNear === b.minNear
&& Vec3.exactEquals(a.position, b.position)
&& Vec3.exactEquals(a.up, b.up)
&& Vec3.exactEquals(a.target, b.target);
@@ -374,7 +370,7 @@ function updatePers(camera: Camera) {
}
function updateClip(camera: Camera) {
let { radius, radiusMax, mode, fog, clipFar, minNear } = camera.state;
let { radius, radiusMax, mode, fog, clipFar } = camera.state;
if (radius < 0.01) radius = 0.01;
const normalizedFar = clipFar ? radius : radiusMax;
@@ -388,12 +384,12 @@ function updateClip(camera: Camera) {
if (mode === 'perspective') {
// set at least to 5 to avoid slow sphere impostor rendering
near = Math.max(Math.min(radiusMax, minNear), near);
far = Math.max(minNear, far);
near = Math.max(Math.min(radiusMax, 5), near);
far = Math.max(5, far);
} else {
// not too close to 0 as it causes issues with outline rendering
near = Math.max(Math.min(radiusMax, minNear), near);
far = Math.max(minNear, far);
near = Math.max(Math.min(radiusMax, 5), near);
far = Math.max(5, far);
}
if (near === far) {

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -13,8 +13,8 @@ import { Camera, ICamera } from '../camera';
import { Viewport } from './util';
export const StereoCameraParams = {
eyeSeparation: PD.Numeric(0.062, { min: 0.02, max: 0.1, step: 0.001 }, { description: 'Distance between left and right camera.' }),
focus: PD.Numeric(10, { min: 1, max: 20, step: 0.1 }, { description: 'Apparent object distance.' }),
eyeSeparation: PD.Numeric(0.064, { min: 0.01, max: 0.5, step: 0.001 }),
focus: PD.Numeric(10, { min: 1, max: 100, step: 0.01 }),
};
export const DefaultStereoCameraProps = PD.getDefaultValues(StereoCameraParams);
export type StereoCameraProps = PD.Values<typeof StereoCameraParams>

View File

@@ -3,7 +3,6 @@
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author David Sehnal <david.sehnal@gmail.com>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { BehaviorSubject, Subscription } from 'rxjs';
@@ -40,10 +39,9 @@ import { Helper } from './helper/helper';
import { Passes } from './passes/passes';
import { shallowEqual } from '../mol-util';
import { MarkingParams } from './passes/marking';
import { GraphicsRenderVariantsBlended, GraphicsRenderVariantsWboit, GraphicsRenderVariantsDpoit } from '../mol-gl/webgl/render-item';
import { GraphicsRenderVariantsBlended, GraphicsRenderVariantsWboit } from '../mol-gl/webgl/render-item';
import { degToRad, radToDeg } from '../mol-math/misc';
import { AssetManager } from '../mol-util/assets';
import { deepClone } from '../mol-util/object';
export const Canvas3DParams = {
camera: PD.Group({
@@ -65,7 +63,6 @@ export const Canvas3DParams = {
cameraClipping: PD.Group({
radius: PD.Numeric(100, { min: 0, max: 99, step: 1 }, { label: 'Clipping', description: 'How much of the scene to show.' }),
far: PD.Boolean(true, { description: 'Hide scene in the distance' }),
minNear: PD.Numeric(5, { min: 0.1, max: 10, step: 0.1 }, { description: 'Note, may cause performance issues rendering impostors when set too small and cause issues with outline rendering when too close to 0.' }),
}, { pivot: 'radius' }),
viewport: PD.MappedStatic('canvas', {
canvas: PD.Group({}),
@@ -86,7 +83,6 @@ export const Canvas3DParams = {
cameraResetDurationMs: PD.Numeric(250, { min: 0, max: 1000, step: 1 }, { description: 'The time it takes to reset the camera.' }),
sceneRadiusFactor: PD.Numeric(1, { min: 1, max: 10, step: 0.1 }),
transparentBackground: PD.Boolean(false),
dpoitIterations: PD.Numeric(2, { min: 1, max: 10, step: 1 }),
multiSample: PD.Group(MultiSampleParams),
postprocessing: PD.Group(PostprocessingParams),
@@ -120,7 +116,6 @@ interface Canvas3DContext {
namespace Canvas3DContext {
export const DefaultAttribs = {
failIfMajorPerformanceCaveat: false,
/** true by default to avoid issues with Safari (Jan 2021) */
antialias: true,
/** true to support multiple Canvas3D objects with a single context */
@@ -130,19 +125,14 @@ namespace Canvas3DContext {
/** extra pixels to around target to check in case target is empty */
pickPadding: 1,
enableWboit: true,
enableDpoit: false,
preferWebGl1: false
};
export type Attribs = typeof DefaultAttribs
export function fromCanvas(canvas: HTMLCanvasElement, assetManager: AssetManager, attribs: Partial<Attribs> = {}): Canvas3DContext {
const a = { ...DefaultAttribs, ...attribs };
if (a.enableWboit && a.enableDpoit) throw new Error('Multiple transparency methods not allowed.');
const { failIfMajorPerformanceCaveat, antialias, preserveDrawingBuffer, pixelScale, preferWebGl1 } = a;
const { antialias, preserveDrawingBuffer, pixelScale, preferWebGl1 } = a;
const gl = getGLContext(canvas, {
failIfMajorPerformanceCaveat,
antialias,
preserveDrawingBuffer,
alpha: true, // the renderer requires an alpha channel
@@ -295,7 +285,7 @@ namespace Canvas3D {
export interface ClickEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys, page?: Vec2, position?: Vec3 }
export function create({ webgl, input, passes, attribs, assetManager }: Canvas3DContext, props: Partial<Canvas3DProps> = {}): Canvas3D {
const p: Canvas3DProps = { ...deepClone(DefaultCanvas3DParams), ...deepClone(props) };
const p: Canvas3DProps = { ...DefaultCanvas3DParams, ...props };
const reprRenderObjects = new Map<Representation.Any, Set<GraphicsRenderObject>>();
const reprUpdatedSubscriptions = new Map<Representation.Any, Subscription>();
@@ -312,7 +302,8 @@ namespace Canvas3D {
let width = 128;
let height = 128;
updateViewport();
const scene = Scene.create(webgl, passes.draw.dpoitEnabled ? GraphicsRenderVariantsDpoit : (passes.draw.wboitEnabled ? GraphicsRenderVariantsWboit : GraphicsRenderVariantsBlended));
const scene = Scene.create(webgl, passes.draw.wboitEnabled ? GraphicsRenderVariantsWboit : GraphicsRenderVariantsBlended);
function getSceneRadius() {
return scene.boundingSphere.radius * p.sceneRadiusFactor;
@@ -323,7 +314,6 @@ namespace Canvas3D {
mode: p.camera.mode,
fog: p.cameraFog.name === 'on' ? p.cameraFog.params.intensity : 0,
clipFar: p.cameraClipping.far,
minNear: p.cameraClipping.minNear,
fov: degToRad(p.camera.fov),
}, { x, y, width, height }, { pixelScale: attribs.pixelScale });
const stereoCamera = new StereoCamera(camera, p.camera.stereo.params);
@@ -689,11 +679,10 @@ namespace Canvas3D {
cameraFog: camera.state.fog > 0
? { name: 'on' as const, params: { intensity: camera.state.fog } }
: { name: 'off' as const, params: {} },
cameraClipping: { far: camera.state.clipFar, radius, minNear: camera.state.minNear },
cameraClipping: { far: camera.state.clipFar, radius },
cameraResetDurationMs: p.cameraResetDurationMs,
sceneRadiusFactor: p.sceneRadiusFactor,
transparentBackground: p.transparentBackground,
dpoitIterations: p.dpoitIterations,
viewport: p.viewport,
postprocessing: { ...p.postprocessing },
@@ -816,9 +805,6 @@ namespace Canvas3D {
if (props.cameraClipping.far !== undefined && props.cameraClipping.far !== camera.state.clipFar) {
cameraState.clipFar = props.cameraClipping.far;
}
if (props.cameraClipping.minNear !== undefined && props.cameraClipping.minNear !== camera.state.minNear) {
cameraState.minNear = props.cameraClipping.minNear;
}
if (props.cameraClipping.radius !== undefined) {
const radius = (getSceneRadius() / 100) * (100 - props.cameraClipping.radius);
if (radius > 0 && radius !== cameraState.radius) {
@@ -831,13 +817,9 @@ namespace Canvas3D {
if (props.camera?.helper) helper.camera.setProps(props.camera.helper);
if (props.camera?.manualReset !== undefined) p.camera.manualReset = props.camera.manualReset;
if (props.camera?.stereo !== undefined) {
Object.assign(p.camera.stereo, props.camera.stereo);
stereoCamera.setProps(p.camera.stereo.params);
}
if (props.camera?.stereo !== undefined) Object.assign(p.camera.stereo, props.camera.stereo);
if (props.cameraResetDurationMs !== undefined) p.cameraResetDurationMs = props.cameraResetDurationMs;
if (props.transparentBackground !== undefined) p.transparentBackground = props.transparentBackground;
if (props.dpoitIterations !== undefined) p.dpoitIterations = props.dpoitIterations;
if (props.viewport !== undefined) {
const doNotUpdate = p.viewport === props.viewport ||
(p.viewport.name === props.viewport.name && shallowEqual(p.viewport.params, props.viewport.params));
@@ -873,7 +855,7 @@ namespace Canvas3D {
}
},
getImagePass: (props: Partial<ImageProps> = {}) => {
return new ImagePass(webgl, assetManager, renderer, scene, camera, helper, passes.draw.wboitEnabled, passes.draw.dpoitEnabled, props);
return new ImagePass(webgl, assetManager, renderer, scene, camera, helper, passes.draw.wboitEnabled, props);
},
getRenderObjects(): GraphicsRenderObject[] {
const renderObjects: GraphicsRenderObject[] = [];
@@ -938,4 +920,4 @@ namespace Canvas3D {
Viewport.set(controls.viewport, x, y, width, height);
}
}
}
}

View File

@@ -49,7 +49,6 @@ const SkyboxParams = {
pz: PD.File({ label: 'Positive Z / Front', accept: 'image/*' }),
}, { isExpanded: true, label: 'Files' }),
}),
blur: PD.Numeric(0, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'Note, this only works in WebGL2 or when "EXT_shader_texture_lod" is available.' }),
...SharedParams,
};
type SkyboxProps = PD.Values<typeof SkyboxParams>
@@ -171,7 +170,6 @@ export class BackgroundPass {
Mat4.invert(m, m);
ValueCell.update(this.renderable.values.uViewDirectionProjectionInverse, m);
ValueCell.updateIfChanged(this.renderable.values.uBlur, props.blur);
ValueCell.updateIfChanged(this.renderable.values.uOpacity, props.opacity);
ValueCell.updateIfChanged(this.renderable.values.uSaturation, props.saturation);
ValueCell.updateIfChanged(this.renderable.values.uLightness, props.lightness);
@@ -369,7 +367,7 @@ function getSkyboxTexture(ctx: WebGLContext, assetManager: AssetManager, faces:
const cubeAssets = getCubeAssets(assetManager, faces);
const cubeFaces = getCubeFaces(assetManager, cubeAssets);
const assets = [cubeAssets.nx, cubeAssets.ny, cubeAssets.nz, cubeAssets.px, cubeAssets.py, cubeAssets.pz];
const texture = ctx.resources.cubeTexture(cubeFaces, true, onload);
const texture = ctx.resources.cubeTexture(cubeFaces, false, onload);
return { texture, assets };
}
@@ -426,15 +424,12 @@ const BackgroundSchema = {
uGradientColorA: UniformSpec('v3'),
uGradientColorB: UniformSpec('v3'),
uGradientRatio: UniformSpec('f'),
uBlur: UniformSpec('f'),
uOpacity: UniformSpec('f'),
uSaturation: UniformSpec('f'),
uLightness: UniformSpec('f'),
dVariant: DefineSpec('string', ['skybox', 'image', 'verticalGradient', 'horizontalGradient', 'radialGradient']),
};
const SkyboxShaderCode = ShaderCode('background', background_vert, background_frag, {
shaderTextureLod: 'optional'
});
const SkyboxShaderCode = ShaderCode('background', background_vert, background_frag);
type BackgroundRenderable = ComputeRenderable<Values<typeof BackgroundSchema>>
function getBackgroundRenderable(ctx: WebGLContext, width: number, height: number): BackgroundRenderable {
@@ -453,7 +448,6 @@ function getBackgroundRenderable(ctx: WebGLContext, width: number, height: numbe
uGradientColorA: ValueCell.create(Vec3()),
uGradientColorB: ValueCell.create(Vec3()),
uGradientRatio: ValueCell.create(0.5),
uBlur: ValueCell.create(0),
uOpacity: ValueCell.create(1),
uSaturation: ValueCell.create(0),
uLightness: ValueCell.create(0),

View File

@@ -1,309 +0,0 @@
/**
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Gianluca Tomasello <giagitom@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*
* Adapted from https://github.com/tsherif/webgl2examples, The MIT License, Copyright © 2017 Tarek Sherif, Shuai Shao
*/
import { QuadSchema, QuadValues } from '../../mol-gl/compute/util';
import { ComputeRenderable, createComputeRenderable } from '../../mol-gl/renderable';
import { TextureSpec, UniformSpec, Values } from '../../mol-gl/renderable/schema';
import { ShaderCode } from '../../mol-gl/shader-code';
import { WebGLContext } from '../../mol-gl/webgl/context';
import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
import { Texture } from '../../mol-gl/webgl/texture';
import { ValueCell } from '../../mol-util';
import { quad_vert } from '../../mol-gl/shader/quad.vert';
import { evaluateDpoit_frag } from '../../mol-gl/shader/evaluate-dpoit.frag';
import { blendBackDpoit_frag } from '../../mol-gl/shader/blend-back-dpoit.frag';
import { Framebuffer } from '../../mol-gl/webgl/framebuffer';
import { Vec2 } from '../../mol-math/linear-algebra';
import { isDebugMode, isTimingMode } from '../../mol-util/debug';
import { isWebGL2 } from '../../mol-gl/webgl/compat';
const BlendBackDpoitSchema = {
...QuadSchema,
tDpoitBackColor: TextureSpec('texture', 'rgba', 'float', 'nearest'),
uTexSize: UniformSpec('v2'),
};
const BlendBackDpoitShaderCode = ShaderCode('blend-back-dpoit', quad_vert, blendBackDpoit_frag);
type BlendBackDpoitRenderable = ComputeRenderable<Values<typeof BlendBackDpoitSchema>>
function getBlendBackDpoitRenderable(ctx: WebGLContext, dopitBlendBackTexture: Texture): BlendBackDpoitRenderable {
const values: Values<typeof BlendBackDpoitSchema> = {
...QuadValues,
tDpoitBackColor: ValueCell.create(dopitBlendBackTexture),
uTexSize: ValueCell.create(Vec2.create(dopitBlendBackTexture.getWidth(), dopitBlendBackTexture.getHeight())),
};
const schema = { ...BlendBackDpoitSchema };
const renderItem = createComputeRenderItem(ctx, 'triangles', BlendBackDpoitShaderCode, schema, values);
return createComputeRenderable(renderItem, values);
}
const EvaluateDpoitSchema = {
...QuadSchema,
tDpoitFrontColor: TextureSpec('texture', 'rgba', 'float', 'nearest'),
uTexSize: UniformSpec('v2'),
};
const EvaluateDpoitShaderCode = ShaderCode('evaluate-dpoit', quad_vert, evaluateDpoit_frag);
type EvaluateDpoitRenderable = ComputeRenderable<Values<typeof EvaluateDpoitSchema>>
function getEvaluateDpoitRenderable(ctx: WebGLContext, dpoitFrontColorTexture: Texture): EvaluateDpoitRenderable {
const values: Values<typeof EvaluateDpoitSchema> = {
...QuadValues,
tDpoitFrontColor: ValueCell.create(dpoitFrontColorTexture),
uTexSize: ValueCell.create(Vec2.create(dpoitFrontColorTexture.getWidth(), dpoitFrontColorTexture.getHeight())),
};
const schema = { ...EvaluateDpoitSchema };
const renderItem = createComputeRenderItem(ctx, 'triangles', EvaluateDpoitShaderCode, schema, values);
return createComputeRenderable(renderItem, values);
}
export class DpoitPass {
private readonly DEPTH_CLEAR_VALUE = -99999.0; // NOTE same constant is set in shaders
private readonly MAX_DEPTH = 1.0;
private readonly MIN_DEPTH = 0.0;
private passCount = 0;
private writeId: number;
private readId: number;
private readonly blendBackRenderable: BlendBackDpoitRenderable;
private readonly renderable: EvaluateDpoitRenderable;
private readonly depthFramebuffers: Framebuffer[];
private readonly colorFramebuffers: Framebuffer[];
private readonly depthTextures: Texture[];
private readonly colorFrontTextures: Texture[];
private readonly colorBackTextures: Texture[];
private _supported = false;
get supported() {
return this._supported;
}
bind() {
const { state, gl, extensions: { blendMinMax } } = this.webgl;
// initialize
this.passCount = 0;
this.depthFramebuffers[0].bind();
state.clearColor(this.DEPTH_CLEAR_VALUE, this.DEPTH_CLEAR_VALUE, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
this.depthFramebuffers[1].bind();
state.clearColor(-this.MIN_DEPTH, this.MAX_DEPTH, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
this.colorFramebuffers[0].bind();
state.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
this.colorFramebuffers[1].bind();
state.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
this.depthFramebuffers[0].bind();
state.blendEquation(blendMinMax!.MAX);
state.depthMask(false);
return {
depth: this.depthTextures[1],
frontColor: this.colorFrontTextures[1],
backColor: this.colorBackTextures[1]
};
}
bindDualDepthPeeling() {
const { state, gl, extensions: { blendMinMax } } = this.webgl;
this.readId = this.passCount % 2;
this.writeId = 1 - this.readId; // ping-pong: 0 or 1
this.passCount += 1; // increment for next pass
this.depthFramebuffers[this.writeId].bind();
state.clearColor(this.DEPTH_CLEAR_VALUE, this.DEPTH_CLEAR_VALUE, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
this.colorFramebuffers[this.writeId].bind();
state.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
this.depthFramebuffers[this.writeId].bind();
state.blendEquation(blendMinMax!.MAX);
state.depthMask(false);
return {
depth: this.depthTextures[this.readId],
frontColor: this.colorFrontTextures[this.readId],
backColor: this.colorBackTextures[this.readId]
};
}
renderBlendBack() {
if (isTimingMode) this.webgl.timer.mark('DpoitPass.renderBlendBack');
const { state, gl } = this.webgl;
state.blendEquation(gl.FUNC_ADD);
state.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
ValueCell.update(this.blendBackRenderable.values.tDpoitBackColor, this.colorBackTextures[this.writeId]);
this.blendBackRenderable.update();
this.blendBackRenderable.render();
if (isTimingMode) this.webgl.timer.markEnd('DpoitPass.renderBlendBack');
}
render() {
if (isTimingMode) this.webgl.timer.mark('DpoitPass.render');
const { state, gl } = this.webgl;
state.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
ValueCell.update(this.renderable.values.tDpoitFrontColor, this.colorFrontTextures[this.writeId]);
this.renderable.update();
this.renderable.render();
if (isTimingMode) this.webgl.timer.markEnd('DpoitPass.render');
}
setSize(width: number, height: number) {
const [w, h] = this.renderable.values.uTexSize.ref.value;
if (width !== w || height !== h) {
for (let i = 0; i < 2; i++) {
this.depthTextures[i].define(width, height);
this.colorFrontTextures[i].define(width, height);
this.colorBackTextures[i].define(width, height);
}
ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height));
ValueCell.update(this.blendBackRenderable.values.uTexSize, Vec2.set(this.blendBackRenderable.values.uTexSize.ref.value, width, height));
}
}
reset() {
if (this._supported) this._init();
}
private _init() {
const { extensions: { drawBuffers } } = this.webgl;
for (let i = 0; i < 2; i++) {
// depth
this.depthFramebuffers[i].bind();
drawBuffers!.drawBuffers([
drawBuffers!.COLOR_ATTACHMENT0,
drawBuffers!.COLOR_ATTACHMENT1,
drawBuffers!.COLOR_ATTACHMENT2
]);
this.colorFrontTextures[i].attachFramebuffer(this.depthFramebuffers[i], 'color0');
this.colorBackTextures[i].attachFramebuffer(this.depthFramebuffers[i], 'color1');
this.depthTextures[i].attachFramebuffer(this.depthFramebuffers[i], 'color2');
// color
this.colorFramebuffers[i].bind();
drawBuffers!.drawBuffers([
drawBuffers!.COLOR_ATTACHMENT0,
drawBuffers!.COLOR_ATTACHMENT1
]);
this.colorFrontTextures[i].attachFramebuffer(this.colorFramebuffers[i], 'color0');
this.colorBackTextures[i].attachFramebuffer(this.colorFramebuffers[i], 'color1');
}
}
static isSupported(webgl: WebGLContext) {
const { extensions: { drawBuffers, textureFloat, colorBufferFloat, blendMinMax } } = webgl;
if (!textureFloat || !colorBufferFloat || !drawBuffers || !blendMinMax) {
if (isDebugMode) {
const missing: string[] = [];
if (!textureFloat) missing.push('textureFloat');
if (!colorBufferFloat) missing.push('colorBufferFloat');
if (!drawBuffers) missing.push('drawBuffers');
if (!blendMinMax) missing.push('blendMinMax');
console.log(`Missing "${missing.join('", "')}" extensions required for "dpoit"`);
}
return false;
} else {
return true;
}
}
constructor(private webgl: WebGLContext, width: number, height: number) {
if (!DpoitPass.isSupported(webgl)) return;
const { resources, extensions: { colorBufferHalfFloat, textureHalfFloat } } = webgl;
// textures
if (isWebGL2(webgl.gl)) {
this.depthTextures = [
resources.texture('image-float32', 'rg', 'float', 'nearest'),
resources.texture('image-float32', 'rg', 'float', 'nearest')
];
this.colorFrontTextures = colorBufferHalfFloat && textureHalfFloat ? [
resources.texture('image-float16', 'rgba', 'fp16', 'nearest'),
resources.texture('image-float16', 'rgba', 'fp16', 'nearest')
] : [
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
resources.texture('image-float32', 'rgba', 'float', 'nearest')
];
this.colorBackTextures = colorBufferHalfFloat && textureHalfFloat ? [
resources.texture('image-float16', 'rgba', 'fp16', 'nearest'),
resources.texture('image-float16', 'rgba', 'fp16', 'nearest')
] : [
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
resources.texture('image-float32', 'rgba', 'float', 'nearest')
];
} else {
// in webgl1 drawbuffers must be in the same format for some reason
this.depthTextures = [
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
resources.texture('image-float32', 'rgba', 'float', 'nearest')
];
this.colorFrontTextures = [
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
resources.texture('image-float32', 'rgba', 'float', 'nearest')
];
this.colorBackTextures = [
resources.texture('image-float32', 'rgba', 'float', 'nearest'),
resources.texture('image-float32', 'rgba', 'float', 'nearest')
];
}
this.depthTextures[0].define(width, height);
this.depthTextures[1].define(width, height);
this.colorFrontTextures[0].define(width, height);
this.colorFrontTextures[1].define(width, height);
this.colorBackTextures[0].define(width, height);
this.colorBackTextures[1].define(width, height);
// framebuffers
this.depthFramebuffers = [resources.framebuffer(), resources.framebuffer()];
this.colorFramebuffers = [resources.framebuffer(), resources.framebuffer()];
// renderables
this.blendBackRenderable = getBlendBackDpoitRenderable(webgl, this.colorBackTextures[0]);
this.renderable = getEvaluateDpoitRenderable(webgl, this.colorFrontTextures[0]);
this._supported = true;
this._init();
}
}

View File

@@ -3,7 +3,6 @@
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { WebGLContext } from '../../mol-gl/webgl/context';
@@ -18,7 +17,6 @@ import { Helper } from '../helper/helper';
import { StereoCamera } from '../camera/stereo';
import { WboitPass } from './wboit';
import { DpoitPass } from './dpoit';
import { AntialiasingPass, PostprocessingPass, PostprocessingProps } from './postprocessing';
import { MarkingPass, MarkingProps } from './marking';
import { CopyRenderable, createCopyRenderable } from '../../mol-gl/compute/util';
@@ -29,7 +27,6 @@ type Props = {
postprocessing: PostprocessingProps;
marking: MarkingProps;
transparentBackground: boolean;
dpoitIterations: number;
}
type RenderContext = {
@@ -55,7 +52,6 @@ export class DrawPass {
private copyFboPostprocessing: CopyRenderable;
private readonly wboit: WboitPass | undefined;
private readonly dpoit: DpoitPass | undefined;
private readonly marking: MarkingPass;
readonly postprocessing: PostprocessingPass;
private readonly antialiasing: AntialiasingPass;
@@ -64,12 +60,9 @@ export class DrawPass {
return !!this.wboit?.supported;
}
get dpoitEnabled() {
return !!this.dpoit?.supported;
}
constructor(private webgl: WebGLContext, assetManager: AssetManager, width: number, height: number, enableWboit: boolean, enableDpoit: boolean) {
constructor(private webgl: WebGLContext, assetManager: AssetManager, width: number, height: number, enableWboit: boolean) {
const { extensions, resources, isWebGL2 } = webgl;
this.drawTarget = createNullRenderTarget(webgl.gl);
this.colorTarget = webgl.createRenderTarget(width, height, true, 'uint8', 'linear');
this.packedDepth = !extensions.depthTexture;
@@ -85,7 +78,6 @@ export class DrawPass {
}
this.wboit = enableWboit ? new WboitPass(webgl, width, height) : undefined;
this.dpoit = enableDpoit ? new DpoitPass(webgl, width, height) : undefined;
this.marking = new MarkingPass(webgl, width, height);
this.postprocessing = new PostprocessingPass(webgl, assetManager, this);
this.antialiasing = new AntialiasingPass(webgl, this);
@@ -96,7 +88,6 @@ export class DrawPass {
reset() {
this.wboit?.reset();
this.dpoit?.reset();
}
setSize(width: number, height: number) {
@@ -120,70 +111,12 @@ export class DrawPass {
this.wboit.setSize(width, height);
}
if (this.dpoit?.supported) {
this.dpoit.setSize(width, height);
}
this.marking.setSize(width, height);
this.postprocessing.setSize(width, height);
this.antialiasing.setSize(width, height);
}
}
private _renderDpoit(renderer: Renderer, camera: ICamera, scene: Scene, iterations: number, transparentBackground: boolean, postprocessingProps: PostprocessingProps) {
if (!this.dpoit?.supported) throw new Error('expected dpoit to be supported');
this.depthTextureOpaque.attachFramebuffer(this.colorTarget.framebuffer, 'depth');
renderer.clear(true);
// render opaque primitives
if (scene.hasOpaque) {
renderer.renderDpoitOpaque(scene.primitives, camera, null);
}
if (PostprocessingPass.isEnabled(postprocessingProps)) {
if (PostprocessingPass.isOutlineEnabled(postprocessingProps)) {
this.depthTargetTransparent.bind();
renderer.clearDepth(true);
if (scene.opacityAverage < 1) {
renderer.renderDepthTransparent(scene.primitives, camera, this.depthTextureOpaque);
}
}
this.postprocessing.render(camera, false, transparentBackground, renderer.props.backgroundColor, postprocessingProps);
}
this.depthTextureOpaque.detachFramebuffer(this.colorTarget.framebuffer, 'depth');
// render transparent primitives
if (scene.opacityAverage < 1) {
const target = PostprocessingPass.isEnabled(postprocessingProps)
? this.postprocessing.target : this.colorTarget;
const dpoitTextures = this.dpoit.bind();
renderer.renderDpoitTransparent(scene.primitives, camera, this.depthTextureOpaque, dpoitTextures);
for (let i = 0; i < iterations; i++) {
if (isTimingMode) this.webgl.timer.mark('DpoitPass.layer');
const dpoitTextures = this.dpoit.bindDualDepthPeeling();
renderer.renderDpoitTransparent(scene.primitives, camera, this.depthTextureOpaque, dpoitTextures);
target.bind();
this.dpoit.renderBlendBack();
if (isTimingMode) this.webgl.timer.markEnd('DpoitPass.layer');
}
// evaluate dpoit
target.bind();
this.dpoit.render();
}
// render transparent volumes
if (scene.volumes.renderables.length > 0) {
renderer.renderDpoitVolume(scene.volumes, camera, this.depthTextureOpaque);
}
}
private _renderWboit(renderer: Renderer, camera: ICamera, scene: Scene, transparentBackground: boolean, postprocessingProps: PostprocessingProps) {
if (!this.wboit?.supported) throw new Error('expected wboit to be supported');
@@ -321,15 +254,13 @@ export class DrawPass {
if (this.wboitEnabled) {
this._renderWboit(renderer, camera, scene, transparentBackground, props.postprocessing);
} else if (this.dpoitEnabled) {
this._renderDpoit(renderer, camera, scene, props.dpoitIterations, transparentBackground, props.postprocessing);
} else {
this._renderBlended(renderer, camera, scene, !volumeRendering && !postprocessingEnabled && !antialiasingEnabled && toDrawingBuffer, transparentBackground, props.postprocessing);
}
const target = postprocessingEnabled
? this.postprocessing.target
: !toDrawingBuffer || volumeRendering || this.wboitEnabled || this.dpoitEnabled
: !toDrawingBuffer || volumeRendering || this.wboitEnabled
? this.colorTarget
: this.drawTarget;
@@ -372,7 +303,7 @@ export class DrawPass {
this.webgl.state.disable(this.webgl.gl.DEPTH_TEST);
if (postprocessingEnabled) {
this.copyFboPostprocessing.render();
} else if (volumeRendering || this.wboitEnabled || this.dpoitEnabled) {
} else if (volumeRendering || this.wboitEnabled) {
this.copyFboTarget.render();
}
}
@@ -392,12 +323,8 @@ export class DrawPass {
renderer.setPixelRatio(this.webgl.pixelRatio);
if (StereoCamera.is(camera)) {
if (isTimingMode) this.webgl.timer.mark('StereoCamera.left');
this._render(renderer, camera.left, scene, helper, toDrawingBuffer, transparentBackground, props);
if (isTimingMode) this.webgl.timer.markEnd('StereoCamera.left');
if (isTimingMode) this.webgl.timer.mark('StereoCamera.right');
this._render(renderer, camera.right, scene, helper, toDrawingBuffer, transparentBackground, props);
if (isTimingMode) this.webgl.timer.markEnd('StereoCamera.right');
} else {
this._render(renderer, camera, scene, helper, toDrawingBuffer, transparentBackground, props);
}
@@ -412,4 +339,4 @@ export class DrawPass {
}
return this.colorTarget;
}
}
}

View File

@@ -22,7 +22,6 @@ import { AssetManager } from '../../mol-util/assets';
export const ImageParams = {
transparentBackground: PD.Boolean(false),
dpoitIterations: PD.Numeric(2, { min: 1, max: 10, step: 1 }),
multiSample: PD.Group(MultiSampleParams),
postprocessing: PD.Group(PostprocessingParams),
marking: PD.Group(MarkingParams),
@@ -49,10 +48,10 @@ export class ImagePass {
get width() { return this._width; }
get height() { return this._height; }
constructor(private webgl: WebGLContext, assetManager: AssetManager, private renderer: Renderer, private scene: Scene, private camera: Camera, helper: Helper, enableWboit: boolean, enableDpoit: boolean, props: Partial<ImageProps>) {
constructor(private webgl: WebGLContext, assetManager: AssetManager, private renderer: Renderer, private scene: Scene, private camera: Camera, helper: Helper, enableWboit: boolean, props: Partial<ImageProps>) {
this.props = { ...PD.getDefaultValues(ImageParams), ...props };
this.drawPass = new DrawPass(webgl, assetManager, 128, 128, enableWboit, enableDpoit);
this.drawPass = new DrawPass(webgl, assetManager, 128, 128, enableWboit);
this.multiSamplePass = new MultiSamplePass(webgl, this.drawPass);
this.multiSampleHelper = new MultiSampleHelper(this.multiSamplePass);

View File

@@ -61,7 +61,6 @@ type Props = {
postprocessing: PostprocessingProps
marking: MarkingProps
transparentBackground: boolean;
dpoitIterations: number;
}
type RenderContext = {

View File

@@ -15,19 +15,16 @@ export class Passes {
readonly pick: PickPass;
readonly multiSample: MultiSamplePass;
constructor(private webgl: WebGLContext, assetManager: AssetManager, attribs: Partial<{ pickScale: number, enableWboit: boolean, enableDpoit: boolean }> = {}) {
constructor(private webgl: WebGLContext, assetManager: AssetManager, attribs: Partial<{ pickScale: number, enableWboit: boolean }> = {}) {
const { gl } = webgl;
this.draw = new DrawPass(webgl, assetManager, gl.drawingBufferWidth, gl.drawingBufferHeight, attribs.enableWboit || false, attribs.enableDpoit || false);
this.draw = new DrawPass(webgl, assetManager, gl.drawingBufferWidth, gl.drawingBufferHeight, attribs.enableWboit || false);
this.pick = new PickPass(webgl, this.draw, attribs.pickScale || 0.25);
this.multiSample = new MultiSamplePass(webgl, this.draw);
}
updateSize() {
const { gl } = this.webgl;
// Avoid setting dimensions to 0x0 because it causes "empty textures are not allowed" error.
const width = Math.max(gl.drawingBufferWidth, 2);
const height = Math.max(gl.drawingBufferHeight, 2);
this.draw.setSize(width, height);
this.draw.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
this.pick.syncSize();
this.multiSample.syncSize();
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -11,7 +11,7 @@ import { ShaderCode } from '../../mol-gl/shader-code';
import { WebGLContext } from '../../mol-gl/webgl/context';
import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
import { RenderTarget } from '../../mol-gl/webgl/render-target';
import { loadImageTexture, Texture } from '../../mol-gl/webgl/texture';
import { createTexture, loadImageTexture, Texture } from '../../mol-gl/webgl/texture';
import { Vec2, Vec4 } from '../../mol-math/linear-algebra';
import { ValueCell } from '../../mol-util';
import { ParamDefinition as PD } from '../../mol-util/param-definition';
@@ -74,7 +74,6 @@ export class SmaaPass {
state.viewport(x, y, width, height);
state.scissor(x, y, width, height);
state.colorMask(true, true, true, true);
state.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
@@ -192,8 +191,8 @@ function getWeightsRenderable(ctx: WebGLContext, edgesTexture: Texture): Weights
const width = edgesTexture.getWidth();
const height = edgesTexture.getHeight();
const areaTexture = ctx.resources.texture('image-uint8', 'rgb', 'ubyte', 'linear');
const searchTexture = ctx.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
const areaTexture = createTexture(ctx.gl, ctx.extensions, 'image-uint8', 'rgb', 'ubyte', 'linear');
const searchTexture = createTexture(ctx.gl, ctx.extensions, 'image-uint8', 'rgba', 'ubyte', 'nearest');
const values: Values<typeof WeightsSchema> = {
...QuadValues,

View File

@@ -18,8 +18,6 @@ import { evaluateWboit_frag } from '../../mol-gl/shader/evaluate-wboit.frag';
import { Framebuffer } from '../../mol-gl/webgl/framebuffer';
import { Vec2 } from '../../mol-math/linear-algebra';
import { isDebugMode, isTimingMode } from '../../mol-util/debug';
import { isWebGL2 } from '../../mol-gl/webgl/compat';
import { Renderbuffer } from '../../mol-gl/webgl/renderbuffer';
const EvaluateWboitSchema = {
...QuadSchema,
@@ -52,7 +50,6 @@ export class WboitPass {
private readonly framebuffer: Framebuffer;
private readonly textureA: Texture;
private readonly textureB: Texture;
private readonly depthRenderbuffer: Renderbuffer;
private _supported = false;
get supported() {
@@ -90,7 +87,6 @@ export class WboitPass {
if (width !== w || height !== h) {
this.textureA.define(width, height);
this.textureB.define(width, height);
this.depthRenderbuffer.setSize(width, height);
ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height));
}
}
@@ -110,8 +106,6 @@ export class WboitPass {
this.textureA.attachFramebuffer(this.framebuffer, 'color0');
this.textureB.attachFramebuffer(this.framebuffer, 'color1');
this.depthRenderbuffer.attachFramebuffer(this.framebuffer);
}
static isSupported(webgl: WebGLContext) {
@@ -134,7 +128,7 @@ export class WboitPass {
constructor(private webgl: WebGLContext, width: number, height: number) {
if (!WboitPass.isSupported(webgl)) return;
const { resources, gl } = webgl;
const { resources } = webgl;
this.textureA = resources.texture('image-float32', 'rgba', 'float', 'nearest');
this.textureA.define(width, height);
@@ -142,10 +136,6 @@ export class WboitPass {
this.textureB = resources.texture('image-float32', 'rgba', 'float', 'nearest');
this.textureB.define(width, height);
this.depthRenderbuffer = isWebGL2(gl)
? resources.renderbuffer('depth32f', 'depth', width, height)
: resources.renderbuffer('depth16', 'depth', width, height);
this.renderable = getEvaluateWboitRenderable(webgl, this.textureA, this.textureB);
this.framebuffer = resources.framebuffer();

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -21,7 +21,6 @@ export type OverpaintData = {
uOverpaintGridDim: ValueCell<Vec3>,
uOverpaintGridTransform: ValueCell<Vec4>,
dOverpaintType: ValueCell<string>,
uOverpaintStrength: ValueCell<number>,
}
export function applyOverpaintColor(array: Uint8Array, start: number, end: number, color: Color) {
@@ -55,7 +54,6 @@ export function createOverpaint(count: number, type: OverpaintType, overpaintDat
uOverpaintGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
uOverpaintGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
dOverpaintType: ValueCell.create(type),
uOverpaintStrength: ValueCell.create(1),
};
}
}
@@ -76,7 +74,6 @@ export function createEmptyOverpaint(overpaintData?: OverpaintData): OverpaintDa
uOverpaintGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
uOverpaintGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
dOverpaintType: ValueCell.create('groupInstance'),
uOverpaintStrength: ValueCell.create(1),
};
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -21,7 +21,6 @@ export type SubstanceData = {
uSubstanceGridDim: ValueCell<Vec3>,
uSubstanceGridTransform: ValueCell<Vec4>,
dSubstanceType: ValueCell<string>,
uSubstanceStrength: ValueCell<number>,
}
export function applySubstanceMaterial(array: Uint8Array, start: number, end: number, material: Material) {
@@ -55,7 +54,6 @@ export function createSubstance(count: number, type: SubstanceType, substanceDat
uSubstanceGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
uSubstanceGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
dSubstanceType: ValueCell.create(type),
uSubstanceStrength: ValueCell.create(1),
};
}
}
@@ -76,7 +74,6 @@ export function createEmptySubstance(substanceData?: SubstanceData): SubstanceDa
uSubstanceGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
uSubstanceGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
dSubstanceType: ValueCell.create('groupInstance'),
uSubstanceStrength: ValueCell.create(1),
};
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -88,7 +88,7 @@ export class FontAtlas {
this.scratchCanvas.width = this.maxWidth;
this.scratchCanvas.height = this.lineHeight;
this.scratchContext = this.scratchCanvas.getContext('2d', { willReadFrequently: true })!;
this.scratchContext = this.scratchCanvas.getContext('2d')!;
this.scratchContext.font = `${p.fontStyle} ${p.fontVariant} ${p.fontWeight} ${fontSize}px ${p.fontFamily}`;
this.scratchContext.fillStyle = 'black';
this.scratchContext.textBaseline = 'middle';

View File

@@ -387,8 +387,6 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
const type = isInstanceType ? 'volumeInstance' : 'volume';
if (isTimingMode) webgl.timer.markEnd('calcTextureMeshColorSmoothing');
// printTextureImage(readTexture(webgl, texture), { scale: 0.75 });
return { texture, gridDim, gridTexDim: Vec2.create(width, height), gridTransform, type };
}

View File

@@ -21,7 +21,6 @@ export type TransparencyData = {
uTransparencyGridDim: ValueCell<Vec3>,
uTransparencyGridTransform: ValueCell<Vec4>,
dTransparencyType: ValueCell<string>,
uTransparencyStrength: ValueCell<number>,
}
export function applyTransparencyValue(array: Uint8Array, start: number, end: number, value: number) {
@@ -64,7 +63,6 @@ export function createTransparency(count: number, type: TransparencyType, transp
uTransparencyGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
uTransparencyGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
dTransparencyType: ValueCell.create(type),
uTransparencyStrength: ValueCell.create(1),
};
}
}
@@ -86,7 +84,6 @@ export function createEmptyTransparency(transparencyData?: TransparencyData): Tr
uTransparencyGridDim: ValueCell.create(Vec3.create(1, 1, 1)),
uTransparencyGridTransform: ValueCell.create(Vec4.create(0, 0, 0, 1)),
dTransparencyType: ValueCell.create('groupInstance'),
uTransparencyStrength: ValueCell.create(1),
};
}
}

View File

@@ -53,17 +53,17 @@ describe('renderer', () => {
scene.commit();
expect(ctx.stats.resourceCounts.attribute).toBe(ctx.isWebGL2 ? 4 : 5);
expect(ctx.stats.resourceCounts.texture).toBe(9);
expect(ctx.stats.resourceCounts.vertexArray).toBe(ctx.extensions.vertexArrayObject ? 6 : 0);
expect(ctx.stats.resourceCounts.program).toBe(6);
expect(ctx.stats.resourceCounts.shader).toBe(12);
expect(ctx.stats.resourceCounts.vertexArray).toBe(ctx.extensions.vertexArrayObject ? 5 : 0);
expect(ctx.stats.resourceCounts.program).toBe(5);
expect(ctx.stats.resourceCounts.shader).toBe(10);
scene.remove(points);
scene.commit();
expect(ctx.stats.resourceCounts.attribute).toBe(0);
expect(ctx.stats.resourceCounts.texture).toBe(1);
expect(ctx.stats.resourceCounts.vertexArray).toBe(0);
expect(ctx.stats.resourceCounts.program).toBe(6);
expect(ctx.stats.resourceCounts.shader).toBe(12);
expect(ctx.stats.resourceCounts.program).toBe(5);
expect(ctx.stats.resourceCounts.shader).toBe(10);
ctx.resources.destroy();
expect(ctx.stats.resourceCounts.program).toBe(0);

View File

@@ -197,7 +197,7 @@ export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture,
gl.finish();
if (isTimingMode) ctx.timer.markEnd('createHistogramPyramid');
// printTextureImage(readTexture(ctx, pyramidTex), { scale: 0.75 });
// printTexture(ctx, pyramidTex, 2)
//

View File

@@ -115,7 +115,6 @@ export function calcActiveVoxels(ctx: WebGLContext, volumeData: Texture, gridDim
// console.log('gridScale', gridScale, 'gridTexDim', gridTexDim, 'gridDim', gridDim);
// console.log('volumeData', volumeData);
// console.log('at', readTexture(ctx, activeVoxelsTex));
// printTextureImage(readTexture(ctx, activeVoxelsTex), { scale: 0.75 });
gl.finish();
if (isTimingMode) ctx.timer.markEnd('calcActiveVoxels');

View File

@@ -199,10 +199,6 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
gl.finish();
if (isTimingMode) ctx.timer.markEnd('createIsosurfaceBuffers');
// printTextureImage(readTexture(ctx, vertexTexture, new Float32Array(width * height * 4)), { scale: 0.75 });
// printTextureImage(readTexture(ctx, groupTexture, new Uint8Array(width * height * 4)), { scale: 0.75 });
// printTextureImage(readTexture(ctx, normalTexture, new Float32Array(width * height * 4)), { scale: 0.75 });
return { vertexTexture, groupTexture, normalTexture, vertexCount: count };
}

View File

@@ -75,9 +75,9 @@ export function getSharedCopyRenderable(ctx: WebGLContext, texture: Texture) {
const ReadTextureName = 'read-texture';
const ReadAlphaTextureName = 'read-alpha-texture';
export function readTexture<T extends Uint8Array | Float32Array | Int32Array = Uint8Array>(ctx: WebGLContext, texture: Texture, array?: T) {
export function readTexture(ctx: WebGLContext, texture: Texture) {
const { gl, resources } = ctx;
if (!array && texture.type !== gl.UNSIGNED_BYTE) throw new Error('unsupported texture type');
if (texture.type !== gl.UNSIGNED_BYTE) throw new Error('unsupported texture type');
if (!ctx.namedFramebuffers[ReadTextureName]) {
ctx.namedFramebuffers[ReadTextureName] = resources.framebuffer();
@@ -86,7 +86,7 @@ export function readTexture<T extends Uint8Array | Float32Array | Int32Array = U
const width = texture.getWidth();
const height = texture.getHeight();
if (!array) array = new Uint8Array(width * height * 4) as T;
const array = new Uint8Array(width * height * 4);
framebuffer.bind();
texture.attachFramebuffer(framebuffer, 0);
ctx.readPixels(0, 0, width, height, array);

View File

@@ -2,7 +2,6 @@
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { ValueCell } from '../../mol-util';
@@ -168,11 +167,6 @@ export type GlobalUniformValues = Values<GlobalUniformSchema>
export const GlobalTextureSchema = {
tDepth: TextureSpec('texture', 'depth', 'ushort', 'nearest'),
// dpoit
tDpoitDepth: TextureSpec('texture', 'rg', 'float', 'nearest'),
tDpoitFrontColor: TextureSpec('texture', 'rgba', 'float', 'nearest'),
tDpoitBackColor: TextureSpec('texture', 'rgba', 'float', 'nearest')
} as const;
export type GlobalTextureSchema = typeof GlobalTextureSchema
export type GlobalTextureValues = Values<GlobalTextureSchema>
@@ -229,7 +223,6 @@ export const OverpaintSchema = {
uOverpaintGridTransform: UniformSpec('v4'),
tOverpaintGrid: TextureSpec('texture', 'rgba', 'ubyte', 'linear'),
dOverpaintType: DefineSpec('string', ['instance', 'groupInstance', 'volumeInstance']),
uOverpaintStrength: UniformSpec('f', 'material'),
} as const;
export type OverpaintSchema = typeof OverpaintSchema
export type OverpaintValues = Values<OverpaintSchema>
@@ -244,7 +237,6 @@ export const TransparencySchema = {
uTransparencyGridTransform: UniformSpec('v4'),
tTransparencyGrid: TextureSpec('texture', 'alpha', 'ubyte', 'linear'),
dTransparencyType: DefineSpec('string', ['instance', 'groupInstance', 'volumeInstance']),
uTransparencyStrength: UniformSpec('f', 'material'),
} as const;
export type TransparencySchema = typeof TransparencySchema
export type TransparencyValues = Values<TransparencySchema>
@@ -258,7 +250,6 @@ export const SubstanceSchema = {
uSubstanceGridTransform: UniformSpec('v4'),
tSubstanceGrid: TextureSpec('texture', 'rgba', 'ubyte', 'linear'),
dSubstanceType: DefineSpec('string', ['instance', 'groupInstance', 'volumeInstance']),
uSubstanceStrength: UniformSpec('f', 'material'),
} as const;
export type SubstanceSchema = typeof SubstanceSchema
export type SubstanceValues = Values<SubstanceSchema>
@@ -336,4 +327,4 @@ export const BaseSchema = {
invariantBoundingSphere: ValueSpec('sphere'),
} as const;
export type BaseSchema = typeof BaseSchema
export type BaseValues = Values<BaseSchema>
export type BaseValues = Values<BaseSchema>

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -8,7 +8,6 @@ import { Sphere3D } from '../../mol-math/geometry';
import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper';
import { TextureFilter } from '../webgl/texture';
import { arrayMinMax } from '../../mol-util/array';
export function calculateTextureInfo(n: number, itemSize: number) {
n = Math.max(n, 2); // observed issues with 1 pixel textures
@@ -43,8 +42,7 @@ export function createTextureImage<T extends Uint8Array | Float32Array>(n: numbe
const DefaultPrintImageOptions = {
scale: 1,
pixelated: false,
id: 'molstar.debug.image',
normalize: false,
id: 'molstar.debug.image'
};
export type PrintImageOptions = typeof DefaultPrintImageOptions
@@ -60,17 +58,7 @@ export function printTextureImage(textureImage: TextureImage<any>, options: Part
}
}
} else if (itemSize === 4) {
if (options.normalize) {
const [min, max] = arrayMinMax(array);
for (let i = 0, il = width * height * 4; i < il; i += 4) {
data[i] = ((array[i] - min) / (max - min)) * 255;
data[i + 1] = ((array[i + 1] - min) / (max - min)) * 255;
data[i + 2] = ((array[i + 2] - min) / (max - min)) * 255;
data[i + 3] = 255;
}
} else {
data.set(array);
}
data.set(array);
} else {
console.warn(`itemSize '${itemSize}' not supported`);
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { Viewport } from '../mol-canvas3d/camera/util';
@@ -71,9 +70,6 @@ interface Renderer {
renderBlendedVolume: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
renderWboitOpaque: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
renderWboitTransparent: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
renderDpoitOpaque: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
renderDpoitTransparent: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null, dpoitTextures: { depth: Texture, frontColor: Texture, backColor: Texture }) => void
renderDpoitVolume: (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => void
setProps: (props: Partial<RendererProps>) => void
setViewport: (x: number, y: number, width: number, height: number) => void
@@ -145,7 +141,7 @@ namespace Renderer {
const enum Flag {
None = 0,
BlendedFront = 1,
BlendedBack = 2,
BlendedBack = 2
}
const enum Mask {
@@ -272,7 +268,7 @@ namespace Renderer {
}
if (r.values.dGeometryType.ref.value === 'directVolume') {
if (variant !== 'colorDpoit' && variant !== 'colorWboit' && variant !== 'colorBlended') {
if (variant !== 'colorWboit' && variant !== 'colorBlended') {
return; // only color supported
}
@@ -606,71 +602,6 @@ namespace Renderer {
if (isTimingMode) ctx.timer.markEnd('Renderer.renderWboitTransparent');
};
const renderDpoitOpaque = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
if (isTimingMode) ctx.timer.mark('Renderer.renderDpoitOpaque');
state.disable(gl.BLEND);
state.enable(gl.DEPTH_TEST);
state.depthMask(true);
updateInternal(group, camera, depthTexture, Mask.Opaque, false);
const { renderables } = group;
for (let i = 0, il = renderables.length; i < il; ++i) {
const r = renderables[i];
// TODO: simplify, handle in renderable.state???
// uAlpha is updated in "render" so we need to recompute it here
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
if ((alpha === 1 && r.values.transparencyAverage.ref.value !== 1 && r.values.dPointStyle?.ref.value !== 'fuzzy' && !r.values.dXrayShaded?.ref.value) || r.values.dTransparentBackfaces?.ref.value === 'opaque') {
renderObject(r, 'colorDpoit', Flag.None);
}
}
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDpoitOpaque');
};
const renderDpoitTransparent = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null, dpoitTextures: { depth: Texture, frontColor: Texture, backColor: Texture }) => {
if (isTimingMode) ctx.timer.mark('Renderer.renderDpoitTransparent');
state.enable(gl.BLEND);
arrayMapUpsert(sharedTexturesList, 'tDpoitDepth', dpoitTextures.depth);
arrayMapUpsert(sharedTexturesList, 'tDpoitFrontColor', dpoitTextures.frontColor);
arrayMapUpsert(sharedTexturesList, 'tDpoitBackColor', dpoitTextures.backColor);
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
const { renderables } = group;
for (let i = 0, il = renderables.length; i < il; ++i) {
const r = renderables[i];
// TODO: simplify, handle in renderable.state???
// uAlpha is updated in "render" so we need to recompute it here
const alpha = clamp(r.values.alpha.ref.value * r.state.alphaFactor, 0, 1);
if (alpha < 1 || r.values.transparencyAverage.ref.value > 0 || r.values.dPointStyle?.ref.value === 'fuzzy' || !!r.values.uBackgroundColor || r.values.dXrayShaded?.ref.value) {
renderObject(r, 'colorDpoit', Flag.None);
}
}
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDpoitTransparent');
};
const renderDpoitVolume = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null) => {
if (isTimingMode) ctx.timer.mark('Renderer.renderDpoitVolume');
state.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
state.enable(gl.BLEND);
updateInternal(group, camera, depthTexture, Mask.Transparent, false);
const { renderables } = group;
for (let i = 0, il = renderables.length; i < il; ++i) {
const r = renderables[i];
if (r.values.dGeometryType.ref.value === 'directVolume') {
renderObject(r, 'colorDpoit', Flag.None);
}
}
if (isTimingMode) ctx.timer.markEnd('Renderer.renderDpoitVolume');
};
return {
clear: (toBackgroundColor: boolean, ignoreTransparentBackground?: boolean) => {
state.enable(gl.SCISSOR_TEST);
@@ -714,9 +645,6 @@ namespace Renderer {
renderBlendedVolume,
renderWboitOpaque,
renderWboitTransparent,
renderDpoitOpaque,
renderDpoitTransparent,
renderDpoitVolume,
setProps: (props: Partial<RendererProps>) => {
if (props.backgroundColor !== undefined && props.backgroundColor !== p.backgroundColor) {
@@ -834,4 +762,4 @@ namespace Renderer {
}
}
export { Renderer };
export { Renderer };

View File

@@ -45,8 +45,8 @@ function calculateBoundingSphere(renderables: GraphicsRenderable[], boundingSphe
}
function renderableSort(a: GraphicsRenderable, b: GraphicsRenderable) {
const drawProgramIdA = (a.getProgram('colorBlended') || a.getProgram('colorWboit') || a.getProgram('colorDpoit')).id;
const drawProgramIdB = (b.getProgram('colorBlended') || b.getProgram('colorWboit') || b.getProgram('colorDpoit')).id;
const drawProgramIdA = (a.getProgram('colorBlended') || a.getProgram('colorWboit')).id;
const drawProgramIdB = (b.getProgram('colorBlended') || a.getProgram('colorWboit')).id;
const materialIdA = a.materialId;
const materialIdB = b.materialId;

View File

@@ -67,7 +67,6 @@ import { texture3d_from_1d_trilinear } from './shader/chunks/texture3d-from-1d-t
import { texture3d_from_2d_linear } from './shader/chunks/texture3d-from-2d-linear.glsl';
import { texture3d_from_2d_nearest } from './shader/chunks/texture3d-from-2d-nearest.glsl';
import { wboit_write } from './shader/chunks/wboit-write.glsl';
import { dpoit_write } from './shader/chunks/dpoit-write.glsl';
const ShaderChunks: { [k: string]: string } = {
apply_fog,
@@ -100,8 +99,7 @@ const ShaderChunks: { [k: string]: string } = {
texture3d_from_1d_trilinear,
texture3d_from_2d_linear,
texture3d_from_2d_nearest,
wboit_write,
dpoit_write
wboit_write
};
const reInclude = /^(?!\/\/)\s*#include\s+(\S+)/gm;

View File

@@ -6,7 +6,6 @@ precision mediump sampler2D;
#if defined(dVariant_skybox)
uniform samplerCube tSkybox;
uniform mat4 uViewDirectionProjectionInverse;
uniform float uBlur;
uniform float uOpacity;
uniform float uSaturation;
uniform float uLightness;
@@ -50,11 +49,7 @@ vec3 lightenColor(vec3 c, float amount) {
void main() {
#if defined(dVariant_skybox)
vec4 t = uViewDirectionProjectionInverse * vPosition;
#ifdef enabledShaderTextureLod
gl_FragColor = textureCubeLodEXT(tSkybox, normalize(t.xyz / t.w), uBlur * 8.0);
#else
gl_FragColor = textureCube(tSkybox, normalize(t.xyz / t.w));
#endif
gl_FragColor = textureCube(tSkybox, normalize(t.xyz / t.w));
gl_FragColor.a = uOpacity;
gl_FragColor.rgb = lightenColor(saturateColor(gl_FragColor.rgb, uSaturation), uLightness);
#elif defined(dVariant_image)

View File

@@ -1,20 +0,0 @@
/**
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
export const blendBackDpoit_frag = `
precision highp float;
uniform sampler2D tDpoitBackColor;
uniform vec2 uTexSize;
void main() {
vec2 coords = gl_FragCoord.xy / uTexSize;
gl_FragColor = texture2D(tDpoitBackColor, coords);
if (gl_FragColor.a == 0.0) {
discard;
}
}
`;

View File

@@ -12,19 +12,8 @@ if (!uTransparentBackground) {
gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor);
}
} else {
#if defined(dRenderVariant_colorDpoit)
if (gl_FragColor.a < 1.0) {
// transparent objects are blended with background color
gl_FragColor.a = fogAlpha;
} else {
// opaque objects need to be pre-multiplied alpha
gl_FragColor.rgb *= fogAlpha;
gl_FragColor.a = fogAlpha;
}
#else
// pre-multiplied alpha expected for transparent background
gl_FragColor.rgb *= fogAlpha;
gl_FragColor.a = fogAlpha;
#endif
// pre-multiplied alpha expected for transparent background
gl_FragColor.rgb *= fogAlpha;
gl_FragColor.a = fogAlpha;
}
`;

View File

@@ -57,7 +57,6 @@ export const apply_light_color = `
RE_IndirectSpecular_Physical(radiance, iblIrradiance, clearcoatRadiance, geometry, physicalMaterial, reflectedLight);
vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular;
outgoingLight = clamp(outgoingLight, 0.01, 0.99); // prevents black artifacts on specular highlight with transparent background
gl_FragColor = vec4(outgoingLight, color.a);
#endif

View File

@@ -42,7 +42,6 @@ export const assign_color_varying = `
#else
vOverpaint.rgb = mix(vColor.rgb, vOverpaint.rgb, vOverpaint.a);
#endif
vOverpaint *= uOverpaintStrength;
#endif
#ifdef dSubstance
@@ -59,7 +58,6 @@ export const assign_color_varying = `
// pre-mix to avoid artifacts due to empty substance
vSubstance.rgb = mix(vec3(uMetalness, uRoughness, uBumpiness), vSubstance.rgb, vSubstance.a);
vSubstance *= uSubstanceStrength;
#endif
#elif defined(dRenderVariant_pick)
#ifdef requiredDrawBuffers
@@ -88,6 +86,5 @@ export const assign_color_varying = `
vec3 tgridPos = (uTransparencyGridTransform.w * (vModelPosition - uTransparencyGridTransform.xyz)) / uTransparencyGridDim;
vTransparency = texture3dFrom2dLinear(tTransparencyGrid, tgridPos, uTransparencyGridDim, uTransparencyTexDim).a;
#endif
vTransparency *= uTransparencyStrength;
#endif
`;

View File

@@ -86,7 +86,7 @@ export const assign_material_color = `
// apply per-group transparency
#if defined(dTransparency) && (defined(dRenderVariant_pick) || defined(dRenderVariant_color))
float ta = 1.0 - vTransparency;
if (vTransparency < 0.09) ta = 1.0; // hard cutoff looks better
if (vTransparency < 0.2) ta = 1.0; // hard cutoff looks better
#if defined(dRenderVariant_pick)
if (ta < uPickingAlphaThreshold)

View File

@@ -39,7 +39,6 @@ uniform float uBumpiness;
uniform vec4 uOverpaintGridTransform;
uniform sampler2D tOverpaintGrid;
#endif
uniform float uOverpaintStrength;
#endif
#ifdef dSubstance
@@ -54,7 +53,6 @@ uniform float uBumpiness;
uniform vec4 uSubstanceGridTransform;
uniform sampler2D tSubstanceGrid;
#endif
uniform float uSubstanceStrength;
#endif
#elif defined(dRenderVariant_pick)
#if __VERSION__ == 100 || !defined(dVaryingGroup)
@@ -88,6 +86,5 @@ uniform float uBumpiness;
uniform vec4 uTransparencyGridTransform;
uniform sampler2D tTransparencyGrid;
#endif
uniform float uTransparencyStrength;
#endif
`;

View File

@@ -39,12 +39,6 @@ uniform int uMarkingType;
#endif
#endif
#if defined(dRenderVariant_colorDpoit)
#define MAX_DPOIT_DEPTH 99999.0 // NOTE constant also set in TypeScript
uniform sampler2D tDpoitDepth;
uniform sampler2D tDpoitFrontColor;
#endif
varying vec3 vModelPosition;
varying vec3 vViewPosition;

View File

@@ -44,9 +44,10 @@ varying vec3 vModelPosition;
varying vec3 vViewPosition;
#if defined(noNonInstancedActiveAttribs)
// int() is needed for some Safari versions
// see https://bugs.webkit.org/show_bug.cgi?id=244152
#define VertexID int(gl_VertexID)
#define VertexID gl_VertexID // for testing
// // int() is needed for some Safari versions
// // see https://bugs.webkit.org/show_bug.cgi?id=244152
// #define VertexID int(gl_VertexID)
#else
attribute float aVertex;
#define VertexID int(aVertex)

View File

@@ -1,7 +1,7 @@
export const common = `
// TODO find a better place for these convenience defines
#if defined(dRenderVariant_colorBlended) || defined(dRenderVariant_colorWboit) || defined(dRenderVariant_colorDpoit)
#if defined(dRenderVariant_colorBlended) || defined(dRenderVariant_colorWboit)
#define dRenderVariant_color
#endif

View File

@@ -1,70 +0,0 @@
/**
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
export const dpoit_write = `
#if defined(dRenderVariant_colorDpoit)
if (uRenderMask == MaskOpaque) {
if (preFogAlpha < 1.0) {
discard;
}
} else if (uRenderMask == MaskTransparent) {
// the 'fragmentDepth > 0.99' check is to handle precision issues with packed depth
vec2 coords = gl_FragCoord.xy / uDrawingBufferSize;
if (preFogAlpha != 1.0 && (fragmentDepth < getDepth(coords) || fragmentDepth > 0.99)) {
#ifdef dTransparentBackfaces_off
if (interior) discard;
#endif
// adapted from https://github.com/tsherif/webgl2examples
// The MIT License, Copyright 2017 Tarek Sherif, Shuai Shao
vec2 lastDepth = texture2D(tDpoitDepth, coords).rg;
vec4 lastFrontColor = texture2D(tDpoitFrontColor, coords);
vec4 fragColor = gl_FragColor;
// depth value always increases
// so we can use MAX blend equation
gl_FragData[2].rg = vec2(-MAX_DPOIT_DEPTH);
// front color always increases
// so we can use MAX blend equation
gl_FragColor = lastFrontColor;
// back color is separately blend afterwards each pass
gl_FragData[1] = vec4(0.0);
float nearestDepth = -lastDepth.x;
float furthestDepth = lastDepth.y;
float alphaMultiplier = 1.0 - lastFrontColor.a;
if (fragmentDepth < nearestDepth || fragmentDepth > furthestDepth) {
// Skip this depth since it's been peeled.
return;
}
if (fragmentDepth > nearestDepth && fragmentDepth < furthestDepth) {
// This needs to be peeled.
// The ones remaining after MAX blended for
// all need-to-peel will be peeled next pass.
gl_FragData[2].rg = vec2(-fragmentDepth, fragmentDepth);
return;
}
// write to back and front color buffer
if (fragmentDepth == nearestDepth) {
gl_FragColor.rgb += fragColor.rgb * fragColor.a * alphaMultiplier;
gl_FragColor.a = 1.0 - alphaMultiplier * (1.0 - fragColor.a);
} else {
gl_FragData[1] += fragColor;
}
} else {
discard;
}
}
#endif
`;

View File

@@ -109,14 +109,14 @@ void main() {
vec3 vViewPosition = vModelPosition + intersection.x * rayDir;
vViewPosition = (uView * vec4(vViewPosition, 1.0)).xyz;
float fragmentDepth = calcDepth(vViewPosition);
if (fragmentDepth < 0.0) discard;
if (fragmentDepth > 1.0) discard;
gl_FragDepthEXT = fragmentDepth;
gl_FragDepthEXT = calcDepth(vViewPosition);
vec3 vModelPosition = (uInvView * vec4(vViewPosition, 1.0)).xyz;
if (gl_FragDepthEXT < 0.0) discard;
if (gl_FragDepthEXT > 1.0) discard;
float fragmentDepth = gl_FragDepthEXT;
#include assign_material_color
#if defined(dRenderVariant_pick)
@@ -142,7 +142,6 @@ void main() {
#include apply_marker_color
#include apply_fog
#include wboit_write
#include dpoit_write
#endif
}
`;
`;

View File

@@ -356,4 +356,4 @@ void main() {
float preFogAlpha = clamp(preFogAlphaBlended, 0.0, 1.0);
#include wboit_write
}
`;
`;

View File

@@ -1,17 +0,0 @@
/**
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
export const evaluateDpoit_frag = `
precision highp float;
uniform sampler2D tDpoitFrontColor;
uniform vec2 uTexSize;
void main() {
vec2 coords = gl_FragCoord.xy / uTexSize;
gl_FragColor = texture2D(tDpoitFrontColor, coords);
}
`;

View File

@@ -159,7 +159,6 @@ void main() {
#include apply_marker_color
#include apply_fog
#include wboit_write
#include dpoit_write
#endif
}
`;
`;

View File

@@ -39,7 +39,6 @@ void main(){
#include apply_marker_color
#include apply_fog
#include wboit_write
#include dpoit_write
#endif
}
`;
`;

View File

@@ -62,7 +62,6 @@ void main() {
#include apply_marker_color
#include apply_fog
#include wboit_write
#include dpoit_write
#endif
}
`;
`;

View File

@@ -55,7 +55,6 @@ void main(){
#include apply_marker_color
#include apply_fog
#include wboit_write
#include dpoit_write
#endif
}
`;
`;

View File

@@ -70,17 +70,17 @@ void main(void){
}
vec3 vViewPosition = cameraPos;
float fragmentDepth = calcDepth(vViewPosition);
if (!flag && fragmentDepth >= 0.0) {
fragmentDepth = 0.0 + (0.0000001 / vRadius);
gl_FragDepthEXT = calcDepth(vViewPosition);
if (!flag && gl_FragDepthEXT >= 0.0) {
gl_FragDepthEXT = 0.0 + (0.0000001 / vRadius);
}
if (fragmentDepth < 0.0) discard;
if (fragmentDepth > 1.0) discard;
gl_FragDepthEXT = fragmentDepth;
vec3 vModelPosition = (uInvView * vec4(vViewPosition, 1.0)).xyz;
if (gl_FragDepthEXT < 0.0) discard;
if (gl_FragDepthEXT > 1.0) discard;
float fragmentDepth = gl_FragDepthEXT;
#include assign_material_color
#if defined(dRenderVariant_pick)
@@ -105,7 +105,6 @@ void main(void){
#include apply_marker_color
#include apply_fog
#include wboit_write
#include dpoit_write
#endif
}
`;
`;

View File

@@ -83,7 +83,6 @@ void main(){
#include apply_marker_color
#include apply_fog
#include wboit_write
#include dpoit_write
#endif
}
`;
`;

View File

@@ -19,9 +19,6 @@ export function isWebGL2(gl: any): gl is WebGL2RenderingContext {
return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext;
}
/**
* See https://registry.khronos.org/webgl/extensions/ANGLE_instanced_arrays/
*/
export interface COMPAT_instanced_arrays {
drawArraysInstanced(mode: number, first: number, count: number, primcount: number): void;
drawElementsInstanced(mode: number, count: number, type: number, offset: number, primcount: number): void;
@@ -49,9 +46,6 @@ export function getInstancedArrays(gl: GLRenderingContext): COMPAT_instanced_arr
}
}
/**
* See https://registry.khronos.org/webgl/extensions/OES_standard_derivatives/
*/
export interface COMPAT_standard_derivatives {
readonly FRAGMENT_SHADER_DERIVATIVE_HINT: number;
}
@@ -66,9 +60,6 @@ export function getStandardDerivatives(gl: GLRenderingContext): COMPAT_standard_
}
}
/**
* See https://registry.khronos.org/webgl/extensions/OES_element_index_uint/
*/
export interface COMPAT_element_index_uint {
}
@@ -76,9 +67,6 @@ export function getElementIndexUint(gl: GLRenderingContext): COMPAT_element_inde
return isWebGL2(gl) ? {} : gl.getExtension('OES_element_index_uint');
}
/**
* See https://registry.khronos.org/webgl/extensions/OES_vertex_array_object/
*/
export interface COMPAT_vertex_array_object {
readonly VERTEX_ARRAY_BINDING: number;
bindVertexArray(arrayObject: WebGLVertexArrayObject | null): void;
@@ -144,9 +132,6 @@ export function getTextureHalfFloatLinear(gl: GLRenderingContext): COMPAT_textur
return gl.getExtension('OES_texture_half_float_linear');
}
/**
* See https://registry.khronos.org/webgl/extensions/EXT_blend_minmax/
*/
export interface COMPAT_blend_minmax {
readonly MIN: number
readonly MAX: number
@@ -162,9 +147,6 @@ export function getBlendMinMax(gl: GLRenderingContext): COMPAT_blend_minmax | nu
}
}
/**
* See https://registry.khronos.org/webgl/extensions/EXT_frag_depth/
*/
export interface COMPAT_frag_depth {
}
@@ -214,9 +196,6 @@ export function getColorBufferHalfFloat(gl: GLRenderingContext): COMPAT_color_bu
}
}
/**
* See https://registry.khronos.org/webgl/extensions/WEBGL_draw_buffers/
*/
export interface COMPAT_draw_buffers {
drawBuffers(buffers: number[]): void;
readonly COLOR_ATTACHMENT0: number;
@@ -289,73 +268,6 @@ export function getDrawBuffers(gl: GLRenderingContext): COMPAT_draw_buffers | nu
}
}
/**
* See https://registry.khronos.org/webgl/extensions/OES_draw_buffers_indexed/
*/
export interface COMPAT_draw_buffers_indexed {
/**
* Enables blending for an individual draw buffer.
*
* @param target must be BLEND.
* @param index is an integer i specifying the draw buffer associated with the symbolic constant DRAW_BUFFERi.
*/
enablei: (target: number, index: number) => void;
/**
* Disables blending for an individual draw buffer.
*
* @param target must be BLEND.
* @param index is an integer i specifying the draw buffer associated with the symbolic constant DRAW_BUFFERi.
*/
disablei: (buf: number, mode: number) => void;
/**
* The buf argument is an integer i that indicates that the blend equations should be modified for DRAW_BUFFERi.
*
* mode accepts the same tokens as mode in blendEquation.
*/
blendEquationi: (target: number, index: number) => void;
/**
* The buf argument is an integer i that indicates that the blend equations should be modified for DRAW_BUFFERi.
*
* modeRGB and modeAlpha accept the same tokens as modeRGB and modeAlpha in blendEquationSeparate.
*/
blendEquationSeparatei: (buf: number, modeRGB: number, modeAlpha: number) => void;
/**
* The buf argument is an integer i that indicates that the blend functions should be modified for DRAW_BUFFERi.
*
* src and dst accept the same tokens as src and dst in blendFunc.
*/
blendFunci: (buf: number, src: number, dst: number) => void;
/**
* The buf argument is an integer i that indicates that the blend functions should be modified for DRAW_BUFFERi.
*
* srcRGB, dstRGB, srcAlpha, and dstAlpha accept the same tokens as srcRGB, dstRGB, srcAlpha, and dstAlpha parameters in blendEquationSeparate.
*/
blendFuncSeparatei: (buf: number, srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number) => void;
/**
* The buf argument is an integer i that indicates that the write mask should be modified for DRAW_BUFFERi.
*
* r, g, b, and a indicate whether R, G, B, or A values, respectively, are written or not (a value of TRUE means that the corresponding value is written).
*/
colorMaski: (buf: number, r: boolean, g: boolean, b: boolean, a: boolean) => void;
}
export function getDrawBuffersIndexed(gl: GLRenderingContext): COMPAT_draw_buffers_indexed | null {
const ext = gl.getExtension('OES_draw_buffers_indexed');
if (ext === null) return null;
return {
enablei: ext.enableiOES.bind(ext),
disablei: ext.disableiOES.bind(ext),
blendEquationi: ext.blendEquationiOES.bind(ext),
blendEquationSeparatei: ext.blendEquationSeparateiOES.bind(ext),
blendFunci: ext.blendFunciOES.bind(ext),
blendFuncSeparatei: ext.blendFuncSeparateiOES.bind(ext),
colorMaski: ext.colorMaskiOES.bind(ext),
};
}
/**
* See https://registry.khronos.org/webgl/extensions/EXT_shader_texture_lod/
*/
export interface COMPAT_shader_texture_lod {
}
@@ -363,9 +275,6 @@ export function getShaderTextureLod(gl: GLRenderingContext): COMPAT_shader_textu
return isWebGL2(gl) ? {} : gl.getExtension('EXT_shader_texture_lod');
}
/**
* See https://registry.khronos.org/webgl/extensions/WEBGL_depth_texture/
*/
export interface COMPAT_depth_texture {
readonly UNSIGNED_INT_24_8: number;
}
@@ -384,9 +293,6 @@ export function getDepthTexture(gl: GLRenderingContext): COMPAT_depth_texture |
}
}
/**
* See https://registry.khronos.org/webgl/extensions/EXT_sRGB/
*/
export interface COMPAT_sRGB {
readonly FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: number;
readonly SRGB8_ALPHA8: number;
@@ -414,9 +320,6 @@ export function getSRGB(gl: GLRenderingContext): COMPAT_sRGB | null {
}
}
/**
* See https://registry.khronos.org/webgl/extensions/EXT_disjoint_timer_query/ and https://registry.khronos.org/webgl/extensions/EXT_disjoint_timer_query_webgl2/
*/
export interface COMPAT_disjoint_timer_query {
/** A GLint indicating the number of bits used to hold the query result for the given target. */
QUERY_COUNTER_BITS: number
@@ -498,31 +401,6 @@ export function getDisjointTimerQuery(gl: GLRenderingContext): COMPAT_disjoint_t
}
}
/**
* See https://registry.khronos.org/webgl/extensions/KHR_parallel_shader_compile/
*/
export interface COMPAT_parallel_shader_compile {
readonly COMPLETION_STATUS: number;
}
export function getParallelShaderCompile(gl: GLRenderingContext): COMPAT_parallel_shader_compile | null {
const ext = gl.getExtension('KHR_parallel_shader_compile');
if (ext === null) return null;
return {
COMPLETION_STATUS: ext.COMPLETION_STATUS_KHR,
};
}
/**
* See https://registry.khronos.org/webgl/extensions/OES_fbo_render_mipmap/
*/
export interface COMPAT_fboRenderMipmap {
}
export function getFboRenderMipmap(gl: GLRenderingContext): COMPAT_fboRenderMipmap | null {
return isWebGL2(gl) ? {} : gl.getExtension('OES_fbo_render_mipmap');
}
export function getNoNonInstancedActiveAttribs(gl: GLRenderingContext): boolean {
if (!isWebGL2(gl)) return false;

View File

@@ -4,14 +4,14 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat, getVertexArrayObject, getDisjointTimerQuery, COMPAT_disjoint_timer_query, getNoNonInstancedActiveAttribs, getDrawBuffersIndexed, COMPAT_draw_buffers_indexed, getParallelShaderCompile, COMPAT_parallel_shader_compile, getFboRenderMipmap, COMPAT_fboRenderMipmap } from './compat';
import { GLRenderingContext, COMPAT_instanced_arrays, COMPAT_standard_derivatives, COMPAT_vertex_array_object, getInstancedArrays, getStandardDerivatives, COMPAT_element_index_uint, getElementIndexUint, COMPAT_texture_float, getTextureFloat, COMPAT_texture_float_linear, getTextureFloatLinear, COMPAT_blend_minmax, getBlendMinMax, getFragDepth, COMPAT_frag_depth, COMPAT_color_buffer_float, getColorBufferFloat, COMPAT_draw_buffers, getDrawBuffers, getShaderTextureLod, COMPAT_shader_texture_lod, getDepthTexture, COMPAT_depth_texture, COMPAT_sRGB, getSRGB, getTextureHalfFloat, getTextureHalfFloatLinear, COMPAT_texture_half_float, COMPAT_texture_half_float_linear, COMPAT_color_buffer_half_float, getColorBufferHalfFloat, getVertexArrayObject, getDisjointTimerQuery, COMPAT_disjoint_timer_query, getNoNonInstancedActiveAttribs } from './compat';
import { isDebugMode } from '../../mol-util/debug';
export type WebGLExtensions = {
instancedArrays: COMPAT_instanced_arrays
elementIndexUint: COMPAT_element_index_uint
standardDerivatives: COMPAT_standard_derivatives
standardDerivatives: COMPAT_standard_derivatives | null
textureFloat: COMPAT_texture_float | null
textureFloatLinear: COMPAT_texture_float_linear | null
textureHalfFloat: COMPAT_texture_half_float | null
@@ -23,12 +23,9 @@ export type WebGLExtensions = {
colorBufferFloat: COMPAT_color_buffer_float | null
colorBufferHalfFloat: COMPAT_color_buffer_half_float | null
drawBuffers: COMPAT_draw_buffers | null
drawBuffersIndexed: COMPAT_draw_buffers_indexed | null
shaderTextureLod: COMPAT_shader_texture_lod | null
sRGB: COMPAT_sRGB | null
disjointTimerQuery: COMPAT_disjoint_timer_query | null
parallelShaderCompile: COMPAT_parallel_shader_compile | null
fboRenderMipmap: COMPAT_fboRenderMipmap | null
noNonInstancedActiveAttribs: boolean
}
@@ -97,10 +94,6 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
if (isDebugMode && drawBuffers === null) {
console.log('Could not find support for "draw_buffers"');
}
const drawBuffersIndexed = getDrawBuffersIndexed(gl);
if (isDebugMode && drawBuffersIndexed === null) {
console.log('Could not find support for "draw_buffers_indexed"');
}
const shaderTextureLod = getShaderTextureLod(gl);
if (isDebugMode && shaderTextureLod === null) {
console.log('Could not find support for "shader_texture_lod"');
@@ -113,39 +106,28 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions {
if (isDebugMode && disjointTimerQuery === null) {
console.log('Could not find support for "disjoint_timer_query"');
}
const parallelShaderCompile = getParallelShaderCompile(gl);
if (isDebugMode && parallelShaderCompile === null) {
console.log('Could not find support for "parallel_shader_compile"');
}
const fboRenderMipmap = getFboRenderMipmap(gl);
if (isDebugMode && fboRenderMipmap === null) {
console.log('Could not find support for "fbo_render_mipmap"');
}
const noNonInstancedActiveAttribs = getNoNonInstancedActiveAttribs(gl);
return {
instancedArrays,
standardDerivatives,
elementIndexUint,
textureFloat,
textureFloatLinear,
textureHalfFloat,
textureHalfFloatLinear,
elementIndexUint,
depthTexture,
blendMinMax,
vertexArrayObject,
fragDepth,
colorBufferFloat,
colorBufferHalfFloat,
drawBuffers,
drawBuffersIndexed,
shaderTextureLod,
sRGB,
disjointTimerQuery,
parallelShaderCompile,
fboRenderMipmap,
noNonInstancedActiveAttribs,
};

View File

@@ -2,7 +2,6 @@
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { createAttributeBuffers, ElementsBuffer, AttributeKind } from './buffer';
@@ -50,12 +49,11 @@ export interface RenderItem<T extends string> {
//
const GraphicsRenderVariant = { colorBlended: '', colorWboit: '', colorDpoit: '', pick: '', depth: '', marking: '' };
const GraphicsRenderVariant = { colorBlended: '', colorWboit: '', pick: '', depth: '', marking: '' };
export type GraphicsRenderVariant = keyof typeof GraphicsRenderVariant
export const GraphicsRenderVariants = Object.keys(GraphicsRenderVariant) as GraphicsRenderVariant[];
export const GraphicsRenderVariantsBlended = GraphicsRenderVariants.filter(v => !['colorWboit', 'colorDpoit'].includes(v));
export const GraphicsRenderVariantsWboit = GraphicsRenderVariants.filter(v => !['colorBlended', 'colorDpoit'].includes(v));
export const GraphicsRenderVariantsDpoit = GraphicsRenderVariants.filter(v => !['colorWboit', 'colorBlended'].includes(v));
export const GraphicsRenderVariantsBlended = GraphicsRenderVariants.filter(v => v !== 'colorWboit');
export const GraphicsRenderVariantsWboit = GraphicsRenderVariants.filter(v => v !== 'colorBlended');
const ComputeRenderVariant = { compute: '' };
export type ComputeRenderVariant = keyof typeof ComputeRenderVariant
@@ -369,4 +367,4 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
}
}
};
}
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { WebGLContext } from './context';
@@ -32,7 +31,7 @@ export type TextureKindValue = {
export type TextureValueType = ValueOf<TextureKindValue>
export type TextureKind = keyof TextureKindValue
export type TextureType = 'ubyte' | 'ushort' | 'float' | 'fp16' | 'int'
export type TextureFormat = 'alpha' | 'rg' | 'rgb' | 'rgba' | 'depth'
export type TextureFormat = 'alpha' | 'rgb' | 'rgba' | 'depth'
/** Numbers are shortcuts for color attachment */
export type TextureAttachment = 'depth' | 'stencil' | 'color0' | 'color1' | 'color2' | 'color3' | 'color4' | 'color5' | 'color6' | 'color7' | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
export type TextureFilter = 'nearest' | 'linear'
@@ -64,10 +63,6 @@ export function getFormat(gl: GLRenderingContext, format: TextureFormat, type: T
case 'rgb':
if (isWebGL2(gl) && type === 'int') return gl.RGB_INTEGER;
return gl.RGB;
case 'rg':
if (isWebGL2(gl) && type === 'float') return gl.RG;
else if (isWebGL2(gl) && type === 'int') return gl.RG_INTEGER;
else throw new Error('texture format "rg" requires webgl2 and type "float" or int"');
case 'rgba':
if (isWebGL2(gl) && type === 'int') return gl.RGBA_INTEGER;
return gl.RGBA;
@@ -85,13 +80,6 @@ export function getInternalFormat(gl: GLRenderingContext, format: TextureFormat,
case 'fp16': return gl.R16F;
case 'int': return gl.R32I;
}
case 'rg':
switch (type) {
case 'ubyte': return gl.RG;
case 'float': return gl.RG32F;
case 'fp16': return gl.RG16F;
case 'int': return gl.RG32I;
}
case 'rgb':
switch (type) {
case 'ubyte': return gl.RGB;
@@ -124,7 +112,6 @@ function getByteCount(format: TextureFormat, type: TextureType, width: number, h
function getFormatSize(format: TextureFormat) {
switch (format) {
case 'alpha': return 1;
case 'rg': return 2;
case 'rgb': return 3;
case 'rgba': return 4;
case 'depth': return 4;

View File

@@ -264,35 +264,28 @@ export namespace ArrayEncoding {
return false;
}
function packingSizeUnsigned(data: Int32Array, upperLimit: number) {
let size = 0;
for (let i = 0, n = data.length; i < n; i++) {
size += (data[i] / upperLimit) | 0;
}
size += data.length;
return size;
}
function packingSizeSigned(data: Int32Array, upperLimit: number) {
function packingSize(data: Int32Array, upperLimit: number) {
const lowerLimit = -upperLimit - 1;
let size = 0;
for (let i = 0, n = data.length; i < n; i++) {
const value = data[i];
if (value >= 0) {
size += (value / upperLimit) | 0;
if (value === 0) {
size += 1;
} else if (value > 0) {
size += Math.ceil(value / upperLimit);
if (value % upperLimit === 0) size += 1;
} else {
size += (value / lowerLimit) | 0;
size += Math.ceil(value / lowerLimit);
if (value % lowerLimit === 0) size += 1;
}
}
size += data.length;
return size;
}
function determinePacking(data: Int32Array): { isSigned: boolean, size: number, bytesPerElement: number } {
const signed = isSigned(data);
const size8 = signed ? packingSizeSigned(data, 0x7F) : packingSizeUnsigned(data, 0xFF);
const size16 = signed ? packingSizeSigned(data, 0x7FFF) : packingSizeUnsigned(data, 0xFFFF);
const size8 = signed ? packingSize(data, 0x7F) : packingSize(data, 0xFF);
const size16 = signed ? packingSize(data, 0x7FFF) : packingSize(data, 0xFFFF);
if (data.length * 4 < size16 * 2) {
// 4 byte packing is the most effective

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.362, IHM 1.17, MA 1.4.3.
* Code-generated 'BIRD' schema file. Dictionary versions: mmCIF 5.360, IHM 1.17, MA 1.4.2.
*
* @author molstar/ciftools package
*/

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.362, IHM 1.17, MA 1.4.3.
* Code-generated 'CCD' schema file. Dictionary versions: mmCIF 5.360, IHM 1.17, MA 1.4.2.
*
* @author molstar/ciftools package
*/

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.362, IHM 1.17, MA 1.4.3.
* Code-generated 'mmCIF' schema file. Dictionary versions: mmCIF 5.360, IHM 1.17, MA 1.4.2.
*
* @author molstar/ciftools package
*/

View File

@@ -2,7 +2,6 @@
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { GridLookup3D } from '../../geometry';
@@ -25,17 +24,9 @@ describe('GridLookup3d', () => {
expect(r.count).toBe(1);
expect(r.indices[0]).toBe(0);
r = grid.nearest(0, 0, 0, 1);
expect(r.count).toBe(1);
expect(r.indices[0]).toBe(0);
r = grid.find(0, 0, 0, 1);
expect(r.count).toBe(3);
expect(sortArray(r.indices)).toEqual([0, 1, 2]);
r = grid.nearest(0, 0, 0, 3);
expect(r.count).toBe(3);
expect(sortArray(r.indices)).toEqual([0, 1, 2]);
});
it('radius', () => {
@@ -47,17 +38,9 @@ describe('GridLookup3d', () => {
expect(r.count).toBe(1);
expect(r.indices[0]).toBe(0);
r = grid.nearest(0, 0, 0, 1);
expect(r.count).toBe(1);
expect(r.indices[0]).toBe(0);
r = grid.find(0, 0, 0, 0.5);
expect(r.count).toBe(2);
expect(sortArray(r.indices)).toEqual([0, 1]);
r = grid.nearest(0, 0, 0, 3);
expect(r.count).toBe(3);
expect(sortArray(r.indices)).toEqual([0, 1, 2]);
});
it('indexed', () => {
@@ -68,15 +51,8 @@ describe('GridLookup3d', () => {
let r = grid.find(0, 0, 0, 0);
expect(r.count).toBe(0);
r = grid.nearest(0, 0, 0, 1);
expect(r.count).toBe(1);
r = grid.find(0, 0, 0, 0.5);
expect(r.count).toBe(1);
expect(sortArray(r.indices)).toEqual([0]);
r = grid.nearest(0, 0, 0, 3);
expect(r.count).toBe(1);
expect(sortArray(r.indices)).toEqual([0]);
});
});
});

View File

@@ -204,7 +204,7 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat
render(texture, false);
}
// printTextureImage(readTexture(webgl, minDistTex), { scale: 0.75 });
// printTexture(webgl, minDistTex, 0.75);
return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale, radiusFactor, resolution, maxRadius };
}

View File

@@ -41,9 +41,8 @@ export namespace Result {
export interface Lookup3D<T = number> {
// The result is mutated with each call to find.
find(x: number, y: number, z: number, radius: number, result?: Result<T>): Result<T>,
nearest(x: number, y: number, z: number, k: number, stopIf?: Function, result?: Result<T>): Result<T>,
check(x: number, y: number, z: number, radius: number): boolean,
readonly boundary: { readonly box: Box3D, readonly sphere: Sphere3D }
/** transient result */
readonly result: Result<T>
}
}

View File

@@ -3,7 +3,6 @@
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
import { Result, Lookup3D } from './common';
@@ -13,7 +12,6 @@ import { PositionData } from '../common';
import { Vec3 } from '../../linear-algebra';
import { OrderedSet } from '../../../mol-data/int';
import { Boundary } from '../boundary';
import { FibonacciHeap } from '../../../mol-util/fibonacci-heap';
interface GridLookup3D<T = number> extends Lookup3D<T> {
readonly buckets: { readonly offset: ArrayLike<number>, readonly count: ArrayLike<number>, readonly array: ArrayLike<number> }
@@ -42,17 +40,6 @@ class GridLookup3DImpl<T extends number = number> implements GridLookup3D<T> {
return ret;
}
nearest(x: number, y: number, z: number, k: number = 1, stopIf?: Function, result?: Result<T>): Result<T> {
this.ctx.x = x;
this.ctx.y = y;
this.ctx.z = z;
this.ctx.k = k;
this.ctx.stopIf = stopIf;
const ret = result ?? this.result;
queryNearest(this.ctx, ret);
return ret;
}
check(x: number, y: number, z: number, radius: number): boolean {
this.ctx.x = x;
this.ctx.y = y;
@@ -234,14 +221,12 @@ interface QueryContext {
x: number,
y: number,
z: number,
k: number,
stopIf?: Function,
radius: number,
isCheck: boolean
}
function createContext(grid: Grid3D): QueryContext {
return { grid, x: 0.1, y: 0.1, z: 0.1, k: 1, stopIf: undefined, radius: 0.1, isCheck: false };
return { grid, x: 0.1, y: 0.1, z: 0.1, radius: 0.1, isCheck: false };
}
function query<T extends number = number>(ctx: QueryContext, result: Result<T>): boolean {
@@ -292,152 +277,4 @@ function query<T extends number = number>(ctx: QueryContext, result: Result<T>):
}
}
return result.count > 0;
}
const tmpDirVec = Vec3();
const tmpVec = Vec3();
const tmpSetG = new Set<number>();
const tmpSetG2 = new Set<number>();
const tmpArrG1 = [0.1];
const tmpArrG2 = [0.1];
const tmpArrG3 = [0.1];
const tmpHeapG = new FibonacciHeap();
function queryNearest<T extends number = number>(ctx: QueryContext, result: Result<T>): boolean {
const { min, expandedBox: box, boundingSphere: { center }, size: [sX, sY, sZ], bucketOffset, bucketCounts, bucketArray, grid, data: { x: px, y: py, z: pz, indices, radius }, delta, maxRadius } = ctx.grid;
const { x, y, z, k, stopIf } = ctx;
const indicesCount = OrderedSet.size(indices);
Result.reset(result);
if (indicesCount === 0 || k <= 0) return false;
let gX, gY, gZ, stop = false, gCount = 1, expandGrid = true, nextGCount = 0, arrG = tmpArrG1, nextArrG = tmpArrG2, maxRange = 0, expandRange = true, gridId: number, gridPointsFinished = false;
const expandedArrG = tmpArrG3, sqMaxRadius = maxRadius * maxRadius;
arrG.length = 0;
expandedArrG.length = 0;
tmpSetG.clear();
tmpHeapG.clear();
Vec3.set(tmpVec, x, y, z);
if (!Box3D.containsVec3(box, tmpVec)) {
// intersect ray pointing to box center
Box3D.nearestIntersectionWithRay(tmpVec, box, tmpVec, Vec3.normalize(tmpDirVec, Vec3.sub(tmpDirVec, center, tmpVec)));
gX = Math.max(0, Math.min(sX - 1, Math.floor((tmpVec[0] - min[0]) / delta[0])));
gY = Math.max(0, Math.min(sY - 1, Math.floor((tmpVec[1] - min[1]) / delta[1])));
gZ = Math.max(0, Math.min(sZ - 1, Math.floor((tmpVec[2] - min[2]) / delta[2])));
} else {
gX = Math.floor((x - min[0]) / delta[0]);
gY = Math.floor((y - min[1]) / delta[1]);
gZ = Math.floor((z - min[2]) / delta[2]);
}
const dX = maxRadius !== 0 ? Math.max(1, Math.min(sX - 1, Math.ceil(maxRadius / delta[0]))) : 1;
const dY = maxRadius !== 0 ? Math.max(1, Math.min(sY - 1, Math.ceil(maxRadius / delta[1]))) : 1;
const dZ = maxRadius !== 0 ? Math.max(1, Math.min(sZ - 1, Math.ceil(maxRadius / delta[2]))) : 1;
arrG.push(gX, gY, gZ, (((gX * sY) + gY) * sZ) + gZ);
while (result.count < indicesCount) {
const arrGLen = gCount * 4;
for (let ig = 0; ig < arrGLen; ig += 4) {
gridId = arrG[ig + 3];
if (!tmpSetG.has(gridId)) {
tmpSetG.add(gridId);
gridPointsFinished = tmpSetG.size >= grid.length;
const bucketIdx = grid[gridId];
if (bucketIdx !== 0) {
const _maxRange = maxRange;
const ki = bucketIdx - 1;
const offset = bucketOffset[ki];
const count = bucketCounts[ki];
const end = offset + count;
for (let i = offset; i < end; i++) {
const bIdx = bucketArray[i];
const idx = OrderedSet.getAt(indices, bIdx);
const dx = px[idx] - x;
const dy = py[idx] - y;
const dz = pz[idx] - z;
let distSq = dx * dx + dy * dy + dz * dz;
if (maxRadius !== 0) {
const r = radius![idx];
distSq -= r * r;
}
if (expandRange && distSq > maxRange) {
maxRange = distSq;
}
tmpHeapG.insert(distSq, bIdx);
}
if (_maxRange < maxRange) expandRange = false;
}
}
}
// find next grid points
nextArrG.length = 0;
nextGCount = 0;
tmpSetG2.clear();
for (let ig = 0; ig < arrGLen; ig += 4) {
gX = arrG[ig];
gY = arrG[ig + 1];
gZ = arrG[ig + 2];
// fill grid points array with valid adiacent positions
for (let ix = -dX; ix <= dX; ix++) {
const xPos = gX + ix;
if (xPos < 0 || xPos >= sX) continue;
for (let iy = -dY; iy <= dY; iy++) {
const yPos = gY + iy;
if (yPos < 0 || yPos >= sY) continue;
for (let iz = -dZ; iz <= dZ; iz++) {
const zPos = gZ + iz;
if (zPos < 0 || zPos >= sZ) continue;
gridId = (((xPos * sY) + yPos) * sZ) + zPos;
if (tmpSetG2.has(gridId)) continue; // already scanned
tmpSetG2.add(gridId);
if (tmpSetG.has(gridId)) continue; // already visited
if (!expandGrid) {
const xP = min[0] + xPos * delta[0] - x;
const yP = min[1] + yPos * delta[1] - y;
const zP = min[2] + zPos * delta[2] - z;
const distSqG = (xP * xP) + (yP * yP) + (zP * zP) - sqMaxRadius; // is sqMaxRadius necessary?
if (distSqG > maxRange) {
expandedArrG.push(xPos, yPos, zPos, gridId);
continue;
}
}
nextArrG.push(xPos, yPos, zPos, gridId);
nextGCount++;
}
}
}
}
expandGrid = false;
if (nextGCount === 0) {
if (k === 1) {
const node = tmpHeapG.findMinimum();
if (node) {
const { key: squaredDistance, value: index } = node!;
// const squaredDistance = node!.key, index = node!.value;
Result.add(result, index as number, squaredDistance as number);
return true;
}
} else {
while (!tmpHeapG.isEmpty() && (gridPointsFinished || tmpHeapG.findMinimum()!.key as number <= maxRange) && result.count < k) {
const node = tmpHeapG.extractMinimum();
const squaredDistance = node!.key, index = node!.value;
Result.add(result, index as number, squaredDistance as number);
if (stopIf && !stop) {
stop = stopIf(index, squaredDistance);
}
}
}
if (result.count >= k || stop || result.count >= indicesCount) return result.count > 0;
expandGrid = true;
expandRange = true;
if (expandedArrG.length > 0) {
for (let i = 0, l = expandedArrG.length; i < l; i++) {
arrG.push(expandedArrG[i]);
}
expandedArrG.length = 0;
gCount = arrG.length;
}
} else {
const tmp = arrG;
arrG = nextArrG;
nextArrG = tmp;
gCount = nextGCount;
}
}
return result.count > 0;
}
}

View File

@@ -138,48 +138,6 @@ namespace Box3D {
a.max[2] < b.min[2] || a.min[2] > b.max[2]
);
}
// const tmpTransformV = Vec3();
export function nearestIntersectionWithRay(out: Vec3, box: Box3D, origin: Vec3, dir: Vec3): Vec3 {
const [minX, minY, minZ] = box.min;
const [maxX, maxY, maxZ] = box.max;
const [x, y, z] = origin;
const invDirX = 1.0 / dir[0];
const invDirY = 1.0 / dir[1];
const invDirZ = 1.0 / dir[2];
let tmin, tmax, tymin, tymax, tzmin, tzmax;
if (invDirX >= 0) {
tmin = (minX - x) * invDirX;
tmax = (maxX - x) * invDirX;
} else {
tmin = (maxX - x) * invDirX;
tmax = (minX - x) * invDirX;
}
if (invDirY >= 0) {
tymin = (minY - y) * invDirY;
tymax = (maxY - y) * invDirY;
} else {
tymin = (maxY - y) * invDirY;
tymax = (minY - y) * invDirY;
}
if (invDirZ >= 0) {
tzmin = (minZ - z) * invDirZ;
tzmax = (maxZ - z) * invDirZ;
} else {
tzmin = (maxZ - z) * invDirZ;
tzmax = (minZ - z) * invDirZ;
}
if (tymin > tmin)
tmin = tymin;
if (tymax < tmax)
tmax = tymax;
if (tzmin > tmin)
tmin = tzmin;
if (tzmax < tmax)
tmax = tzmax;
Vec3.scale(out, dir, tmin);
return Vec3.set(out, out[0] + x, out[1] + y, out[2] + z);
}
}
export { Box3D };
export { Box3D };

View File

@@ -277,12 +277,6 @@ namespace Sphere3D {
export function distance(a: Sphere3D, b: Sphere3D) {
return Vec3.distance(a.center, b.center) - a.radius + b.radius;
}
/** Get the distance of v from sphere. If negative, v is inside sphere */
export function distanceToVec(sphere: Sphere3D, v: Vec3): number {
const { center, radius } = sphere;
return Vec3.distance(v, center) - radius;
}
}
export { Sphere3D };
export { Sphere3D };

View File

@@ -1,11 +1,11 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { lerp as scalar_lerp } from '../../mol-math/interpolate';
import { defaults } from '../../mol-util';
import { Mat3 } from '../linear-algebra/3d/mat3';
import { Mat4 } from '../linear-algebra/3d/mat4';
import { Quat } from '../linear-algebra/3d/quat';
@@ -29,13 +29,11 @@ interface SymmetryOperator {
readonly hkl: Vec3,
/** spacegroup symmetry operator index, -1 if not applicable */
readonly spgrOp: number,
/** unique (external) key, -1 if not available */
readonly key: number,
readonly matrix: Mat4,
/** cache the inverse of the transform */
// cache the inverse of the transform
readonly inverse: Mat4,
/** optimize the identity case */
// optimize the identity case
readonly isIdentity: boolean,
/**
@@ -53,20 +51,19 @@ namespace SymmetryOperator {
export const RotationTranslationEpsilon = 0.005;
export type CreateInfo = { assembly?: SymmetryOperator['assembly'], ncsId?: number, hkl?: Vec3, spgrOp?: number, key?: number }
export type CreateInfo = { assembly?: SymmetryOperator['assembly'], ncsId?: number, hkl?: Vec3, spgrOp?: number }
export function create(name: string, matrix: Mat4, info?: CreateInfo | SymmetryOperator): SymmetryOperator {
let { assembly, ncsId, hkl, spgrOp, key } = info || { };
let { assembly, ncsId, hkl, spgrOp } = info || { };
const _hkl = hkl ? Vec3.clone(hkl) : Vec3();
spgrOp = spgrOp ?? -1;
key = key ?? -1;
spgrOp = defaults(spgrOp, -1);
ncsId = ncsId || -1;
const isIdentity = Mat4.isIdentity(matrix);
const suffix = getSuffix(info, isIdentity);
if (isIdentity) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId, suffix, key };
if (isIdentity) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId, suffix };
if (!Mat4.isRotationAndTranslation(matrix, RotationTranslationEpsilon)) {
console.warn(`Symmetry operator (${name}) should be a composition of rotation and translation.`);
}
return { name, assembly, matrix, inverse: Mat4.invert(Mat4(), matrix), isIdentity: false, hkl: _hkl, spgrOp, key, ncsId, suffix };
return { name, assembly, matrix, inverse: Mat4.invert(Mat4(), matrix), isIdentity: false, hkl: _hkl, spgrOp, ncsId, suffix };
}
function isSymmetryOperator(x: any): x is SymmetryOperator {

View File

@@ -35,7 +35,7 @@ function Vec3() {
namespace Vec3 {
export function zero(): Vec3 {
const out = [0.1, 0.0, 0.0]; // ensure backing array of type double
const out = [0.1, 0.0, 0.0];
out[0] = 0;
return out as any;
}

View File

@@ -32,7 +32,6 @@ const DnaAtomIdsList = [
/** Used to reduce false positives for atom name-based type guessing */
const NonPolymerNames = new Set([
'FMN', 'NCN', 'FNS', 'FMA', 'ATP', 'ADP', 'AMP', 'GTP', 'GDP', 'GMP', // Mononucleotides
'LIG'
]);
const StandardComponents = (function () {

View File

@@ -39,7 +39,7 @@ export function getAtomSiteTemplate(data: string, count: number) {
};
}
export function getAtomSite(sites: AtomSiteTemplate, terIndices: Set<number>): { [K in keyof mmCIF_Schema['atom_site'] | 'partial_charge']?: CifField } {
export function getAtomSite(sites: AtomSiteTemplate, hasTer: boolean): { [K in keyof mmCIF_Schema['atom_site'] | 'partial_charge']?: CifField } {
const pdbx_PDB_model_num = CifField.ofStrings(sites.pdbx_PDB_model_num);
const auth_asym_id = CifField.ofTokens(sites.auth_asym_id);
const auth_seq_id = CifField.ofTokens(sites.auth_seq_id);
@@ -67,17 +67,21 @@ export function getAtomSite(sites: AtomSiteTemplate, terIndices: Set<number>): {
const seqId = auth_seq_id.int(i);
let atomId = auth_atom_id.str(i);
let asymIdChanged = false;
if (modelNum !== currModelNum) {
asymIdCounts.clear();
atomIdCounts.clear();
currModelNum = modelNum;
currAsymId = asymId;
currSeqId = seqId;
asymIdChanged = true;
currLabelAsymId = asymId;
} else if (currAsymId !== asymId) {
atomIdCounts.clear();
currAsymId = asymId;
currSeqId = seqId;
asymIdChanged = true;
currLabelAsymId = asymId;
} else if (currSeqId !== seqId) {
atomIdCounts.clear();
@@ -87,7 +91,7 @@ export function getAtomSite(sites: AtomSiteTemplate, terIndices: Set<number>): {
if (asymIdCounts.has(asymId)) {
// only change the chains name if there are TER records
// otherwise assume repeated chain name use is from interleaved chains
if (terIndices.has(i)) {
if (hasTer && asymIdChanged) {
const asymIdCount = asymIdCounts.get(asymId)! + 1;
asymIdCounts.set(asymId, asymIdCount);
currLabelAsymId = `${asymId}_${asymIdCount}`;

View File

@@ -51,7 +51,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> {
let modelNum = 0, modelStr = '';
let conectRange: [number, number] | undefined = undefined;
const terIndices = new Set<number>();
let hasTer = false;
for (let i = 0, _i = lines.count; i < _i; i++) {
let s = indices[2 * i], e = indices[2 * i + 1];
@@ -164,7 +164,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> {
break;
case 'T':
if (substringStartsWith(data, s, e, 'TER')) {
terIndices.add(atomSite.index);
hasTer = true;
}
}
}
@@ -183,7 +183,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> {
atomSite.label_entity_id[i] = entityBuilder.getEntityId(compId, moleculeType, asymIds.value(i));
}
const atom_site = getAtomSite(atomSite, terIndices);
const atom_site = getAtomSite(atomSite, hasTer);
if (!isPdbqt) delete atom_site.partial_charge;
if (conectRange) {

View File

@@ -65,7 +65,7 @@ export namespace ComponentBond {
return e;
}
const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount, pdbx_ordinal } = data;
const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount } = data;
let entry = addEntry(comp_id.value(0)!);
for (let i = 0; i < _rowCount; i++) {
@@ -74,7 +74,6 @@ export namespace ComponentBond {
const nameB = atom_id_2.value(i)!;
const order = value_order.value(i)!;
const aromatic = pdbx_aromatic_flag.value(i) === 'y';
const key = pdbx_ordinal.value(i);
if (entry.id !== id) {
entry = addEntry(id);
@@ -90,29 +89,29 @@ export namespace ComponentBond {
case 'quad': ord = 4; break;
}
entry.add(nameA, nameB, ord, flags, key);
entry.add(nameA, nameB, ord, flags);
}
return entries;
}
export class Entry {
readonly map: Map<string, Map<string, { order: number, flags: number, key: number }>> = new Map();
readonly map: Map<string, Map<string, { order: number, flags: number }>> = new Map();
add(a: string, b: string, order: number, flags: number, key: number, swap = true) {
add(a: string, b: string, order: number, flags: number, swap = true) {
const e = this.map.get(a);
if (e !== void 0) {
const f = e.get(b);
if (f === void 0) {
e.set(b, { order, flags, key });
e.set(b, { order, flags });
}
} else {
const map = new Map<string, { order: number, flags: number, key: number }>();
map.set(b, { order, flags, key });
const map = new Map<string, { order: number, flags: number }>();
map.set(b, { order, flags });
this.map.set(a, map);
}
if (swap) this.add(b, a, order, flags, key, false);
if (swap) this.add(b, a, order, flags, false);
}
constructor(public readonly id: string) { }

View File

@@ -14,8 +14,6 @@ import { ElementIndex } from '../../../../mol-model/structure';
export type IndexPairsProps = {
readonly key: ArrayLike<number>
readonly operatorA: ArrayLike<number>
readonly operatorB: ArrayLike<number>
readonly order: ArrayLike<number>
readonly distance: ArrayLike<number>
readonly flag: ArrayLike<BondType.Flag>
@@ -26,22 +24,18 @@ export type IndexPairBonds = { bonds: IndexPairs, maxDistance: number }
function getGraph(indexA: ArrayLike<ElementIndex>, indexB: ArrayLike<ElementIndex>, props: Partial<IndexPairsProps>, count: number): IndexPairs {
const builder = new IntAdjacencyGraph.EdgeBuilder(count, indexA, indexB);
const key = new Int32Array(builder.slotCount);
const operatorA = new Array(builder.slotCount);
const operatorB = new Array(builder.slotCount);
const order = new Int8Array(builder.slotCount);
const distance = new Array(builder.slotCount);
const flag = new Array(builder.slotCount);
for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
builder.addNextEdge();
builder.assignProperty(key, props.key ? props.key[i] : -1);
builder.assignProperty(operatorA, props.operatorA ? props.operatorA[i] : -1);
builder.assignProperty(operatorB, props.operatorB ? props.operatorB[i] : -1);
builder.assignProperty(order, props.order ? props.order[i] : 1);
builder.assignProperty(distance, props.distance ? props.distance[i] : -1);
builder.assignProperty(flag, props.flag ? props.flag[i] : BondType.Flag.Covalent);
}
return builder.createGraph({ key, operatorA, operatorB, order, distance, flag });
return builder.createGraph({ key, order, distance, flag });
}
export namespace IndexPairBonds {
@@ -56,10 +50,6 @@ export namespace IndexPairBonds {
indexA: Column<number>,
indexB: Column<number>,
key?: Column<number>,
/** Operator key for indexA. Used in bond computation. */
operatorA?: Column<number>,
/** Operator key for indexB. Used in bond computation. */
operatorB?: Column<number>,
order?: Column<number>,
/**
* Useful for bonds in periodic cells. That is, only bonds within the given
@@ -93,30 +83,12 @@ export namespace IndexPairBonds {
const indexA = pairs.indexA.toArray() as ArrayLike<ElementIndex>;
const indexB = pairs.indexB.toArray() as ArrayLike<ElementIndex>;
const key = pairs.key && pairs.key.toArray();
const operatorA = pairs.operatorA && pairs.operatorA.toArray();
const operatorB = pairs.operatorB && pairs.operatorB.toArray();
const order = pairs.order && pairs.order.toArray();
const distance = pairs.distance && pairs.distance.toArray();
const flag = pairs.flag && pairs.flag.toArray();
return {
bonds: getGraph(indexA, indexB, { key, operatorA, operatorB, order, distance, flag }, count),
bonds: getGraph(indexA, indexB, { key, order, distance, flag }, count),
maxDistance: p.maxDistance
};
}
/** Like `getEdgeIndex` but taking `edgeProps.operatorA` and `edgeProps.operatorB` into account */
export function getEdgeIndexForOperators(bonds: IndexPairs, i: ElementIndex, j: ElementIndex, opI: number, opJ: number): number {
let a, b, opA, opB;
if (i < j) {
a = i; b = j;
opA = opI; opB = opJ;
} else {
a = j; b = i;
opA = opJ; opB = opI;
}
for (let t = bonds.offset[a], _t = bonds.offset[a + 1]; t < _t; t++) {
if (bonds.b[t] === b && bonds.edgeProps.operatorA[t] === opA && bonds.edgeProps.operatorB[t] === opB) return t;
}
return -1;
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -71,12 +71,12 @@ namespace CustomModelProperty {
},
ref: (data: Model, add: boolean) => data.customProperties.reference(builder.descriptor, add),
get: (data: Model) => get(data)?.data,
set: (data: Model, props: Partial<PD.Values<Params>> = {}, value?: Value) => {
set: (data: Model, props: Partial<PD.Values<Params>> = {}) => {
const property = get(data);
const p = PD.merge(builder.defaultParams, property.props, props);
if (!PD.areEqual(builder.defaultParams, property.props, p)) {
// this invalidates property.value
set(data, p, value);
set(data, p, undefined);
// dispose of assets
data.customProperties.assets(builder.descriptor);
}
@@ -96,7 +96,7 @@ namespace CustomModelProperty {
getParams: () => ({ value: PD.Value(defaultValue, { isHidden: true }) }),
isApplicable: () => true,
obtain: async (ctx: CustomProperty.Context, data: Model, props: Partial<PD.Values<typeof defaultParams>>) => {
return { ...PD.getDefaultValues(defaultParams), ...props };
return { value: props.value ?? defaultValue };
}
});
}

View File

@@ -22,8 +22,6 @@ import { LocationIterator } from '../../../mol-geo/util/location-iterator';
import { InteractionFlag } from '../interactions/common';
import { Unit } from '../../../mol-model/structure/structure';
import { Sphere3D } from '../../../mol-math/geometry';
import { assertUnreachable } from '../../../mol-util/type-helpers';
import { InteractionsSharedParams } from './shared';
function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<InteractionsInterUnitParams>, mesh?: Mesh) {
if (!structure.hasAtomic) return Mesh.createEmpty(mesh);
@@ -33,7 +31,7 @@ function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: S
const { contacts, unitsFeatures } = interactions;
const { edgeCount, edges } = contacts;
const { sizeFactor, parentDisplay } = props;
const { sizeFactor } = props;
if (!edgeCount) return Mesh.createEmpty(mesh);
@@ -72,48 +70,14 @@ function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: S
if (child) {
const b = edges[edgeIndex];
const childUnitA = child.unitMap.get(b.unitA);
if (!childUnitA) return true;
if (parentDisplay === 'stub') {
const childUnitA = child.unitMap.get(b.unitA);
if (!childUnitA) return true;
const unitA = structure.unitMap.get(b.unitA);
const { offsets, members } = unitsFeatures.get(b.unitA);
for (let i = offsets[b.indexA], il = offsets[b.indexA + 1]; i < il; ++i) {
const eA = unitA.elements[members[i]];
if (!SortedArray.has(childUnitA.elements, eA)) return true;
}
} else if (parentDisplay === 'full' || parentDisplay === 'between') {
let flagA = false;
let flagB = false;
const childUnitA = child.unitMap.get(b.unitA);
if (!childUnitA) {
flagA = true;
} else {
const unitA = structure.unitMap.get(b.unitA);
const { offsets, members } = unitsFeatures.get(b.unitA);
for (let i = offsets[b.indexA], il = offsets[b.indexA + 1]; i < il; ++i) {
const eA = unitA.elements[members[i]];
if (!SortedArray.has(childUnitA.elements, eA)) flagA = true;
}
}
const childUnitB = child.unitMap.get(b.unitB);
if (!childUnitB) {
flagB = true;
} else {
const unitB = structure.unitMap.get(b.unitB);
const { offsets, members } = unitsFeatures.get(b.unitB);
for (let i = offsets[b.indexB], il = offsets[b.indexB + 1]; i < il; ++i) {
const eB = unitB.elements[members[i]];
if (!SortedArray.has(childUnitB.elements, eB)) flagB = true;
}
}
return parentDisplay === 'full' ? flagA && flagB : flagA === flagB;
} else {
assertUnreachable(parentDisplay);
const unitA = structure.unitMap.get(b.unitA);
const { offsets, members } = unitsFeatures.get(b.unitA);
for (let i = offsets[b.indexA], il = offsets[b.indexA + 1]; i < il; ++i) {
const eA = unitA.elements[members[i]];
if (!SortedArray.has(childUnitA.elements, eA)) return true;
}
}
@@ -137,7 +101,10 @@ function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: S
export const InteractionsInterUnitParams = {
...ComplexMeshParams,
...LinkCylinderParams,
...InteractionsSharedParams,
sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }),
dashCount: PD.Numeric(6, { min: 2, max: 10, step: 2 }),
dashScale: PD.Numeric(0.4, { min: 0, max: 2, step: 0.1 }),
includeParent: PD.Boolean(false),
};
export type InteractionsInterUnitParams = typeof InteractionsInterUnitParams
@@ -154,8 +121,7 @@ export function InteractionsInterUnitVisual(materialId: number): ComplexVisual<I
newProps.dashCount !== currentProps.dashCount ||
newProps.dashScale !== currentProps.dashScale ||
newProps.dashCap !== currentProps.dashCap ||
newProps.radialSegments !== currentProps.radialSegments ||
newProps.parentDisplay !== currentProps.parentDisplay
newProps.radialSegments !== currentProps.radialSegments
);
const interactionsHash = InteractionsProvider.get(newStructure).version;

View File

@@ -22,8 +22,6 @@ import { Interactions } from '../interactions/interactions';
import { InteractionFlag } from '../interactions/common';
import { Sphere3D } from '../../../mol-math/geometry';
import { StructureGroup } from '../../../mol-repr/structure/visual/util/common';
import { assertUnreachable } from '../../../mol-util/type-helpers';
import { InteractionsSharedParams } from './shared';
async function createIntraUnitInteractionsCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<InteractionsIntraUnitParams>, mesh?: Mesh) {
if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh);
@@ -40,7 +38,7 @@ async function createIntraUnitInteractionsCylinderMesh(ctx: VisualContext, unit:
const { x, y, z, members, offsets } = features;
const { edgeCount, a, b, edgeProps: { flag } } = contacts;
const { sizeFactor, parentDisplay } = props;
const { sizeFactor } = props;
if (!edgeCount) return Mesh.createEmpty(mesh);
@@ -62,31 +60,10 @@ async function createIntraUnitInteractionsCylinderMesh(ctx: VisualContext, unit:
if (flag[edgeIndex] === InteractionFlag.Filtered) return true;
if (childUnit) {
if (parentDisplay === 'stub') {
const f = a[edgeIndex];
for (let i = offsets[f], il = offsets[f + 1]; i < il; ++i) {
const e = unit.elements[members[offsets[i]]];
if (!SortedArray.has(childUnit.elements, e)) return true;
}
} else if (parentDisplay === 'full' || parentDisplay === 'between') {
let flagA = false;
let flagB = false;
const fA = a[edgeIndex];
for (let i = offsets[fA], il = offsets[fA + 1]; i < il; ++i) {
const eA = unit.elements[members[offsets[i]]];
if (!SortedArray.has(childUnit.elements, eA)) flagA = true;
}
const fB = b[edgeIndex];
for (let i = offsets[fB], il = offsets[fB + 1]; i < il; ++i) {
const eB = unit.elements[members[offsets[i]]];
if (!SortedArray.has(childUnit.elements, eB)) flagB = true;
}
return parentDisplay === 'full' ? flagA && flagB : flagA === flagB;
} else {
assertUnreachable(parentDisplay);
const f = a[edgeIndex];
for (let i = offsets[f], jl = offsets[f + 1]; i < jl; ++i) {
const e = unit.elements[members[offsets[i]]];
if (!SortedArray.has(childUnit.elements, e)) return true;
}
}
@@ -109,7 +86,10 @@ async function createIntraUnitInteractionsCylinderMesh(ctx: VisualContext, unit:
export const InteractionsIntraUnitParams = {
...UnitsMeshParams,
...LinkCylinderParams,
...InteractionsSharedParams,
sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }),
dashCount: PD.Numeric(6, { min: 2, max: 10, step: 2 }),
dashScale: PD.Numeric(0.4, { min: 0, max: 2, step: 0.1 }),
includeParent: PD.Boolean(false),
};
export type InteractionsIntraUnitParams = typeof InteractionsIntraUnitParams
@@ -126,8 +106,7 @@ export function InteractionsIntraUnitVisual(materialId: number): UnitsVisual<Int
newProps.dashCount !== currentProps.dashCount ||
newProps.dashScale !== currentProps.dashScale ||
newProps.dashCap !== currentProps.dashCap ||
newProps.radialSegments !== currentProps.radialSegments ||
newProps.parentDisplay !== currentProps.parentDisplay
newProps.radialSegments !== currentProps.radialSegments
);
const interactionsHash = InteractionsProvider.get(newStructureGroup.structure).version;

View File

@@ -1,16 +0,0 @@
/**
* Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
export const InteractionsSharedParams = {
sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }),
dashCount: PD.Numeric(6, { min: 2, max: 10, step: 2 }),
dashScale: PD.Numeric(0.4, { min: 0, max: 2, step: 0.1 }),
includeParent: PD.Boolean(false),
parentDisplay: PD.Select('stub', PD.arrayToOptions(['stub', 'full', 'between'] as const), { description: 'Only has an effect when "includeParent" is enabled. "Stub" shows just the child side of interactions to the parent. "Full" shows both sides of interactions to the parent. "Between" shows only interactions to the parent.' }),
};
export type InteractionsSharedParams = typeof InteractionsSharedParams

View File

@@ -241,9 +241,7 @@ namespace Loci {
? Structure.toStructureElementLoci(loci.structure)
: ShapeGroup.isLoci(loci)
? Shape.Loci(loci.shape)
: Volume.Cell.isLoci(loci)
? Volume.Loci(loci.volume)
: loci;
: loci;
},
'elementInstances': (loci: Loci) => {
return StructureElement.Loci.is(loci)

View File

@@ -213,9 +213,6 @@ export namespace Model {
export type Index = number;
export const Index = CustomModelProperty.createSimple<Index>('index', 'static');
export type MaxIndex = number;
export const MaxIndex = CustomModelProperty.createSimple<MaxIndex>('max_index', 'static');
export function getRoot(model: Model) {
return model.parent || model;
}

View File

@@ -12,7 +12,6 @@ import * as modifiers from './query/queries/modifiers';
import * as filters from './query/queries/filters';
import * as combinators from './query/queries/combinators';
import * as internal from './query/queries/internal';
import * as atomset from './query/queries/atom-set';
import { Predicates as pred } from './query/predicates';
export const Queries = {
@@ -21,8 +20,7 @@ export const Queries = {
modifiers,
combinators,
pred,
internal,
atomset
internal
};
export { StructureSelection, StructureQuery };
export { StructureSelection, StructureQuery };

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Structure, StructureElement, Unit } from '../structure';
@@ -114,7 +113,6 @@ class QueryContextBondInfo<U extends Unit = Unit> {
bIndex: StructureElement.UnitIndex = 0 as StructureElement.UnitIndex;
type: BondType = BondType.Flag.None;
order: number = 0;
key: number = -1;
private testFn: QueryPredicate = defaultBondTest;
@@ -155,6 +153,6 @@ class QueryContextBondInfo<U extends Unit = Unit> {
}
get length() {
return StructureElement.Location.distance(this.a, this.b);
return StructureElement.Location.distance(this.a, this. b);
}
}

View File

@@ -1,36 +0,0 @@
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Koya Sakuma
* Adapted from MolQL implemtation of atom-set.ts
*
* Copyright (c) 2017 MolQL contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { StructureQuery } from '../query';
import { StructureSelection } from '../selection';
import { getCurrentStructureProperties } from './filters';
import { QueryContext, QueryFn } from '../context';
export function atomCount(ctx: QueryContext) {
return ctx.currentStructure.elementCount;
}
export function countQuery(query: StructureQuery) {
return (ctx: QueryContext) => {
const sel = query(ctx);
return StructureSelection.structureCount(sel);
};
}
export function propertySet(prop: QueryFn<any>) {
return (ctx: QueryContext) => {
const set = new Set();
return getCurrentStructureProperties(ctx, prop, set);
};
}

View File

@@ -1,13 +1,12 @@
/**
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { SetUtils } from '../../../../mol-util/set';
import { Unit } from '../../structure';
import { QueryContext, QueryFn } from '../context';
import { QueryContext, QueryFn, QueryPredicate } from '../context';
import { StructureQuery } from '../query';
import { StructureSelection } from '../selection';
import { structureAreIntersecting } from '../utils/structure-set';
@@ -17,7 +16,7 @@ import { Structure } from '../../structure/structure';
import { StructureElement } from '../../structure/element';
import { SortedArray } from '../../../../mol-data/int';
export function pick(query: StructureQuery, pred: QueryFn<any>): StructureQuery {
export function pick(query: StructureQuery, pred: QueryPredicate): StructureQuery {
return ctx => {
const sel = query(ctx);
const ret = StructureSelection.LinearBuilder(ctx.inputStructure);
@@ -51,7 +50,9 @@ export function first(query: StructureQuery): StructureQuery {
};
}
export function getCurrentStructureProperties(ctx: QueryContext, props: QueryFn<any>, set: Set<any>) {
export interface UnitTypeProperties { atomic?: QueryFn, coarse?: QueryFn }
export function getCurrentStructureProperties(ctx: QueryContext, props: UnitTypeProperties, set: Set<any>) {
const { units } = ctx.currentStructure;
const l = ctx.pushCurrentElement();
@@ -60,9 +61,9 @@ export function getCurrentStructureProperties(ctx: QueryContext, props: QueryFn<
l.unit = unit;
const elements = unit.elements;
const fn = props;
// if (Unit.isAtomic(unit)) fn = props.atomic;
// else fn = props.coarse;
let fn;
if (Unit.isAtomic(unit)) fn = props.atomic;
else fn = props.coarse;
if (!fn) continue;
for (let j = 0, _j = elements.length; j < _j; j++) {
@@ -76,7 +77,7 @@ export function getCurrentStructureProperties(ctx: QueryContext, props: QueryFn<
return set;
}
function getSelectionProperties(ctx: QueryContext, query: StructureQuery, props: QueryFn<any>) {
function getSelectionProperties(ctx: QueryContext, query: StructureQuery, props: UnitTypeProperties) {
const set = new Set();
const sel = query(ctx);
@@ -91,7 +92,7 @@ function getSelectionProperties(ctx: QueryContext, query: StructureQuery, props:
return set;
}
export function withSameAtomProperties(query: StructureQuery, propertySource: StructureQuery, props: QueryFn<any>): StructureQuery {
export function withSameAtomProperties(query: StructureQuery, propertySource: StructureQuery, props: UnitTypeProperties): StructureQuery {
return ctx => {
const sel = query(ctx);
const propSet = getSelectionProperties(ctx, propertySource, props);
@@ -101,7 +102,7 @@ export function withSameAtomProperties(query: StructureQuery, propertySource: St
StructureSelection.forEach(sel, (s, i) => {
ctx.currentStructure = s;
const currentProps = getCurrentStructureProperties(ctx, props, new Set());
if (SetUtils.isSuperset(propSet, currentProps)) {
if (SetUtils.isSuperset(currentProps, propSet)) {
ret.add(s);
}
@@ -247,7 +248,7 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) {
const inputUnit = input.unitMap.get(unit.id) as Unit.Atomic;
const { offset, b, edgeProps: { flags, order, key } } = inputUnit.bonds;
const { offset, b, edgeProps: { flags, order } } = inputUnit.bonds;
const bondedUnits = interBonds.getConnectedUnits(unit.id);
const buCount = bondedUnits.length;
@@ -272,7 +273,6 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) {
atomicBond.bIndex = b[l] as StructureElement.UnitIndex;
atomicBond.type = flags[l];
atomicBond.order = order[l];
atomicBond.key = key[l];
if (atomicBond.test(queryCtx, true)) return true;
}
@@ -295,7 +295,6 @@ function checkConnected(ctx: IsConnectedToCtx, structure: Structure) {
atomicBond.bIndex = bond.indexB;
atomicBond.type = bond.props.flag;
atomicBond.order = bond.props.order;
atomicBond.key = bond.props.key;
if (atomicBond.test(queryCtx, true)) return true;
}
}
@@ -343,4 +342,4 @@ export function isConnectedTo({ query, target, disjunct, invert, bondTest }: IsC
return ret.getSelection();
};
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -322,7 +322,7 @@ export function bondedAtomicPairs(bondTest?: QueryPredicate): StructureQuery {
for (const unit of structure.units) {
if (unit.kind !== Unit.Kind.Atomic) continue;
const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order, key } } = unit.bonds;
const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order } } = unit.bonds;
atomicBond.a.unit = unit;
atomicBond.b.unit = unit;
for (let i = 0 as StructureElement.UnitIndex, _i = unit.elements.length; i < _i; i++) {
@@ -335,7 +335,6 @@ export function bondedAtomicPairs(bondTest?: QueryPredicate): StructureQuery {
atomicBond.b.element = unit.elements[intraBondB[lI]];
atomicBond.type = flags[lI];
atomicBond.order = order[lI];
atomicBond.key = key[lI];
// No need to "swap test" because each bond direction will be visited eventually.
if (atomicBond.test(ctx, false)) {
const b = structure.subsetBuilder(false);
@@ -359,7 +358,6 @@ export function bondedAtomicPairs(bondTest?: QueryPredicate): StructureQuery {
atomicBond.bIndex = bond.indexB;
atomicBond.order = bond.props.order;
atomicBond.type = bond.props.flag;
atomicBond.key = bond.props.key;
// No need to "swap test" because each bond direction will be visited eventually.
if (atomicBond.test(ctx, false)) {

View File

@@ -1,8 +1,7 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Segmentation, SortedArray } from '../../../../mol-data/int';
@@ -371,7 +370,7 @@ function expandConnected(ctx: QueryContext, structure: Structure) {
}
const inputUnitA = inputStructure.unitMap.get(unit.id) as Unit.Atomic;
const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order, key } } = inputUnitA.bonds;
const { offset: intraBondOffset, b: intraBondB, edgeProps: { flags, order } } = inputUnitA.bonds;
atomicBond.setStructure(inputStructure);
@@ -398,7 +397,6 @@ function expandConnected(ctx: QueryContext, structure: Structure) {
atomicBond.b.element = bElement;
atomicBond.type = flags[lI];
atomicBond.order = order[lI];
atomicBond.key = key[lI];
if (atomicBond.test(ctx, true)) {
builder.addToUnit(unit.id, bElement);
@@ -429,7 +427,6 @@ function expandConnected(ctx: QueryContext, structure: Structure) {
atomicBond.b.element = bElement;
atomicBond.type = bond.props.flag;
atomicBond.order = bond.props.order;
atomicBond.key = bond.props.key;
if (atomicBond.test(ctx, true)) {
builder.addToUnit(bondedUnit.unitB, bElement);

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -173,7 +173,6 @@ const unit = {
multiChain: p(l => Unit.Traits.is(l.unit.traits, Unit.Trait.MultiChain)),
object_primitive: p(l => l.unit.objectPrimitive),
operator_name: p(l => l.unit.conformation.operator.name),
operator_key: p(l => l.unit.conformation.operator.key),
model_index: p(l => l.unit.model.modelNum),
model_label: p(l => l.unit.model.label),
model_entry_id: p(l => l.unit.model.entryId),

View File

@@ -1224,7 +1224,7 @@ namespace Structure {
const closeUnits = lookup.findUnitIndices(imageCenter[0], imageCenter[1], imageCenter[2], bs.radius + maxRadius);
for (let i = 0; i < closeUnits.count; i++) {
const other = structure.units[closeUnits.indices[i]];
if (other.elements.length > 3 && !Box3D.overlaps(bbox, other.boundary.box)) continue;
if (!Box3D.overlaps(bbox, other.boundary.box)) continue;
if (!validUnit(other) || unit.id >= other.id || !validUnitPair(unit, other)) continue;
if (other.elements.length >= unit.elements.length) callback(unit, other);
@@ -1357,9 +1357,6 @@ namespace Structure {
export type Index = number;
export const Index = CustomStructureProperty.createSimple<Index>('index', 'root');
export type MaxIndex = number;
export const MaxIndex = CustomStructureProperty.createSimple<MaxIndex>('max_index', 'root');
const PrincipalAxesProp = '__PrincipalAxes__';
export function getPrincipalAxes(structure: Structure): PrincipalAxes {
if (structure.currentPropertyData[PrincipalAxesProp]) return structure.currentPropertyData[PrincipalAxesProp];

View File

@@ -15,17 +15,16 @@ import { InterUnitGraph } from '../../../../../mol-math/graph/inter-unit-graph';
type IntraUnitBonds = IntAdjacencyGraph<StructureElement.UnitIndex, {
readonly order: ArrayLike<number>,
readonly flags: ArrayLike<BondType.Flag>
readonly key: ArrayLike<number>,
}, {
/** can remap even with dynamicBonds on, e.g., for water molecules */
readonly canRemap?: boolean
}>
namespace IntraUnitBonds {
export const Empty: IntraUnitBonds = IntAdjacencyGraph.create([], [], [], 0, { flags: [], order: [], key: [] });
export const Empty: IntraUnitBonds = IntAdjacencyGraph.create([], [], [], 0, { flags: [], order: [] });
}
type InterUnitEdgeProps = { readonly order: number, readonly flag: BondType.Flag, readonly key: number }
type InterUnitEdgeProps = { readonly order: number, readonly flag: BondType.Flag }
class InterUnitBonds extends InterUnitGraph<number, StructureElement.UnitIndex, InterUnitEdgeProps> {
/** Get inter-unit bond given a bond-location */

View File

@@ -71,8 +71,6 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
const testDistanceSq = (bRadius + maxRadius) * (bRadius + maxRadius);
builder.startUnitPair(unitA.id, unitB.id);
const opKeyA = unitA.conformation.operator.key;
const opKeyB = unitB.conformation.operator.key;
for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) {
const aI = atomsA[_aI];
@@ -82,7 +80,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
if (!props.forceCompute && indexPairs) {
const { maxDistance } = indexPairs;
const { offset, b, edgeProps: { order, distance, flag, key, operatorA, operatorB } } = indexPairs.bonds;
const { offset, b, edgeProps: { order, distance, flag } } = indexPairs.bonds;
const srcA = sourceIndex.value(aI);
const aeI = getElementIdx(type_symbolA.value(aI));
@@ -92,11 +90,6 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
const _bI = SortedArray.indexOf(unitB.elements, bI) as StructureElement.UnitIndex;
if (_bI < 0) continue;
const opA = operatorA[i];
const opB = operatorB[i];
if ((opA >= 0 && opA !== opKeyA && opA !== opKeyB) ||
(opB >= 0 && opB !== opKeyB && opB !== opKeyA)) continue;
const beI = getElementIdx(type_symbolA.value(bI));
const d = distance[i];
@@ -120,7 +113,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
}
if (add) {
builder.add(_aI, _bI, { order: order[i], flag: flag[i], key: key[i] });
builder.add(_aI, _bI, { order: order[i], flag: flag[i] });
}
}
continue; // assume `indexPairs` supplies all bonds
@@ -138,7 +131,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
// check if the bond is within MAX_RADIUS for this pair of units
if (getDistance(unitA, aI, unitB, p.atomIndex) > maxRadius) continue;
builder.add(_aI, _bI, { order: se.order, flag: se.flags, key: se.rowIndex });
builder.add(_aI, _bI, { order: se.order, flag: se.flags });
added = true;
}
// assume, for an atom, that if any inter unit bond is given
@@ -194,8 +187,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
const compIdB = label_comp_idB.value(residueIndexB[bI]);
builder.add(_aI, _bI, {
order: getInterBondOrderFromTable(compIdA, compIdB, atomIdA, atomIdB),
flag: (isMetal ? BondType.Flag.MetallicCoordination : BondType.Flag.Covalent) | BondType.Flag.Computed,
key: -1
flag: (isMetal ? BondType.Flag.MetallicCoordination : BondType.Flag.Covalent) | BondType.Flag.Computed
});
}
}

View File

@@ -24,19 +24,17 @@ import { Model } from '../../../model/model';
// avoiding namespace lookup improved performance in Chrome (Aug 2020)
const v3distance = Vec3.distance;
function getGraph(atomA: StructureElement.UnitIndex[], atomB: StructureElement.UnitIndex[], _order: number[], _flags: number[], _key: number[], atomCount: number, canRemap: boolean): IntraUnitBonds {
function getGraph(atomA: StructureElement.UnitIndex[], atomB: StructureElement.UnitIndex[], _order: number[], _flags: number[], atomCount: number, canRemap: boolean): IntraUnitBonds {
const builder = new IntAdjacencyGraph.EdgeBuilder(atomCount, atomA, atomB);
const flags = new Uint16Array(builder.slotCount);
const order = new Int8Array(builder.slotCount);
const key = new Uint32Array(builder.slotCount);
for (let i = 0, _i = builder.edgeCount; i < _i; i++) {
builder.addNextEdge();
builder.assignProperty(flags, _flags[i]);
builder.assignProperty(order, _order[i]);
builder.assignProperty(key, _key[i]);
}
return builder.createGraph({ flags, order, key }, { canRemap });
return builder.createGraph({ flags, order }, { canRemap });
}
const tmpDistVecA = Vec3();
@@ -55,7 +53,7 @@ function findIndexPairBonds(unit: Unit.Atomic) {
const { type_symbol } = unit.model.atomicHierarchy.atoms;
const atomCount = unit.elements.length;
const { maxDistance } = indexPairs;
const { offset, b, edgeProps: { order, distance, flag, key, operatorA, operatorB } } = indexPairs.bonds;
const { offset, b, edgeProps: { order, distance, flag } } = indexPairs.bonds;
const { atomSourceIndex: sourceIndex } = unit.model.atomicHierarchy;
const { invertedIndex } = Model.getInvertedAtomSourceIndex(unit.model);
@@ -64,9 +62,6 @@ function findIndexPairBonds(unit: Unit.Atomic) {
const atomB: StructureElement.UnitIndex[] = [];
const flags: number[] = [];
const orders: number[] = [];
const keys: number[] = [];
const opKey = unit.conformation.operator.key;
for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) {
const aI = atoms[_aI];
@@ -82,10 +77,6 @@ function findIndexPairBonds(unit: Unit.Atomic) {
const _bI = SortedArray.indexOf(unit.elements, bI) as StructureElement.UnitIndex;
if (_bI < 0) continue;
const opA = operatorA[i];
const opB = operatorB[i];
if ((opA >= 0 && opA !== opKey) || (opB >= 0 && opB !== opKey)) continue;
const beI = getElementIdx(type_symbol.value(bI));
const d = distance[i];
@@ -113,12 +104,11 @@ function findIndexPairBonds(unit: Unit.Atomic) {
atomB[atomB.length] = _bI;
orders[orders.length] = order[i];
flags[flags.length] = flag[i];
keys[keys.length] = key[i];
}
}
}
return getGraph(atomA, atomB, orders, flags, keys, atomCount, false);
return getGraph(atomA, atomB, orders, flags, atomCount, false);
}
function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBonds {
@@ -142,10 +132,9 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
const atomB: StructureElement.UnitIndex[] = [];
const flags: number[] = [];
const order: number[] = [];
const key: number[] = [];
let lastResidue = -1;
let componentMap: Map<string, Map<string, { flags: number, order: number, key: number }>> | undefined = void 0;
let componentMap: Map<string, Map<string, { flags: number, order: number }>> | undefined = void 0;
let isWatery = true, isDictionaryBased = true, isSequenced = true;
@@ -173,7 +162,6 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
atomB[atomB.length] = _bI;
flags[flags.length] = se.flags;
order[order.length] = se.order;
key[key.length] = se.rowIndex;
if (!hasStructConn) structConnAdded.clear();
hasStructConn = true;
@@ -242,7 +230,6 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
flag |= BondType.Flag.MetallicCoordination;
}
flags[flags.length] = flag;
key[key.length] = e.key;
}
continue;
}
@@ -256,7 +243,6 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
atomB[atomB.length] = _bI;
order[order.length] = getIntraBondOrderFromTable(compId, atomIdA, label_atom_id.value(bI));
flags[flags.length] = (isMetal ? BondType.Flag.MetallicCoordination : BondType.Flag.Covalent) | BondType.Flag.Computed;
key[key.length] = -1;
const seqIdB = label_seq_id.value(rbI);
@@ -267,7 +253,7 @@ function findBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUnitBon
}
const canRemap = isWatery || (isDictionaryBased && isSequenced);
return getGraph(atomA, atomB, order, flags, key, atomCount, canRemap);
return getGraph(atomA, atomB, order, flags, atomCount, canRemap);
}
function computeIntraUnitBonds(unit: Unit.Atomic, props?: Partial<BondComputationProps>) {

Some files were not shown because too many files have changed in this diff Show More