diff --git a/docs/source/conf.py b/docs/source/conf.py index d18e5c2..ac03567 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ author = 'LinkunGao' # The full version, including alpha/beta/rc tags -release = 'v1.13.12' +release = 'v1.13.13' # -- General configuration --------------------------------------------------- diff --git a/docs/source/release/release.md b/docs/source/release/release.md index 1b29d9d..28367b5 100644 --- a/docs/source/release/release.md +++ b/docs/source/release/release.md @@ -1334,3 +1334,79 @@ const resetMainAreaSize = (factor: number) => { ## Release v1.13.12 - Fixed gui repeat issue + + ## Release v1.13.13 - version for Nuxt - heart app + + - removed Gltf exporter, because it cannot be build in Nuxt app. + - Update the vtkloader + + - modified the opts, now we can customise the material `wireframe`, `color`, `transparent`, and `opacity`. + ```ts + scene?.loadVtks([ + { + name: "heart_inner", + urls, + opts: { wireframe: true, color: "#cccccc" }, + }, + { + name: "heart_outer", + urls: urls_1, + opts: { + wireframe: false, + color: "rgb(214, 211, 212)", + transparent: true, + opacity: 0.5, + }, + }, + ]); + ``` + - types + ```ts + interface IOptVTKLoader { + wireframe?: boolean; + color?: string | number; + transparent?: boolean; + opacity?: number; + } + ``` + + - Update the dicom loader + - we can use `getMesh`, `getCopperVolume` in copperSence.loadDicom() opts. + ```ts + scene.loadDicom(urls, { + gui, + getMesh(mesh) { + console.log(mesh); + }, + getCopperVolume(copperVolume, updateTexture) { + copperVolume.windowWidth = 424; + copperVolume.windowCenter = 236; + updateTexture(copperVolume); + }, + setAnimation(currentValue, depth, depthStep, copperVolume) { + currentValue += depthStep; + if (currentValue > depth) { + currentValue = 0; + } + return currentValue; + }, + }); + ``` + - optsType: + ```ts + interface dicomLoaderOptsType { + gui?: GUI; + getMesh?: (mesh: THREE.Mesh) => void; + getCopperVolume?: ( + copperVolume: copperVolumeType, + updateTexture: Function + ) => void; + setAnimation?: ( + currentValue: number, + depth: number, + depthStep: number, + copperVolume: copperVolumeType + ) => number; + } + ``` + - We can in getCopperVolume() function to update the volume windowWidth and windowCenter diff --git a/package-lock.json b/package-lock.json index 1f5444a..d917595 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "copper3d_visualisation", - "version": "1.13.12", + "version": "1.13.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "copper3d_visualisation", - "version": "1.13.12", + "version": "1.13.13", "license": "Apache-2.0", "dependencies": { "@types/dat.gui": "^0.7.7", diff --git a/package.json b/package.json index 19c5c06..565bd0c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "copper3d_visualisation", "description": "A 3d visualisation package base on threejs provides multiple scenes and Nrrd image load funtion.", - "version": "1.13.12", + "version": "1.13.13", "main": "dist/bundle.umd.js", "moudle": "dist/bundle.esm.js", "types": "dist/types/index.d.ts", diff --git a/src/Loader/copperVtkLoader.ts b/src/Loader/copperVtkLoader.ts index efe6efc..21896f1 100644 --- a/src/Loader/copperVtkLoader.ts +++ b/src/Loader/copperVtkLoader.ts @@ -1,21 +1,28 @@ import { VTKLoader } from "three/examples/jsm/loaders/VTKLoader.js"; import * as THREE from "three"; +import { IOptVTKLoader } from "../types/types"; const vtkLoader = new VTKLoader(); -const vtkmaterial = new THREE.MeshStandardMaterial({ +const materialConfig = { wireframe: false, side: THREE.DoubleSide, color: 0xfff000, -}); +}; + export function copperVtkLoader( url: string, scene: THREE.Scene, - content: THREE.Group + content: THREE.Group, + opts?: IOptVTKLoader ) { vtkLoader.load(url, function (geometry) { geometry.center(); geometry.computeVertexNormals(); + const vtkmaterial = new THREE.MeshStandardMaterial(materialConfig); + if (opts) { + configOpts(vtkmaterial, opts); + } const mesh = new THREE.Mesh(geometry, vtkmaterial); mesh.scale.multiplyScalar(0.1); @@ -25,6 +32,28 @@ export function copperVtkLoader( }); } -export function copperMultipleVtk() { +export function copperMultipleVtk(opts?: IOptVTKLoader) { + const vtkmaterial = new THREE.MeshStandardMaterial(materialConfig); + if (opts) { + configOpts(vtkmaterial, opts); + } return { vtkLoader, vtkmaterial }; } + +function configOpts( + vtkmaterial: THREE.MeshStandardMaterial, + opts: IOptVTKLoader +) { + if (opts.wireframe) { + vtkmaterial.wireframe = opts.wireframe; + } + if (opts.color) { + vtkmaterial.color.set(opts.color); + } + if (opts.transparent) { + vtkmaterial.transparent = opts.transparent; + } + if (opts.opacity) { + vtkmaterial.opacity = opts.opacity; + } +} diff --git a/src/Renderer/baseRenderer.ts b/src/Renderer/baseRenderer.ts index bc00126..f02d903 100644 --- a/src/Renderer/baseRenderer.ts +++ b/src/Renderer/baseRenderer.ts @@ -5,7 +5,7 @@ import { environments, environmentType } from "../lib/environment/index"; import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader"; import Stats from "three/examples/jsm/libs/stats.module"; import { GUI, GUIController } from "dat.gui"; -import ExportGltf from "../Utils/gltfExporter"; + import { optType, stateType, modelVisualisationDataType } from "../types/types"; export default class baseRenderer { @@ -24,7 +24,6 @@ export default class baseRenderer { private visualiseFolder: GUI | null; private visualCtrls: Array = []; private cameraFolder: GUI | null; - private exporter: ExportGltf | null = null; constructor(container: HTMLDivElement, options?: optType) { this.container = container; @@ -57,14 +56,6 @@ export default class baseRenderer { directColor: 0xffffff, bgColor1: "#5454ad", bgColor2: "#18e5a7", - exportGltf: () => { - if (!this.exporter) { - this.exporter = new ExportGltf({ - animations: this.currentScene.exportContent.animations, - }); - } - this.exporter.export(this.currentScene.exportContent); - }, }; this.visualiseFolder = null; this.cameraFolder = null; diff --git a/src/Scene/commonSceneMethod.ts b/src/Scene/commonSceneMethod.ts index 2d7b877..318c708 100644 --- a/src/Scene/commonSceneMethod.ts +++ b/src/Scene/commonSceneMethod.ts @@ -195,14 +195,21 @@ export default class commonScene { const finishLoad = (copperVolume: copperVolumeType) => { if (gui) gui.add(this, "depthStep").min(0.01).max(1).step(0.01); - const texture2dMesh = createTexture2D_Array( + const texture2d = createTexture2D_Array( copperVolume, depth, this.scene as THREE.Scene, gui ); - let value = (texture2dMesh.material as any).uniforms["depth"].value; + if (opts?.getMesh) { + opts.getMesh(texture2d.mesh); + } + if (opts?.getCopperVolume) { + opts.getCopperVolume(texture2d.copperVolume, texture2d.updateTexture); + } + + let value = (texture2d.mesh.material as any).uniforms["depth"].value; const render_texture2d = () => { // if (value > depth) { @@ -211,8 +218,16 @@ export default class commonScene { // eval( // "value += this.depthStep;if (value > depth) {value = 0;}" // ); + + // console.log(copperVolume); + if (opts?.setAnimation) { - value = opts.setAnimation(value, depth, this.depthStep); + value = opts.setAnimation( + value, + depth, + this.depthStep, + copperVolume + ); } else { value += this.depthStep; if (value > depth || value < 0.0) { @@ -222,7 +237,7 @@ export default class commonScene { } } - (texture2dMesh.material as any).uniforms["depth"].value = value; + (texture2d.mesh.material as any).uniforms["depth"].value = value; }; this.addPreRenderCallbackFunction(render_texture2d); }; diff --git a/src/Scene/copperScene.ts b/src/Scene/copperScene.ts index 8b804df..5768613 100644 --- a/src/Scene/copperScene.ts +++ b/src/Scene/copperScene.ts @@ -98,7 +98,8 @@ export default class copperScene extends baseScene { loadVtks(models: Array) { let count = 0; - const { vtkLoader, vtkmaterial } = copperMultipleVtk(); + let { vtkLoader } = copperMultipleVtk(); + const group = new THREE.Group(); const finishInterval = setInterval(() => { @@ -148,6 +149,7 @@ export default class copperScene extends baseScene { geometries: Array, model: vtkModels ) => { + let { vtkmaterial } = copperMultipleVtk(model.opts); let geometry = geometries[0]; geometries.forEach((child, index) => { if (index === 0) { diff --git a/src/Utils/gltfExporter.ts b/src/Utils/gltfExporter.ts deleted file mode 100644 index b8b5b0b..0000000 --- a/src/Utils/gltfExporter.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter"; -import { optionsGltfExporterType } from "../types/types"; - -export default class ExportGltf { - private gltfExporter: GLTFExporter = new GLTFExporter(); - private options: optionsGltfExporterType = { - trs: false, - onlyVisible: true, - truncateDrawRange: true, - binary: false, - maxTextureSize: 40960000000, - animations: [], - }; - private link: HTMLAnchorElement; - - constructor(opts: optionsGltfExporterType) { - Object.assign(this.options, opts); - this.link = document.createElement("a"); - this.link.style.display = "none"; - document.body.appendChild(this.link); - } - - export(input: any) { - const name: string = input.name ? input.name : "export"; - this.gltfExporter.parse( - input, - (result) => { - if (result instanceof ArrayBuffer) { - this.saveArrayBuffer(result, name + ".glb"); - } else { - const output = JSON.stringify(result, null, 2); - this.saveString(output, name + ".gltf"); - } - }, - function (error) { - console.log("An error happened during parsing", error); - }, - this.options - ); - } - - save(blob: Blob, fileName: string) { - this.link.href = URL.createObjectURL(blob); - this.link.download = fileName; - this.link.click(); - } - saveString(text: string, fileName: string) { - this.save(new Blob([text], { type: "text/plain" }), fileName); - } - saveArrayBuffer(buffer: ArrayBuffer, fileName: string) { - this.save( - new Blob([buffer], { type: "application/octet-stream" }), - fileName - ); - } -} diff --git a/src/Utils/texture2d.ts b/src/Utils/texture2d.ts index fc1fb39..539253f 100644 --- a/src/Utils/texture2d.ts +++ b/src/Utils/texture2d.ts @@ -45,7 +45,7 @@ export function createTexture2D_Array( depth: number, scene: THREE.Scene, gui?: GUI -): THREE.Mesh { +) { planeWidth = copperVolume.width / 2; planeHeight = copperVolume.height / 2; @@ -64,20 +64,22 @@ export function createTexture2D_Array( texture.needsUpdate = true; if (gui) { gui - .add(state, "windowWidth") + .add(copperVolume, "windowWidth") .min(1) .max(copperVolume.windowWidth * 2) .step(1) - .onChange(() => { - updateTexture(); + .onChange((value) => { + copperVolume.windowWidth = value; + updateTexture(copperVolume); }); gui - .add(state, "windowCenter") + .add(copperVolume, "windowCenter") .min(1) .max(copperVolume.windowCenter * 2) .step(1) - .onChange(() => { - updateTexture(); + .onChange((value) => { + copperVolume.windowCenter = value; + updateTexture(copperVolume); }); } @@ -99,20 +101,22 @@ export function createTexture2D_Array( scene.add(mesh); mesh.name = "texture2d_mesh_array"; - function updateTexture() { - let voiLUT; - let lut = getLut( - copperVolume.uint16, - state.windowWidth, - state.windowCenter, - copperVolume.invert, - voiLUT - ); - for (let i = 0, len = copperVolume.uint16.length; i < len; i++) { - copperVolume.uint8[i] = lut.lutArray[copperVolume.uint16[i]]; + function updateTexture(copperVolumeUp: copperVolumeType) { + if (!!copperVolumeUp) { + let voiLUT; + let lut = getLut( + copperVolumeUp.uint16, + copperVolumeUp.windowWidth, + copperVolumeUp.windowCenter, + copperVolumeUp.invert, + voiLUT + ); + for (let i = 0, len = copperVolumeUp.uint16.length; i < len; i++) { + copperVolumeUp.uint8[i] = lut.lutArray[copperVolumeUp.uint16[i]]; + } + texture.needsUpdate = true; } - texture.needsUpdate = true; } - return mesh; + return { mesh, copperVolume, updateTexture }; } diff --git a/src/index.ts b/src/index.ts index 58e21a8..361e434 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,14 +31,15 @@ import { loadingBarType, paintImageType, exportPaintImageType, + IOptVTKLoader, } from "./types/types"; import "./css/style.css"; -export const REVISION = "v1.13.12"; +export const REVISION = "v1.13.13"; console.log( - "%cCopper3D Visualisation %cBeta:v1.13.12", + "%cCopper3D Visualisation %cBeta:v1.13.13", "padding: 3px;color:white; background:#023047", "padding: 3px;color:white; background:#f50a25" ); @@ -75,4 +76,5 @@ export type { loadingBarType, paintImageType, exportPaintImageType, + IOptVTKLoader, }; diff --git a/src/types/types.ts b/src/types/types.ts index ef29779..40bb34a 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -185,6 +185,7 @@ interface optionsGltfExporterType { interface vtkModels { name: string; urls: Array; + opts?: IOptVTKLoader; } interface undoType { @@ -207,10 +208,15 @@ interface copperVolumeType { interface dicomLoaderOptsType { gui?: GUI; getMesh?: (mesh: THREE.Mesh) => void; + getCopperVolume?: ( + copperVolume: copperVolumeType, + updateTexture: Function + ) => void; setAnimation?: ( currentValue: number, depth: number, - depthStep: number + depthStep: number, + copperVolume: copperVolumeType ) => number; } @@ -218,6 +224,13 @@ interface skipSlicesDictType { [key: string]: any; } +interface IOptVTKLoader { + wireframe?: boolean; + color?: string | number; + transparent?: boolean; + opacity?: number; +} + export type { SceneMapType, optType, @@ -247,4 +260,5 @@ export type { skipSlicesDictType, exportPaintImagesType, exportPaintImageType, + IOptVTKLoader, };