shape.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /**
  2. * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
  7. import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder';
  8. import { BoxCage } from '../../mol-geo/primitive/box';
  9. import { Box3D, Sphere3D } from '../../mol-math/geometry';
  10. import { Mat4, Vec3 } from '../../mol-math/linear-algebra';
  11. import { Shape } from '../../mol-model/shape';
  12. import { Task } from '../../mol-task';
  13. import { ColorNames } from '../../mol-util/color/names';
  14. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  15. import { PluginStateObject as SO, PluginStateTransform } from '../objects';
  16. export { BoxShape3D };
  17. type BoxShape3D = typeof BoxShape3D
  18. const BoxShape3D = PluginStateTransform.BuiltIn({
  19. name: 'box-shape-3d',
  20. display: 'Box Shape',
  21. from: SO.Root,
  22. to: SO.Shape.Provider,
  23. params: {
  24. bottomLeft: PD.Vec3(Vec3()),
  25. topRight: PD.Vec3(Vec3.create(1, 1, 1)),
  26. radius: PD.Numeric(0.15, { min: 0.01, max: 4, step: 0.01 }),
  27. color: PD.Color(ColorNames.red)
  28. }
  29. })({
  30. canAutoUpdate() {
  31. return true;
  32. },
  33. apply({ params }) {
  34. return Task.create('Shape Representation', async ctx => {
  35. return new SO.Shape.Provider({
  36. label: 'Box',
  37. data: params,
  38. params: Mesh.Params,
  39. getShape: (_, data: typeof params) => {
  40. const mesh = getBoxMesh(Box3D.create(params.bottomLeft, params.topRight), params.radius);
  41. return Shape.create('Box', data, mesh, () => data.color, () => 1, () => 'Box');
  42. },
  43. geometryUtils: Mesh.Utils
  44. }, { label: 'Box' });
  45. });
  46. }
  47. });
  48. export function getBoxMesh(box: Box3D, radius: number, oldMesh?: Mesh) {
  49. const diag = Vec3.sub(Vec3(), box.max, box.min);
  50. const translateUnit = Mat4.fromTranslation(Mat4(), Vec3.create(0.5, 0.5, 0.5));
  51. const scale = Mat4.fromScaling(Mat4(), diag);
  52. const translate = Mat4.fromTranslation(Mat4(), box.min);
  53. const transform = Mat4.mul3(Mat4(), translate, scale, translateUnit);
  54. // TODO: optimize?
  55. const state = MeshBuilder.createState(256, 128, oldMesh);
  56. state.currentGroup = 1;
  57. MeshBuilder.addCage(state, transform, BoxCage(), radius, 2, 20);
  58. const mesh = MeshBuilder.getMesh(state);
  59. const center = Vec3.scaleAndAdd(Vec3(), box.min, diag, 0.5);
  60. const sphereRadius = Vec3.distance(box.min, center);
  61. mesh.setBoundingSphere(Sphere3D.create(center, sphereRadius));
  62. return mesh;
  63. }