Source: primitives/Face.js

  1. /**
  2. * @description Face is a triangle or a quad.
  3. * If the face is a quad, both triangles composin the quad,
  4. * shader the same normal - thanks to this flat shaded materials have quads shaded
  5. * the same way which is nicer than havong each triangle have a slightly different normal.
  6. *
  7. * Currently it supports the following attributes: aPosition, aNormal, aUV and aColor.
  8. * Should support aTangent and aBinormal soon too.
  9. *
  10. * @class Face
  11. * @memberof SQR
  12. *
  13. */
  14. SQR.Face = function() {
  15. if(!(this instanceof SQR.Face)) return new SQR.Face();
  16. }
  17. /**
  18. * Set the vertex positions. For vertices a, b, c, and d is creates a quad as in the example below.
  19. *
  20. * @method setPosition
  21. * @memberof SQR.Face.prototype
  22. *
  23. * @param {SQR.V3} a - the first vertex position
  24. * @param {SQR.V3} b - the second vertex position
  25. * @param {SQR.V3} c - the thrid vertex position
  26. * @param {SQR.V3=} d - the optional fourth vertex position
  27. *
  28. * @example
  29. //
  30. // a - b
  31. // | / |
  32. // c - d
  33. //
  34. // resulting triangles: `abc, cbd`
  35. //
  36. */
  37. SQR.Face.prototype.setPosition = function(a, b, c, d) {
  38. var t = this;
  39. t.a = a || new SQR.V3();
  40. t.b = b || new SQR.V3();
  41. t.c = c || new SQR.V3();
  42. t.d = d;
  43. return t;
  44. }
  45. SQR.Face.prototype.setIndex = function(va, ia, ib, ic, id) {
  46. var t = this;
  47. t.indexed = true;
  48. t.ia = ia;
  49. t.ib = ib;
  50. t.ic = ic;
  51. t.id = id;
  52. t.vertexArray = va;
  53. return t;
  54. }
  55. SQR.Face.prototype.flip = function() {
  56. var t = this;
  57. var tmp = t.b;
  58. t.b = t.c;
  59. t.c = tmp;
  60. }
  61. /**
  62. * Set the normal shared by all the vertices
  63. * @method setNormal
  64. * @memberof SQR.Face.prototype
  65. */
  66. SQR.Face.prototype.setNormal = function(n) {
  67. this.normal = n;
  68. return this;
  69. }
  70. /**
  71. * Set the texture coordinates for each vertex
  72. *
  73. * @method setUV
  74. * @memberof SQR.Face.prototype
  75. *
  76. * @param {SQR.V2} a - the first vertex texture coordinate
  77. * @param {SQR.V2} b - the second vertex texture coordinate
  78. * @param {SQR.V2} c - the thrid vertex texture coordinate
  79. * @param {SQR.V2=} d - the optional fourth vertex texture coordinate
  80. */
  81. SQR.Face.prototype.setUV = function(uva, uvb, uvc, uvd) {
  82. var t = this;
  83. t.uva = uva;
  84. t.uvb = uvb;
  85. t.uvc = uvc;
  86. t.uvd = uvd;
  87. return t;
  88. }
  89. /**
  90. * Set the vertex color for each vertex
  91. * <br><br>
  92. * <strong>WARNING! Colors are not passed to the buffer currently (will be added in the future).</strong>
  93. *
  94. * @method setColor
  95. * @memberof SQR.Face.prototype
  96. *
  97. * @param {SQR.V2} a - the first vertex color
  98. * @param {SQR.V2} b - the second vertex color
  99. * @param {SQR.V2} c - the thrid vertex color
  100. * @param {SQR.V2=} d - the optional fourth vertex color
  101. */
  102. SQR.Face.prototype.setColor = function(ca, cb, cc, cd) {
  103. var t = this;
  104. t.ca = ca;
  105. t.cb = cb;
  106. t.cc = cc;
  107. t.cd = cd;
  108. return t;
  109. }
  110. /**
  111. * Calculte the normal for this face. Regardless of whether there are 3 or 4 vertices
  112. * the normal is calculated for the frst 3 of them an applied to the entire face.
  113. * @method calculateNormal
  114. * @memberof SQR.Face.prototype
  115. */
  116. SQR.Face.prototype.calculateNormal = function() {
  117. var t = this;
  118. var t1 = SQR.V3.__tv1;
  119. var t2 = SQR.V3.__tv2;
  120. var va = t.vertexArray;
  121. t.normal = t.normal || new SQR.V3();
  122. if(t.indexed) {
  123. t1.sub(va[t.ia], va[t.ib]);
  124. if(t1.isZero()) t1.sub(va[t.ia], va[t.id]);
  125. t2.sub(va[t.ic], va[t.ia]);
  126. } else {
  127. t1.sub(t.a, t.b);
  128. if(t1.isZero()) t1.sub(t.a, t.d);
  129. t2.sub(t.c, t.a);
  130. }
  131. t.normal.cross(t1, t2);
  132. return t;
  133. }
  134. SQR.Face.prototype.v = SQR.Face.prototype.setPosition;
  135. SQR.Face.prototype.i = SQR.Face.prototype.setIndex;
  136. SQR.Face.prototype.n = SQR.Face.prototype.setNormal;
  137. SQR.Face.prototype.uv = SQR.Face.prototype.setUV;
  138. SQR.Face.prototype.cl = SQR.Face.prototype.setColor;
  139. SQR.Face.prototype.cn = SQR.Face.prototype.calculateNormal;
  140. SQR.Face.prototype.addNormalToVertices = function() {
  141. var t = this;
  142. var va = t.vertexArray;
  143. var a = t.indexed ? va[t.ia] : t.a;
  144. var b = t.indexed ? va[t.ib] : t.b;
  145. var c = t.indexed ? va[t.ic] : t.c;
  146. var d = t.indexed ? va[t.id] : t.d;
  147. a.addNormal(t.normal);
  148. b.addNormal(t.normal);
  149. c.addNormal(t.normal);
  150. if(d) d.addNormal(t.normal);
  151. return t;
  152. }
  153. SQR.Face.prototype.toBuffer = function(geo, position, perVertextNormal, preNormalizeNormal) {
  154. var t = this;
  155. var ap = 'aPosition', an = 'aNormal', au = 'aUV';
  156. var c = position;
  157. if(geo.attributes[ap]) {
  158. geo.set(ap, c+0, t.a).set(ap, c+1, t.b).set(ap, c+2, t.c);
  159. if(t.d) geo.set(ap, c+3, t.c).set(ap, c+4, t.b).set(ap, c+5, t.d);
  160. }
  161. if(geo.attributes[an] && (t.normal || perVertextNormal)) {
  162. var v = perVertextNormal, n = t.normal;
  163. if(preNormalizeNormal && !v) t.normal.norm();
  164. geo.set(an, c+0, v ? t.a.normal : n)
  165. .set(an, c+1, v ? t.b.normal : n)
  166. .set(an, c+2, v ? t.c.normal : n);
  167. if(t.d) {
  168. geo.set(an, c+3, v ? t.c.normal : n)
  169. .set(an, c+4, v ? t.b.normal : n)
  170. .set(an, c+5, v ? t.d.normal : n);
  171. }
  172. }
  173. if(geo.attributes[au] && t.uva) {
  174. geo.set(au, c+0, t.uva).set(au, c+1, t.uvb).set(au, c+2, t.uvc);
  175. if(t.d) geo.set(au, c+3, t.uvc).set(au, c+4, t.uvb).set(au, c+5, t.uvd);
  176. }
  177. return t.d ? 6 : 3;
  178. }