瀏覽代碼

Added VTP support for VTK.

Now you can load vtp files (can be binary, ascii and compressed).
Also added a example related to it. It depends on the Zlib.js inflate.
It can be optimized a little more.

I havent tested on large variety of files, but for smaller ones, it should work.
It does not support Int64 numbers yet, so any model that has such numbers might not load correctly.
There is still a problem of converting the binary compressed string to the original data if the string is not in this format XXXX==XXXX. But it works for most cases.
Sagar Dwibhashyam 9 年之前
父節點
當前提交
31ff1e7b92

+ 15 - 0
examples/js/libs/inflate.min.js

@@ -0,0 +1,15 @@
+/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var m=this;function q(c,d){var a=c.split("."),b=m;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&void 0!==d?b[e]=d:b=b[e]?b[e]:b[e]={}};var s="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function t(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,l,p,n,r,K;for(n=0;n<d;++n)c[n]>a&&(a=c[n]),c[n]<b&&(b=c[n]);e=1<<a;f=new (s?Uint32Array:Array)(e);g=1;h=0;for(k=2;g<=a;){for(n=0;n<d;++n)if(c[n]===g){l=0;p=h;for(r=0;r<g;++r)l=l<<1|p&1,p>>=1;K=g<<16|n;for(r=l;r<e;r+=k)f[r]=K;++h}++g;h<<=1;k<<=1}return[f,a,b]};function u(c,d){this.g=[];this.h=32768;this.d=this.f=this.a=this.l=0;this.input=s?new Uint8Array(c):c;this.m=!1;this.i=v;this.s=!1;if(d||!(d={}))d.index&&(this.a=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.s=d.resize);switch(this.i){case w:this.b=32768;this.c=new (s?Uint8Array:Array)(32768+this.h+258);break;case v:this.b=0;this.c=new (s?Uint8Array:Array)(this.h);this.e=this.A;this.n=this.w;this.j=this.z;break;default:throw Error("invalid inflate mode");
+}}var w=0,v=1,x={u:w,t:v};
+u.prototype.k=function(){for(;!this.m;){var c=y(this,3);c&1&&(this.m=!0);c>>>=1;switch(c){case 0:var d=this.input,a=this.a,b=this.c,e=this.b,f=d.length,g=void 0,h=void 0,k=b.length,l=void 0;this.d=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=d[a++]|d[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=d[a++]|d[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case w:for(;e+
+g>b.length;){l=k-e;g-=l;if(s)b.set(d.subarray(a,a+l),e),e+=l,a+=l;else for(;l--;)b[e++]=d[a++];this.b=e;b=this.e();e=this.b}break;case v:for(;e+g>b.length;)b=this.e({p:2});break;default:throw Error("invalid inflate mode");}if(s)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.a=a;this.b=e;this.c=b;break;case 1:this.j(z,A);break;case 2:B(this);break;default:throw Error("unknown BTYPE: "+c);}}return this.n()};
+var C=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],D=s?new Uint16Array(C):C,E=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],F=s?new Uint16Array(E):E,G=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],H=s?new Uint8Array(G):G,I=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],J=s?new Uint16Array(I):I,L=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,
+13],M=s?new Uint8Array(L):L,N=new (s?Uint8Array:Array)(288),O,P;O=0;for(P=N.length;O<P;++O)N[O]=143>=O?8:255>=O?9:279>=O?7:8;var z=t(N),Q=new (s?Uint8Array:Array)(30),R,S;R=0;for(S=Q.length;R<S;++R)Q[R]=5;var A=t(Q);function y(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h;b<d;){if(f>=g)throw Error("input buffer is broken");a|=e[f++]<<b;b+=8}h=a&(1<<d)-1;c.f=a>>>d;c.d=b-d;c.a=f;return h}
+function T(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h=d[0],k=d[1],l,p;b<k&&!(f>=g);)a|=e[f++]<<b,b+=8;l=h[a&(1<<k)-1];p=l>>>16;c.f=a>>p;c.d=b-p;c.a=f;return l&65535}
+function B(c){function d(a,c,b){var d,e=this.q,f,g;for(g=0;g<a;)switch(d=T(this,c),d){case 16:for(f=3+y(this,2);f--;)b[g++]=e;break;case 17:for(f=3+y(this,3);f--;)b[g++]=0;e=0;break;case 18:for(f=11+y(this,7);f--;)b[g++]=0;e=0;break;default:e=b[g++]=d}this.q=e;return b}var a=y(c,5)+257,b=y(c,5)+1,e=y(c,4)+4,f=new (s?Uint8Array:Array)(D.length),g,h,k,l;for(l=0;l<e;++l)f[D[l]]=y(c,3);if(!s){l=e;for(e=f.length;l<e;++l)f[D[l]]=0}g=t(f);h=new (s?Uint8Array:Array)(a);k=new (s?Uint8Array:Array)(b);c.q=0;
+c.j(t(d.call(c,a,g,h)),t(d.call(c,b,g,k)))}u.prototype.j=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length-258,f,g,h,k;256!==(f=T(this,c));)if(256>f)b>=e&&(this.b=b,a=this.e(),b=this.b),a[b++]=f;else{g=f-257;k=F[g];0<H[g]&&(k+=y(this,H[g]));f=T(this,d);h=J[f];0<M[f]&&(h+=y(this,M[f]));b>=e&&(this.b=b,a=this.e(),b=this.b);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b};
+u.prototype.z=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length,f,g,h,k;256!==(f=T(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=F[g];0<H[g]&&(k+=y(this,H[g]));f=T(this,d);h=J[f];0<M[f]&&(h+=y(this,M[f]));b+k>e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b};
+u.prototype.e=function(){var c=new (s?Uint8Array:Array)(this.b-32768),d=this.b-32768,a,b,e=this.c;if(s)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;a<b;++a)c[a]=e[a+32768]}this.g.push(c);this.l+=c.length;if(s)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];this.b=32768;return e};
+u.prototype.A=function(c){var d,a=this.input.length/this.a+1|0,b,e,f,g=this.input,h=this.c;c&&("number"===typeof c.p&&(a=c.p),"number"===typeof c.v&&(a+=c.v));2>a?(b=(g.length-this.a)/this.o[2],f=258*(b/2)|0,e=f<h.length?h.length+f:h.length<<1):e=h.length*a;s?(d=new Uint8Array(e),d.set(h)):d=h;return this.c=d};
+u.prototype.n=function(){var c=0,d=this.c,a=this.g,b,e=new (s?Uint8Array:Array)(this.l+(this.b-32768)),f,g,h,k;if(0===a.length)return s?this.c.subarray(32768,this.b):this.c.slice(32768,this.b);f=0;for(g=a.length;f<g;++f){b=a[f];h=0;for(k=b.length;h<k;++h)e[c++]=b[h]}f=32768;for(g=this.b;f<g;++f)e[c++]=d[f];this.g=[];return this.buffer=e};
+u.prototype.w=function(){var c,d=this.b;s?this.s?(c=new Uint8Array(d),c.set(this.c.subarray(0,d))):c=this.c.subarray(0,d):(this.c.length>d&&(this.c.length=d),c=this.c);return this.buffer=c};function U(c,d){var a,b;this.input=c;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.B=d.verify);a=c[this.a++];b=c[this.a++];switch(a&15){case V:this.method=V;break;default:throw Error("unsupported compression method");}if(0!==((a<<8)+b)%31)throw Error("invalid fcheck flag:"+((a<<8)+b)%31);if(b&32)throw Error("fdict flag is not supported");this.r=new u(c,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})}
+U.prototype.k=function(){var c=this.input,d,a;d=this.r.k();this.a=this.r.a;if(this.B){a=(c[this.a++]<<24|c[this.a++]<<16|c[this.a++]<<8|c[this.a++])>>>0;var b=d;if("string"===typeof b){var e=b.split(""),f,g;f=0;for(g=e.length;f<g;f++)e[f]=(e[f].charCodeAt(0)&255)>>>0;b=e}for(var h=1,k=0,l=b.length,p,n=0;0<l;){p=1024<l?1024:l;l-=p;do h+=b[n++],k+=h;while(--p);h%=65521;k%=65521}if(a!==(k<<16|h)>>>0)throw Error("invalid adler-32 checksum");}return d};var V=8;q("Zlib.Inflate",U);q("Zlib.Inflate.prototype.decompress",U.prototype.k);var W={ADAPTIVE:x.t,BLOCK:x.u},X,Y,Z,$;if(Object.keys)X=Object.keys(W);else for(Y in X=[],Z=0,W)X[Z++]=Y;Z=0;for($=X.length;Z<$;++Z)Y=X[Z],q("Zlib.Inflate.BufferType."+Y,W[Y]);}).call(this); //@ sourceMappingURL=inflate.min.js.map

File diff suppressed because it is too large
+ 4 - 0
examples/js/libs/inflate.min.js.map


+ 364 - 6
examples/js/loaders/VTKLoader.js

@@ -1,8 +1,11 @@
 /**
  * @author mrdoob / http://mrdoob.com/
  * @author Alex Pletzer
+ * @author Sagar DV / https://dvenkatsagar.github.io
  */
 
+// Work In Progress
+// Custom VTKLoader based on the original but with extra xml polydata support
 THREE.VTKLoader = function( manager ) {
 
 	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
@@ -528,21 +531,376 @@ THREE.VTKLoader.prototype = {
 
 		}
 
-		// get the 5 first lines of the files to check if there is the key word binary
+		function parseXML(stringFile){
+			// Changes XML to JSON, based on https://davidwalsh.name/convert-xml-json
+			var xmlToJson = function (xml) {
+
+				// Create the return object
+				var obj = {};
+
+				if (xml.nodeType == 1) { // element
+					// do attributes
+					if (xml.attributes) {
+						if (xml.attributes.length > 0) {
+						obj["attributes"] = {};
+							for (var j = 0; j < xml.attributes.length; j++) {
+								var attribute = xml.attributes.item(j);
+								obj["attributes"][attribute.nodeName] = attribute.nodeValue.trim();
+							}
+						}
+					}
+				} else if (xml.nodeType == 3) { // text
+					obj = xml.nodeValue.trim();
+				}
 
-		var meta = String.fromCharCode.apply( null, new Uint8Array( data, 0, 250 ) ).split( '\n' );
+				// do children
+			 	if (xml.hasChildNodes()) {
+					for(var i = 0; i < xml.childNodes.length; i++) {
+						var item = xml.childNodes.item(i);
+						var nodeName = item.nodeName;
+						if (typeof(obj[nodeName]) == "undefined") {
+							var tmp = xmlToJson(item);
+							if(tmp != ""){
+								obj[nodeName] = tmp;
+							}
+						} else {
+							if (typeof(obj[nodeName].push) == "undefined") {
+								var old = obj[nodeName];
+								obj[nodeName] = [];
+								obj[nodeName].push(old);
+							}
+							var tmp = xmlToJson(item);
+							if(tmp != ""){
+								obj[nodeName].push(tmp);
+							}
+						}
+					}
+				}
+				return obj;
+			};
+
+			// Taken from Base64-js
+			var Base64toByteArray = function(b64) {
+					var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
+					var i;
+					var lookup = [];
+					var revLookup = [];
+				  var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+				  var len = code.length;
+
+				  for (i = 0; i < len; i++) {
+				    lookup[i] = code[i];
+				  }
+
+				  for (i = 0; i < len; ++i) {
+				    revLookup[code.charCodeAt(i)] = i;
+				  }
+				  revLookup['-'.charCodeAt(0)] = 62;
+				  revLookup['_'.charCodeAt(0)] = 63;
+
+				  var j, l, tmp, placeHolders, arr;
+				  var len = b64.length;
+
+				  if (len % 4 > 0) {
+				    throw new Error('Invalid string. Length must be a multiple of 4');
+				  }
+
+				  placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0;
+				  arr = new Arr(len * 3 / 4 - placeHolders);
+				  l = placeHolders > 0 ? len - 4 : len;
+
+					var L = 0;
+				  for (i = 0, j = 0; i < l; i += 4, j += 3) {
+				    tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)];
+				    arr[L++] = (tmp & 0xFF0000) >> 16;
+				    arr[L++] = (tmp & 0xFF00) >> 8;
+				    arr[L++] = tmp & 0xFF;
+				  }
+
+				  if (placeHolders === 2) {
+				    tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4);
+				    arr[L++] = tmp & 0xFF;
+				  } else if (placeHolders === 1) {
+				    tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2);
+				    arr[L++] = (tmp >> 8) & 0xFF;
+				    arr[L++] = tmp & 0xFF;
+				  }
+
+				  return arr;
+				}
+
+				var parseDataArray = function(ele, compressed){
+					// Check the format
+					if (ele.attributes.format == "binary"){
+						if(compressed){
+							// Split the blob_header and compressed Data
+							if(ele["#text"].indexOf('==') != -1){
+								var data = ele["#text"].split("==");
+								//console.log(data);
+								if (data.length == 2){
+									var blob = data.shift();
+									var content = data.shift();
+									if(content == ""){
+										content = blob + "==";
+									}
+								}else if(data.length > 2){
+									var blob = data.shift();
+									var content = data.shift();
+									content = content + "==";
+								}else if (data.length < 2){
+									var content = data.shift();
+									content = content + "==";
+								}
+
+								// Convert to bytearray
+								var arr = Base64toByteArray(content);
+								// decompress
+								var inflate = new Zlib.Inflate(arr,{resize:true,verify:true});
+								var content = inflate.decompress();
+							}else{
+								var content = Base64toByteArray(ele["#text"]);
+							}
+						}else{
+							var content = Base64toByteArray(ele["#text"]);
+						}
+						var content = content.buffer;
+					}else{
+						if(ele["#text"]){
+							var content = ele["#text"].replace(/\n/g," ").split(" ").filter(function(el,idx,arr){
+								if(el != ""){
+									return el;
+								}
+							});
+						}else{
+							var content = new Int32Array(0).buffer;
+						}
+					}
+					delete ele["#text"];
+					// Get the content and optimize it
+					if(ele.attributes.type == 'Float32'){
+						var txt = new Float32Array(content);
+						if(ele.attributes.format == "binary"){
+							if(!compressed){
+								txt = txt.filter(function(el,idx,arr){if(idx != 0){return true;}});
+							}
+						}
+					}else if (ele.attributes.type == 'Int64'){
+						var txt = new Int32Array(content);
+						if(ele.attributes.format == "binary"){
+							if(!compressed){
+								txt = txt.filter(function(el,idx,arr){if(idx!=0){return true;}});
+							}
+							txt = txt.filter(function(el,idx,arr){if(idx%2!=1){return true;}});
+						}
+					}
+
+					//console.log(txt);
+					return txt;
+				}
+
+
+			// Main part
+			// Get Dom
+			var dom = null;
+			if (window.DOMParser) {
+				try {
+						dom = (new DOMParser()).parseFromString(stringFile, "text/xml");
+				}catch (e) {
+					dom = null;
+				}
+			}else if (window.ActiveXObject) {
+				try {
+						dom = new ActiveXObject('Microsoft.XMLDOM');
+						dom.async = false;
+						if (!dom.loadXML(xml)){
+							throw new Error(dom.parseError.reason + dom.parseError.srcText);
+						}
+				}catch (e) {
+					dom = null;
+				}
+			}else{
+				 throw new Error("Cannot parse xml string!");
+			}
+
+			// Get the doc
+			var doc = dom.documentElement;
+			// Convert to json
+			var json = xmlToJson(doc);
+			var points = [];
+			var normals = [];
+			var indices = [];
+
+			if(json.PolyData){
+				var piece = json.PolyData.Piece;
+				var compressed = json.attributes.hasOwnProperty("compressor");
+				// Can be optimized
+				// Loop through the sections
+				var sections = ["PointData", "Points", "Strips", "Polys"];// +["CellData", "Verts", "Lines"];
+				var sectionIndex = 0, numberOfSections = sections.length;
+				while (sectionIndex < numberOfSections){
+					var section = piece[sections[sectionIndex]];
+					// If it has a DataArray in it
+					if(section.DataArray){
+						// Depending on the number of DataArrays
+						if(Object.prototype.toString.call( section.DataArray ) === '[object Array]'){
+							var arr = section.DataArray;
+						}else{
+							var arr = [section.DataArray];
+						}
 
+						var dataArrayIndex = 0, numberOfDataArrays = arr.length;
+						while(dataArrayIndex < numberOfDataArrays){
+							// Parse the DataArray
+							arr[dataArrayIndex].text = parseDataArray(arr[dataArrayIndex],compressed);
+							dataArrayIndex++;
+						}
 
-		if ( meta[ 2 ].includes( 'ASCII' ) ) {
+						switch(sections[sectionIndex]){
+
+							// if iti is point data
+							case "PointData" :
+								var numberOfPoints = parseInt(piece.attributes.NumberOfPoints);
+								var normalsName = section.attributes.Normals;
+								if (numberOfPoints > 0){
+									for(var i = 0, len = arr.length; i < len; i++){
+										if(normalsName == arr[i].attributes.Name){
+											var components = arr[i].attributes.NumberOfComponents;
+											normals = new Float32Array(numberOfPoints * components);
+											normals.set(arr[i].text,0);
+										}
+									}
+								}
+								//console.log("Normals", normals);
+								break;
+
+							// if it is points
+							case "Points" :
+								var numberOfPoints = parseInt(piece.attributes.NumberOfPoints);
+								if (numberOfPoints > 0){
+									var components = section.DataArray.attributes.NumberOfComponents;
+									points = new Float32Array( numberOfPoints * components );
+									points.set(section.DataArray.text, 0);
+								}
+								//console.log("Points", points);
+								break;
+
+							// if it is strips
+							case "Strips" :
+								var numberOfStrips = parseInt(piece.attributes.NumberOfStrips);
+								if(numberOfStrips > 0){
+									var connectivity = new Int32Array(section.DataArray[0].text.length);
+									var offset = new Int32Array(section.DataArray[1].text.length);
+									connectivity.set(section.DataArray[0].text, 0);
+									offset.set(section.DataArray[1].text, 0);
+
+									var size = numberOfStrips + connectivity.length;
+									indices = new Uint32Array( 3 * size - 9 * numberOfStrips );
+									var indicesIndex = 0;
+									for (var i = 0,len = numberOfStrips; i < len; i++) {
+										var strip = [];
+										for (var s = 0,len1 = offset[i], len0 = 0; s < len1 - len0; s++) {
+											strip.push (connectivity[s]);
+											if(i > 0){
+												len0 = offset[i-1];
+											}
+										}
+										for (var j = 0,len1 = offset[i], len0 = 0; j < len1 - len0 - 2; j++) {
+											if ( j % 2 ) {
+												indices[ indicesIndex++ ] = strip[ j ];
+												indices[ indicesIndex++ ] = strip[ j + 2 ];
+												indices[ indicesIndex++ ] = strip[ j + 1 ];
+											}else{
+												indices[ indicesIndex++ ] = strip[ j ];
+												indices[ indicesIndex++ ] = strip[ j + 1 ];
+												indices[ indicesIndex++ ] = strip[ j + 2 ];
+											}
+											if(i > 0){
+												len0 = offset[i-1];
+											}
+										}
+									}
+								}
+								//console.log("Strips", indices);
+								break;
+
+							// if it is polys
+							case "Polys" :
+								var numberOfPolys = parseInt(piece.attributes.NumberOfPolys);
+								if(numberOfPolys > 0){
+									var connectivity = new Int32Array(section.DataArray[0].text.length);
+									var offset = new Int32Array(section.DataArray[1].text.length);
+									connectivity.set(section.DataArray[0].text, 0);
+									offset.set(section.DataArray[1].text, 0);
+
+									var size = numberOfPolys + connectivity.length;
+									indices = new Uint32Array( 3 * size - 9 * numberOfPolys );
+									var indicesIndex = 0, connectivityIndex = 0;
+									var i = 0,len = numberOfPolys, len0 = 0;
+									while(i < len){
+										var poly = [];
+										var s = 0, len1 = offset[i];
+										while(s < len1 - len0){
+											poly.push (connectivity[connectivityIndex++]);
+											s++;
+										}
+										var j = 1;
+										while(j < len1 - len0 - 1){
+											indices[ indicesIndex++ ] = poly[ 0 ];
+											indices[ indicesIndex++ ] = poly[ j ];
+											indices[ indicesIndex++ ] = poly[ j + 1 ];
+											j++;
+										}
+										i++;
+										len0 = offset[i-1];
+									}
+								}
+								//console.log("Polys", indices);
+								break;
 
+							default :
+								break;
+						}
+					}
+					sectionIndex++;
+				}
+
+				var geometry = new THREE.BufferGeometry();
+				geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( points, 3 ) );
+
+				if ( normals.length == points.length ) {
+
+					geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+
+				}
+				//console.log(json);
+				return geometry;
+			}else{
+				/* TODO for vtu,vti,and other xml formats*/
+			}
+		}
+
+		function getStringFile(data){
 			var stringFile = '';
 			var charArray = new Uint8Array( data );
-			for ( var i = 0; i < charArray.length; i ++ ) {
+			var i = 0;
+			var len = charArray.length;
+			while(len--){
+				stringFile += String.fromCharCode( charArray[ i++ ] );
+			}
+			return stringFile;
+		}
 
-				stringFile += String.fromCharCode( charArray[ i ] );
+		// get the 5 first lines of the files to check if there is the key word binary
+		var meta = String.fromCharCode.apply( null, new Uint8Array( data, 0, 250 ) ).split( '\n' );
+		if (meta[0].indexOf("xml") != -1){
 
-			}
+			var stringFile = getStringFile(data);
+			return parseXML(stringFile);
+
+		}else if ( meta[ 2 ].includes( 'ASCII' ) ) {
 
+			var stringFile = getStringFile(data);
 			return parseASCII( stringFile );
 
 		} else {

+ 80 - 0
examples/models/vtk/cube_ascii.vtp

@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
+  <PolyData>
+    <Piece NumberOfPoints="24" NumberOfVerts="0" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="6">
+      <PointData Normals="Normals" TCoords="TCoords">
+        <DataArray type="Float32" Name="Normals" NumberOfComponents="3" format="ascii" RangeMin="1" RangeMax="1">
+          -1 0 0 -1 0 0
+          -1 0 0 -1 0 0
+          1 0 0 1 0 0
+          1 0 0 1 0 0
+          0 -1 0 0 -1 0
+          0 -1 0 0 -1 0
+          0 1 0 0 1 0
+          0 1 0 0 1 0
+          0 0 -1 0 0 -1
+          0 0 -1 0 0 -1
+          0 0 1 0 0 1
+          0 0 1 0 0 1
+        </DataArray>
+        <DataArray type="Float32" Name="TCoords" NumberOfComponents="2" format="ascii" RangeMin="0.70710678119" RangeMax="2.1213203436">
+          -0.5 -0.5 1.5 -0.5 -0.5 1.5
+          1.5 1.5 0.5 -0.5 -1.5 -0.5
+          0.5 1.5 -1.5 1.5 0.5 0.5
+          0.5 -1.5 -1.5 0.5 -1.5 -1.5
+          -0.5 0.5 -0.5 -1.5 1.5 0.5
+          1.5 -1.5 0.5 -0.5 -1.5 -0.5
+          0.5 1.5 -1.5 1.5 -0.5 -0.5
+          1.5 -0.5 -0.5 1.5 1.5 1.5
+        </DataArray>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="ascii" RangeMin="1.7320508076" RangeMax="1.7320508076">
+          -1 -1 -1 -1 -1 1
+          -1 1 -1 -1 1 1
+          1 -1 -1 1 -1 1
+          1 1 -1 1 1 1
+          -1 -1 -1 -1 -1 1
+          1 -1 -1 1 -1 1
+          -1 1 -1 -1 1 1
+          1 1 -1 1 1 1
+          -1 -1 -1 1 -1 -1
+          -1 1 -1 1 1 -1
+          -1 -1 1 1 -1 1
+          -1 1 1 1 1 1
+        </DataArray>
+      </Points>
+      <Verts>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+      </Verts>
+      <Lines>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+      </Lines>
+      <Strips>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+      </Strips>
+      <Polys>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="0" RangeMax="23">
+          0 1 3 2 4 6
+          7 5 8 10 11 9
+          12 13 15 14 16 18
+          19 17 20 21 23 22
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="4" RangeMax="24">
+          4 8 12 16 20 24
+        </DataArray>
+      </Polys>
+    </Piece>
+  </PolyData>
+</VTKFile>

+ 54 - 0
examples/models/vtk/cube_binary.vtp

@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
+  <PolyData>
+    <Piece NumberOfPoints="24" NumberOfVerts="0" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="6">
+      <PointData Normals="Normals" TCoords="TCoords">
+        <DataArray type="Float32" Name="Normals" NumberOfComponents="3" format="binary" RangeMin="1" RangeMax="1">
+          AQAAAACAAAAgAQAAGQAAAA==eJxjYGjYzwAHRLHtSWMTbe6gtAMA+HsX6Q==
+        </DataArray>
+        <DataArray type="Float32" Name="TCoords" NumberOfComponents="2" format="binary" RangeMin="0.70710678119" RangeMax="2.1213203436">
+          AQAAAACAAADAAAAANAAAAA==eJxjYGDYzwDGB+wZUNgwzAAVPwCVY4DJ7UeSh+IDMHXI7P2oZsD0wMwgaD5e9wEAQ9Ep0Q==
+        </DataArray>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="binary" RangeMin="1.7320508076" RangeMax="1.7320508076">
+          AQAAAACAAAAgAQAALAAAAA==eJxjYGjYz4CJ7dFoGNseixg2OWxq0c3HZQ4+ewmZj4uPSy02e1EwADNPR7k=
+        </DataArray>
+      </Points>
+      <Verts>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+      </Verts>
+      <Lines>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+      </Lines>
+      <Strips>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+      </Strips>
+      <Polys>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="0" RangeMax="23">
+          AQAAAACAAADAAAAANgAAAA==eJwtxUkCQCAAAMCSfQuF///UwcxlQvhFJzdu3Xtw59GzF09evTl79+HLxaerb79+/AFJAAEV
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="4" RangeMax="24">
+          AQAAAACAAAAwAAAAGAAAAA==eJxjYYAADijNA6UFoLQIlJaA0gAHMABV
+        </DataArray>
+      </Polys>
+    </Piece>
+  </PolyData>
+</VTKFile>

+ 54 - 0
examples/models/vtk/cube_no_compression.vtp

@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32">
+  <PolyData>
+    <Piece NumberOfPoints="24" NumberOfVerts="0" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="6">
+      <PointData Normals="Normals" TCoords="TCoords">
+        <DataArray type="Float32" Name="Normals" NumberOfComponents="3" format="binary" RangeMin="1" RangeMax="1">
+          IAEAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPw==
+        </DataArray>
+        <DataArray type="Float32" Name="TCoords" NumberOfComponents="2" format="binary" RangeMin="0.70710678119" RangeMax="2.1213203436">
+          wAAAAAAAAL8AAAC/AADAPwAAAL8AAAC/AADAPwAAwD8AAMA/AAAAPwAAAL8AAMC/AAAAvwAAAD8AAMA/AADAvwAAwD8AAAA/AAAAPwAAAD8AAMC/AADAvwAAAD8AAMC/AADAvwAAAL8AAAA/AAAAvwAAwL8AAMA/AAAAPwAAwD8AAMC/AAAAPwAAAL8AAMC/AAAAvwAAAD8AAMA/AADAvwAAwD8AAAC/AAAAvwAAwD8AAAC/AAAAvwAAwD8AAMA/AADAPw==
+        </DataArray>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="binary" RangeMin="1.7320508076" RangeMax="1.7320508076">
+          IAEAAAAAgL8AAIC/AACAvwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPw==
+        </DataArray>
+      </Points>
+      <Verts>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+      </Verts>
+      <Lines>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+      </Lines>
+      <Strips>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+      </Strips>
+      <Polys>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="0" RangeMax="23">
+          wAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAGAAAAAAAAAAcAAAAAAAAABQAAAAAAAAAIAAAAAAAAAAoAAAAAAAAACwAAAAAAAAAJAAAAAAAAAAwAAAAAAAAADQAAAAAAAAAPAAAAAAAAAA4AAAAAAAAAEAAAAAAAAAASAAAAAAAAABMAAAAAAAAAEQAAAAAAAAAUAAAAAAAAABUAAAAAAAAAFwAAAAAAAAAWAAAAAAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="4" RangeMax="24">
+          MAAAAAQAAAAAAAAACAAAAAAAAAAMAAAAAAAAABAAAAAAAAAAFAAAAAAAAAAYAAAAAAAAAA==
+        </DataArray>
+      </Polys>
+    </Piece>
+  </PolyData>
+</VTKFile>

+ 168 - 0
examples/webgl_loader_xml_vtk.html

@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title></title>
+    <script src="../build/three.min.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+    <script src='js/libs/inflate.min.js'></script>
+		<script src="js/loaders/VTKLoader.js"></script>
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+    <style>
+      body {
+        font-family: Monospace;
+        background-color: #000000;
+        margin: 0px;
+        overflow: hidden;
+      }
+
+      #info {
+        color: #fff;
+        position: absolute;
+        top: 10px;
+        width: 100%;
+        text-align: center;
+        z-index: 100;
+        display:block;
+      }
+
+      a { color: skyblue }
+      .button { background:#999; color:#eee; padding:0.2em 0.5em; cursor:pointer }
+      .highlight { background:orange; color:#fff; }
+
+      span {
+        display: inline-block;
+        width: 60px;
+        float: left;
+        text-align: center;
+      }
+    </style>
+  </head>
+  <body>
+    <script>
+    if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+    var container, stats, camera, cameraTarget, scene, renderer, controls;
+
+    init();
+    animate();
+
+    function init() {
+      scene = new THREE.Scene();
+      scene.fog = new THREE.FogExp2( 0x2d2d2d, 0.002 );
+
+      // renderer
+      renderer = new THREE.WebGLRenderer( { antialias: false } );
+      renderer.setClearColor( scene.fog.color );
+      renderer.setPixelRatio( window.devicePixelRatio );
+      renderer.setSize( window.innerWidth, window.innerHeight );
+
+      container = document.createElement( 'div' );
+      document.body.appendChild(container);
+      container.appendChild( renderer.domElement );
+
+      camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 15 );
+      camera.position.set( 1, 1, 1 );
+      controls = new THREE.OrbitControls( camera, renderer.domElement );
+      controls.enableDamping = true;
+      controls.dampingFactor = 0.25;
+      controls.enableZoom = true;
+
+      // vtk file
+      var loader = new THREE.VTKLoader();
+      loader.load( 'models/vtk/cube_ascii.vtp', function ( geometry ) {
+        //geometry.mergeVertices();
+        geometry.computeFaceNormals();
+        geometry.computeVertexNormals();
+        //geometry.center();
+
+        var material = new THREE.MeshLambertMaterial( { color: 0x00ff00 } );
+        var mesh = new THREE.Mesh( geometry, material );
+
+        mesh.position.set(0,0,0);
+        mesh.rotation.set(Math.PI/2,0,0);
+        mesh.scale.multiplyScalar( 0.1 );
+        mesh.updateMatrix();
+        mesh.matrixAutoUpdate = false;
+
+        scene.add( mesh );
+      });
+
+      loader.load( 'models/vtk/cube_binary.vtp', function ( geometry1 ) {
+        //geometry.mergeVertices();
+        geometry1.computeFaceNormals();
+        geometry1.computeVertexNormals();
+        //geometry.center();
+
+        var material1 = new THREE.MeshLambertMaterial( { color: 0x0000ff } );
+        var mesh1 = new THREE.Mesh( geometry1, material1 );
+
+        mesh1.position.set(0.5,0,0);
+        mesh1.rotation.set(Math.PI/2,0,0);
+        mesh1.scale.multiplyScalar( 0.1 );
+        mesh1.updateMatrix();
+        mesh1.matrixAutoUpdate = false;
+
+        scene.add( mesh1 );
+      });
+
+      loader.load( 'models/vtk/cube_no_compression.vtp', function ( geometry2 ) {
+        //geometry.mergeVertices();
+        geometry2.computeFaceNormals();
+        geometry2.computeVertexNormals();
+        //geometry.center();
+
+        var material2 = new THREE.MeshLambertMaterial( { color: 0xff0000 } );
+        var mesh2 = new THREE.Mesh( geometry2, material2 );
+
+        mesh2.position.set(-0.5,0,0);
+        mesh2.scale.multiplyScalar( 0.1 );
+        mesh2.matrixAutoUpdate = true;
+
+        scene.add( mesh2 );
+      });
+
+      // Lights
+      light = new THREE.DirectionalLight( 0xffffff );
+      light.position.set( 5, 5, 5 );
+      scene.add( light );
+
+      light = new THREE.DirectionalLight( 0xffffff );
+      light.position.set( -5, -5, -5 );
+      scene.add( light );
+
+      light = new THREE.AmbientLight( 0x222222 );
+      scene.add( light );
+
+      // stats
+      stats = new Stats();
+      stats.domElement.style.position = 'absolute';
+      stats.domElement.style.top = '0px';
+      stats.domElement.style.zIndex = 100;
+      container.appendChild( stats.domElement );
+
+      // resize
+      window.addEventListener( 'resize', onWindowResize, false );
+    }
+
+    function onWindowResize() {
+      camera.aspect = window.innerWidth / window.innerHeight;
+      camera.updateProjectionMatrix();
+      renderer.setSize( window.innerWidth, window.innerHeight );
+    }
+
+    function animate() {
+      requestAnimationFrame( animate );
+      stats.update();
+      controls.update();
+      render();
+    }
+
+    function render() {
+      renderer.render( scene, camera );
+    }
+
+    </script>
+  </body>
+</html>

Some files were not shown because too many files changed in this diff