marching-cubes.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /**
  2. * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import './index.html';
  7. import { resizeCanvas } from '../../mol-canvas3d/util';
  8. import { Canvas3DParams, Canvas3D, Canvas3DContext } from '../../mol-canvas3d/canvas3d';
  9. import { ColorNames } from '../../mol-util/color/names';
  10. import { PositionData, Box3D, Sphere3D } from '../../mol-math/geometry';
  11. import { OrderedSet } from '../../mol-data/int';
  12. import { Vec3 } from '../../mol-math/linear-algebra';
  13. import { computeGaussianDensity, computeGaussianDensityTexture2d } from '../../mol-math/geometry/gaussian-density';
  14. import { calcActiveVoxels } from '../../mol-gl/compute/marching-cubes/active-voxels';
  15. import { createHistogramPyramid } from '../../mol-gl/compute/histogram-pyramid/reduction';
  16. import { createIsosurfaceBuffers } from '../../mol-gl/compute/marching-cubes/isosurface';
  17. import { TextureMesh } from '../../mol-geo/geometry/texture-mesh/texture-mesh';
  18. import { Color } from '../../mol-util/color';
  19. import { createRenderObject } from '../../mol-gl/render-object';
  20. import { Representation } from '../../mol-repr/representation';
  21. import { computeMarchingCubesMesh } from '../../mol-geo/util/marching-cubes/algorithm';
  22. import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
  23. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  24. import { AssetManager } from '../../mol-util/assets';
  25. const parent = document.getElementById('app')!;
  26. parent.style.width = '100%';
  27. parent.style.height = '100%';
  28. const canvas = document.createElement('canvas');
  29. parent.appendChild(canvas);
  30. resizeCanvas(canvas, parent);
  31. const assetManager = new AssetManager();
  32. const canvas3d = Canvas3D.create(Canvas3DContext.fromCanvas(canvas, assetManager), PD.merge(Canvas3DParams, PD.getDefaultValues(Canvas3DParams), {
  33. renderer: { backgroundColor: ColorNames.white },
  34. camera: { mode: 'orthographic' }
  35. }));
  36. canvas3d.animate();
  37. async function init() {
  38. const { webgl } = canvas3d;
  39. const position: PositionData = {
  40. x: [0, 2],
  41. y: [0, 2],
  42. z: [0, 2],
  43. indices: OrderedSet.ofSortedArray([0, 1]),
  44. };
  45. const box = Box3D.create(Vec3.create(0, 0, 0), Vec3.create(2, 2, 2));
  46. const radius = () => 1.8;
  47. const props = {
  48. resolution: 0.1,
  49. radiusOffset: 0,
  50. smoothness: 1.5
  51. };
  52. const isoValue = Math.exp(-props.smoothness);
  53. if (true) {
  54. console.time('gpu gaussian2');
  55. const densityTextureData2 = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run();
  56. webgl.waitForGpuCommandsCompleteSync();
  57. console.timeEnd('gpu gaussian2');
  58. console.time('gpu mc2');
  59. console.time('gpu mc active2');
  60. const activeVoxelsTex2 = calcActiveVoxels(webgl, densityTextureData2.texture, densityTextureData2.gridDim, densityTextureData2.gridTexDim, isoValue, densityTextureData2.gridTexScale);
  61. webgl.waitForGpuCommandsCompleteSync();
  62. console.timeEnd('gpu mc active2');
  63. console.time('gpu mc pyramid2');
  64. const compacted2 = createHistogramPyramid(webgl, activeVoxelsTex2, densityTextureData2.gridTexScale, densityTextureData2.gridTexDim);
  65. webgl.waitForGpuCommandsCompleteSync();
  66. console.timeEnd('gpu mc pyramid2');
  67. console.time('gpu mc vert2');
  68. createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue, false, true, Vec3.create(0, 1, 2), true);
  69. webgl.waitForGpuCommandsCompleteSync();
  70. console.timeEnd('gpu mc vert2');
  71. console.timeEnd('gpu mc2');
  72. }
  73. console.time('gpu gaussian');
  74. const densityTextureData = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run();
  75. webgl.waitForGpuCommandsCompleteSync();
  76. console.timeEnd('gpu gaussian');
  77. console.time('gpu mc');
  78. console.time('gpu mc active');
  79. const activeVoxelsTex = calcActiveVoxels(webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, isoValue, densityTextureData.gridTexScale);
  80. webgl.waitForGpuCommandsCompleteSync();
  81. console.timeEnd('gpu mc active');
  82. console.time('gpu mc pyramid');
  83. const compacted = createHistogramPyramid(webgl, activeVoxelsTex, densityTextureData.gridTexScale, densityTextureData.gridTexDim);
  84. webgl.waitForGpuCommandsCompleteSync();
  85. console.timeEnd('gpu mc pyramid');
  86. console.time('gpu mc vert');
  87. const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue, false, true, Vec3.create(0, 1, 2), true);
  88. webgl.waitForGpuCommandsCompleteSync();
  89. console.timeEnd('gpu mc vert');
  90. console.timeEnd('gpu mc');
  91. console.log({ ...webgl.stats, programCount: webgl.stats.resourceCounts.program, shaderCount: webgl.stats.resourceCounts.shader });
  92. const mcBoundingSphere = Sphere3D.fromBox3D(Sphere3D(), densityTextureData.bbox);
  93. const mcIsosurface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, mcBoundingSphere);
  94. const mcIsoSurfaceProps = {
  95. ...PD.getDefaultValues(TextureMesh.Params),
  96. doubleSided: true,
  97. flatShaded: true,
  98. alpha: 1.0
  99. };
  100. const mcIsoSurfaceValues = TextureMesh.Utils.createValuesSimple(mcIsosurface, mcIsoSurfaceProps, Color(0x112299), 1);
  101. // console.log('mcIsoSurfaceValues', mcIsoSurfaceValues)
  102. const mcIsoSurfaceState = TextureMesh.Utils.createRenderableState(mcIsoSurfaceProps);
  103. const mcIsoSurfaceRenderObject = createRenderObject('texture-mesh', mcIsoSurfaceValues, mcIsoSurfaceState, -1);
  104. const mcIsoSurfaceRepr = Representation.fromRenderObject('texture-mesh', mcIsoSurfaceRenderObject);
  105. canvas3d.add(mcIsoSurfaceRepr);
  106. canvas3d.requestCameraReset();
  107. //
  108. console.time('cpu gaussian');
  109. const densityData = await computeGaussianDensity(position, box, radius, props).run();
  110. console.timeEnd('cpu gaussian');
  111. console.log({ densityData });
  112. const params = {
  113. isoLevel: isoValue,
  114. scalarField: densityData.field,
  115. idField: densityData.idField
  116. };
  117. console.time('cpu mc');
  118. const surface = await computeMarchingCubesMesh(params).run();
  119. console.timeEnd('cpu mc');
  120. console.log('surface', surface);
  121. Mesh.transform(surface, densityData.transform);
  122. const meshProps = {
  123. ...PD.getDefaultValues(Mesh.Params),
  124. doubleSided: true,
  125. flatShaded: false,
  126. alpha: 1.0
  127. };
  128. const meshValues = Mesh.Utils.createValuesSimple(surface, meshProps, Color(0x995511), 1);
  129. const meshState = Mesh.Utils.createRenderableState(meshProps);
  130. const meshRenderObject = createRenderObject('mesh', meshValues, meshState, -1);
  131. const meshRepr = Representation.fromRenderObject('mesh', meshRenderObject);
  132. canvas3d.add(meshRepr);
  133. canvas3d.requestCameraReset();
  134. }
  135. init();