glTFLoaderUtils.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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.addEventListener( 'load', function ( event ) {
  69. delegate.streamAvailable(path, xhr.response);
  70. }, false );
  71. xhr.addEventListener( 'error', function ( event ) {
  72. delegate.handleError(THREE.GLTFLoaderUtils.XMLHTTPREQUEST_STATUS_ERROR, xhr.status);
  73. }, false );
  74. xhr.send(null);
  75. }
  76. },
  77. send: { value: 0, writable: true },
  78. requested: { value: 0, writable: true },
  79. _handleRequest: {
  80. value: function(request) {
  81. var resourceStatus = this._resourcesStatus[request.id];
  82. if (resourceStatus)
  83. {
  84. this._resourcesStatus[request.id] ++;
  85. }
  86. else
  87. {
  88. this._resourcesStatus[request.id] = 1;
  89. }
  90. var streamStatus = this._streamsStatus[request.path];
  91. if (streamStatus && streamStatus.status === "loading" )
  92. {
  93. streamStatus.requests.push(request);
  94. return;
  95. }
  96. this._streamsStatus[request.path] = { status : "loading", requests : [ request ] };
  97. var self = this;
  98. var processResourceDelegate = {};
  99. processResourceDelegate.streamAvailable = function(path, res_) {
  100. var streamStatus = self._streamsStatus[path];
  101. var requests = streamStatus.requests;
  102. requests.forEach( function(req_) {
  103. var subArray = res_.slice(req_.range[0], req_.range[1]);
  104. var convertedResource = req_.delegate.convert(subArray, req_.ctx);
  105. self._storeResource(req_.id, convertedResource);
  106. req_.delegate.resourceAvailable(convertedResource, req_.ctx);
  107. -- self._resourcesStatus[req_.id];
  108. }, this);
  109. delete self._streamsStatus[path];
  110. };
  111. processResourceDelegate.handleError = function(errorCode, info) {
  112. request.delegate.handleError(errorCode, info);
  113. }
  114. this._loadStream(request.path, request.type, processResourceDelegate);
  115. }
  116. },
  117. _elementSizeForGLType: {
  118. value: function(glType) {
  119. switch (glType) {
  120. case WebGLRenderingContext.FLOAT :
  121. return Float32Array.BYTES_PER_ELEMENT;
  122. case WebGLRenderingContext.UNSIGNED_BYTE :
  123. return Uint8Array.BYTES_PER_ELEMENT;
  124. case WebGLRenderingContext.UNSIGNED_SHORT :
  125. return Uint16Array.BYTES_PER_ELEMENT;
  126. case WebGLRenderingContext.FLOAT_VEC2 :
  127. return Float32Array.BYTES_PER_ELEMENT * 2;
  128. case WebGLRenderingContext.FLOAT_VEC3 :
  129. return Float32Array.BYTES_PER_ELEMENT * 3;
  130. case WebGLRenderingContext.FLOAT_VEC4 :
  131. return Float32Array.BYTES_PER_ELEMENT * 4;
  132. case WebGLRenderingContext.FLOAT_MAT3 :
  133. return Float32Array.BYTES_PER_ELEMENT * 9;
  134. case WebGLRenderingContext.FLOAT_MAT4 :
  135. return Float32Array.BYTES_PER_ELEMENT * 16;
  136. default:
  137. return null;
  138. }
  139. }
  140. },
  141. _handleWrappedBufferViewResourceLoading: {
  142. value: function(wrappedBufferView, delegate, ctx) {
  143. var bufferView = wrappedBufferView.bufferView;
  144. var buffer = bufferView.buffer;
  145. var byteOffset = wrappedBufferView.byteOffset + bufferView.description.byteOffset;
  146. var range = [ byteOffset, (this._elementSizeForGLType(wrappedBufferView.type) * wrappedBufferView.count) + byteOffset ];
  147. this._handleRequest({ "id" : wrappedBufferView.id,
  148. "range" : range,
  149. "type" : buffer.description.type,
  150. "path" : buffer.description.path,
  151. "delegate" : delegate,
  152. "ctx" : ctx }, null);
  153. }
  154. },
  155. getBuffer: {
  156. value: function(wrappedBufferView, delegate, ctx) {
  157. var savedBuffer = this._getResource(wrappedBufferView.id);
  158. if (savedBuffer) {
  159. return savedBuffer;
  160. } else {
  161. this._handleWrappedBufferViewResourceLoading(wrappedBufferView, delegate, ctx);
  162. }
  163. return null;
  164. }
  165. },
  166. getFile: {
  167. value: function(request, delegate, ctx) {
  168. request.delegate = delegate;
  169. request.ctx = ctx;
  170. this._handleRequest({ "id" : request.id,
  171. "path" : request.path,
  172. "range" : [ 0 ],
  173. "type" : "text",
  174. "delegate" : delegate,
  175. "ctx" : ctx }, null);
  176. return null;
  177. }
  178. },
  179. });