├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── document-request.md │ └── feature_request.md ├── labeler.yml ├── pr-branch-labeler.yml ├── pull_request_template.md ├── release.yml └── workflows │ ├── deploy-api-docs.yaml │ ├── labeler.yaml │ └── npm-publish.yml ├── .gitignore ├── .readthedocs.yaml ├── LICENSE ├── README.md ├── apidocs ├── .vitepress │ └── config.js ├── apidocConfig.json ├── crawlerConfig.json ├── index.md ├── package-lock.json ├── package.json ├── typedoc.js └── typedoc.json ├── docs ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── Intro │ └── index.md │ ├── _static │ ├── abi-vrw-rgb.png │ ├── css │ │ └── theme_overrides.css │ ├── images │ │ ├── f_06.png │ │ ├── intro_01.jpg │ │ ├── release_1.3.4_show_hide.gif │ │ ├── release_1_11_1.jpg │ │ ├── t_07.jpg │ │ ├── t_09.jpg │ │ ├── t_11.jpg │ │ ├── t_11_1.gif │ │ ├── t_12.gif │ │ ├── t_13.jpg │ │ ├── t_14.jpg │ │ ├── t_15.png │ │ └── transfer_function │ │ │ ├── 1 │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.001.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.002.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.003.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.004.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.005.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.006.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.007.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.008.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.009.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.010.png │ │ │ ├── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.011.png │ │ │ └── Aspose.Words.fa8b7deb-afbc-4380-bace-f2d6706ba597.012.png │ │ │ ├── 2 │ │ │ ├── Aspose.Words.19819821-06c3-4585-8590-fea343ac9b62.001.png │ │ │ ├── Aspose.Words.19819821-06c3-4585-8590-fea343ac9b62.002.png │ │ │ ├── Aspose.Words.19819821-06c3-4585-8590-fea343ac9b62.003.png │ │ │ ├── Aspose.Words.19819821-06c3-4585-8590-fea343ac9b62.004.png │ │ │ ├── Aspose.Words.19819821-06c3-4585-8590-fea343ac9b62.005.png │ │ │ ├── Aspose.Words.19819821-06c3-4585-8590-fea343ac9b62.006.png │ │ │ └── Aspose.Words.19819821-06c3-4585-8590-fea343ac9b62.007.png │ │ │ └── 3 │ │ │ ├── Aspose.Words.c8e250d2-d3b1-4695-bbb1-2039471f26e8.001.png │ │ │ ├── Aspose.Words.c8e250d2-d3b1-4695-bbb1-2039471f26e8.002.png │ │ │ ├── Aspose.Words.c8e250d2-d3b1-4695-bbb1-2039471f26e8.003.png │ │ │ ├── Aspose.Words.c8e250d2-d3b1-4695-bbb1-2039471f26e8.004.png │ │ │ ├── Aspose.Words.c8e250d2-d3b1-4695-bbb1-2039471f26e8.005.png │ │ │ ├── Aspose.Words.c8e250d2-d3b1-4695-bbb1-2039471f26e8.006.png │ │ │ └── Aspose.Words.c8e250d2-d3b1-4695-bbb1-2039471f26e8.007.png │ └── video │ │ ├── 2d dynamic demo.mp4 │ │ └── drawing_demo.mp4 │ ├── acknowledgements │ └── index.md │ ├── api │ └── index.rst │ ├── conf.py │ ├── examples │ └── index.md │ ├── features │ ├── 01_showModel.md │ ├── 02_exportGltf.md │ ├── 03_nrrdloader.md │ ├── 04_kiwrious.md │ ├── 05_animation.md │ ├── 06_nrrd_tools.md │ ├── 07_nrrd_transfer_function.md │ ├── 08_transfer_large_file.md │ └── index.rst │ ├── index.rst │ ├── release │ ├── index.rst │ └── release.md │ └── tutorial │ ├── 01_loadGltf.md │ ├── 02_pickModel.md │ ├── 03_shareView.md │ ├── 04_resetView.md │ ├── 05_convertPos.md │ ├── 06_addLabel.md │ ├── 07_loadNrrd.md │ ├── 08_renderOnDemond.md │ ├── 09_multipleScene.md │ ├── 10_kiwriousHeart.md │ ├── 10_kiwriousInNuxtjs.rst │ ├── 11_dragAndResetNrrd.md │ ├── 12_drawOnNrrdSlice.md │ ├── 13_newDrawingFunction.md │ ├── 14_drawContrastWithMain.md │ ├── 15_drawContrastInMainArea.md │ ├── 16_loadMultipleVtks.md │ ├── 17_texture2d_heartmodel.md │ ├── 18_texture2d_nrrd_sharder.md │ ├── index.rst │ └── kiwrious │ ├── libunicorn.out.wasm │ └── prog.bin ├── index.d.ts ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── Controls │ ├── Copper3dTrackballControls.ts │ └── copperControls.ts ├── Loader │ ├── copperDicomLoader.ts │ ├── copperGltfLoader.ts │ ├── copperNrrdLoader.ts │ ├── copperOBJLoader.ts │ └── copperVtkLoader.ts ├── Renderer │ ├── baseRenderer.ts │ ├── copperMSceneRenderer.ts │ ├── copperRenderer.ts │ └── copperRendererOnDemond.ts ├── Scene │ ├── baseScene.ts │ ├── commonSceneMethod.ts │ ├── copperMScene.ts │ ├── copperScene.ts │ └── copperSceneOnDemond.ts ├── Utils │ ├── MeshNodeTool.ts │ ├── add3DLabel.ts │ ├── convet.ts │ ├── download.ts │ ├── getVOILUT.ts │ ├── kiwrious │ │ └── configKiwrious.ts │ ├── raycaster.ts │ ├── segmentation │ │ ├── CommToolsData.ts │ │ ├── DragOperator.ts │ │ ├── DrawToolCore.ts │ │ ├── NrrdTools.ts │ │ └── coreTools │ │ │ ├── archive.ts │ │ │ ├── coreType.ts │ │ │ ├── divControlTools.ts │ │ │ └── gui.ts │ ├── texture2d.ts │ ├── utils.ts │ └── workers │ │ └── reformatSaveDataWorker.ts ├── css │ ├── images │ │ ├── cm_gray.png │ │ ├── cm_viridis.png │ │ └── decal_texture │ │ │ ├── LICENSE.TXT │ │ │ ├── decal-diffuse.png │ │ │ └── decal-normal.jpg │ └── style.css ├── index.ts ├── lib │ ├── dicom_pharser_dictionary.ts │ ├── environment │ │ ├── footprint_court_2k.hdr │ │ ├── index.ts │ │ └── venice_sunset_1k.hdr │ ├── shader │ │ ├── texture2d_frag.glsl │ │ └── texture2d_vertex.glsl │ ├── three-vignette.frag │ ├── three-vignette.ts │ └── three-vignette.vert └── types │ └── types.ts └── tsconfig.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 🪲 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Description 11 | A clear and concise description of what the bug is. 12 | 13 | ## Steps to Reproduce 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | ## Expected behavior 21 | A clear and concise description of what you expected to happen. 22 | 23 | ## Screenshots 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | ## Environment details: 27 | - OS: [e.g. Ubuntu 20.04] 28 | - Python version: [e.g. 3.9.12] 29 | 30 | ## Additional context 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/document-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Document request 📖 3 | about: Suggest any missing documentations you will love to see 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Area missing in documentation 11 | A clear and concise description of what the part of the documentation is missing 12 | 13 | ## Version details 14 | The version of sparc-me you are using 15 | 16 | ## Additional context 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 🛠️ 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Problem 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | ## Suggested solution(s) 14 | A clear and concise description of what you want to happen. 15 | 16 | ## Alternatives you have considered 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | ## Additional context 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | "@documentation": 2 | - docs/source/**/* 3 | "@controls": 4 | - src/Controls/**/* 5 | "@core": 6 | - src/core/**/* 7 | "@css": 8 | - src/css/**/* 9 | "@lib": 10 | - src/lib/**/* 11 | "@loader": 12 | - src/Loader/**/* 13 | "@copperDicomLoader": 14 | - src/Loader/copperDicomLoader.ts 15 | "@copperGltfLoader": 16 | - src/Loader/copperGltfLoader.ts 17 | "@copperNrrdLoader": 18 | - src/Loader/copperNrrdLoader.ts 19 | "@copperOBJLoader": 20 | - src/Loader/copperOBJLoader.ts 21 | "@copperVtkLoader": 22 | - src/Loader/copperVtkLoader.ts 23 | "@renderer": 24 | - src/Renderer/**/* 25 | "@scene": 26 | - src/Scene/**/* 27 | "@utils": 28 | - src/Utils/**/* 29 | "@Utils/nrrd_tools": 30 | - src/Utils/nrrd_tools.ts 31 | "@eslint": 32 | - packages/eslint-config-custom/**/* 33 | "@stack": 34 | - packages/stack/**/* 35 | - stacks/**/* 36 | "@tsconfig": 37 | - packages/tsconfig/**/* 38 | "@ui": 39 | - packages/ui/**/* 40 | "documentation": 41 | - "*.md" 42 | "workflow": 43 | - .github/**/* 44 | "tests": 45 | - "**/*.spec.*" 46 | -------------------------------------------------------------------------------- /.github/pr-branch-labeler.yml: -------------------------------------------------------------------------------- 1 | breaking: 2 | head: ["breaking/*", "bc/*", "major/*"] 3 | feature: 4 | head: ["feat/*", "feature/*", "enhancement/*", "minor/*"] 5 | bug: 6 | head: ["bugfix/*", "hotfix/*", "fix/*", "bug/*"] 7 | chore: 8 | head: ["chore/*", "maint/*", "refactor/*"] 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description: 2 | Describe what changes you are adding 3 | 4 | ## Related issue(s): 5 | Mention related issues 6 | 7 | ## Test Environment: 8 | Specify the testing enviroment. e.g. OS, Python version 9 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - ignore-release 5 | categories: 6 | - title: Breaking Changes 🛠 7 | labels: 8 | - breaking 9 | - bc 10 | - major 11 | - title: Exciting New Features 🎉 12 | labels: 13 | - feature 14 | - enhancement 15 | - minor 16 | - title: Bug fixes 🪳 17 | labels: 18 | - bug 19 | - bugfix 20 | - fix 21 | - title: Other Changes 22 | labels: 23 | - "*" 24 | -------------------------------------------------------------------------------- /.github/workflows/deploy-api-docs.yaml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a VitePress site to GitHub Pages 2 | # 3 | name: Deploy VitePress site to Pages 4 | 5 | on: 6 | # Runs on pushes targeting the `main` branch. Change this to `master` if you're 7 | # using the `master` branch as the default branch. 8 | release: 9 | types: [created] 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 15 | permissions: 16 | contents: read 17 | pages: write 18 | id-token: write 19 | 20 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 21 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 22 | concurrency: 23 | group: pages 24 | cancel-in-progress: false 25 | 26 | jobs: 27 | # Build job 28 | build: 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v3 33 | with: 34 | fetch-depth: 0 # Not needed if lastUpdated is not enabled 35 | # - uses: pnpm/action-setup@v2 # Uncomment this if you're using pnpm 36 | # - uses: oven-sh/setup-bun@v1 # Uncomment this if you're using Bun 37 | - name: Setup Node 38 | uses: actions/setup-node@v3 39 | with: 40 | node-version: 18 41 | cache: npm # or pnpm / yarn 42 | # - name: Setup Pages 43 | # uses: actions/configure-pages@v3 44 | # - name: Change directory to apidocs 45 | # run: cd apidocs/ 46 | - name: Install copper3d dependencies 47 | run: npm ci 48 | - name: Install api dependencies 49 | run: | 50 | cd apidocs/ 51 | npm ci # or pnpm install / yarn install / bun install 52 | - name: Build with VitePress 53 | run: | 54 | cd apidocs/ 55 | npm run docs:build 56 | touch .vitepress/dist/.nojekyll 57 | # cp -r dist/ .vitepress/dist/ 58 | 59 | - name: Upload artifact 60 | uses: actions/upload-artifact@v3 61 | with: 62 | name: production-files 63 | path: ./apidocs/.vitepress/dist 64 | 65 | # Deployment job 66 | 67 | deploy: 68 | name: Deploy 69 | needs: build 70 | runs-on: ubuntu-latest 71 | 72 | steps: 73 | - name: Download artifact 74 | uses: actions/download-artifact@v3 75 | with: 76 | name: production-files 77 | path: ./apidocs/.vitepress/dist 78 | - name: Deploy to Github Pages 79 | uses: peaceiris/actions-gh-pages@v3 80 | with: 81 | github_token: ${{secrets.COPPER3D_GITHUB_TOKEN}} 82 | publish_dir: ./apidocs/.vitepress/dist 83 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yaml: -------------------------------------------------------------------------------- 1 | # Read .github/labeler.yml and apply labels to PRs based on the files that have changed. 2 | name: "Pull Request Labeler" 3 | on: 4 | - pull_request 5 | 6 | jobs: 7 | # Apply labels based on the location of changed files, configured by .github/labeler.yml 8 | changed_files: 9 | permissions: 10 | contents: read 11 | pull-requests: write 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/labeler@v4 15 | with: 16 | repo-token: "${{ secrets.COPPER3D_GITHUB_TOKEN }}" 17 | 18 | # Apply labels based on branch name, configured by .github/pr-branch-labeler.yml 19 | branch_name: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Label PRs 23 | uses: ffittschen/pr-branch-labeler@v1 24 | if: github.event.action == 'opened' # Only run the action when the PR was first opened 25 | with: 26 | repo-token: ${{ secrets.COPPER3D_GITHUB_TOKEN }} 27 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | publish-npm: 12 | name: publish 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-node@v3 17 | with: 18 | node-version: 16 19 | registry-url: https://registry.npmjs.org/ 20 | 21 | - run: npm ci --ignore-scripts 22 | - run: npm run build 23 | - run: npm publish 24 | env: 25 | NODE_AUTH_TOKEN: ${{secrets.COOPER3D_NPM_TOKEN}} 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | /docs/build 10 | 11 | apidist 12 | 13 | .vscode/* 14 | !.vscode/extensions.json 15 | .idea 16 | .DS_Store 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 19 | 20 | cache 21 | 22 | # Runtime data 23 | pids 24 | *.pid 25 | *.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | lib-cov 30 | 31 | # Coverage directory used by tools like istanbul 32 | coverage 33 | *.lcov 34 | 35 | # nyc test coverage 36 | .nyc_output 37 | 38 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 39 | .grunt 40 | 41 | # Bower dependency directory (https://bower.io/) 42 | bower_components 43 | 44 | # node-waf configuration 45 | .lock-wscript 46 | 47 | # Compiled binary addons (https://nodejs.org/api/addons.html) 48 | build/Release 49 | 50 | # Dependency directories 51 | node_modules/ 52 | jspm_packages/ 53 | 54 | # TypeScript v1 declaration files 55 | typings/ 56 | 57 | # TypeScript cache 58 | *.tsbuildinfo 59 | 60 | # Optional npm cache directory 61 | .npm 62 | 63 | # Optional eslint cache 64 | .eslintcache 65 | 66 | # Microbundle cache 67 | .rpt2_cache/ 68 | .rts2_cache_cjs/ 69 | .rts2_cache_es/ 70 | .rts2_cache_umd/ 71 | 72 | # Optional REPL history 73 | .node_repl_history 74 | 75 | # Output of 'npm pack' 76 | *.tgz 77 | 78 | # Yarn Integrity file 79 | .yarn-integrity 80 | 81 | # dotenv environment variables file 82 | .env 83 | .env.test 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | 88 | # Next.js build output 89 | .next 90 | 91 | # Nuxt.js build / generate output 92 | .nuxt 93 | dist 94 | 95 | # Gatsby files 96 | .cache/ 97 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 98 | # https://nextjs.org/blog/next-9-1#public-directory-support 99 | # public 100 | 101 | # vuepress build output 102 | .vuepress/dist 103 | 104 | # Serverless directories 105 | .serverless/ 106 | 107 | # FuseBox cache 108 | .fusebox/ 109 | 110 | # DynamoDB Local files 111 | .dynamodb/ 112 | 113 | # TernJS port file 114 | .tern-port 115 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-20.04 11 | tools: 12 | python: "3.7" 13 | # You can also specify other tool versions: 14 | # nodejs: "16" 15 | # rust: "1.55" 16 | # golang: "1.17" 17 | 18 | # Build documentation in the docs/ directory with Sphinx 19 | sphinx: 20 | configuration: docs/source/conf.py 21 | 22 | # If using Sphinx, optionally build your docs in additional formats such as PDF 23 | # formats: 24 | # - pdf 25 | 26 | # Optionally declare the Python requirements required to build your docs 27 | python: 28 | install: 29 | - requirements: docs/requirements.txt 30 | 31 | formats: 32 | - pdf 33 | - epub 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # copper3d 2 | 3 | [![NPM Package][npm]][npm-url] 4 | [![Read the Docs][readthedocs]][readthedocs-url] 5 | [![Copper3d Examples][examples]][examples-url] 6 | [![NRRD_Segmentation_Tool example][nrrd_example]][nrrd_example-url] 7 | [![MedTech Heart example][heart_example]][heart_example-url] 8 | 9 | A 3d visualisation package base on threejs provides multiple scenes and Nrrd image load funtion. 10 | 11 | ### Documentation: 12 | 13 | https://copper3d-visualisation.readthedocs.io/en/latest/ 14 | 15 | ### Previous versions 16 | 17 | Old: https://www.npmjs.com/package/copper3d_visualisation 18 | Very old: https://www.npmjs.com/package/gltfloader-plugin-test 19 | 20 | ### Example 21 | 22 | [Pick model with Gltfloader](https://linkungao.github.io/loadHumanModel_example/) 23 | 24 | [Copper3d_examples](https://linkungao.github.io/copper3d_examples) 25 | 26 | ### Useage 27 | 28 | - Load demo 29 | 30 | ```ts 31 | import * as Copper from "copper3d"; 32 | import { getCurrentInstance, onMounted } from "vue"; 33 | let refs = null; 34 | let appRenderer; 35 | onMounted(() => { 36 | let { $refs } = (getCurrentInstance() as any).proxy; 37 | refs = $refs; 38 | const bg: HTMLDivElement = refs.classfy; 39 | appRenderer = new Copper.copperRenderer(bg); 40 | const scene = appRenderer.getCurrentScene(); 41 | scene.createDemoMesh(); 42 | appRenderer.animate(); 43 | }); 44 | ``` 45 | 46 | - Add options (curently only control gui) 47 | 48 | ```ts 49 | appRenderer = new Copper.copperRenderer(bg, { guiOpen: true }); 50 | ``` 51 | 52 | - Load multiple scenes with gltf-loader 53 | 54 | ```ts 55 | import * as Copper from "copper3d"; 56 | import { getCurrentInstance, onMounted } from "vue"; 57 | 58 | let refs = null; 59 | let appRenderer; 60 | onMounted(() => { 61 | let { $refs } = (getCurrentInstance() as any).proxy; 62 | refs = $refs; 63 | const bg: HTMLDivElement = refs.classfy; 64 | appRenderer = new Copper.copperRenderer(bg); 65 | appRenderer.animate(); 66 | loadModel("/Healthy.glb", "health"); 67 | }); 68 | 69 | function loadModel(url, name) { 70 | let scene1 = appRenderer.getSceneByName(name); 71 | if (scene1 == undefined) { 72 | const scene1 = appRenderer.createScene(name); 73 | appRenderer.setCurrentScene(scene1); 74 | scene1.loadViewUrl("/noInfarct_view.json"); 75 | scene1.loadGltf(url); 76 | } else { 77 | appRenderer.setCurrentScene(scene1); 78 | } 79 | } 80 | ``` 81 | 82 | #### Viewdata Structure 83 | 84 | ```ts 85 | CameraViewPoint { 86 | nearPlane: number = 0.1; 87 | farPlane: number = 2000.0; 88 | eyePosition: Array = [0.0, 0.0, 0.0]; 89 | targetPosition: Array = [0.0, 0.0, 0.0]; 90 | upVector: Array = [0.0, 1.0, 0.0]; 91 | } 92 | ``` 93 | 94 | --- 95 | 96 | [npm]: https://img.shields.io/npm/v/copper3d 97 | [npm-url]: https://www.npmjs.com/package/copper3d 98 | [readthedocs]: https://img.shields.io/readthedocs/copper3d_visualisation 99 | [readthedocs-url]: https://copper3d-visualisation.readthedocs.io/en/latest/ 100 | [examples]: https://img.shields.io/badge/copper3d__visualisation-examples-orange 101 | [examples-url]: https://linkungao.github.io/copper3d_examples 102 | [nrrd_example]: https://img.shields.io/badge/Nrrd__Segmentation__tool-example-orange 103 | [nrrd_example-url]: https://abi-web-apps.github.io/NRRD_Segmentation_Tool/ 104 | [heart_example-url]: https://uoa-heart-mechanics-research.github.io/medtech-heart/model-heart 105 | [heart_example]: https://img.shields.io/badge/Medtech%20Heart-example-brightgreen 106 | 107 | #### Acknowledgements 108 | 109 | Special thanks to [Duke University dataset](https://wiki.cancerimagingarchive.net/pages/viewpage.action?pageId=70226903) provides these awsome MRI data!!! 110 | -------------------------------------------------------------------------------- /apidocs/.vitepress/config.js: -------------------------------------------------------------------------------- 1 | // docs/.vitepress/config.js 2 | import apidocConfig from "../apidocConfig.json"; 3 | 4 | export default { 5 | title: "Copper3d API", 6 | base: "/copper3d_visualisation/", 7 | themeConfig: { 8 | repo: "LinkunGao/copper3d_visualisation", 9 | sidebar: { 10 | "/apidist/": apidocConfig, 11 | }, 12 | search: { 13 | provider: "algolia", 14 | options: { 15 | appId: "T4ABFE0UY4", 16 | apiKey: "10d8841459f0b508e1394464b203cb63", 17 | indexName: "copper3d-visualisation", 18 | locales: { 19 | zh: { 20 | placeholder: "搜索文档", 21 | translations: { 22 | button: { 23 | buttonText: "搜索文档", 24 | buttonAriaLabel: "搜索文档", 25 | }, 26 | modal: { 27 | searchBox: { 28 | resetButtonTitle: "清除查询条件", 29 | resetButtonAriaLabel: "清除查询条件", 30 | cancelButtonText: "取消", 31 | cancelButtonAriaLabel: "取消", 32 | }, 33 | startScreen: { 34 | recentSearchesTitle: "搜索历史", 35 | noRecentSearchesText: "没有搜索历史", 36 | saveRecentSearchButtonTitle: "保存至搜索历史", 37 | removeRecentSearchButtonTitle: "从搜索历史中移除", 38 | favoriteSearchesTitle: "收藏", 39 | removeFavoriteSearchButtonTitle: "从收藏中移除", 40 | }, 41 | errorScreen: { 42 | titleText: "无法获取结果", 43 | helpText: "你可能需要检查你的网络连接", 44 | }, 45 | footer: { 46 | selectText: "选择", 47 | navigateText: "切换", 48 | closeText: "关闭", 49 | searchByText: "搜索提供者", 50 | }, 51 | noResultsScreen: { 52 | noResultsText: "无法找到相关结果", 53 | suggestedQueryText: "你可以尝试查询", 54 | reportMissingResultsText: "你认为该查询应该有结果?", 55 | reportMissingResultsLinkText: "点击反馈", 56 | }, 57 | }, 58 | }, 59 | }, 60 | }, 61 | }, 62 | }, 63 | }, 64 | }; 65 | -------------------------------------------------------------------------------- /apidocs/apidocConfig.json: -------------------------------------------------------------------------------- 1 | [{"text":"Controls/Copper3dTrackballControls","items":[{"text":"Controls/Copper3dTrackballControls","link":"/apidist/modules/Controls_Copper3dTrackballControls"},{"text":"Class:Copper3dTrackballControls","link":"/apidist/classes/Controls_Copper3dTrackballControls.Copper3dTrackballControls"}]},{"text":"Controls/copperControls","items":[{"text":"Controls/copperControls","link":"/apidist/modules/Controls_copperControls"},{"text":"Class:CameraViewPoint","link":"/apidist/classes/Controls_copperControls.CameraViewPoint"},{"text":"Class:Controls","link":"/apidist/classes/Controls_copperControls.Controls"}]},{"text":"Loader/copperNrrdLoader","items":[{"text":"Loader/copperNrrdLoader","link":"/apidist/modules/Loader_copperNrrdLoader"},{"text":"Interface:optsType","link":"/apidist/interfaces/Loader_copperNrrdLoader.optsType"},{"text":"Function:addBoxHelper","link":"/apidist/functions/Loader_copperNrrdLoader.addBoxHelper"},{"text":"Function:copperNrrdLoader","link":"/apidist/functions/Loader_copperNrrdLoader.copperNrrdLoader"},{"text":"Function:copperNrrdTexture3dLoader","link":"/apidist/functions/Loader_copperNrrdLoader.copperNrrdTexture3dLoader"},{"text":"Function:getWholeSlices","link":"/apidist/functions/Loader_copperNrrdLoader.getWholeSlices"}]},{"text":"Renderer/baseRenderer","items":[{"text":"Renderer/baseRenderer","link":"/apidist/modules/Renderer_baseRenderer"},{"text":"Class:baseRenderer","link":"/apidist/classes/Renderer_baseRenderer.baseRenderer"}]},{"text":"Renderer/copperMSceneRenderer","items":[{"text":"Renderer/copperMSceneRenderer","link":"/apidist/modules/Renderer_copperMSceneRenderer"},{"text":"Class:copperMSceneRenderer","link":"/apidist/classes/Renderer_copperMSceneRenderer.copperMSceneRenderer"}]},{"text":"Renderer/copperRenderer","items":[{"text":"Renderer/copperRenderer","link":"/apidist/modules/Renderer_copperRenderer"},{"text":"Class:copperRenderer","link":"/apidist/classes/Renderer_copperRenderer.copperRenderer"}]},{"text":"Renderer/copperRenderer","items":[{"text":"Renderer/copperRenderer","link":"/apidist/modules/Renderer_copperRenderer"},{"text":"Type:copperRenderer","link":"/apidist/types/Renderer_copperRenderer.copperRenderer"}]},{"text":"Renderer/copperRenderer","items":[{"text":"Renderer/copperRenderer","link":"/apidist/modules/Renderer_copperRenderer"},{"text":"Type:copperRenderer","link":"/apidist/types/Renderer_copperRenderer.copperRenderer"}]},{"text":"Renderer/copperRenderer","items":[{"text":"Renderer/copperRenderer","link":"/apidist/modules/Renderer_copperRenderer"},{"text":"Type:copperRenderer","link":"/apidist/types/Renderer_copperRenderer.copperRenderer"}]},{"text":"Scene/baseScene","items":[{"text":"Scene/baseScene","link":"/apidist/modules/Scene_baseScene"},{"text":"Class:baseScene","link":"/apidist/classes/Scene_baseScene.baseScene"}]},{"text":"Scene/commonSceneMethod","items":[{"text":"Scene/commonSceneMethod","link":"/apidist/modules/Scene_commonSceneMethod"},{"text":"Class:commonScene","link":"/apidist/classes/Scene_commonSceneMethod.commonScene"}]},{"text":"Scene/copperMScene","items":[{"text":"Scene/copperMScene","link":"/apidist/modules/Scene_copperMScene"},{"text":"Class:copperMScene","link":"/apidist/classes/Scene_copperMScene.copperMScene"}]},{"text":"Scene/copperScene","items":[{"text":"Scene/copperScene","link":"/apidist/modules/Scene_copperScene"},{"text":"Class:copperScene","link":"/apidist/classes/Scene_copperScene.copperScene"}]},{"text":"Scene/copperSceneOnDemond","items":[{"text":"Scene/copperSceneOnDemond","link":"/apidist/modules/Scene_copperSceneOnDemond"},{"text":"Class:copperSceneOnDemond","link":"/apidist/classes/Scene_copperSceneOnDemond.copperSceneOnDemond"}]},{"text":"Utils/MeshNodeTool","items":[{"text":"Utils/MeshNodeTool","link":"/apidist/modules/Utils_MeshNodeTool"},{"text":"Class:Element","link":"/apidist/classes/Utils_MeshNodeTool.Element"},{"text":"Class:MeshNodeTool","link":"/apidist/classes/Utils_MeshNodeTool.MeshNodeTool"},{"text":"Class:Node","link":"/apidist/classes/Utils_MeshNodeTool.Node"}]},{"text":"Utils/segmentation/CommToolsData","items":[{"text":"Utils/segmentation/CommToolsData","link":"/apidist/modules/Utils_segmentation_CommToolsData"},{"text":"Class:CommToolsData","link":"/apidist/classes/Utils_segmentation_CommToolsData.CommToolsData"}]},{"text":"Utils/segmentation/DragOperator","items":[{"text":"Utils/segmentation/DragOperator","link":"/apidist/modules/Utils_segmentation_DragOperator"},{"text":"Class:DragOperator","link":"/apidist/classes/Utils_segmentation_DragOperator.DragOperator"}]},{"text":"Utils/segmentation/DrawToolCore","items":[{"text":"Utils/segmentation/DrawToolCore","link":"/apidist/modules/Utils_segmentation_DrawToolCore"},{"text":"Class:DrawToolCore","link":"/apidist/classes/Utils_segmentation_DrawToolCore.DrawToolCore"}]},{"text":"Utils/segmentation/NrrdTools","items":[{"text":"Utils/segmentation/NrrdTools","link":"/apidist/modules/Utils_segmentation_NrrdTools"},{"text":"Class:NrrdTools","link":"/apidist/classes/Utils_segmentation_NrrdTools.NrrdTools"}]},{"text":"Utils/segmentation/coreTools/gui","items":[{"text":"Utils/segmentation/coreTools/gui","link":"/apidist/modules/Utils_segmentation_coreTools_gui"},{"text":"Function:removeGuiFolderChilden","link":"/apidist/functions/Utils_segmentation_coreTools_gui.removeGuiFolderChilden"},{"text":"Function:setupGui","link":"/apidist/functions/Utils_segmentation_coreTools_gui.setupGui"}]},{"text":"Utils/utils","items":[{"text":"Utils/utils","link":"/apidist/modules/Utils_utils"},{"text":"Function:H3","link":"/apidist/functions/Utils_utils.H3"},{"text":"Function:L3","link":"/apidist/functions/Utils_utils.L3"},{"text":"Function:calcDistance","link":"/apidist/functions/Utils_utils.calcDistance"},{"text":"Function:fullScreenListenner","link":"/apidist/functions/Utils_utils.fullScreenListenner"},{"text":"Function:getWightsH3H3H3","link":"/apidist/functions/Utils_utils.getWightsH3H3H3"},{"text":"Function:getWightsL3L3L3","link":"/apidist/functions/Utils_utils.getWightsL3L3L3"},{"text":"Function:isIOS","link":"/apidist/functions/Utils_utils.isIOS"},{"text":"Function:loading","link":"/apidist/functions/Utils_utils.loading"},{"text":"Function:perturbRandom","link":"/apidist/functions/Utils_utils.perturbRandom"},{"text":"Function:switchEraserSize","link":"/apidist/functions/Utils_utils.switchEraserSize"},{"text":"Function:switchPencilIcon","link":"/apidist/functions/Utils_utils.switchPencilIcon"},{"text":"Function:throttle","link":"/apidist/functions/Utils_utils.throttle"},{"text":"Function:traverseMaterials","link":"/apidist/functions/Utils_utils.traverseMaterials"}]}] -------------------------------------------------------------------------------- /apidocs/crawlerConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_name": "copper3d-visualisation", 3 | "start_urls": ["https://linkungao.github.io/copper3d_visualisation/"], 4 | "rateLimit": 8, 5 | "maxDepth": 10, 6 | "selectors": { 7 | "lvl0": { 8 | "selector": "", 9 | "defaultValue": "Documentation" 10 | }, 11 | "lvl1": ".content h1", 12 | "lvl2": ".content h2", 13 | "lvl3": ".content h3", 14 | "lvl4": ".content h4", 15 | "lvl5": ".content h5", 16 | "content": ".content p, .content li", 17 | "lang": { 18 | "selector": "/html/@lang", 19 | "type": "xpath", 20 | "global": true 21 | } 22 | }, 23 | "selectors_exclude": [ 24 | "aside", 25 | ".page-footer", 26 | ".next-and-prev-link", 27 | ".table-of-contents" 28 | ], 29 | "custom_settings": { 30 | "attributesForFaceting": ["lang", "tags"] 31 | }, 32 | "js_render": true 33 | } 34 | -------------------------------------------------------------------------------- /apidocs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | title: Home 5 | 6 | hero: 7 | name: Copper3d 8 | tagline: A visualisation tool base on threejs. It provides Dicom loader, Nrrd Segmentation Tools, Create vtk animation functions. 9 | actions: 10 | - theme: sponsor 11 | text: Copper3d ReadMe 12 | link: /apidist/README 13 | - theme: brand 14 | text: Copper3d core API 15 | link: /apidist/modules 16 | --- 17 | -------------------------------------------------------------------------------- /apidocs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "copper3d_api_doc", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "docs": "npx typedoc --options ./typedoc.json", 8 | "dev": "node typedoc.js && vitepress dev .", 9 | "docs:build": "node typedoc.js && vitepress build .", 10 | "serve": "node typedoc.js && vitepress serve .", 11 | "docs:preview": "vitepress preview " 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "typedoc": "^0.25.1", 18 | "typedoc-plugin-markdown": "^3.16.0", 19 | "vitepress": "^1.0.0-rc.20", 20 | "vue": "^3.3.4" 21 | }, 22 | "dependencies": { 23 | "three": "^0.156.1", 24 | "vitepress-plugin-search": "^1.0.4-alpha.20" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apidocs/typedoc.js: -------------------------------------------------------------------------------- 1 | const TypeDoc = require("typedoc"); 2 | const path = require("path"); 3 | const fs = require("fs"); 4 | 5 | // root folder path 6 | function rootPath(...args) { 7 | return path.join(__dirname, "..", ...args); 8 | } 9 | 10 | async function main() { 11 | // Application.bootstrap also exists, which will not load plugins 12 | // Also accepts an array of option readers if you want to disable 13 | // TypeDoc's tsconfig.json/package.json/typedoc.json option readers 14 | 15 | const entries = [ 16 | // rootPath("src/index.ts"), 17 | rootPath("src/Renderer/baseRenderer.ts"), 18 | rootPath("src/Renderer/copperMSceneRenderer.ts"), 19 | rootPath("src/Renderer/copperRenderer.ts"), 20 | rootPath("src/Renderer/copperRenderer.ts"), 21 | rootPath("src/Renderer/copperRenderer.ts"), 22 | rootPath("src/Renderer/copperRenderer.ts"), 23 | rootPath("src/Scene/baseScene.ts"), 24 | rootPath("src/Scene/commonSceneMethod.ts"), 25 | rootPath("src/Scene/copperMScene.ts"), 26 | rootPath("src/Scene/copperScene.ts"), 27 | rootPath("src/Scene/copperSceneOnDemond.ts"), 28 | rootPath("src/Controls/copperControls.ts"), 29 | rootPath("src/Controls/Copper3dTrackballControls.ts"), 30 | rootPath("src/Utils/MeshNodeTool.ts"), 31 | rootPath("src/Utils/segmentation/NrrdTools.ts"), 32 | rootPath("src/Utils/segmentation/DragOperator.ts"), 33 | rootPath("src/Utils/segmentation/DrawToolCore.ts"), 34 | rootPath("src/Utils/segmentation/CommToolsData.ts"), 35 | rootPath("src/Utils/utils.ts"), 36 | rootPath("src/Loader/copperNrrdLoader.ts"), 37 | rootPath("src/Utils/segmentation/coreTools/gui.ts"), 38 | ]; 39 | const app = await TypeDoc.Application.bootstrapWithPlugins({ 40 | entryPoints: entries, 41 | }); 42 | 43 | const project = await app.convert(); 44 | 45 | if (project) { 46 | // Project may not have converted correctly 47 | const outputDir = "apidist"; 48 | 49 | const jsonDir = path.join(outputDir, "documentation.json"); 50 | // Rendered docs 51 | await app.generateDocs(project, outputDir); 52 | // Alternatively generate JSON output 53 | await app.generateJson(project, jsonDir); 54 | await resolveConfig(jsonDir); 55 | } 56 | } 57 | 58 | main().catch(console.error); 59 | 60 | /** generate sidebar configuration */ 61 | async function resolveConfig(jsonDir) { 62 | const result = []; 63 | 64 | // read json doucmentation data structure 65 | const buffer = await fs.promises.readFile(jsonDir, "utf8"); 66 | const data = JSON.parse(buffer.toString()); 67 | if (!data.children || data.children.length <= 0) { 68 | return; 69 | } 70 | 71 | data.children.forEach((module) => { 72 | if (module.kind !== 2) { 73 | return; 74 | } 75 | // Module as first menu 76 | const moduleConfig = { 77 | text: module.name, 78 | items: [{ text: module.name, link: getModulePath(module.name) }], 79 | }; 80 | module.children.forEach((sub) => { 81 | // class, interface, type, function as second menu 82 | if (sub.kind === 128) { 83 | moduleConfig.items.push({ 84 | text: `Class:${sub.name}`, 85 | link: getClassPath(module.name, sub.name), 86 | }); 87 | } else if (sub.kind === 256) { 88 | moduleConfig.items.push({ 89 | text: `Interface:${sub.name}`, 90 | link: getInterfacePath(module.name, sub.name), 91 | }); 92 | } else if (sub.kind === 4194304) { 93 | moduleConfig.items.push({ 94 | text: `Type:${sub.name}`, 95 | link: getTypePath(module.name, sub.name), 96 | }); 97 | } else if (sub.kind === 64) { 98 | moduleConfig.items.push({ 99 | text: `Function:${sub.name}`, 100 | link: getFunctionPath(module.name, sub.name), 101 | }); 102 | } 103 | }); 104 | result.push(moduleConfig); 105 | }); 106 | 107 | // 转换成的导航数据输出到 doc/apidocConfig.json 108 | await fs.promises.writeFile( 109 | path.join(__dirname, "apidocConfig.json"), 110 | JSON.stringify(result), 111 | "utf8" 112 | ); 113 | } 114 | 115 | function transformModuleName(name) { 116 | return name.replace(/\//g, "_"); 117 | } 118 | 119 | function getModulePath(name) { 120 | return path 121 | .join("/apidist/modules", `${transformModuleName(name)}`) 122 | .replace(/\\/g, "/"); 123 | } 124 | 125 | function getClassPath(moduleName, className) { 126 | return path 127 | .join("/apidist/classes", `${transformModuleName(moduleName)}.${className}`) 128 | .replace(/\\/g, "/"); 129 | } 130 | 131 | function getInterfacePath(moduleName, interfaceName) { 132 | return path 133 | .join( 134 | "/apidist/interfaces", 135 | `${transformModuleName(moduleName)}.${interfaceName}` 136 | ) 137 | .replace(/\\/g, "/"); 138 | } 139 | 140 | function getTypePath(moduleName, typeName) { 141 | return path 142 | .join("/apidist/types", `${transformModuleName(moduleName)}.${typeName}`) 143 | .replace(/\\/g, "/"); 144 | } 145 | 146 | function getFunctionPath(moduleName, functionName) { 147 | return path 148 | .join( 149 | "/apidist/functions", 150 | `${transformModuleName(moduleName)}.${functionName}` 151 | ) 152 | .replace(/\\/g, "/"); 153 | } 154 | -------------------------------------------------------------------------------- /apidocs/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": ["../src/index.ts"], 4 | "plugin": ["typedoc-plugin-markdown"], 5 | "out": "./apidist" 6 | } 7 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx_book_theme 2 | sphinx_copybutton 3 | recommonmark -------------------------------------------------------------------------------- /docs/source/Intro/index.md: -------------------------------------------------------------------------------- 1 | # Introdction 2 | 3 | Copper3D is a library base on Three.js! 4 | 5 | The main function for this library includes: multiple scene, gltfloader plugin, and GUI. In the future, this library also will develop MRI/nrrd loaders function. Although, threejs has already included those functions, this library will simplify the proccess of build a 3D visualization app by using these functions. 6 | 7 | The main purpose of this library is to provide a stable loader function, a high quality model loading, and nice GUI control. 8 | 9 | **Notice:** 10 | 11 | Currently the library is under develop period, the npm package name is `temporary`, it will be `change` after. 12 | 13 | - `Functions` 14 | - `Gltfloader plugin` 15 | Allows user to load multiple GLTF models in different pages with one WebGLRender. 16 | Allows user easily to control and interact with load models. 17 | - `GUI` 18 | A nice GUI for user to control and debug APP, and config background. 19 | - `Multiple Scenes` 20 | Allows user to create multiple scene in a signle page, and allows data sharing between each scene. 21 | Each scene can has its own GUI for Customization. 22 | - `MRI/NRRD Loader` 23 | A loader allows user easily to load MRI/NRRD images on a visualisation APP. And, it will provide a nice GUI for user to interact with customisation model and MRI/NRRD model. 24 | 25 | ## Base Implementation 26 | 27 | ### Install the library 28 | 29 | Install the library in a visualisation APP (Vue, Vite, React) 30 | 31 | - Demo use vite 32 | 33 | - Install 34 | 35 | ```bash 36 | mkdir demo-for-copper3d 37 | cd demo-for-copper3d 38 | npm init vite@latest 39 | cd your vite-app 40 | npm i gltfloader-plugin-test 41 | ``` 42 | 43 | - Create a container for Copper3d Gltfloader plugin 44 | 45 | ```html 46 | 49 | 55 | ``` 56 | 57 | - Load your first demo model. 58 | 59 | ```ts 60 |