Skip to content

Commit

Permalink
use closest great or equal power f 2 size of x,y dimension of loaded …
Browse files Browse the repository at this point in the history
…volume (render problems on old GPUs)

Additionally:
+ Added error report if load incomplete Dicom folder
+ More accurate integer numbers calc
+ Common loading finalization for different file formats
+ More error reports for Dicom format loader
  • Loading branch information
VladislavShubnikov committed Sep 25, 2018
1 parent 43c0f2c commit 7922bc7
Show file tree
Hide file tree
Showing 15 changed files with 507 additions and 156 deletions.
10 changes: 8 additions & 2 deletions app/scripts/menu.js
Expand Up @@ -255,6 +255,9 @@ export default class Menu {
fillColorBarColorsFromRGB(colors) {
const HEX_BASE = 16;
let r, g, b;
if (colors === null) {
return;
}
for (let i = 0; i < this.colorBarColors.length; ++i) {
r = colors[4 * i].toString(HEX_BASE).padStart(2, '0'); // eslint-disable-line
g = colors[4 * i + 1].toString(HEX_BASE).padStart(2, '0'); // eslint-disable-line
Expand Down Expand Up @@ -453,7 +456,9 @@ export default class Menu {
tf2dValues[i].x = tf2dSlider.x[i + 1];
tf2dValues[i].y = tf2dValues[i].value = tf2dSlider.y[i + 1];
}
this.engine3d.setTransferFuncColors(tf2dSlider.handleColor);
if (tf2dSlider.handleColor !== null) {
this.engine3d.setTransferFuncColors(tf2dSlider.handleColor);
}
const colors = this.engine3d.updateTransferFuncTexture(tf2dValues.map(z => z.x), tf2dValues.map(z => z.value));
this.fillColorBarColorsFromRGB(colors);
this.transFunc2dSlider.flush();
Expand Down Expand Up @@ -956,7 +961,8 @@ export default class Menu {
const volSize = {
x: this.engine2d.m_volumeHeader.m_pixelWidth,
y: this.engine2d.m_volumeHeader.m_pixelHeight,
z: volData.length / this.engine2d.m_volumeHeader.m_pixelWidth / this.engine2d.m_volumeHeader.m_pixelHeight,
z: Math.floor(volData.length / this.engine2d.m_volumeHeader.m_pixelWidth /
this.engine2d.m_volumeHeader.m_pixelHeight),
pixdim1: this.engine2d.m_volumeBox.x / this.engine2d.m_volumeHeader.m_pixelWidth,
pixdim2: this.engine2d.m_volumeBox.y / this.engine2d.m_volumeHeader.m_pixelHeight,
pixdim3: this.engine2d.m_volumeBox.z / this.engine2d.m_volumeHeader.m_pixelDepth,
Expand Down
48 changes: 29 additions & 19 deletions lib/scripts/graphics2d/graphics2d.js
Expand Up @@ -76,6 +76,7 @@ export default class Graphics2d {
this.m_width = width;
this.m_height = height;
this.m_material = null;
this.m_mesh = null;
console.log(`Graphics2d create size = ${width} * ${height}`);

//! Volume data
Expand Down Expand Up @@ -138,7 +139,7 @@ export default class Graphics2d {
new THREE.Vector2(0.0, 0.0),
new THREE.Vector2(1.0, 1.0),
]);
let normal;
const normal = new THREE.Vector3();
THREE.Triangle.getNormal(v0, v1, v2, normal);


Expand Down Expand Up @@ -263,12 +264,13 @@ export default class Graphics2d {
//this.m_gradTool.clear();
//this.m_materialsTex2d.m_uniforms.currentGradient.value = this.m_gradTool.m_gradient;
this.m_contrastBrightTool.clear();
this.m_materialsTex2d.m_uniforms.contrast.value = this.m_contrastBrightTool.m_contrast;
this.m_materialsTex2d.m_uniforms.brightness.value = this.m_contrastBrightTool.m_brightness;
this.m_materialsTex2d.m_uniforms.flag.value = false;
this.m_filterTool.clear();
this.m_materialsTex2d.m_uniforms.sigma.value = this.m_filterTool.m_sigma;
//this.m_materialsTex2d.m_uniforms.sigmaB.value = this.m_filterTool.m_sigmaB;
if (this.m_materialsTex2d !== null) {
this.m_materialsTex2d.m_uniforms.contrast.value = this.m_contrastBrightTool.m_contrast;
this.m_materialsTex2d.m_uniforms.brightness.value = this.m_contrastBrightTool.m_brightness;
this.m_materialsTex2d.m_uniforms.flag.value = false;
this.m_filterTool.clear();
this.m_materialsTex2d.m_uniforms.sigma.value = this.m_filterTool.m_sigma;
}
}

clear2DTools() {
Expand Down Expand Up @@ -1427,6 +1429,11 @@ export default class Graphics2d {
const yDim = this.m_volumeHeader.m_pixelHeight;
const zDim = this.m_volumeHeader.m_pixelDepth;

if (volTexture === null) {
console.log('no vol texture data');
return;
}

// const off = xDim/2 + (yDim/2) * xDim + (zDim/2)*xDim*yDim;
// const valLog = this.m_volumeData[off];
// console.log(`createTileMaps with ${valLog}`);
Expand Down Expand Up @@ -1651,12 +1658,13 @@ export default class Graphics2d {
//this.m_gradTool.clear();
//this.m_materialsTex2d.m_uniforms.currentGradient.value = this.m_gradTool.m_gradient;
this.m_contrastBrightTool.clear();
this.m_materialsTex2d.m_uniforms.contrast.value = this.m_contrastBrightTool.m_contrast;
this.m_materialsTex2d.m_uniforms.brightness.value = this.m_contrastBrightTool.m_brightness;
this.m_materialsTex2d.m_uniforms.flag.value = false;
this.m_filterTool.clear();
this.m_materialsTex2d.m_uniforms.sigma.value = this.m_filterTool.m_sigma;
//this.m_materialsTex2d.m_uniforms.sigmaB.value = this.m_filterTool.m_sigmaB;
if (this.m_materialsTex2d !== null) {
this.m_materialsTex2d.m_uniforms.contrast.value = this.m_contrastBrightTool.m_contrast;
this.m_materialsTex2d.m_uniforms.brightness.value = this.m_contrastBrightTool.m_brightness;
this.m_materialsTex2d.m_uniforms.flag.value = false;
this.m_filterTool.clear();
this.m_materialsTex2d.m_uniforms.sigma.value = this.m_filterTool.m_sigma;
}
}

getSliceAxis() {
Expand Down Expand Up @@ -1694,12 +1702,14 @@ export default class Graphics2d {
* Render something on screen
*/
render() {
this.m_renderer.render(this.m_scene, this.m_camera);
// update text
this.updateText();
// need not update vertices no more
this.m_geometry.verticesNeedUpdate = false;
this.m_geometry.uvsNeedUpdate = false;
if (this.m_mesh !== null) {
this.m_renderer.render(this.m_scene, this.m_camera);
// update text
this.updateText();
// need not update vertices no more
this.m_geometry.verticesNeedUpdate = false;
this.m_geometry.uvsNeedUpdate = false;
} // if mesh exists
} // render
} // class Graphics2d

Expand Down
2 changes: 1 addition & 1 deletion lib/scripts/graphics2d/meshtext2d.js
Expand Up @@ -169,7 +169,7 @@ export default class MeshText2D extends Text2D {
new THREE.Vector2(0.0, 1.0),
new THREE.Vector2(X_TEXT_COORD_MAX, 1.0 - Y_TEXT_COORD_MAX),
]);
let normal;
const normal = new THREE.Vector3();
THREE.Triangle.getNormal(v0, v1, v2, normal);

// eslint-disable-next-line
Expand Down
2 changes: 1 addition & 1 deletion lib/scripts/graphics2d/mprrenderer.js
Expand Up @@ -249,7 +249,7 @@ export default class MprRenderer {
new THREE.Vector2(0.0, 0.0),
new THREE.Vector2(1.0, 1.0),
];
let normal;
const normal = new THREE.Vector3();
THREE.Triangle.getNormal(v0, v1, v2, normal);


Expand Down
62 changes: 37 additions & 25 deletions lib/scripts/graphics3d/graphics3d.js
Expand Up @@ -631,44 +631,47 @@ export default class Graphics3d {

const VAL_3 = 3;
const HALF = 0.5;
const OFF_0 = 0;
const OFF_1 = 1;
const OFF_2 = 2;

const max = this.geometry.boundingBox.max;
const min = this.geometry.boundingBox.min;
if ((nonEmptyBoxMin.x < 0.0) || (nonEmptyBoxMin.x < 0.0) || (nonEmptyBoxMin.z < 0.0)) {
const v = nonEmptyBoxMin;
console.log(`invalid non empty box min = ${v.x}, ${v.y}, ${v.z}`);
}
if ((nonEmptyBoxMax.x > 1.0) || (nonEmptyBoxMax.x > 1.0) || (nonEmptyBoxMax.z > 1.0)) {
const v = nonEmptyBoxMax;
console.log(`invalid non empty box max = ${v.x}, ${v.y}, ${v.z}`);
}
const offset = new THREE.Vector3(0 - min.x, 0 - min.y, 0 - min.z);
const range = new THREE.Vector3(max.x - min.x, max.y - min.y, max.z - min.z);
const uvw = new Float32Array(this.geometry.getAttribute('position').count * VAL_3);
this.geo_offset1 = new THREE.Vector3(0, 0, 0);
this.geo_offset1 = offset;
this.geo_offset2 = new THREE.Vector3(0, 0, 0);
this.geo_offset2.x = nonEmptyBoxMin.x + HALF;
this.geo_offset2.x = nonEmptyBoxMin.x - HALF;
this.geo_offset2.y = nonEmptyBoxMin.y - HALF;
this.geo_offset2.z = nonEmptyBoxMin.z - HALF;
this.geo_scale = new THREE.Vector3(0, 0, 0);
this.geo_scale.x = (nonEmptyBoxMax.x - nonEmptyBoxMin.x) / range.x;
this.geo_scale.y = (nonEmptyBoxMax.y - nonEmptyBoxMin.y) / range.y;
this.geo_scale.z = (nonEmptyBoxMax.z - nonEmptyBoxMin.z) / range.z;

for (let i = 0; i < this.geometry.getAttribute('position').count; i++) {
const vx = this.geometry.getAttribute('position').getX(i);
const vy = this.geometry.getAttribute('position').getY(i);
const vz = this.geometry.getAttribute('position').getZ(i);
// eslint-disable-next-line
uvw[i * VAL_3 + 0] = -(vx + this.geo_offset1.x) * this.geo_scale.x + this.geo_offset2.x;
// eslint-disable-next-line
uvw[i * VAL_3 + 1] = (vy + this.geo_offset1.y) * this.geo_scale.y + this.geo_offset2.y;
// eslint-disable-next-line
uvw[i * VAL_3 + 2] = (vz + this.geo_offset1.z) * this.geo_scale.z + this.geo_offset2.z;
uvw[i * VAL_3 + OFF_0] = -(vx + this.geo_offset1.x) * this.geo_scale.x - this.geo_offset2.x;
uvw[i * VAL_3 + OFF_1] = +(vy + this.geo_offset1.y) * this.geo_scale.y + this.geo_offset2.y;
uvw[i * VAL_3 + OFF_2] = +(vz + this.geo_offset1.z) * this.geo_scale.z + this.geo_offset2.z;
/*
uvw[i * VAL_3 + 0] = -vx;
// eslint-disable-next-line
uvw[i * VAL_3 + 1] = vy;
// eslint-disable-next-line
uvw[i * VAL_3 + 2] = vz;
uvw[i * VAL_3 + 0] = -(vx + offset.x) * (nonEmptyBoxMax.x - nonEmptyBoxMin.x) / range.x + nonEmptyBoxMin.x + HALF;
// eslint-disable-next-line
uvw[i * VAL_3 + 1] = (vy + offset.y) * (nonEmptyBoxMax.y - nonEmptyBoxMin.y) / range.y + nonEmptyBoxMin.y - HALF;
// eslint-disable-next-line
uvw[i * VAL_3 + 2] = (vz + offset.z) * (nonEmptyBoxMax.z - nonEmptyBoxMin.z) / range.z + nonEmptyBoxMin.z - HALF;
*/
}
Expand All @@ -681,6 +684,9 @@ export default class Graphics3d {

const VAL_3 = 3;
const HALF = 0.5;
const OFF_0 = 0;
const OFF_1 = 1;
const OFF_2 = 2;

const max = this.geometrySphere.boundingBox.max;
const min = this.geometrySphere.boundingBox.min;
Expand All @@ -703,11 +709,11 @@ export default class Graphics3d {
const vy = this.geometrySphere.getAttribute('position').getY(i);
const vz = this.geometrySphere.getAttribute('position').getZ(i);
// eslint-disable-next-line
uvw[i * VAL_3 + 0] = vx;//-(vx + this.geo_offset1.x) * this.geo_scale.x + this.geo_offset2.x;
uvw[i * VAL_3 + OFF_0] = vx;//-(vx + this.geo_offset1.x) * this.geo_scale.x + this.geo_offset2.x;
// eslint-disable-next-line
uvw[i * VAL_3 + 1] = vy;//(vy + this.geo_offset1.y) * this.geo_scale.y + this.geo_offset2.y;
uvw[i * VAL_3 + OFF_1] = vy;//(vy + this.geo_offset1.y) * this.geo_scale.y + this.geo_offset2.y;
// eslint-disable-next-line
uvw[i * VAL_3 + 2] = vz;//(vz + this.geo_offset1.z) * this.geo_scale.z + this.geo_offset2.z;
uvw[i * VAL_3 + OFF_2] = vz;//(vz + this.geo_offset1.z) * this.geo_scale.z + this.geo_offset2.z;
/*
uvw[i * VAL_3 + 0] = -vx;
// eslint-disable-next-line
Expand All @@ -726,7 +732,6 @@ export default class Graphics3d {
this.geometrySphere.getAttribute('uvw').needsUpdate = true;
}


/*
createTetraGeometry() {
const genTetra = new TetrahedronGenerator();
Expand Down Expand Up @@ -776,6 +781,9 @@ export default class Graphics3d {
}
updateClipPlaneGeometry() {
const VAL_3 = 3;
const OFF_0 = 0;
const OFF_1 = 1;
const OFF_2 = 2;
const uvw = new Float32Array(this.planeGeometry.getAttribute('position').count * VAL_3);
const l2w = new THREE.Matrix4();
l2w.getInverse(this.mesh.matrix);
Expand All @@ -792,11 +800,9 @@ export default class Graphics3d {
v.applyMatrix4(invPerspective);
v.applyMatrix4(invView);
v.applyMatrix4(l2w);
uvw[i * VAL_3 + 0] = -(v.x + this.geo_offset1.x) * this.geo_scale.x + this.geo_offset2.x;
// eslint-disable-next-line
uvw[i * VAL_3 + 1] = (v.y + this.geo_offset1.y) * this.geo_scale.y + this.geo_offset2.y;
// eslint-disable-next-line
uvw[i * VAL_3 + 2] = (v.z + this.geo_offset1.z) * this.geo_scale.z + this.geo_offset2.z;
uvw[i * VAL_3 + OFF_0] = -(v.x + this.geo_offset1.x) * this.geo_scale.x + this.geo_offset2.x;
uvw[i * VAL_3 + OFF_1] = (v.y + this.geo_offset1.y) * this.geo_scale.y + this.geo_offset2.y;
uvw[i * VAL_3 + OFF_2] = (v.z + this.geo_offset1.z) * this.geo_scale.z + this.geo_offset2.z;
/*
// eslint-disable-next-line
uvw[i * VAL_3 + 0] = -v.x;
Expand Down Expand Up @@ -898,6 +904,9 @@ export default class Graphics3d {
}
this.volumeUpdater = new VolumeFilter3D();
this.engine2d.volumeUpdater = this.volumeUpdater;
// !!!!!!!!!!!!!! TEST !!!!!!!!!!!
// Do not create texture
// return;

this.volTexture = this.volumeUpdater.createUpdatableVolumeTex(this.engine2d, isRoiVolume, this.roiPalette);
if (this.origVolumeTex) {
Expand All @@ -910,7 +919,6 @@ export default class Graphics3d {
this.texVolumeAO.dispose();
}
this.texVolumeAO = this.volumeUpdater.gettexVolumeAO();

if (this.renderer.getContext().getExtension('OES_texture_float')) {
if (this.bfTexture) {
this.bfTexture.dispose();
Expand Down Expand Up @@ -990,7 +998,6 @@ export default class Graphics3d {
console.log(`startRot = ${this.curFileDataType.startRotX} ${this.curFileDataType.startRotY}`);
this.orbitControl.setMesh(this.mesh);


// Create material for volume render to texture
const offsets = [];
const nOffs = 64;
Expand Down Expand Up @@ -1101,7 +1108,9 @@ export default class Graphics3d {
* @param ctrlPts Array of control points of type HEX = color value
*/
setTransferFuncColors(ctrlPtsColorsHex) {
this.volumeUpdater.setTransferFuncColors(ctrlPtsColorsHex);
if ((this.volumeUpdater !== null) && (ctrlPtsColorsHex !== null)) {
this.volumeUpdater.setTransferFuncColors(ctrlPtsColorsHex);
}
}

/**
Expand All @@ -1110,7 +1119,10 @@ export default class Graphics3d {
* //intensity [0,255] opacity [0,1]
*/
updateTransferFuncTexture(intensities, opacities) {
return this.volumeUpdater.updateTransferFuncTexture(intensities, opacities);
if (this.volumeUpdater !== null) {
return this.volumeUpdater.updateTransferFuncTexture(intensities, opacities);
}
return null;
}

/**
Expand Down
37 changes: 36 additions & 1 deletion lib/scripts/graphics3d/volumeFilter3d.js
Expand Up @@ -28,6 +28,28 @@ import MaterialAO from '../gfx/matAO';

/** Class Graphics3d is used for 3d render */
export default class VolumeFilter3d {
constructor() {
this.sceneBlur = null;
this.material = null;
this.cameraOrtho = null;
this.rendererBlur = null;
this.selectedROIs = null;
this.numTfPixels = 0;
this.transferFuncRgba = null;
this.texRoiColor = null;
this.texRoiId = null;
this.lastSize = [];
this.lastDepth = [];
this.lastRotationVector = [];
this.lastTarget = [];
this.lastBackDistance = [];
this.resetflag = false;
this.sceneAO = null;
this.rendererAO = null;
this.vectors = null;
this.vectorsTex = null;
this.texVolumeAO = null;
}

/**
* Filtering the source data and building the normals on the GPU
Expand Down Expand Up @@ -103,6 +125,12 @@ export default class VolumeFilter3d {
this.vectorsTex.magFilter = THREE.NearestFilter;
this.vectorsTex.minFilter = THREE.NearestFilter;
this.vectorsTex.needsUpdate = true;
if (!Number.isInteger(this.xTex)) {
console.log(`!!! Non-integer array size = ${this.xTex}`);
}
if (!Number.isInteger(this.yTex)) {
console.log(`!!! Non-integer array size = ${this.yTex}`);
}

this.bufferTextureAO = new Uint8Array(this.xTex * this.yTex);
for (let y = 0; y < this.yTex; y++) {
Expand Down Expand Up @@ -224,6 +252,9 @@ export default class VolumeFilter3d {
* //intensity [0,255] opacity [0,1]
*/
updateTransferFuncTexture(intensities, opacities) {
if (this.transferFuncRgba === null) {
return null;
}
for (let curPt = 0; curPt < intensities.length - 1; curPt++) {
const pixStart = Math.floor(intensities[curPt]);
const pixEnd = Math.floor(intensities[curPt + 1]);
Expand Down Expand Up @@ -778,6 +809,9 @@ export default class VolumeFilter3d {
const TWO = 2;
const ONE = 1;
const zDimSqrt = TWO ** (ONE + Math.floor(Math.log(Math.sqrt(zDim)) / Math.log(TWO)));
if (!Number.isInteger(zDimSqrt)) {
console.log(`!!! zDimSqrt should be integer, but = ${zDimSqrt}`);
}
const xTex = xDim * zDimSqrt;
const yTex = yDim * zDimSqrt;
const numPixelsBuffer = xTex * yTex;
Expand Down Expand Up @@ -863,8 +897,9 @@ export default class VolumeFilter3d {
const numPixelsBuffer = xTex * yTex;
this.bufferMask = new Uint8Array(numPixelsBuffer);
for (let y = 0; y < yTex; y++) {
const yOff = y * xTex;
for (let x = 0; x < xTex; x++) {
this.bufferMask[x + y * xTex] = 255.0;
this.bufferMask[x + yOff] = 255;
}
}
if (this.updatableTextureMask) {
Expand Down

0 comments on commit 7922bc7

Please sign in to comment.