threepipe
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SVGMesh.ts 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Author: Axel Antoine
  2. // mail: ax.antoine@gmail.com
  3. // website: https://axantoine.com
  4. // 09/12/2021
  5. // Loki, Inria project-team with Université de Lille
  6. // within the Joint Research Unit UMR 9189 CNRS-Centrale
  7. // Lille-Université de Lille, CRIStAL.
  8. // https://loki.lille.inria.fr
  9. // LICENCE: Licence.md
  10. import {Color, Material, Mesh, Vector3} from 'three';
  11. import {HalfedgeDS} from '../../three-mesh-halfedge';
  12. import {acceleratedRaycast, CENTER, MeshBVH, MeshBVHOptions} from 'three-mesh-bvh';
  13. import {computeMorphedGeometry, disposeMesh} from '../utils/buffergeometry';
  14. type ColorMaterial = Material & {color: Color};
  15. export interface SVGMeshOptions {
  16. bvhOptions?: MeshBVHOptions;
  17. }
  18. /**
  19. * SVGTexture allows to add a texture to a SVGMesh.
  20. * Raster image (.jpeg, .png) or vector graphics (.svg) are supported.
  21. */
  22. export interface SVGTexture {
  23. /**
  24. * Name of the texture
  25. */
  26. name: string;
  27. /**
  28. * DataUrl to the image and vector graphics texture
  29. */
  30. url: string;
  31. }
  32. /**
  33. * Mesh object that can be rendered as SVG.
  34. * Wrapper class around three mesh object that duplicates geometry if needed (i.e.
  35. * for SkinnedMesh) and computes BVH and HalfEdgeStructure on demand)
  36. */
  37. export class SVGMesh {
  38. readonly sourceMesh: Mesh;
  39. readonly threeMesh = new Mesh();
  40. readonly hes: HalfedgeDS;
  41. readonly bvhOptions: MeshBVHOptions;
  42. bvh: MeshBVH;
  43. drawFills = true;
  44. drawVisibleContours = true;
  45. drawHiddenContours = true;
  46. isUsingBVHForRaycasting = false;
  47. texture?: SVGTexture;
  48. constructor(mesh: Mesh, options: SVGMeshOptions = {}) {
  49. this.sourceMesh = mesh;
  50. this.threeMesh.copy(mesh);
  51. // if(this.sourceMesh.geometry.index){
  52. // this.threeMesh.geometry = this.sourceMesh.geometry.toNonIndexed();
  53. // }else {
  54. this.threeMesh.geometry = this.sourceMesh.geometry.clone();
  55. // }
  56. // this.threeMesh.geometry = toIndexedGeometry(this.sourceMesh.geometry, 1);
  57. // Setup HES
  58. this.hes = new HalfedgeDS();
  59. // const t = this.hes.addEdge
  60. // this.hes.addEdge = (...args)=>{
  61. // try{
  62. // return t.call(this.hes, ...args)
  63. // }catch(e){
  64. // console.error(e)
  65. // console.log('args', args)
  66. // }
  67. // }
  68. // Setup BVH
  69. const bvhOptions = {
  70. maxLeafTris: 1,
  71. strategy: CENTER,
  72. ...options?.bvhOptions
  73. }
  74. this.bvhOptions = bvhOptions
  75. this.bvh = new MeshBVH(this.threeMesh.geometry, bvhOptions);
  76. this.threeMesh.geometry.boundsTree = this.bvh;
  77. this.threeMesh.raycast = acceleratedRaycast;
  78. }
  79. /**
  80. * Adds a SVGtexture to the mesh.
  81. *
  82. * @param texture The image or vector graphics texture to use.
  83. */
  84. addTexture(texture: SVGTexture) {
  85. this.texture = texture;
  86. }
  87. updateMorphGeometry() {
  88. computeMorphedGeometry(this.sourceMesh, this.threeMesh.geometry);
  89. }
  90. // private _i= 0
  91. updateBVH(updateMorphGeometry = true) {
  92. // if(this._i) return
  93. // this._i++
  94. updateMorphGeometry && this.updateMorphGeometry();
  95. this.bvh.refit();
  96. }
  97. updateHES(updateMorphGeometry = true) {
  98. // if(!force && this.hes.faces.length) return
  99. updateMorphGeometry && this.updateMorphGeometry();
  100. this.hes.setFromGeometry(this.threeMesh.geometry, 1e-10);
  101. }
  102. localToWorld(target: Vector3): Vector3 {
  103. return this.threeMesh.localToWorld(target);
  104. }
  105. colorForFaceIndex(faceIndex: number): null | Color {
  106. if (Array.isArray(this.material)) {
  107. for (const group of this.threeMesh.geometry.groups) {
  108. if (group.start <= faceIndex &&
  109. faceIndex < (group.start + group.count) &&
  110. group.materialIndex != undefined &&
  111. group.materialIndex < this.material.length) {
  112. return colorForMaterial(this.material[group.materialIndex]);
  113. }
  114. }
  115. return null;
  116. }
  117. return colorForMaterial(this.material);
  118. }
  119. dispose() {
  120. disposeMesh(this.threeMesh);
  121. }
  122. get material() { return this.threeMesh.material; }
  123. get matrixWorld() { return this.threeMesh.matrixWorld; }
  124. get name() { return this.threeMesh.name; }
  125. set name(name: string) { this.threeMesh.name = name; }
  126. updateObject(){
  127. // const g = this.sourceMesh.geometry;
  128. // const ud = this.sourceMesh.userData;
  129. // this.sourceMesh.userData = {};
  130. // this.threeMesh.copy(this.sourceMesh, false);
  131. // this.sourceMesh.userData = ud;
  132. // this.threeMesh.geometry = g;
  133. this.threeMesh.position.copy(this.sourceMesh.position);
  134. this.threeMesh.quaternion.copy(this.sourceMesh.quaternion);
  135. this.threeMesh.scale.copy(this.sourceMesh.scale);
  136. this.threeMesh.updateMatrix();
  137. this.threeMesh.updateMatrixWorld();
  138. }
  139. remakeBVH(){
  140. this.bvh = new MeshBVH(this.threeMesh.geometry, this.bvhOptions);
  141. this.threeMesh.geometry.boundsTree = this.bvh;
  142. }
  143. }
  144. function colorForMaterial(material: Material) {
  145. const colorMaterial = material as ColorMaterial;
  146. return colorMaterial.color;
  147. }