|
@@ -1,5 +1,5 @@
|
|
/**
|
|
/**
|
|
- * Copyright (c) 2018-2020 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 Alexander Rose <alexander.rose@weirdbyte.de>
|
|
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
|
*/
|
|
*/
|
|
@@ -26,8 +26,7 @@ import { TransformData } from '../transform-data';
|
|
import { createEmptyTransparency } from '../transparency-data';
|
|
import { createEmptyTransparency } from '../transparency-data';
|
|
import { createTransferFunctionTexture, getControlPointsFromVec2Array } from './transfer-function';
|
|
import { createTransferFunctionTexture, getControlPointsFromVec2Array } from './transfer-function';
|
|
import { createEmptyClipping } from '../clipping-data';
|
|
import { createEmptyClipping } from '../clipping-data';
|
|
-import { Grid, Volume } from '../../../mol-model/volume';
|
|
|
|
-import { ColorNames } from '../../../mol-util/color/names';
|
|
|
|
|
|
+import { Grid } from '../../../mol-model/volume';
|
|
import { createEmptySubstance } from '../substance-data';
|
|
import { createEmptySubstance } from '../substance-data';
|
|
|
|
|
|
const VolumeBox = Box();
|
|
const VolumeBox = Box();
|
|
@@ -48,6 +47,7 @@ export interface DirectVolume {
|
|
readonly unitToCartn: ValueCell<Mat4>
|
|
readonly unitToCartn: ValueCell<Mat4>
|
|
readonly cartnToUnit: ValueCell<Mat4>
|
|
readonly cartnToUnit: ValueCell<Mat4>
|
|
readonly packedGroup: ValueCell<boolean>
|
|
readonly packedGroup: ValueCell<boolean>
|
|
|
|
+ readonly axisOrder: ValueCell<Vec3>
|
|
|
|
|
|
/** Bounding sphere of the volume */
|
|
/** Bounding sphere of the volume */
|
|
readonly boundingSphere: Sphere3D
|
|
readonly boundingSphere: Sphere3D
|
|
@@ -56,10 +56,10 @@ export interface DirectVolume {
|
|
}
|
|
}
|
|
|
|
|
|
export namespace DirectVolume {
|
|
export namespace DirectVolume {
|
|
- export function create(bbox: Box3D, gridDimension: Vec3, transform: Mat4, unitToCartn: Mat4, cellDim: Vec3, texture: Texture, stats: Grid['stats'], packedGroup: boolean, directVolume?: DirectVolume): DirectVolume {
|
|
|
|
|
|
+ export function create(bbox: Box3D, gridDimension: Vec3, transform: Mat4, unitToCartn: Mat4, cellDim: Vec3, texture: Texture, stats: Grid['stats'], packedGroup: boolean, axisOrder: Vec3, directVolume?: DirectVolume): DirectVolume {
|
|
return directVolume ?
|
|
return directVolume ?
|
|
- update(bbox, gridDimension, transform, unitToCartn, cellDim, texture, stats, packedGroup, directVolume) :
|
|
|
|
- fromData(bbox, gridDimension, transform, unitToCartn, cellDim, texture, stats, packedGroup);
|
|
|
|
|
|
+ update(bbox, gridDimension, transform, unitToCartn, cellDim, texture, stats, packedGroup, axisOrder, directVolume) :
|
|
|
|
+ fromData(bbox, gridDimension, transform, unitToCartn, cellDim, texture, stats, packedGroup, axisOrder);
|
|
}
|
|
}
|
|
|
|
|
|
function hashCode(directVolume: DirectVolume) {
|
|
function hashCode(directVolume: DirectVolume) {
|
|
@@ -70,7 +70,7 @@ export namespace DirectVolume {
|
|
]);
|
|
]);
|
|
}
|
|
}
|
|
|
|
|
|
- function fromData(bbox: Box3D, gridDimension: Vec3, transform: Mat4, unitToCartn: Mat4, cellDim: Vec3, texture: Texture, stats: Grid['stats'], packedGroup: boolean): DirectVolume {
|
|
|
|
|
|
+ function fromData(bbox: Box3D, gridDimension: Vec3, transform: Mat4, unitToCartn: Mat4, cellDim: Vec3, texture: Texture, stats: Grid['stats'], packedGroup: boolean, axisOrder: Vec3): DirectVolume {
|
|
const boundingSphere = Sphere3D();
|
|
const boundingSphere = Sphere3D();
|
|
let currentHash = -1;
|
|
let currentHash = -1;
|
|
|
|
|
|
@@ -101,6 +101,7 @@ export namespace DirectVolume {
|
|
return boundingSphere;
|
|
return boundingSphere;
|
|
},
|
|
},
|
|
packedGroup: ValueCell.create(packedGroup),
|
|
packedGroup: ValueCell.create(packedGroup),
|
|
|
|
+ axisOrder: ValueCell.create(axisOrder),
|
|
setBoundingSphere(sphere: Sphere3D) {
|
|
setBoundingSphere(sphere: Sphere3D) {
|
|
Sphere3D.copy(boundingSphere, sphere);
|
|
Sphere3D.copy(boundingSphere, sphere);
|
|
currentHash = hashCode(directVolume);
|
|
currentHash = hashCode(directVolume);
|
|
@@ -109,7 +110,7 @@ export namespace DirectVolume {
|
|
return directVolume;
|
|
return directVolume;
|
|
}
|
|
}
|
|
|
|
|
|
- function update(bbox: Box3D, gridDimension: Vec3, transform: Mat4, unitToCartn: Mat4, cellDim: Vec3, texture: Texture, stats: Grid['stats'], packedGroup: boolean, directVolume: DirectVolume): DirectVolume {
|
|
|
|
|
|
+ function update(bbox: Box3D, gridDimension: Vec3, transform: Mat4, unitToCartn: Mat4, cellDim: Vec3, texture: Texture, stats: Grid['stats'], packedGroup: boolean, axisOrder: Vec3, directVolume: DirectVolume): DirectVolume {
|
|
const width = texture.getWidth();
|
|
const width = texture.getWidth();
|
|
const height = texture.getHeight();
|
|
const height = texture.getHeight();
|
|
const depth = texture.getDepth();
|
|
const depth = texture.getDepth();
|
|
@@ -126,6 +127,7 @@ export namespace DirectVolume {
|
|
ValueCell.update(directVolume.unitToCartn, unitToCartn);
|
|
ValueCell.update(directVolume.unitToCartn, unitToCartn);
|
|
ValueCell.update(directVolume.cartnToUnit, Mat4.invert(Mat4(), unitToCartn));
|
|
ValueCell.update(directVolume.cartnToUnit, Mat4.invert(Mat4(), unitToCartn));
|
|
ValueCell.updateIfChanged(directVolume.packedGroup, packedGroup);
|
|
ValueCell.updateIfChanged(directVolume.packedGroup, packedGroup);
|
|
|
|
+ ValueCell.updateIfChanged(directVolume.axisOrder, Vec3.fromArray(directVolume.axisOrder.ref.value, axisOrder, 0));
|
|
return directVolume;
|
|
return directVolume;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -138,47 +140,19 @@ export namespace DirectVolume {
|
|
const texture = createNullTexture();
|
|
const texture = createNullTexture();
|
|
const stats = Grid.One.stats;
|
|
const stats = Grid.One.stats;
|
|
const packedGroup = false;
|
|
const packedGroup = false;
|
|
- return create(bbox, gridDimension, transform, unitToCartn, cellDim, texture, stats, packedGroup, directVolume);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- export function createRenderModeParam(stats?: Grid['stats']) {
|
|
|
|
- const isoValueParam = stats
|
|
|
|
- ? Volume.createIsoValueParam(Volume.IsoValue.relative(2), stats)
|
|
|
|
- : Volume.IsoValueParam;
|
|
|
|
-
|
|
|
|
- return PD.MappedStatic('volume', {
|
|
|
|
- isosurface: PD.Group({
|
|
|
|
- isoValue: isoValueParam,
|
|
|
|
- singleLayer: PD.Boolean(false, { isEssential: true }),
|
|
|
|
- }, { isFlat: true }),
|
|
|
|
- volume: PD.Group({
|
|
|
|
- controlPoints: PD.LineGraph([
|
|
|
|
- Vec2.create(0.19, 0.0), Vec2.create(0.2, 0.05), Vec2.create(0.25, 0.05), Vec2.create(0.26, 0.0),
|
|
|
|
- Vec2.create(0.79, 0.0), Vec2.create(0.8, 0.05), Vec2.create(0.85, 0.05), Vec2.create(0.86, 0.0),
|
|
|
|
- ]),
|
|
|
|
- list: PD.ColorList({
|
|
|
|
- kind: 'interpolate',
|
|
|
|
- colors: [
|
|
|
|
- [ColorNames.white, 0],
|
|
|
|
- [ColorNames.red, 0.25],
|
|
|
|
- [ColorNames.white, 0.5],
|
|
|
|
- [ColorNames.blue, 0.75],
|
|
|
|
- [ColorNames.white, 1]
|
|
|
|
- ]
|
|
|
|
- }, { offsets: true }),
|
|
|
|
- }, { isFlat: true })
|
|
|
|
- }, { isEssential: true });
|
|
|
|
|
|
+ const axisOrder = Vec3.create(0, 1, 2);
|
|
|
|
+ return create(bbox, gridDimension, transform, unitToCartn, cellDim, texture, stats, packedGroup, axisOrder, directVolume);
|
|
}
|
|
}
|
|
|
|
|
|
export const Params = {
|
|
export const Params = {
|
|
...BaseGeometry.Params,
|
|
...BaseGeometry.Params,
|
|
- doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo),
|
|
|
|
- flipSided: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
|
|
|
- flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
|
|
|
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
|
ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
|
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
|
xrayShaded: PD.Boolean(false, BaseGeometry.ShadingCategory),
|
|
- renderMode: createRenderModeParam(),
|
|
|
|
- stepsPerCell: PD.Numeric(5, { min: 1, max: 20, step: 1 }),
|
|
|
|
|
|
+ controlPoints: PD.LineGraph([
|
|
|
|
+ Vec2.create(0.19, 0.0), Vec2.create(0.2, 0.05), Vec2.create(0.25, 0.05), Vec2.create(0.26, 0.0),
|
|
|
|
+ Vec2.create(0.79, 0.0), Vec2.create(0.8, 0.05), Vec2.create(0.85, 0.05), Vec2.create(0.86, 0.0),
|
|
|
|
+ ], { isEssential: true }),
|
|
|
|
+ stepsPerCell: PD.Numeric(3, { min: 1, max: 10, step: 1 }),
|
|
jumpLength: PD.Numeric(0, { min: 0, max: 20, step: 0.1 }),
|
|
jumpLength: PD.Numeric(0, { min: 0, max: 20, step: 0.1 }),
|
|
};
|
|
};
|
|
export type Params = typeof Params
|
|
export type Params = typeof Params
|
|
@@ -217,13 +191,6 @@ export namespace DirectVolume {
|
|
return LocationIterator(groupCount, instanceCount, 1, getLocation);
|
|
return LocationIterator(groupCount, instanceCount, 1, getLocation);
|
|
}
|
|
}
|
|
|
|
|
|
- function getNormalizedIsoValue(out: Vec2, isoValue: Volume.IsoValue, stats: Vec4) {
|
|
|
|
- const [min, max, mean, sigma] = stats;
|
|
|
|
- const value = Volume.IsoValue.toAbsolute(isoValue, { min, max, mean, sigma }).absoluteValue;
|
|
|
|
- Vec2.set(out, (value - min) / (max - min), (0 - min) / (max - min));
|
|
|
|
- return out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
function getMaxSteps(gridDim: Vec3, stepsPerCell: number) {
|
|
function getMaxSteps(gridDim: Vec3, stepsPerCell: number) {
|
|
return Math.ceil(Vec3.magnitude(gridDim) * stepsPerCell);
|
|
return Math.ceil(Vec3.magnitude(gridDim) * stepsPerCell);
|
|
}
|
|
}
|
|
@@ -256,18 +223,12 @@ export namespace DirectVolume {
|
|
const invariantBoundingSphere = Sphere3D.clone(directVolume.boundingSphere);
|
|
const invariantBoundingSphere = Sphere3D.clone(directVolume.boundingSphere);
|
|
const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount);
|
|
const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount);
|
|
|
|
|
|
- const controlPoints = props.renderMode.name === 'volume' ? getControlPointsFromVec2Array(props.renderMode.params.controlPoints) : [];
|
|
|
|
- const transferTex = createTransferFunctionTexture(controlPoints, props.renderMode.name === 'volume' ? props.renderMode.params.list.colors : []);
|
|
|
|
-
|
|
|
|
- const isoValue = props.renderMode.name === 'isosurface'
|
|
|
|
- ? props.renderMode.params.isoValue
|
|
|
|
- : Volume.IsoValue.relative(2);
|
|
|
|
-
|
|
|
|
- const singleLayer = props.renderMode.name === 'isosurface'
|
|
|
|
- ? props.renderMode.params.singleLayer
|
|
|
|
- : false;
|
|
|
|
|
|
+ const controlPoints = getControlPointsFromVec2Array(props.controlPoints);
|
|
|
|
+ const transferTex = createTransferFunctionTexture(controlPoints);
|
|
|
|
|
|
return {
|
|
return {
|
|
|
|
+ dGeometryType: ValueCell.create('directVolume'),
|
|
|
|
+
|
|
...color,
|
|
...color,
|
|
...marker,
|
|
...marker,
|
|
...overpaint,
|
|
...overpaint,
|
|
@@ -283,7 +244,6 @@ export namespace DirectVolume {
|
|
invariantBoundingSphere: ValueCell.create(invariantBoundingSphere),
|
|
invariantBoundingSphere: ValueCell.create(invariantBoundingSphere),
|
|
uInvariantBoundingSphere: ValueCell.create(Vec4.ofSphere(invariantBoundingSphere)),
|
|
uInvariantBoundingSphere: ValueCell.create(Vec4.ofSphere(invariantBoundingSphere)),
|
|
|
|
|
|
- uIsoValue: ValueCell.create(getNormalizedIsoValue(Vec2(), isoValue, directVolume.gridStats.ref.value)),
|
|
|
|
uBboxMin: bboxMin,
|
|
uBboxMin: bboxMin,
|
|
uBboxMax: bboxMax,
|
|
uBboxMax: bboxMax,
|
|
uBboxSize: bboxSize,
|
|
uBboxSize: bboxSize,
|
|
@@ -292,7 +252,6 @@ export namespace DirectVolume {
|
|
uJumpLength: ValueCell.create(props.jumpLength),
|
|
uJumpLength: ValueCell.create(props.jumpLength),
|
|
uTransform: gridTransform,
|
|
uTransform: gridTransform,
|
|
uGridDim: gridDimension,
|
|
uGridDim: gridDimension,
|
|
- dRenderMode: ValueCell.create(props.renderMode.name),
|
|
|
|
tTransferTex: transferTex,
|
|
tTransferTex: transferTex,
|
|
uTransferScale: ValueCell.create(getTransferScale(props.stepsPerCell)),
|
|
uTransferScale: ValueCell.create(getTransferScale(props.stepsPerCell)),
|
|
|
|
|
|
@@ -305,11 +264,8 @@ export namespace DirectVolume {
|
|
uCartnToUnit: directVolume.cartnToUnit,
|
|
uCartnToUnit: directVolume.cartnToUnit,
|
|
uUnitToCartn: directVolume.unitToCartn,
|
|
uUnitToCartn: directVolume.unitToCartn,
|
|
dPackedGroup: directVolume.packedGroup,
|
|
dPackedGroup: directVolume.packedGroup,
|
|
- dSingleLayer: ValueCell.create(singleLayer),
|
|
|
|
|
|
+ dAxisOrder: ValueCell.create(directVolume.axisOrder.ref.value.join('')),
|
|
|
|
|
|
- uDoubleSided: ValueCell.create(props.doubleSided),
|
|
|
|
- dFlatShaded: ValueCell.create(props.flatShaded),
|
|
|
|
- dFlipSided: ValueCell.create(props.flipSided),
|
|
|
|
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
|
dIgnoreLight: ValueCell.create(props.ignoreLight),
|
|
dXrayShaded: ValueCell.create(props.xrayShaded),
|
|
dXrayShaded: ValueCell.create(props.xrayShaded),
|
|
};
|
|
};
|
|
@@ -323,20 +279,11 @@ export namespace DirectVolume {
|
|
|
|
|
|
function updateValues(values: DirectVolumeValues, props: PD.Values<Params>) {
|
|
function updateValues(values: DirectVolumeValues, props: PD.Values<Params>) {
|
|
BaseGeometry.updateValues(values, props);
|
|
BaseGeometry.updateValues(values, props);
|
|
- ValueCell.updateIfChanged(values.uDoubleSided, props.doubleSided);
|
|
|
|
- ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded);
|
|
|
|
- ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);
|
|
|
|
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
|
ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight);
|
|
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
|
ValueCell.updateIfChanged(values.dXrayShaded, props.xrayShaded);
|
|
- ValueCell.updateIfChanged(values.dRenderMode, props.renderMode.name);
|
|
|
|
-
|
|
|
|
- if (props.renderMode.name === 'isosurface') {
|
|
|
|
- ValueCell.updateIfChanged(values.uIsoValue, getNormalizedIsoValue(values.uIsoValue.ref.value, props.renderMode.params.isoValue, values.uGridStats.ref.value));
|
|
|
|
- ValueCell.updateIfChanged(values.dSingleLayer, props.renderMode.params.singleLayer);
|
|
|
|
- } else if (props.renderMode.name === 'volume') {
|
|
|
|
- const controlPoints = getControlPointsFromVec2Array(props.renderMode.params.controlPoints);
|
|
|
|
- createTransferFunctionTexture(controlPoints, props.renderMode.params.list.colors, values.tTransferTex);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ const controlPoints = getControlPointsFromVec2Array(props.controlPoints);
|
|
|
|
+ createTransferFunctionTexture(controlPoints, values.tTransferTex);
|
|
|
|
|
|
ValueCell.updateIfChanged(values.uMaxSteps, getMaxSteps(values.uGridDim.ref.value, props.stepsPerCell));
|
|
ValueCell.updateIfChanged(values.uMaxSteps, getMaxSteps(values.uGridDim.ref.value, props.stepsPerCell));
|
|
ValueCell.updateIfChanged(values.uStepScale, getStepScale(values.uCellDim.ref.value, props.stepsPerCell));
|
|
ValueCell.updateIfChanged(values.uStepScale, getStepScale(values.uCellDim.ref.value, props.stepsPerCell));
|
|
@@ -360,14 +307,14 @@ export namespace DirectVolume {
|
|
function createRenderableState(props: PD.Values<Params>): RenderableState {
|
|
function createRenderableState(props: PD.Values<Params>): RenderableState {
|
|
const state = BaseGeometry.createRenderableState(props);
|
|
const state = BaseGeometry.createRenderableState(props);
|
|
state.opaque = false;
|
|
state.opaque = false;
|
|
- state.writeDepth = props.renderMode.name === 'isosurface';
|
|
|
|
|
|
+ state.writeDepth = false;
|
|
return state;
|
|
return state;
|
|
}
|
|
}
|
|
|
|
|
|
function updateRenderableState(state: RenderableState, props: PD.Values<Params>) {
|
|
function updateRenderableState(state: RenderableState, props: PD.Values<Params>) {
|
|
BaseGeometry.updateRenderableState(state, props);
|
|
BaseGeometry.updateRenderableState(state, props);
|
|
state.opaque = false;
|
|
state.opaque = false;
|
|
- state.writeDepth = props.renderMode.name === 'isosurface';
|
|
|
|
|
|
+ state.writeDepth = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|