babylon.glTFFileLoaderUtils.ts 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. module BABYLON {
  2. /**
  3. * Utils functions for GLTF
  4. */
  5. export class GLTFUtils {
  6. /**
  7. * Sets the given "parameter" matrix
  8. * @param scene: the {BABYLON.Scene} object
  9. * @param source: the source node where to pick the matrix
  10. * @param parameter: the GLTF technique parameter
  11. * @param uniformName: the name of the shader's uniform
  12. * @param shaderMaterial: the shader material
  13. */
  14. public static SetMatrix(scene: Scene, source: Node, parameter: IGLTFTechniqueParameter, uniformName: string, shaderMaterial: ShaderMaterial | Effect): void {
  15. var mat: Matrix = null;
  16. if (parameter.semantic === "MODEL") {
  17. mat = source.getWorldMatrix();
  18. }
  19. else if (parameter.semantic === "PROJECTION") {
  20. mat = scene.getProjectionMatrix();
  21. }
  22. else if (parameter.semantic === "VIEW") {
  23. mat = scene.getViewMatrix();
  24. }
  25. else if (parameter.semantic === "MODELVIEWINVERSETRANSPOSE") {
  26. mat = Matrix.Transpose(source.getWorldMatrix().multiply(scene.getViewMatrix()).invert());
  27. }
  28. else if (parameter.semantic === "MODELVIEW") {
  29. mat = source.getWorldMatrix().multiply(scene.getViewMatrix());
  30. }
  31. else if (parameter.semantic === "MODELVIEWPROJECTION") {
  32. mat = source.getWorldMatrix().multiply(scene.getTransformMatrix());
  33. }
  34. else if (parameter.semantic === "MODELINVERSE") {
  35. mat = source.getWorldMatrix().invert();
  36. }
  37. else if (parameter.semantic === "VIEWINVERSE") {
  38. mat = scene.getViewMatrix().invert();
  39. }
  40. else if (parameter.semantic === "PROJECTIONINVERSE") {
  41. mat = scene.getProjectionMatrix().invert();
  42. }
  43. else if (parameter.semantic === "MODELVIEWINVERSE") {
  44. mat = source.getWorldMatrix().multiply(scene.getViewMatrix()).invert();
  45. }
  46. else if (parameter.semantic === "MODELVIEWPROJECTIONINVERSE") {
  47. mat = source.getWorldMatrix().multiply(scene.getTransformMatrix()).invert();
  48. }
  49. else if (parameter.semantic === "MODELINVERSETRANSPOSE") {
  50. mat = Matrix.Transpose(source.getWorldMatrix().invert());
  51. }
  52. else {
  53. debugger;
  54. }
  55. switch (parameter.type) {
  56. case EParameterType.FLOAT_MAT2: shaderMaterial.setMatrix2x2(uniformName, Matrix.GetAsMatrix2x2(mat)); break;
  57. case EParameterType.FLOAT_MAT3: shaderMaterial.setMatrix3x3(uniformName, Matrix.GetAsMatrix3x3(mat)); break;
  58. case EParameterType.FLOAT_MAT4: shaderMaterial.setMatrix(uniformName, mat); break;
  59. default: break;
  60. }
  61. }
  62. /**
  63. * Sets the given "parameter" matrix
  64. * @param shaderMaterial: the shader material
  65. * @param uniform: the name of the shader's uniform
  66. * @param value: the value of the uniform
  67. * @param type: the uniform's type (EParameterType FLOAT, VEC2, VEC3 or VEC4)
  68. */
  69. public static SetUniform(shaderMaterial: ShaderMaterial | Effect, uniform: string, value: any, type: number): boolean {
  70. switch (type) {
  71. case EParameterType.FLOAT: shaderMaterial.setFloat(uniform, value); return true;
  72. case EParameterType.FLOAT_VEC2: shaderMaterial.setVector2(uniform, Vector2.FromArray(value)); return true;
  73. case EParameterType.FLOAT_VEC3: shaderMaterial.setVector3(uniform, Vector3.FromArray(value)); return true;
  74. case EParameterType.FLOAT_VEC4: shaderMaterial.setVector4(uniform, Vector4.FromArray(value)); return true;
  75. default: return false;
  76. }
  77. }
  78. /**
  79. * If the uri is a base64 string
  80. * @param uri: the uri to test
  81. */
  82. public static IsBase64(uri: string): boolean {
  83. return uri.length < 5 ? false : uri.substr(0, 5) === "data:";
  84. }
  85. /**
  86. * Returns the wrap mode of the texture
  87. * @param mode: the mode value
  88. */
  89. public static GetWrapMode(mode: number): number {
  90. switch (mode) {
  91. case ETextureWrapMode.CLAMP_TO_EDGE: return Texture.CLAMP_ADDRESSMODE;
  92. case ETextureWrapMode.MIRRORED_REPEAT: return Texture.MIRROR_ADDRESSMODE;
  93. case ETextureWrapMode.REPEAT: return Texture.WRAP_ADDRESSMODE;
  94. default: return Texture.WRAP_ADDRESSMODE;
  95. }
  96. }
  97. /**
  98. * Loads a texture from its name
  99. * @param gltfRuntime: the gltf runtime
  100. * @param name: the name of the texture
  101. */
  102. public static LoadTexture(gltfRuntime: IGLTFRuntime, name: string): Texture {
  103. var texture: IGLTFTexture = gltfRuntime.textures[name];
  104. if (!texture || !texture.source) {
  105. return null;
  106. }
  107. if (texture.babylonTexture) {
  108. return texture.babylonTexture;
  109. }
  110. var sampler: IGLTFSampler = gltfRuntime.samplers[texture.sampler];
  111. var source: IGLTFImage = gltfRuntime.images[texture.source];
  112. var newTexture: Texture = null;
  113. var createMipMaps = (sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_NEAREST) ||
  114. (sampler.minFilter === ETextureFilterType.NEAREST_MIPMAP_LINEAR) ||
  115. (sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_NEAREST) ||
  116. (sampler.minFilter === ETextureFilterType.LINEAR_MIPMAP_LINEAR);
  117. var samplingMode = Texture.BILINEAR_SAMPLINGMODE;
  118. if (GLTFUtils.IsBase64(source.uri)) {
  119. newTexture = new Texture(source.uri, gltfRuntime.scene, !createMipMaps, true, samplingMode, null, null, source.uri, true);
  120. }
  121. else {
  122. newTexture = new Texture(gltfRuntime.rootUrl + source.uri, gltfRuntime.scene, !createMipMaps, true, samplingMode);
  123. }
  124. newTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
  125. newTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
  126. newTexture.name = name;
  127. texture.babylonTexture = newTexture;
  128. return newTexture;
  129. }
  130. /**
  131. * Returns the byte stride giving an accessor
  132. * @param accessor: the GLTF accessor objet
  133. */
  134. public static GetByteStrideFromType(accessor: IGLTFAccessor): number {
  135. // Needs this function since "byteStride" isn't requiered in glTF format
  136. var type = accessor.type;
  137. switch (type) {
  138. case "VEC2": return 2;
  139. case "VEC3": return 3;
  140. case "VEC4": return 4;
  141. case "MAT2": return 4;
  142. case "MAT3": return 9;
  143. case "MAT4": return 16;
  144. default: return 1;
  145. }
  146. }
  147. /**
  148. * Returns the texture filter mode giving a mode value
  149. * @param mode: the filter mode value
  150. */
  151. public static GetTextureFilterMode(mode: number): ETextureFilterType {
  152. switch (mode) {
  153. case ETextureFilterType.LINEAR:
  154. case ETextureFilterType.LINEAR_MIPMAP_NEAREST:
  155. case ETextureFilterType.LINEAR_MIPMAP_LINEAR: return Texture.TRILINEAR_SAMPLINGMODE;
  156. case ETextureFilterType.NEAREST:
  157. case ETextureFilterType.NEAREST_MIPMAP_NEAREST: return Texture.NEAREST_SAMPLINGMODE;
  158. default: return Texture.BILINEAR_SAMPLINGMODE;
  159. }
  160. }
  161. public static GetBufferFromBufferView(gltfRuntime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): any {
  162. var byteOffset = bufferView.byteOffset + byteOffset;
  163. var loadedBufferView = gltfRuntime.loadedBufferViews[bufferView.buffer];
  164. if (byteOffset + byteLength > loadedBufferView.byteLength) {
  165. throw new Error("Buffer access is out of range");
  166. }
  167. var buffer = loadedBufferView.buffer;
  168. byteOffset += loadedBufferView.byteOffset;
  169. switch (componentType) {
  170. case EComponentType.BYTE: return new Int8Array(buffer, byteOffset, byteLength);
  171. case EComponentType.UNSIGNED_BYTE: return new Uint8Array(buffer, byteOffset, byteLength);
  172. case EComponentType.SHORT: return new Int16Array(buffer, byteOffset, byteLength);
  173. case EComponentType.UNSIGNED_SHORT: return new Uint16Array(buffer, byteOffset, byteLength);
  174. default: return new Float32Array(buffer, byteOffset, byteLength);
  175. }
  176. }
  177. /**
  178. * Returns a buffer from its accessor
  179. * @param gltfRuntime: the GLTF runtime
  180. * @param accessor: the GLTF accessor
  181. */
  182. public static GetBufferFromAccessor(gltfRuntime: IGLTFRuntime, accessor: IGLTFAccessor): any {
  183. var bufferView: IGLTFBufferView = gltfRuntime.bufferViews[accessor.bufferView];
  184. var byteLength = accessor.count * GLTFUtils.GetByteStrideFromType(accessor);
  185. return GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, accessor.byteOffset, byteLength, accessor.componentType);
  186. }
  187. /**
  188. * Decodes a buffer view into a string
  189. * @param view: the buffer view
  190. */
  191. public static DecodeBufferToText(view: ArrayBufferView): string {
  192. var result = "";
  193. var length = view.byteLength;
  194. for (var i = 0; i < length; ++i) {
  195. result += String.fromCharCode(view[i]);
  196. }
  197. return result;
  198. }
  199. }
  200. }