ShapeGeometry.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { BufferGeometry } from '../core/BufferGeometry.js';
  2. import { Float32BufferAttribute } from '../core/BufferAttribute.js';
  3. import { Shape } from '../extras/core/Shape.js';
  4. import { ShapeUtils } from '../extras/ShapeUtils.js';
  5. import { Vector2 } from '../math/Vector2.js';
  6. class ShapeGeometry extends BufferGeometry {
  7. constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) {
  8. super();
  9. this.type = 'ShapeGeometry';
  10. this.parameters = {
  11. shapes: shapes,
  12. curveSegments: curveSegments
  13. };
  14. // buffers
  15. const indices = [];
  16. const vertices = [];
  17. const normals = [];
  18. const uvs = [];
  19. // helper variables
  20. let groupStart = 0;
  21. let groupCount = 0;
  22. // allow single and array values for "shapes" parameter
  23. if ( Array.isArray( shapes ) === false ) {
  24. addShape( shapes );
  25. } else {
  26. for ( let i = 0; i < shapes.length; i ++ ) {
  27. addShape( shapes[ i ] );
  28. this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
  29. groupStart += groupCount;
  30. groupCount = 0;
  31. }
  32. }
  33. // build geometry
  34. this.setIndex( indices );
  35. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  36. this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  37. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  38. // helper functions
  39. function addShape( shape ) {
  40. const indexOffset = vertices.length / 3;
  41. const points = shape.extractPoints( curveSegments );
  42. let shapeVertices = points.shape;
  43. const shapeHoles = points.holes;
  44. // check direction of vertices
  45. if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
  46. shapeVertices = shapeVertices.reverse();
  47. }
  48. for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
  49. const shapeHole = shapeHoles[ i ];
  50. if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
  51. shapeHoles[ i ] = shapeHole.reverse();
  52. }
  53. }
  54. const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
  55. // join vertices of inner and outer paths to a single array
  56. for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
  57. const shapeHole = shapeHoles[ i ];
  58. shapeVertices = shapeVertices.concat( shapeHole );
  59. }
  60. // vertices, normals, uvs
  61. for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
  62. const vertex = shapeVertices[ i ];
  63. vertices.push( vertex.x, vertex.y, 0 );
  64. normals.push( 0, 0, 1 );
  65. uvs.push( vertex.x, vertex.y ); // world uvs
  66. }
  67. // incides
  68. for ( let i = 0, l = faces.length; i < l; i ++ ) {
  69. const face = faces[ i ];
  70. const a = face[ 0 ] + indexOffset;
  71. const b = face[ 1 ] + indexOffset;
  72. const c = face[ 2 ] + indexOffset;
  73. indices.push( a, b, c );
  74. groupCount += 3;
  75. }
  76. }
  77. }
  78. toJSON() {
  79. const data = super.toJSON();
  80. const shapes = this.parameters.shapes;
  81. return toJSON( shapes, data );
  82. }
  83. static fromJSON( data, shapes ) {
  84. const geometryShapes = [];
  85. for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
  86. const shape = shapes[ data.shapes[ j ] ];
  87. geometryShapes.push( shape );
  88. }
  89. return new ShapeGeometry( geometryShapes, data.curveSegments );
  90. }
  91. }
  92. function toJSON( shapes, data ) {
  93. data.shapes = [];
  94. if ( Array.isArray( shapes ) ) {
  95. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  96. const shape = shapes[ i ];
  97. data.shapes.push( shape.uuid );
  98. }
  99. } else {
  100. data.shapes.push( shapes.uuid );
  101. }
  102. return data;
  103. }
  104. export { ShapeGeometry, ShapeGeometry as ShapeBufferGeometry };
粤ICP备19079148号