2
0

ParametricGeometry.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /**
  2. * @author zz85 / https://github.com/zz85
  3. * @author Mugen87 / https://github.com/Mugen87
  4. *
  5. * Parametric Surfaces Geometry
  6. * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
  7. */
  8. import { Geometry } from '../core/Geometry.js';
  9. import { BufferGeometry } from '../core/BufferGeometry.js';
  10. import { Float32BufferAttribute } from '../core/BufferAttribute.js';
  11. import { Vector3 } from '../math/Vector3.js';
  12. // ParametricGeometry
  13. function ParametricGeometry( func, slices, stacks ) {
  14. Geometry.call( this );
  15. this.type = 'ParametricGeometry';
  16. this.parameters = {
  17. func: func,
  18. slices: slices,
  19. stacks: stacks
  20. };
  21. this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
  22. this.mergeVertices();
  23. }
  24. ParametricGeometry.prototype = Object.create( Geometry.prototype );
  25. ParametricGeometry.prototype.constructor = ParametricGeometry;
  26. // ParametricBufferGeometry
  27. function ParametricBufferGeometry( func, slices, stacks ) {
  28. BufferGeometry.call( this );
  29. this.type = 'ParametricBufferGeometry';
  30. this.parameters = {
  31. func: func,
  32. slices: slices,
  33. stacks: stacks
  34. };
  35. // buffers
  36. var indices = [];
  37. var vertices = [];
  38. var normals = [];
  39. var uvs = [];
  40. var EPS = 0.00001;
  41. var normal = new Vector3();
  42. var p0 = new Vector3(), p1 = new Vector3();
  43. var pu = new Vector3(), pv = new Vector3();
  44. var i, j;
  45. // generate vertices, normals and uvs
  46. var sliceCount = slices + 1;
  47. for ( i = 0; i <= stacks; i ++ ) {
  48. var v = i / stacks;
  49. for ( j = 0; j <= slices; j ++ ) {
  50. var u = j / slices;
  51. // vertex
  52. p0 = func( u, v, p0 );
  53. vertices.push( p0.x, p0.y, p0.z );
  54. // normal
  55. // approximate tangent vectors via finite differences
  56. if ( u - EPS >= 0 ) {
  57. p1 = func( u - EPS, v, p1 );
  58. pu.subVectors( p0, p1 );
  59. } else {
  60. p1 = func( u + EPS, v, p1 );
  61. pu.subVectors( p1, p0 );
  62. }
  63. if ( v - EPS >= 0 ) {
  64. p1 = func( u, v - EPS, p1 );
  65. pv.subVectors( p0, p1 );
  66. } else {
  67. p1 = func( u, v + EPS, p1 );
  68. pv.subVectors( p1, p0 );
  69. }
  70. // cross product of tangent vectors returns surface normal
  71. normal.crossVectors( pu, pv ).normalize();
  72. normals.push( normal.x, normal.y, normal.z );
  73. // uv
  74. uvs.push( u, v );
  75. }
  76. }
  77. // generate indices
  78. for ( i = 0; i < stacks; i ++ ) {
  79. for ( j = 0; j < slices; j ++ ) {
  80. var a = i * sliceCount + j;
  81. var b = i * sliceCount + j + 1;
  82. var c = ( i + 1 ) * sliceCount + j + 1;
  83. var d = ( i + 1 ) * sliceCount + j;
  84. // faces one and two
  85. indices.push( a, b, d );
  86. indices.push( b, c, d );
  87. }
  88. }
  89. // build geometry
  90. this.setIndex( indices );
  91. this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  92. this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
  93. this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  94. }
  95. ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
  96. ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
  97. export { ParametricGeometry, ParametricBufferGeometry };