marching-cubes.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /**
  2. * Copyright (c) 2019 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 { Canvas3D } from '../../mol-canvas3d/canvas3d';
  9. import { RendererParams } from '../../mol-gl/renderer';
  10. import { ColorNames } from '../../mol-util/color/names';
  11. import { PositionData, Box3D, Sphere3D } from '../../mol-math/geometry';
  12. import { OrderedSet } from '../../mol-data/int';
  13. import { Vec3 } from '../../mol-math/linear-algebra';
  14. import { computeGaussianDensityTexture2d, computeGaussianDensity } from '../../mol-math/geometry/gaussian-density';
  15. import { calcActiveVoxels } from '../../mol-gl/compute/marching-cubes/active-voxels';
  16. import { createHistogramPyramid } from '../../mol-gl/compute/histogram-pyramid/reduction';
  17. import { createIsosurfaceBuffers } from '../../mol-gl/compute/marching-cubes/isosurface';
  18. import { TextureMesh } from '../../mol-geo/geometry/texture-mesh/texture-mesh';
  19. import { Color } from '../../mol-util/color';
  20. import { createRenderObject } from '../../mol-gl/render-object';
  21. import { Representation } from '../../mol-repr/representation';
  22. import { computeMarchingCubesMesh } from '../../mol-geo/util/marching-cubes/algorithm';
  23. import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
  24. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  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 canvas3d = Canvas3D.fromCanvas(canvas, {
  32. renderer: { ...PD.getDefaultValues(RendererParams), backgroundColor: ColorNames.white },
  33. cameraMode: 'orthographic'
  34. })
  35. canvas3d.animate()
  36. async function init() {
  37. const { webgl } = canvas3d
  38. const position: PositionData = {
  39. x: [0, 2],
  40. y: [0, 2],
  41. z: [0, 2],
  42. indices: OrderedSet.ofSortedArray([0, 1]),
  43. }
  44. const box = Box3D.create(Vec3.create(0, 0, 0), Vec3.create(2, 2, 2))
  45. const radius = () => 1.8
  46. const props = {
  47. resolution: 0.1,
  48. radiusOffset: 0,
  49. smoothness: 1.5
  50. }
  51. const isoValue = Math.exp(-props.smoothness)
  52. if (true) {
  53. console.time('gpu gaussian2')
  54. const densityTextureData2 = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run()
  55. webgl.waitForGpuCommandsCompleteSync()
  56. console.timeEnd('gpu gaussian2')
  57. console.time('gpu mc2')
  58. console.time('gpu mc active2')
  59. const activeVoxelsTex2 = calcActiveVoxels(webgl, densityTextureData2.texture, densityTextureData2.gridDim, densityTextureData2.gridTexDim, isoValue, densityTextureData2.gridTexScale)
  60. webgl.waitForGpuCommandsCompleteSync()
  61. console.timeEnd('gpu mc active2')
  62. console.time('gpu mc pyramid2')
  63. const compacted2 = createHistogramPyramid(webgl, activeVoxelsTex2, densityTextureData2.gridTexScale)
  64. webgl.waitForGpuCommandsCompleteSync()
  65. console.timeEnd('gpu mc pyramid2')
  66. console.time('gpu mc vert2')
  67. createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue)
  68. webgl.waitForGpuCommandsCompleteSync()
  69. console.timeEnd('gpu mc vert2')
  70. console.timeEnd('gpu mc2')
  71. }
  72. console.time('gpu gaussian')
  73. const densityTextureData = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run()
  74. webgl.waitForGpuCommandsCompleteSync()
  75. console.timeEnd('gpu gaussian')
  76. console.time('gpu mc')
  77. console.time('gpu mc active')
  78. const activeVoxelsTex = calcActiveVoxels(webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, isoValue, densityTextureData.gridTexScale)
  79. webgl.waitForGpuCommandsCompleteSync()
  80. console.timeEnd('gpu mc active')
  81. console.time('gpu mc pyramid')
  82. const compacted = createHistogramPyramid(webgl, activeVoxelsTex, densityTextureData.gridTexScale)
  83. webgl.waitForGpuCommandsCompleteSync()
  84. console.timeEnd('gpu mc pyramid')
  85. console.time('gpu mc vert')
  86. const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue)
  87. webgl.waitForGpuCommandsCompleteSync()
  88. console.timeEnd('gpu mc vert')
  89. console.timeEnd('gpu mc')
  90. console.log({ ...webgl.stats, programCount: webgl.stats.resourceCounts.program, shaderCount: webgl.stats.resourceCounts.shader })
  91. const mcBoundingSphere = Sphere3D.fromBox3D(Sphere3D(), densityTextureData.bbox)
  92. const mcIsosurface = TextureMesh.create(gv.vertexCount, 1, gv.vertexGroupTexture, gv.normalTexture, mcBoundingSphere)
  93. const mcIsoSurfaceProps = { doubleSided: true, flatShaded: true, alpha: 1.0 }
  94. const mcIsoSurfaceValues = TextureMesh.Utils.createValuesSimple(mcIsosurface, mcIsoSurfaceProps, Color(0x112299), 1)
  95. // console.log('mcIsoSurfaceValues', mcIsoSurfaceValues)
  96. const mcIsoSurfaceState = TextureMesh.Utils.createRenderableState(mcIsoSurfaceProps)
  97. const mcIsoSurfaceRenderObject = createRenderObject('texture-mesh', mcIsoSurfaceValues, mcIsoSurfaceState, -1)
  98. const mcIsoSurfaceRepr = Representation.fromRenderObject('texture-mesh', mcIsoSurfaceRenderObject)
  99. canvas3d.add(mcIsoSurfaceRepr)
  100. canvas3d.resetCamera()
  101. //
  102. console.time('cpu gaussian')
  103. const densityData = await computeGaussianDensity(position, box, radius, { ...props, useGpu: false }, webgl).run()
  104. console.timeEnd('cpu gaussian')
  105. console.log({ densityData })
  106. const params = {
  107. isoLevel: isoValue,
  108. scalarField: densityData.field,
  109. idField: densityData.idField
  110. }
  111. console.time('cpu mc')
  112. const surface = await computeMarchingCubesMesh(params).run()
  113. console.timeEnd('cpu mc')
  114. console.log('surface', surface)
  115. Mesh.transformImmediate(surface, densityData.transform)
  116. const meshProps = { doubleSided: true, flatShaded: false, alpha: 1.0 }
  117. const meshValues = Mesh.Utils.createValuesSimple(surface, meshProps, Color(0x995511), 1)
  118. const meshState = Mesh.Utils.createRenderableState(meshProps)
  119. const meshRenderObject = createRenderObject('mesh', meshValues, meshState, -1)
  120. const meshRepr = Representation.fromRenderObject('mesh', meshRenderObject)
  121. canvas3d.add(meshRepr)
  122. canvas3d.resetCamera()
  123. }
  124. init()