index.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. function getVertexBuffer(vertexData) {
  2. const vertexCount = vertexData.length / 12;
  3. const noise = 0.03;
  4. for (let i = 0; i < vertexCount; i++) {
  5. const vertexIndex = i * 12;
  6. // x
  7. vertexData[vertexIndex] = vertexData[vertexIndex] + Math.random() * noise - noise / 2;
  8. // y
  9. vertexData[vertexIndex + 1] = vertexData[vertexIndex + 1]+ Math.random() * noise - noise / 2;
  10. // z
  11. vertexData[vertexIndex + 2] = vertexData[vertexIndex + 2] + Math.random() * noise - noise / 2;
  12. // normal x
  13. // vertexData[vertexIndex + 3]
  14. // normal y
  15. // vertexData[vertexIndex + 4]
  16. // normal z
  17. // vertexData[vertexIndex + 5]
  18. // u
  19. // vertexData[vertexIndex + 6]
  20. // v
  21. // vertexData[vertexIndex + 7]
  22. // r
  23. vertexData[vertexIndex + 8] = i / vertexCount;
  24. // g
  25. vertexData[vertexIndex + 9] = i / vertexCount;
  26. // b
  27. vertexData[vertexIndex + 10] = i / vertexCount;
  28. // a
  29. // vertexData[vertexIndex + 11]
  30. }
  31. return new Float32Array(vertexData);
  32. }
  33. function buildSphere(
  34. vertexs,
  35. indices,
  36. radius = 1,
  37. widthSegments = 32,
  38. heightSegments = 16,
  39. phiStart = Math.PI /2,
  40. phiLength = Math.PI * 2,
  41. thetaStart = Math.PI,
  42. thetaLength = Math.PI
  43. ) {
  44. widthSegments = Math.max( 3, Math.floor( widthSegments ) );
  45. heightSegments = Math.max( 2, Math.floor( heightSegments ) );
  46. const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
  47. let index = 0;
  48. const grid = [];
  49. // generate vertices, normals and uvs
  50. for ( let iy = 0; iy <= heightSegments; iy ++ ) {
  51. const verticesRow = [];
  52. const v = iy / heightSegments;
  53. // special case for the poles
  54. let uOffset = 0;
  55. if ( iy == 0 && thetaStart == 0 ) {
  56. uOffset = 0.5 / widthSegments;
  57. } else if ( iy == heightSegments && thetaEnd == Math.PI ) {
  58. uOffset = - 0.5 / widthSegments;
  59. }
  60. for ( let ix = 0; ix <= widthSegments; ix ++ ) {
  61. const u = ix / widthSegments;
  62. // vertex
  63. const vertexX = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
  64. const vertexY = radius * Math.cos( thetaStart + v * thetaLength );
  65. const vertexZ = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
  66. vertexs.push(vertexX, vertexY, vertexZ);
  67. // normal
  68. vertexs.push(vertexX / 3, vertexY / 3, vertexZ / 3);
  69. // uv
  70. vertexs.push(u + uOffset, 1 - v );
  71. // color
  72. vertexs.push(0, 0, 0, 1);
  73. verticesRow.push( index ++ );
  74. }
  75. grid.push( verticesRow );
  76. }
  77. // indices
  78. for ( let iy = 0; iy < heightSegments; iy ++ ) {
  79. for ( let ix = 0; ix < widthSegments; ix ++ ) {
  80. const a = grid[ iy ][ ix + 1 ];
  81. const b = grid[ iy ][ ix ];
  82. const c = grid[ iy + 1 ][ ix ];
  83. const d = grid[ iy + 1 ][ ix + 1 ];
  84. if ( iy !== 0 || thetaStart > 0 ) indices.push( a, d, b );
  85. if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, d, c );
  86. }
  87. }
  88. }
  89. Component({
  90. behaviors: [require('../../common/share-behavior').default],
  91. properties: {
  92. a: Number,
  93. },
  94. data: {
  95. loaded: false
  96. },
  97. lifetimes: {},
  98. methods: {
  99. handleReady({detail}) {
  100. const xrScene = this.scene = detail.value;
  101. console.log('xr-scene', xrScene);
  102. const xrFrameSystem = wx.getXrFrameSystem()
  103. this.geometryRoot = this.scene.getElementById('geometryRoot');
  104. const geoRadius = 1;
  105. this.vertexData = [];
  106. this.indexData = [];
  107. // 构造圆形的 顶点信息,可以通过增加切分区域增加顶点数量
  108. // 一般复杂人物 vertex 长度 77030 index 88266
  109. buildSphere(this.vertexData, this.indexData, geoRadius, 64, 64);
  110. console.log('vertexDataCount', this.vertexData.length);
  111. console.log('indexDataCount', this.indexData.length);
  112. // 注册 Geometry 信息
  113. xrFrameSystem.registerGeometry('man', scene => {
  114. const vl = scene.createVertexLayout({
  115. attributes: [
  116. {
  117. name: "a_position",
  118. format: xrFrameSystem.EVertexFormat.FLOAT3,
  119. offset: 0,
  120. usage: xrFrameSystem.EVertexLayoutUsage.POSITION
  121. },
  122. {
  123. name: "a_normal",
  124. format: xrFrameSystem.EVertexFormat.FLOAT3,
  125. offset: 12,
  126. usage: xrFrameSystem.EVertexLayoutUsage.NORMAL,
  127. },
  128. {
  129. name: "a_texCoord",
  130. format: xrFrameSystem.EVertexFormat.FLOAT2,
  131. offset: 24,
  132. usage: xrFrameSystem.EVertexLayoutUsage.UV0
  133. },
  134. {
  135. name: "a_color",
  136. format: xrFrameSystem.EVertexFormat.FLOAT4,
  137. offset: 32,
  138. usage: xrFrameSystem.EVertexLayoutUsage.COLOR
  139. }
  140. ],
  141. stride: 48
  142. });
  143. // VertexBuffer IndexBuffer 不能动态更改长度,需要一开始设定较大的长度。
  144. const vb = new Float32Array(this.vertexData.length);
  145. const ib = new Uint16Array(this.indexData);
  146. const geo = scene.createGeometry(vl, vb, ib);
  147. geo.setBoundBall(new xrFrameSystem.Vector3(), 1);
  148. geo.addSubMesh(ib.length, 0, 0);
  149. return geo;
  150. });
  151. this.geoElem = xrScene.createElement(xrFrameSystem.XRMesh, {
  152. geometry: "man",
  153. material: 'simple-mat',
  154. position: "0 0 0"
  155. });
  156. this.geometryRoot.addChild(this.geoElem);
  157. // 延时保证挂载与初始化完毕
  158. setTimeout(()=>{
  159. this.meshGeo = this.geoElem.getComponent(xrFrameSystem.Mesh);
  160. this.geometryGeo = this.meshGeo.geometry;
  161. this.matGeo = this.meshGeo.material;
  162. // 使用顶点色
  163. this.matGeo.setMacro("WX_USE_COLOR_0", true);
  164. // 设定 绘制双面
  165. this.matGeo.setRenderState("cullOn", false);
  166. xrScene.event.add('tick', this.handleTick.bind(this));
  167. },100);
  168. },
  169. handleAssetsProgress: function({detail}) {
  170. console.log('assets progress', detail.value);
  171. },
  172. handleAssetsLoaded: function({detail}) {
  173. console.log('assets loaded', detail.value);
  174. },
  175. handleTick(delta) {
  176. const vb = getVertexBuffer(this.vertexData);
  177. const ib = new Uint16Array(this.indexData);
  178. this.geometryGeo.uploadVertexBuffer(0, vb);
  179. this.geometryGeo.uploadIndexBuffer(0, ib);
  180. },
  181. }
  182. })