glTFLoaderUtils.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /**
  2. * @author Tony Parisi / http://www.tonyparisi.com/
  3. */
  4. THREE.GLTFLoaderUtils = Object.create(Object, {
  5. // errors
  6. MISSING_DESCRIPTION: { value: "MISSING_DESCRIPTION" },
  7. INVALID_PATH: { value: "INVALID_PATH" },
  8. INVALID_TYPE: { value: "INVALID_TYPE" },
  9. XMLHTTPREQUEST_STATUS_ERROR: { value: "XMLHTTPREQUEST_STATUS_ERROR" },
  10. NOT_FOUND: { value: "NOT_FOUND" },
  11. // misc constants
  12. ARRAY_BUFFER: { value: "ArrayBuffer" },
  13. _streams : { value:{}, writable: true },
  14. _streamsStatus: { value: {}, writable: true },
  15. _resources: { value: {}, writable: true },
  16. _resourcesStatus: { value: {}, writable: true },
  17. // initialization
  18. init: {
  19. value: function() {
  20. this._streams = {};
  21. this._streamsStatus = {};
  22. this._resources = {};
  23. this._resourcesStatus = {};
  24. }
  25. },
  26. //manage entries
  27. _containsResource: {
  28. enumerable: false,
  29. value: function(resourceID) {
  30. return this._resources[resourceID] ? true : false;
  31. }
  32. },
  33. _storeResource: {
  34. enumerable: false,
  35. value: function(resourceID, resource) {
  36. if (!resourceID) {
  37. console.log("ERROR: entry does not contain id, cannot store");
  38. return;
  39. }
  40. if (this._containsResource[resourceID]) {
  41. console.log("WARNING: resource:"+resourceID+" is already stored, overriding");
  42. }
  43. this._resources[resourceID] = resource;
  44. }
  45. },
  46. _getResource: {
  47. enumerable: false,
  48. value: function(resourceID) {
  49. return this._resources[resourceID];
  50. }
  51. },
  52. _loadStream: {
  53. value: function(path, type, delegate) {
  54. var self = this;
  55. if (!type) {
  56. delegate.handleError(THREE.GLTFLoaderUtils.INVALID_TYPE, null);
  57. return;
  58. }
  59. if (!path) {
  60. delegate.handleError(THREE.GLTFLoaderUtils.INVALID_PATH);
  61. return;
  62. }
  63. var xhr = new XMLHttpRequest();
  64. xhr.open('GET', path, true);
  65. xhr.responseType = (type === this.ARRAY_BUFFER) ? "arraybuffer" : "text";
  66. //if this is not specified, 1 "big blob" scenes fails to load.
  67. xhr.setRequestHeader("If-Modified-Since", "Sat, 01 Jan 1970 00:00:00 GMT");
  68. xhr.onload = function(e) {
  69. if ((xhr.status == 200) || (xhr.status == 206)) {
  70. delegate.streamAvailable(path, xhr.response);
  71. } else {
  72. delegate.handleError(THREE.GLTFLoaderUtils.XMLHTTPREQUEST_STATUS_ERROR, this.status);
  73. }
  74. };
  75. xhr.send(null);
  76. }
  77. },
  78. send: { value: 0, writable: true },
  79. requested: { value: 0, writable: true },
  80. _handleRequest: {
  81. value: function(request) {
  82. var resourceStatus = this._resourcesStatus[request.id];
  83. if (resourceStatus)
  84. {
  85. this._resourcesStatus[request.id]++;
  86. }
  87. else
  88. {
  89. this._resourcesStatus[request.id] = 1;
  90. }
  91. var streamStatus = this._streamsStatus[request.path];
  92. if (streamStatus && streamStatus.status === "loading" )
  93. {
  94. streamStatus.requests.push(request);
  95. return;
  96. }
  97. this._streamsStatus[request.path] = { status : "loading", requests : [request] };
  98. var self = this;
  99. var processResourceDelegate = {};
  100. processResourceDelegate.streamAvailable = function(path, res_) {
  101. var streamStatus = self._streamsStatus[path];
  102. var requests = streamStatus.requests;
  103. requests.forEach( function(req_) {
  104. var subArray = res_.slice(req_.range[0], req_.range[1]);
  105. var convertedResource = req_.delegate.convert(subArray, req_.ctx);
  106. self._storeResource(req_.id, convertedResource);
  107. req_.delegate.resourceAvailable(convertedResource, req_.ctx);
  108. --self._resourcesStatus[req_.id];
  109. }, this);
  110. delete self._streamsStatus[path];
  111. };
  112. processResourceDelegate.handleError = function(errorCode, info) {
  113. request.delegate.handleError(errorCode, info);
  114. }
  115. this._loadStream(request.path, request.type, processResourceDelegate);
  116. }
  117. },
  118. _elementSizeForGLType: {
  119. value: function(glType) {
  120. switch (glType) {
  121. case WebGLRenderingContext.FLOAT :
  122. return Float32Array.BYTES_PER_ELEMENT;
  123. case WebGLRenderingContext.UNSIGNED_BYTE :
  124. return Uint8Array.BYTES_PER_ELEMENT;
  125. case WebGLRenderingContext.UNSIGNED_SHORT :
  126. return Uint16Array.BYTES_PER_ELEMENT;
  127. case WebGLRenderingContext.FLOAT_VEC2 :
  128. return Float32Array.BYTES_PER_ELEMENT * 2;
  129. case WebGLRenderingContext.FLOAT_VEC3 :
  130. return Float32Array.BYTES_PER_ELEMENT * 3;
  131. case WebGLRenderingContext.FLOAT_VEC4 :
  132. return Float32Array.BYTES_PER_ELEMENT * 4;
  133. case WebGLRenderingContext.FLOAT_MAT3 :
  134. return Float32Array.BYTES_PER_ELEMENT * 9;
  135. case WebGLRenderingContext.FLOAT_MAT4 :
  136. return Float32Array.BYTES_PER_ELEMENT * 16;
  137. default:
  138. return null;
  139. }
  140. }
  141. },
  142. _handleWrappedBufferViewResourceLoading: {
  143. value: function(wrappedBufferView, delegate, ctx) {
  144. var bufferView = wrappedBufferView.bufferView;
  145. var buffer = bufferView.buffer;
  146. var byteOffset = wrappedBufferView.byteOffset + bufferView.description.byteOffset;
  147. var range = [byteOffset , (this._elementSizeForGLType(wrappedBufferView.type) * wrappedBufferView.count) + byteOffset];
  148. this._handleRequest({ "id" : wrappedBufferView.id,
  149. "range" : range,
  150. "type" : buffer.description.type,
  151. "path" : buffer.description.path,
  152. "delegate" : delegate,
  153. "ctx" : ctx }, null);
  154. }
  155. },
  156. getBuffer: {
  157. value: function(wrappedBufferView, delegate, ctx) {
  158. var savedBuffer = this._getResource(wrappedBufferView.id);
  159. if (savedBuffer) {
  160. return savedBuffer;
  161. } else {
  162. this._handleWrappedBufferViewResourceLoading(wrappedBufferView, delegate, ctx);
  163. }
  164. return null;
  165. }
  166. },
  167. getFile: {
  168. value: function(request, delegate, ctx) {
  169. request.delegate = delegate;
  170. request.ctx = ctx;
  171. this._handleRequest({ "id" : request.id,
  172. "path" : request.path,
  173. "range" : [0],
  174. "type" : "text",
  175. "delegate" : delegate,
  176. "ctx" : ctx }, null);
  177. return null;
  178. }
  179. },
  180. });