|
@@ -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 {
|