molstar
Version:
A comprehensive macromolecular library.
135 lines • 6.93 kB
JavaScript
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { __assign, __awaiter, __generator } from "tslib";
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
import { Box3D } from '../../mol-math/geometry';
import { Grid, Volume } from '../../mol-model/volume';
import { DirectVolume } from '../../mol-geo/geometry/direct-volume/direct-volume';
import { VolumeVisual, VolumeRepresentation, VolumeRepresentationProvider } from './representation';
import { LocationIterator } from '../../mol-geo/util/location-iterator';
import { NullLocation } from '../../mol-model/location';
import { Interval } from '../../mol-data/int';
import { EmptyLoci } from '../../mol-model/loci';
import { createVolumeTexture2d, createVolumeTexture3d, eachVolumeLoci, getVolumeTexture2dLayout } from './util';
function getBoundingBox(gridDimension, transform) {
var bbox = Box3D();
Box3D.add(bbox, gridDimension);
Box3D.transform(bbox, bbox, transform);
return bbox;
}
// 2d volume texture
export function createDirectVolume2d(ctx, webgl, volume, directVolume) {
var gridDimension = volume.grid.cells.space.dimensions;
var _a = getVolumeTexture2dLayout(gridDimension), width = _a.width, height = _a.height;
if (Math.max(width, height) > webgl.maxTextureSize / 2) {
throw new Error('volume too large for direct-volume rendering');
}
var textureImage = createVolumeTexture2d(volume, 'normals');
// debugTexture(createImageData(textureImage.array, textureImage.width, textureImage.height), 1/3)
var transform = Grid.getGridToCartesianTransform(volume.grid);
var bbox = getBoundingBox(gridDimension, transform);
var texture = directVolume ? directVolume.gridTexture.ref.value : webgl.resources.texture('image-uint8', 'rgba', 'ubyte', 'linear');
texture.load(textureImage);
var _b = getUnitToCartn(volume.grid), unitToCartn = _b.unitToCartn, cellDim = _b.cellDim;
return DirectVolume.create(bbox, gridDimension, transform, unitToCartn, cellDim, texture, volume.grid.stats, false, directVolume);
}
// 3d volume texture
function getUnitToCartn(grid) {
if (grid.transform.kind === 'matrix') {
return {
unitToCartn: Mat4.mul(Mat4(), grid.transform.matrix, Mat4.fromScaling(Mat4(), grid.cells.space.dimensions)),
cellDim: Mat4.getScaling(Vec3(), grid.transform.matrix)
};
}
var box = grid.transform.fractionalBox;
var size = Box3D.size(Vec3(), box);
return {
unitToCartn: Mat4.mul3(Mat4(), grid.transform.cell.fromFractional, Mat4.fromTranslation(Mat4(), box.min), Mat4.fromScaling(Mat4(), size)),
cellDim: Vec3.div(Vec3(), grid.transform.cell.size, grid.cells.space.dimensions)
};
}
export function createDirectVolume3d(ctx, webgl, volume, directVolume) {
var gridDimension = volume.grid.cells.space.dimensions;
if (Math.max.apply(Math, gridDimension) > webgl.max3dTextureSize / 2) {
throw new Error('volume too large for direct-volume rendering');
}
var textureVolume = createVolumeTexture3d(volume);
var transform = Grid.getGridToCartesianTransform(volume.grid);
var bbox = getBoundingBox(gridDimension, transform);
var texture = directVolume ? directVolume.gridTexture.ref.value : webgl.resources.texture('volume-uint8', 'rgba', 'ubyte', 'linear');
texture.load(textureVolume);
var _a = getUnitToCartn(volume.grid), unitToCartn = _a.unitToCartn, cellDim = _a.cellDim;
return DirectVolume.create(bbox, gridDimension, transform, unitToCartn, cellDim, texture, volume.grid.stats, false, directVolume);
}
//
export function createDirectVolume(ctx, volume, theme, props, directVolume) {
return __awaiter(this, void 0, void 0, function () {
var runtime, webgl;
return __generator(this, function (_a) {
runtime = ctx.runtime, webgl = ctx.webgl;
if (webgl === undefined)
throw new Error('DirectVolumeVisual requires `webgl` in props');
return [2 /*return*/, webgl.isWebGL2 ?
createDirectVolume3d(runtime, webgl, volume, directVolume) :
createDirectVolume2d(runtime, webgl, volume, directVolume)];
});
});
}
function getLoci(volume, props) {
return props.renderMode.name === 'isosurface'
? Volume.Isosurface.Loci(volume, props.renderMode.params.isoValue)
: Volume.Loci(volume);
}
export function getDirectVolumeLoci(pickingId, volume, props, id) {
var objectId = pickingId.objectId, groupId = pickingId.groupId;
if (id === objectId) {
return Volume.Cell.Loci(volume, Interval.ofSingleton(groupId));
}
return EmptyLoci;
}
export function eachDirectVolume(loci, volume, props, apply) {
var isoValue = props.renderMode.name === 'isosurface'
? props.renderMode.params.isoValue : undefined;
return eachVolumeLoci(loci, volume, isoValue, apply);
}
//
export var DirectVolumeParams = __assign(__assign({}, DirectVolume.Params), { quality: __assign(__assign({}, DirectVolume.Params.quality), { isEssential: false }) });
export function getDirectVolumeParams(ctx, volume) {
var p = PD.clone(DirectVolumeParams);
p.renderMode = DirectVolume.createRenderModeParam(volume.grid.stats);
return p;
}
export function DirectVolumeVisual(materialId) {
return VolumeVisual({
defaultProps: PD.getDefaultValues(DirectVolumeParams),
createGeometry: createDirectVolume,
createLocationIterator: function (volume) { return LocationIterator(volume.grid.cells.data.length, 1, 1, function () { return NullLocation; }); },
getLoci: getDirectVolumeLoci,
eachLocation: eachDirectVolume,
setUpdateState: function (state, volume, newProps, currentProps) {
},
geometryUtils: DirectVolume.Utils,
dispose: function (geometry) {
geometry.gridTexture.ref.value.destroy();
}
}, materialId);
}
export function DirectVolumeRepresentation(ctx, getParams) {
return VolumeRepresentation('Direct Volume', ctx, getParams, DirectVolumeVisual, getLoci);
}
export var DirectVolumeRepresentationProvider = VolumeRepresentationProvider({
name: 'direct-volume',
label: 'Direct Volume',
description: 'Direct rendering of volumetric data.',
factory: DirectVolumeRepresentation,
getParams: getDirectVolumeParams,
defaultValues: PD.getDefaultValues(DirectVolumeParams),
defaultColorTheme: { name: 'uniform' },
defaultSizeTheme: { name: 'uniform' },
isApplicable: function (volume) { return !Volume.isEmpty(volume); }
});
//# sourceMappingURL=direct-volume.js.map