@mattburlage/react-file-viewer
Version:
Extendable file viewer for web
1,060 lines (931 loc) • 172 kB
JavaScript
/* Copyright (c) 2016, xBIM Team, Northumbria University. All rights reserved.
This javascript library is part of xBIM project. It is provided under the same
Common Development and Distribution License (CDDL) as the xBIM Toolkit. For
more information see http://www.openbim.org
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
function xBinaryReader() {
this._buffer = null;
this._position = 0;
}
xBinaryReader.prototype.onloaded = function () { };
xBinaryReader.prototype.onerror = function () { };
xBinaryReader.prototype.load = function (source) {
this._position = 0;
var self = this;
if (typeof (source) == 'undefined' || source == null) throw 'Source must be defined';
if (typeof (source) == 'string') {
var xhr;
xhr = new XMLHttpRequest();
xhr.open("GET", source, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var fReader = new FileReader();
fReader.onloadend = function () {
if (fReader.result) {
//set data buffer for next processing
self._buffer = fReader.result;
//do predefined processing of the data
if (self.onloaded) {
self.onloaded();
}
}
};
fReader.readAsArrayBuffer(xhr.response);
}
//throw exception as a warning
if (xhr.readyState == 4 && xhr.status != 200) {
var msg = 'Failed to fetch binary data from server. Server code: ' + xhr.status +
'. This might be due to CORS policy of your browser if you run this as a local file.';
if (self.onerror) self.onerror(msg);
throw msg;
}
};
xhr.responseType = 'blob';
xhr.send();
}
else if (source instanceof Blob || source instanceof File) {
var fReader = new FileReader();
fReader.onloadend = function () {
if (fReader.result) {
//set data buffer for next processing
self._buffer = fReader.result;
//do predefined processing of the data
if (self.onloaded) {
self.onloaded();
}
}
};
fReader.readAsArrayBuffer(source);
}
else if (source instanceof ArrayBuffer) {
this._buffer = source;
}
};
xBinaryReader.prototype.getIsEOF = function (type, count) {
if (typeof (this._position) === "undefined")
throw "Position is not defined";
return this._position == this._buffer.byteLength;
};
xBinaryReader.prototype.read = function (arity, count, ctor) {
if(typeof (count) === "undefined") count = 1;
var length = arity * count;
var offset = this._position;
this._position += length;
var result;
return count === 1 ?
new ctor(this._buffer.slice(offset, offset + length))[0] :
new ctor(this._buffer.slice(offset, offset + length));
};
xBinaryReader.prototype.readByte = function (count) {
return this.read(1, count, Uint8Array);
};
xBinaryReader.prototype.readUint8 = function (count) {
return this.read(1, count, Uint8Array);
};
xBinaryReader.prototype.readInt16 = function (count) {
return this.read(2, count, Int16Array);
};
xBinaryReader.prototype.readUint16 = function (count) {
return this.read(2, count, Uint16Array);
};
xBinaryReader.prototype.readInt32 = function (count) {
return this.read(4, count, Int32Array);
};
xBinaryReader.prototype.readUint32 = function (count) {
return this.read(4, count, Uint32Array);
};
xBinaryReader.prototype.readFloat32 = function (count) {
return this.read(4, count, Float32Array);
};
xBinaryReader.prototype.readFloat64 = function (count) {
return this.read(8, count, Float64Array);
};
//functions for a higher objects like points, colours and matrices
xBinaryReader.prototype.readChar = function (count) {
if (typeof (count) === "undefined") count = 1;
var bytes = this.readByte(count);
var result = new Array(count);
for (var i in bytes) {
result[i] = String.fromCharCode(bytes[i]);
}
return count ===1 ? result[0] : result;
};
xBinaryReader.prototype.readPoint = function (count) {
if (typeof (count) === "undefined") count = 1;
var coords = this.readFloat32(count * 3);
var result = new Array(count);
for (var i = 0; i < count; i++) {
var offset = i * 3 * 4;
//only create new view on the buffer so that no new memory is allocated
var point = new Float32Array(coords.buffer, offset, 3);
result[i] = point;
}
return count === 1 ? result[0] : result;
};
xBinaryReader.prototype.readRgba = function (count) {
if (typeof (count) === "undefined") count = 1;
var values = this.readByte(count * 4);
var result = new Array(count);
for (var i = 0; i < count ; i++) {
var offset = i * 4;
var colour = new Uint8Array(values.buffer, offset, 4);
result[i] = colour;
}
return count === 1 ? result[0] : result;
};
xBinaryReader.prototype.readPackedNormal = function (count) {
if (typeof (count) === "undefined") count = 1;
var values = this.readUint8(count * 2);
var result = new Array(count);
for (var i = 0; i < count; i++) {
var uv = new Uint8Array(values.buffer, i * 2, 2);
result[i] = uv;
}
return count === 1 ? result[0] : result;
};
xBinaryReader.prototype.readMatrix4x4 = function (count) {
if (typeof (count) === "undefined") count = 1;
var values = this.readFloat32(count * 16);
var result = new Array(count);
for (var i = 0; i < count; i++) {
var offset = i * 16 * 4;
var matrix = new Float32Array(values.buffer, offset, 16);
result[i] = matrix;
}
return count === 1 ? result[0] : result;
};
xBinaryReader.prototype.readMatrix4x4_64 = function (count) {
if (typeof (count) === "undefined") count = 1;
var values = this.readFloat64(count * 16);
var result = new Array(count);
for (var i = 0; i < count; i++) {
var offset = i * 16 * 8;
var matrix = new Float64Array(values.buffer, offset, 16);
result[i] = matrix;
}
return count === 1 ? result[0] : result;
};function xModelGeometry() {
//all this data is to be fed into GPU as attributes
this.normals = [];
this.indices = [];
this.products = [];
this.transformations = [];
this.styleIndices = [];
this.states = []; //this is the only array we need to keep alive on client side to be able to change appearance of the model
//these will be sent to GPU as the textures
this.vertices = [];
this.matrices = [];
this.styles = [];
this.meter = 1000;
//this will be used to change appearance of the objects
//map objects have a format:
//map = {
// productID: int,
// type: int,
// bBox: Float32Array(6),
// spans: [Int32Array([int, int]),Int32Array([int, int]), ...] //spanning indexes defining shapes of product and it's state
//};
this.productMap = {};
}
xModelGeometry.prototype.parse = function (binReader) {
var br = binReader;
var magicNumber = br.readInt32();
if (magicNumber != 94132117) throw 'Magic number mismatch.';
var version = br.readByte();
var numShapes = br.readInt32();
var numVertices = br.readInt32();
var numTriangles = br.readInt32();
var numMatrices = br.readInt32();;
var numProducts = br.readInt32();;
var numStyles = br.readInt32();;
this.meter = br.readFloat32();;
var numRegions = br.readInt16();
//set size of arrays to be square usable for texture data
//TODO: reflect support for floating point textures
var square = function (arity, count) {
if (typeof (arity) == 'undefined' || typeof (count) == 'undefined') {
throw 'Wrong arguments';
}
if (count == 0) return 0;
var byteLength = count * arity;
var imgSide = Math.ceil(Math.sqrt(byteLength / 4));
//clamp to parity
while ((imgSide * 4) % arity != 0) {
imgSide++
}
var result = imgSide * imgSide * 4 / arity;
return result;
};
//create target buffers of correct size (avoid reallocation of memory)
this.vertices = new Float32Array(square(4, numVertices * 3));
this.normals = new Uint8Array(numTriangles * 6);
this.indices = new Float32Array(numTriangles * 3);
this.styleIndices = new Uint16Array(numTriangles * 3);
this.styles = new Uint8Array(square(1, (numStyles + 1) * 4)); //+1 is for a default style
this.products = new Float32Array(numTriangles * 3);
this.states = new Uint8Array(numTriangles * 3 * 2); //place for state and restyling
this.transformations = new Float32Array(numTriangles * 3);
this.matrices = new Float32Array(square(4, numMatrices * 16));
this.productMap = {};
this.regions = new Array(numRegions);
var iVertex = 0;
var iIndexForward = 0;
var iIndexBackward = numTriangles * 3;
var iTransform = 0;
var iMatrix = 0;
var stateEnum = xState;
var typeEnum = xProductType;
for (var i = 0; i < numRegions; i++) {
this.regions[i] = {
population: br.readInt32(),
centre: br.readFloat32(3),
bbox: br.readFloat32(6)
}
}
var styleMap = [];
styleMap.getStyle = function(id) {
for (var i = 0; i < this.length; i++) {
var item = this[i];
if (item.id == id) return item;
}
return null;
};
var iStyle = 0;
for (iStyle; iStyle < numStyles; iStyle++) {
var styleId = br.readInt32();
var R = br.readFloat32() * 255;
var G = br.readFloat32() * 255;
var B = br.readFloat32() * 255;
var A = br.readFloat32() * 255;
this.styles.set([R, G, B, A], iStyle * 4);
styleMap.push({ id: styleId, index: iStyle, transparent: A < 254 });
}
this.styles.set([255, 255, 255, 255], iStyle * 4);
var defaultStyle = { id: -1, index: iStyle, transparent: A < 254 }
styleMap.push(defaultStyle);
for (var i = 0; i < numProducts ; i++) {
var productLabel = br.readInt32();
var prodType = br.readInt16();
var bBox = br.readFloat32(6);
var map = {
productID: productLabel,
type: prodType,
bBox: bBox,
spans: []
};
this.productMap[productLabel] = map;
}
for (var iShape = 0; iShape < numShapes; iShape++) {
var repetition = br.readInt32();
var shapeList = [];
for (var iProduct = 0; iProduct < repetition; iProduct++) {
var prodLabel = br.readInt32();
var instanceTypeId = br.readInt16();
var instanceLabel = br.readInt32();
var styleId = br.readInt32();
var transformation = null;
if (repetition > 1) {
transformation = version === 1 ? br.readFloat32(16) : br.readFloat64(16);
this.matrices.set(transformation, iMatrix);
iMatrix += 16;
}
var styleItem = styleMap.getStyle(styleId);
if (styleItem === null)
styleItem = defaultStyle;
shapeList.push({
pLabel: prodLabel,
iLabel: instanceLabel,
style: styleItem.index,
transparent: styleItem.transparent,
transform: transformation != null ? iTransform++ : 0xFFFF
});
}
//read shape geometry
var shapeGeom = new xTriangulatedShape();
shapeGeom.parse(br);
//copy shape data into inner array and set to null so it can be garbage collected
shapeList.forEach(function (shape) {
var iIndex = 0;
//set iIndex according to transparency either from beginning or at the end
if (shape.transparent) {
iIndex = iIndexBackward - shapeGeom.indices.length;
}
else {
iIndex = iIndexForward;
}
var begin = iIndex;
var map = this.productMap[shape.pLabel];
if (typeof (map) === "undefined") {
//throw "Product hasn't been defined before.";
map = {
productID: 0,
type: typeEnum.IFCOPENINGELEMENT,
bBox: new Float32Array(6),
spans: []
};
this.productMap[shape.pLabel] = map;
}
this.normals.set(shapeGeom.normals, iIndex * 2);
//switch spaces and openings off by default
var state = map.type == typeEnum.IFCSPACE || map.type == typeEnum.IFCOPENINGELEMENT ?
stateEnum.HIDDEN :
0xFF; //0xFF is for the default state
//fix indices to right absolute position. It is relative to the shape.
for (var i = 0; i < shapeGeom.indices.length; i++) {
this.indices[iIndex] = shapeGeom.indices[i] + iVertex / 3;
this.products[iIndex] = shape.pLabel;
this.styleIndices[iIndex] = shape.style;
this.transformations[iIndex] = shape.transform;
this.states[2 * iIndex] = state; //set state
this.states[2 * iIndex + 1] = 0xFF; //default style
iIndex++;
}
var end = iIndex;
map.spans.push(new Int32Array([begin, end]));
if (shape.transparent) iIndexBackward -= shapeGeom.indices.length;
else iIndexForward += shapeGeom.indices.length;
}, this);
//copy geometry and keep track of amount so that we can fix indices to right position
//this must be the last step to have correct iVertex number above
this.vertices.set(shapeGeom.vertices, iVertex);
iVertex += shapeGeom.vertices.length;
shapeGeom = null;
}
//binary reader should be at the end by now
if (!br.getIsEOF()) {
//throw 'Binary reader is not at the end of the file.';
}
this.transparentIndex = iIndexForward;
};
//Source has to be either URL of wexBIM file or Blob representing wexBIM file
xModelGeometry.prototype.load = function (source) {
//binary reading
var br = new xBinaryReader();
var self = this;
br.onloaded = function () {
self.parse(br);
if (self.onloaded) {
self.onloaded();
}
};
br.onerror = function (msg) {
if (self.onerror) self.onerror(msg);
};
br.load(source);
};
xModelGeometry.prototype.onloaded = function () { };
xModelGeometry.prototype.onerror = function () { };//this class holds pointers to textures, uniforms and data buffers which
//make up a model in GPU
//gl: WebGL context
//model: xModelGeometry
//fpt: bool (floating point texture support)
function xModelHandle(gl, model, fpt) {
if (typeof (gl) == 'undefined' || typeof (model) == 'undefined' || typeof (fpt) == 'undefined') {
throw 'WebGL context and geometry model must be specified';
}
this._gl = gl;
this._model = model;
this._fpt = fpt;
/**
* unique ID which can be used to identify this handle
*/
this.id = xModelHandle._instancesNum++;
/**
* indicates if this model should be used in a rendering loop or not.
*/
this.stopped = false;
this.count = model.indices.length;
//data structure
this.vertexTexture = gl.createTexture();
this.matrixTexture = gl.createTexture();
this.styleTexture = gl.createTexture();
this.stateStyleTexture = gl.createTexture();
this.vertexTextureSize = 0;
this.matrixTextureSize = 0;
this.styleTextureSize = 0;
this.normalBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.productBuffer = gl.createBuffer();
this.styleBuffer = gl.createBuffer();
this.stateBuffer = gl.createBuffer();
this.transformationBuffer = gl.createBuffer();
//small texture which can be used to overwrite appearance of the products
this.stateStyle = new Uint8Array(15 * 15 * 4);
this._feedCompleted = false;
this.region = model.regions[0];
//set the most populated region
model.regions.forEach(function (region) {
if (region.population > this.region.population) {
this.region = region;
}
}, this);
//set default region if no region is defined. This shouldn't ever happen if model contains any geometry.
if (typeof (this.region) == 'undefined') {
this.region = {
population: 1,
centre: [0.0, 0.0, 0.0],
bbox: [0.0, 0.0, 0.0, 10 * model.meter, 10 * model.meter, 10 * model.meter]
}
}
}
/**
* Static counter to keep unique ID of the model handles
*/
xModelHandle._instancesNum = 0;
//this function sets this model as an active one
//it needs an argument 'pointers' which contains pointers to
//shader attributes and uniforms which are to be set.
//pointers = {
// normalAttrPointer: null,
// indexlAttrPointer: null,
// productAttrPointer: null,
// stateAttrPointer: null,
// styleAttrPointer: null,
// transformationAttrPointer: null,
//
// matrixSamplerUniform: null,
// vertexSamplerUniform: null,
// styleSamplerUniform: null,
// stateStyleSamplerUniform: null,
//
// vertexTextureSizeUniform: null,
// matrixTextureSizeUniform: null,
// styleTextureSizeUniform: null,
//};
xModelHandle.prototype.setActive = function (pointers) {
if (this.stopped) return;
var gl = this._gl;
//set predefined textures
if (this.vertexTextureSize > 0) {
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, this.vertexTexture);
}
if (this.matrixTextureSize > 0) {
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, this.matrixTexture);
}
if (this.styleTextureSize > 0) {
gl.activeTexture(gl.TEXTURE3);
gl.bindTexture(gl.TEXTURE_2D, this.styleTexture);
}
//this texture has constant size
gl.activeTexture(gl.TEXTURE4);
gl.bindTexture(gl.TEXTURE_2D, this.stateStyleTexture);
//set attributes and uniforms
gl.bindBuffer(gl.ARRAY_BUFFER, this.normalBuffer);
gl.vertexAttribPointer(pointers.normalAttrPointer, 2, gl.UNSIGNED_BYTE, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.indexBuffer);
gl.vertexAttribPointer(pointers.indexlAttrPointer, 1, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.productBuffer);
gl.vertexAttribPointer(pointers.productAttrPointer, 1, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.stateBuffer);
gl.vertexAttribPointer(pointers.stateAttrPointer, 2, gl.UNSIGNED_BYTE, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.styleBuffer);
gl.vertexAttribPointer(pointers.styleAttrPointer, 1, gl.UNSIGNED_SHORT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this.transformationBuffer);
gl.vertexAttribPointer(pointers.transformationAttrPointer, 1, gl.FLOAT, false, 0, 0);
gl.uniform1i(pointers.vertexSamplerUniform, 1);
gl.uniform1i(pointers.matrixSamplerUniform, 2);
gl.uniform1i(pointers.styleSamplerUniform, 3);
gl.uniform1i(pointers.stateStyleSamplerUniform, 4);
gl.uniform1i(pointers.vertexTextureSizeUniform, this.vertexTextureSize);
gl.uniform1i(pointers.matrixTextureSizeUniform, this.matrixTextureSize);
gl.uniform1i(pointers.styleTextureSizeUniform, this.styleTextureSize);
};
//this function must be called AFTER 'setActive()' function which sets up active buffers and uniforms
xModelHandle.prototype.draw = function (mode) {
if (this.stopped) return;
var gl = this._gl;
if (typeof (mode) === "undefined") {
//draw image frame
gl.drawArrays(gl.TRIANGLES, 0, this.count);
return;
}
if (mode === "solid") {
gl.drawArrays(gl.TRIANGLES, 0, this._model.transparentIndex);
return;
}
if (mode === "transparent") {
gl.drawArrays(gl.TRIANGLES, this._model.transparentIndex, this.count - this._model.transparentIndex);
return;
}
};
xModelHandle.prototype.drawProduct = function (ID) {
if (this.stopped) return;
var gl = this._gl;
var map = this.getProductMap(ID);
//var i = 3; //3 is for a glass panel
//gl.drawArrays(gl.TRIANGLES, map.spans[i][0], map.spans[i][1] - map.spans[i][0]);
if (map != null) {
map.spans.forEach(function (span) {
gl.drawArrays(gl.TRIANGLES, span[0], span[1] - span[0]);
}, this);
}
};
xModelHandle.prototype.getProductMap = function (ID) {
var map = this._model.productMap[ID];
if (typeof (map) !== "undefined") return map;
return null;
};
xModelHandle.prototype.unload = function () {
var gl = this._gl;
gl.deleteTexture(this.vertexTexture);
gl.deleteTexture(this.matrixTexture);
gl.deleteTexture(this.styleTexture);
gl.deleteTexture(this.stateStyleTexture);
gl.deleteBuffer(this.normalBuffer);
gl.deleteBuffer(this.indexBuffer);
gl.deleteBuffer(this.productBuffer);
gl.deleteBuffer(this.styleBuffer);
gl.deleteBuffer(this.stateBuffer);
gl.deleteBuffer(this.transformationBuffer);
};
xModelHandle.prototype.feedGPU = function () {
if (this._feedCompleted) {
throw 'GPU can bee fed only once. It discards unnecessary data which cannot be restored again.';
}
var gl = this._gl;
var model = this._model;
//fill all buffers
this._bufferData(this.normalBuffer, model.normals);
this._bufferData(this.indexBuffer, model.indices);
this._bufferData(this.productBuffer, model.products);
this._bufferData(this.stateBuffer, model.states);
this._bufferData(this.transformationBuffer, model.transformations);
this._bufferData(this.styleBuffer, model.styleIndices);
//fill in all textures
this.vertexTextureSize = this._bufferTexture(this.vertexTexture, model.vertices, 3);
this.matrixTextureSize = this._bufferTexture(this.matrixTexture, model.matrices, 4);
this.styleTextureSize = this._bufferTexture(this.styleTexture, model.styles);
//this has a constant size 15 which is defined in vertex shader
this._bufferTexture(this.stateStyleTexture, this.stateStyle);
//Forget everything except for states and styles (this should save some RAM).
//data is already loaded to GPU by now
model.normals = null;
model.indices = null;
model.products = null;
model.transformations = null;
model.styleIndices = null;
model.vertices = null;
model.matrices = null;
this._feedCompleted = true;
};
xModelHandle.prototype.refreshStyles = function () {
this._bufferTexture(this.stateStyleTexture, this.stateStyle);
};
xModelHandle.prototype._bufferData = function (pointer, data) {
var gl = this._gl;
gl.bindBuffer(gl.ARRAY_BUFFER, pointer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
};
xModelHandle.prototype._bufferTexture = function (pointer, data, arity) {
var gl = this._gl;
if (data.length == 0) return 0;
//detect floating point texture support and data type
var fp = this._fpt && data instanceof Float32Array;
//compute size of the image (length should be correct already)
var size = 0;
var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
if (fp) {
//recompute to smaller size, but make it +1 to make sure it is all right
size = Math.ceil(Math.sqrt(Math.ceil(data.length / arity))) + 1;
}
else {
var dim = Math.sqrt(data.byteLength / 4);
size = Math.ceil(dim);
}
if (size == 0) return 0;
if (size > maxSize) throw 'Too much data! It cannot fit into the texture.';
gl.bindTexture(gl.TEXTURE_2D, pointer);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); //this is our convention
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); //this should preserve values of alpha
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, 0); //this should preserve values of colours
if (fp) {
//create new data buffer and fill it in with data
var image = null;
if (size * size * arity != data.length) {
image = new Float32Array(size * size * arity);
image.set(data);
}
else {
image = data;
}
var type = null;
switch (arity) {
case 1: type = gl.ALPHA; break;
case 3: type = gl.RGB; break;
case 4: type = gl.RGBA; break;
}
gl.texImage2D(gl.TEXTURE_2D, 0, type, size, size, 0, type, gl.FLOAT, image);
}
else {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(data.buffer));
}
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); //Prevents s-coordinate wrapping (repeating).
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); //Prevents t-coordinate wrapping (repeating).
return size;
};
xModelHandle.prototype.getState = function (id) {
if (typeof (id) === "undefined") throw "id must be defined";
var map = this.getProductMap(id);
if (map === null) return null;
var span = map.spans[0];
if (typeof (span) == "undefined") return null;
return this._model.states[span[0] * 2];
}
xModelHandle.prototype.getStyle = function (id) {
if (typeof (id) === "undefined") throw "id must be defined";
var map = this.getProductMap(id);
if (map === null) return null;
var span = map.spans[0];
if (typeof (span) == "undefined") return null;
return this._model.states[span[0] * 2 + 1];
}
xModelHandle.prototype.setState = function (state, args) {
if (typeof (state) != 'number' && state < 0 && state > 255) throw 'You have to specify state as an ID of state or index in style pallete.';
if (typeof (args) == 'undefined') throw 'You have to specify products as an array of product IDs or as a product type ID';
var maps = [];
//it is type
if (typeof (args) == 'number') {
for (var n in this._model.productMap) {
var map = this._model.productMap[n];
if (map.type == args) maps.push(map);
}
}
//it is a list of IDs
else {
for (var l = 0; l < args.length; l++) {
var id = args[l];
var map = this.getProductMap(id);
if (map != null) maps.push(map);
}
}
//shift +1 if it is an overlay colour style or 0 if it is a state.
var shift = state <= 225 ? 1 : 0;
maps.forEach(function (map) {
map.spans.forEach(function (span) {
//set state or style
for (var k = span[0]; k < span[1]; k++) {
this._model.states[k * 2 + shift] = state;
}
}, this);
}, this);
//buffer data to GPU
this._bufferData(this.stateBuffer, this._model.states);
};
xModelHandle.prototype.resetStates = function () {
for (var i = 0; i < this._model.states.length; i += 2) {
this._model.states[i] = xState.UNDEFINED;
}
//buffer data to GPU
this._bufferData(this.stateBuffer, this._model.states);
};
xModelHandle.prototype.resetStyles = function () {
for (var i = 0; i < this._model.states.length; i += 2) {
this._model.states[i + 1] = xState.UNSTYLED;
}
//buffer data to GPU
this._bufferData(this.stateBuffer, this._model.states);
};
xModelHandle.prototype.getModelState = function() {
var result = [];
var products = this._model.productMap;
for (var i in products) {
if (!products.hasOwnProperty(i)) {
continue;
}
var map = products[i];
var span = map.spans[0];
if (typeof (span) == "undefined") continue;
var state = this._model.states[span[0] * 2];
var style = this._model.states[span[0] * 2 + 1];
result.push([map.productID, state + (style << 8)]);
}
return result;
};
xModelHandle.prototype.restoreModelState = function (state) {
state.forEach(function (s) {
var id = s[0];
var style = s[1] >> 8;
var state = s[1] - (style << 8);
var map = this.getProductMap(id);
if (map != null) {
map.spans.forEach(function (span) {
//set state or style
for (var k = span[0]; k < span[1]; k++) {
this._model.states[k * 2] = state;
this._model.states[k * 2 + 1] = style;
}
}, this);
}
}, this);
//buffer data to GPU
this._bufferData(this.stateBuffer, this._model.states);
};
var xProductInheritance = { name: "IfcProduct", id: 20, abs: true, children: [{ name: "IfcElement", id: 19, abs: true, children: [{ name: "IfcDistributionElement", id: 44, abs: false, children: [{ name: "IfcDistributionFlowElement", id: 45, abs: false, children: [{ name: "IfcDistributionChamberElement", id: 180, abs: false }, { name: "IfcEnergyConversionDevice", id: 175, abs: false, children: [{ name: "IfcAirToAirHeatRecovery", id: 1097, abs: false }, { name: "IfcBoiler", id: 1105, abs: false }, { name: "IfcBurner", id: 1109, abs: false }, { name: "IfcChiller", id: 1119, abs: false }, { name: "IfcCoil", id: 1124, abs: false }, { name: "IfcCondenser", id: 1132, abs: false }, { name: "IfcCooledBeam", id: 1141, abs: false }, { name: "IfcCoolingTower", id: 1142, abs: false }, { name: "IfcEngine", id: 1164, abs: false }, { name: "IfcEvaporativeCooler", id: 1166, abs: false }, { name: "IfcEvaporator", id: 1167, abs: false }, { name: "IfcHeatExchanger", id: 1187, abs: false }, { name: "IfcHumidifier", id: 1188, abs: false }, { name: "IfcTubeBundle", id: 1305, abs: false }, { name: "IfcUnitaryEquipment", id: 1310, abs: false }, { name: "IfcElectricGenerator", id: 1160, abs: false }, { name: "IfcElectricMotor", id: 1161, abs: false }, { name: "IfcMotorConnection", id: 1216, abs: false }, { name: "IfcSolarDevice", id: 1270, abs: false }, { name: "IfcTransformer", id: 1303, abs: false }] }, { name: "IfcFlowController", id: 121, abs: false, children: [{ name: "IfcElectricDistributionPoint", id: 242, abs: false }, { name: "IfcAirTerminalBox", id: 1096, abs: false }, { name: "IfcDamper", id: 1148, abs: false }, { name: "IfcFlowMeter", id: 1182, abs: false }, { name: "IfcValve", id: 1311, abs: false }, { name: "IfcElectricDistributionBoard", id: 1157, abs: false }, { name: "IfcElectricTimeControl", id: 1162, abs: false }, { name: "IfcProtectiveDevice", id: 1235, abs: false }, { name: "IfcSwitchingDevice", id: 1290, abs: false }] }, { name: "IfcFlowFitting", id: 467, abs: false, children: [{ name: "IfcDuctFitting", id: 1153, abs: false }, { name: "IfcPipeFitting", id: 1222, abs: false }, { name: "IfcCableCarrierFitting", id: 1111, abs: false }, { name: "IfcCableFitting", id: 1113, abs: false }, { name: "IfcJunctionBox", id: 1195, abs: false }] }, { name: "IfcFlowMovingDevice", id: 502, abs: false, children: [{ name: "IfcCompressor", id: 1131, abs: false }, { name: "IfcFan", id: 1177, abs: false }, { name: "IfcPump", id: 1238, abs: false }] }, { name: "IfcFlowSegment", id: 574, abs: false, children: [{ name: "IfcDuctSegment", id: 1154, abs: false }, { name: "IfcPipeSegment", id: 1223, abs: false }, { name: "IfcCableCarrierSegment", id: 1112, abs: false }, { name: "IfcCableSegment", id: 1115, abs: false }] }, { name: "IfcFlowStorageDevice", id: 371, abs: false, children: [{ name: "IfcTank", id: 1293, abs: false }, { name: "IfcElectricFlowStorageDevice", id: 1159, abs: false }] }, { name: "IfcFlowTerminal", id: 46, abs: false, children: [{ name: "IfcFireSuppressionTerminal", id: 1179, abs: false }, { name: "IfcSanitaryTerminal", id: 1262, abs: false }, { name: "IfcStackTerminal", id: 1277, abs: false }, { name: "IfcWasteTerminal", id: 1315, abs: false }, { name: "IfcAirTerminal", id: 1095, abs: false }, { name: "IfcMedicalDevice", id: 1212, abs: false }, { name: "IfcSpaceHeater", id: 1272, abs: false }, { name: "IfcAudioVisualAppliance", id: 1099, abs: false }, { name: "IfcCommunicationsAppliance", id: 1127, abs: false }, { name: "IfcElectricAppliance", id: 1156, abs: false }, { name: "IfcLamp", id: 1198, abs: false }, { name: "IfcLightFixture", id: 1199, abs: false }, { name: "IfcOutlet", id: 1219, abs: false }] }, { name: "IfcFlowTreatmentDevice", id: 425, abs: false, children: [{ name: "IfcInterceptor", id: 1193, abs: false }, { name: "IfcDuctSilencer", id: 1155, abs: false }, { name: "IfcFilter", id: 1178, abs: false }] }] }, { name: "IfcDistributionControlElement", id: 468, abs: false, children: [{ name: "IfcProtectiveDeviceTrippingUnit", id: 1236, abs: false }, { name: "IfcActuator", id: 1091, abs: false }, { name: "IfcAlarm", id: 1098, abs: false }, { name: "IfcController", id: 1139, abs: false }, { name: "IfcFlowInstrument", id: 1181, abs: false }, { name: "IfcSensor", id: 1264, abs: false }, { name: "IfcUnitaryControlElement", id: 1308, abs: false }] }] }, { name: "IfcElementComponent", id: 424, abs: true, children: [{ name: "IfcDiscreteAccessory", id: 423, abs: false }, { name: "IfcFastener", id: 535, abs: false, children: [{ name: "IfcMechanicalFastener", id: 536, abs: false }] }, { name: "IfcReinforcingElement", id: 262, abs: true, children: [{ name: "IfcReinforcingBar", id: 571, abs: false }, { name: "IfcReinforcingMesh", id: 531, abs: false }, { name: "IfcTendon", id: 261, abs: false }, { name: "IfcTendonAnchor", id: 675, abs: false }] }, { name: "IfcBuildingElementPart", id: 220, abs: false }, { name: "IfcMechanicalFastener", id: 536, abs: false }, { name: "IfcVibrationIsolator", id: 1312, abs: false }] }, { name: "IfcFeatureElement", id: 386, abs: true, children: [{ name: "IfcFeatureElementSubtraction", id: 499, abs: true, children: [{ name: "IfcEdgeFeature", id: 764, abs: true, children: [{ name: "IfcChamferEdgeFeature", id: 765, abs: false }, { name: "IfcRoundedEdgeFeature", id: 766, abs: false }] }, { name: "IfcOpeningElement", id: 498, abs: false, children: [{ name: "IfcOpeningStandardCase", id: 1217, abs: false }] }, { name: "IfcVoidingFeature", id: 1313, abs: false }] }, { name: "IfcFeatureElementAddition", id: 385, abs: true, children: [{ name: "IfcProjectionElement", id: 384, abs: false }] }, { name: "IfcSurfaceFeature", id: 1287, abs: false }] }, { name: "IfcBuildingElement", id: 26, abs: true, children: [{ name: "IfcBuildingElementComponent", id: 221, abs: true, children: [{ name: "IfcBuildingElementPart", id: 220, abs: false }, { name: "IfcReinforcingElement", id: 262, abs: true, children: [{ name: "IfcReinforcingBar", id: 571, abs: false }, { name: "IfcReinforcingMesh", id: 531, abs: false }, { name: "IfcTendon", id: 261, abs: false }, { name: "IfcTendonAnchor", id: 675, abs: false }] }] }, { name: "IfcFooting", id: 120, abs: false }, { name: "IfcPile", id: 572, abs: false }, { name: "IfcBeam", id: 171, abs: false, children: [{ name: "IfcBeamStandardCase", id: 1104, abs: false }] }, { name: "IfcColumn", id: 383, abs: false, children: [{ name: "IfcColumnStandardCase", id: 1126, abs: false }] }, { name: "IfcCurtainWall", id: 456, abs: false }, { name: "IfcDoor", id: 213, abs: false, children: [{ name: "IfcDoorStandardCase", id: 1151, abs: false }] }, { name: "IfcMember", id: 310, abs: false, children: [{ name: "IfcMemberStandardCase", id: 1214, abs: false }] }, { name: "IfcPlate", id: 351, abs: false, children: [{ name: "IfcPlateStandardCase", id: 1224, abs: false }] }, { name: "IfcRailing", id: 350, abs: false }, { name: "IfcRamp", id: 414, abs: false }, { name: "IfcRampFlight", id: 348, abs: false }, { name: "IfcRoof", id: 347, abs: false }, { name: "IfcSlab", id: 99, abs: false, children: [{ name: "IfcSlabElementedCase", id: 1268, abs: false }, { name: "IfcSlabStandardCase", id: 1269, abs: false }] }, { name: "IfcStair", id: 346, abs: false }, { name: "IfcStairFlight", id: 25, abs: false }, { name: "IfcWall", id: 452, abs: false, children: [{ name: "IfcWallStandardCase", id: 453, abs: false }, { name: "IfcWallElementedCase", id: 1314, abs: false }] }, { name: "IfcWindow", id: 667, abs: false, children: [{ name: "IfcWindowStandardCase", id: 1316, abs: false }] }, { name: "IfcBuildingElementProxy", id: 560, abs: false }, { name: "IfcCovering", id: 382, abs: false }, { name: "IfcChimney", id: 1120, abs: false }, { name: "IfcShadingDevice", id: 1265, abs: false }] }, { name: "IfcElementAssembly", id: 18, abs: false }, { name: "IfcFurnishingElement", id: 253, abs: false, children: [{ name: "IfcFurniture", id: 1184, abs: false }, { name: "IfcSystemFurnitureElement", id: 1291, abs: false }] }, { name: "IfcTransportElement", id: 416, abs: false }, { name: "IfcVirtualElement", id: 168, abs: false }, { name: "IfcElectricalElement", id: 23, abs: false }, { name: "IfcEquipmentElement", id: 212, abs: false }, { name: "IfcCivilElement", id: 1122, abs: false }, { name: "IfcGeographicElement", id: 1185, abs: false }] }, { name: "IfcPort", id: 179, abs: true, children: [{ name: "IfcDistributionPort", id: 178, abs: false }] }, { name: "IfcProxy", id: 447, abs: false }, { name: "IfcStructuralActivity", id: 41, abs: true, children: [{ name: "IfcStructuralAction", id: 40, abs: true, children: [{ name: "IfcStructuralLinearAction", id: 463, abs: false, children: [{ name: "IfcStructuralLinearActionVarying", id: 464, abs: false }] }, { name: "IfcStructuralPlanarAction", id: 39, abs: false, children: [{ name: "IfcStructuralPlanarActionVarying", id: 357, abs: false }] }, { name: "IfcStructuralPointAction", id: 356, abs: false }, { name: "IfcStructuralCurveAction", id: 1279, abs: false, children: [{ name: "IfcStructuralLinearAction", id: 463, abs: false }] }, { name: "IfcStructuralSurfaceAction", id: 1284, abs: false, children: [{ name: "IfcStructuralPlanarAction", id: 39, abs: false }] }] }, { name: "IfcStructuralReaction", id: 355, abs: true, children: [{ name: "IfcStructuralPointReaction", id: 354, abs: false }, { name: "IfcStructuralCurveReaction", id: 1280, abs: false }, { name: "IfcStructuralSurfaceReaction", id: 1285, abs: false }] }] }, { name: "IfcStructuralItem", id: 226, abs: true, children: [{ name: "IfcStructuralConnection", id: 265, abs: true, children: [{ name: "IfcStructuralCurveConnection", id: 534, abs: false }, { name: "IfcStructuralPointConnection", id: 533, abs: false }, { name: "IfcStructuralSurfaceConnection", id: 264, abs: false }] }, { name: "IfcStructuralMember", id: 225, abs: true, children: [{ name: "IfcStructuralCurveMember", id: 224, abs: false, children: [{ name: "IfcStructuralCurveMemberVarying", id: 227, abs: false }] }, { name: "IfcStructuralSurfaceMember", id: 420, abs: false, children: [{ name: "IfcStructuralSurfaceMemberVarying", id: 421, abs: false }] }] }] }, { name: "IfcAnnotation", id: 634, abs: false }, { name: "IfcSpatialStructureElement", id: 170, abs: true, children: [{ name: "IfcBuilding", id: 169, abs: false }, { name: "IfcBuildingStorey", id: 459, abs: false }, { name: "IfcSite", id: 349, abs: false }, { name: "IfcSpace", id: 454, abs: false }] }, { name: "IfcGrid", id: 564, abs: false }, { name: "IfcSpatialElement", id: 1273, abs: true, children: [{ name: "IfcSpatialStructureElement", id: 170, abs: true, children: [{ name: "IfcBuilding", id: 169, abs: false }, { name: "IfcBuildingStorey", id: 459, abs: false }, { name: "IfcSite", id: 349, abs: false }, { name: "IfcSpace", id: 454, abs: false }] }, { name: "IfcExternalSpatialStructureElement", id: 1175, abs: true, children: [{ name: "IfcExternalSpatialElement", id: 1174, abs: false }] }, { name: "IfcSpatialZone", id: 1275, abs: false }] }] };
/**
* Enumeration of product types.
* @readonly
* @enum {number}
*/
var xProductType = {
IFCDISTRIBUTIONELEMENT: 44,
IFCDISTRIBUTIONFLOWELEMENT: 45,
IFCDISTRIBUTIONCHAMBERELEMENT: 180,
IFCENERGYCONVERSIONDEVICE: 175,
IFCAIRTOAIRHEATRECOVERY: 1097,
IFCBOILER: 1105,
IFCBURNER: 1109,
IFCCHILLER: 1119,
IFCCOIL: 1124,
IFCCONDENSER: 1132,
IFCCOOLEDBEAM: 1141,
IFCCOOLINGTOWER: 1142,
IFCENGINE: 1164,
IFCEVAPORATIVECOOLER: 1166,
IFCEVAPORATOR: 1167,
IFCHEATEXCHANGER: 1187,
IFCHUMIDIFIER: 1188,
IFCTUBEBUNDLE: 1305,
IFCUNITARYEQUIPMENT: 1310,
IFCELECTRICGENERATOR: 1160,
IFCELECTRICMOTOR: 1161,
IFCMOTORCONNECTION: 1216,
IFCSOLARDEVICE: 1270,
IFCTRANSFORMER: 1303,
IFCFLOWCONTROLLER: 121,
IFCELECTRICDISTRIBUTIONPOINT: 242,
IFCAIRTERMINALBOX: 1096,
IFCDAMPER: 1148,
IFCFLOWMETER: 1182,
IFCVALVE: 1311,
IFCELECTRICDISTRIBUTIONBOARD: 1157,
IFCELECTRICTIMECONTROL: 1162,
IFCPROTECTIVEDEVICE: 1235,
IFCSWITCHINGDEVICE: 1290,
IFCFLOWFITTING: 467,
IFCDUCTFITTING: 1153,
IFCPIPEFITTING: 1222,
IFCCABLECARRIERFITTING: 1111,
IFCCABLEFITTING: 1113,
IFCJUNCTIONBOX: 1195,
IFCFLOWMOVINGDEVICE: 502,
IFCCOMPRESSOR: 1131,
IFCFAN: 1177,
IFCPUMP: 1238,
IFCFLOWSEGMENT: 574,
IFCDUCTSEGMENT: 1154,
IFCPIPESEGMENT: 1223,
IFCCABLECARRIERSEGMENT: 1112,
IFCCABLESEGMENT: 1115,
IFCFLOWSTORAGEDEVICE: 371,
IFCTANK: 1293,
IFCELECTRICFLOWSTORAGEDEVICE: 1159,
IFCFLOWTERMINAL: 46,
IFCFIRESUPPRESSIONTERMINAL: 1179,
IFCSANITARYTERMINAL: 1262,
IFCSTACKTERMINAL: 1277,
IFCWASTETERMINAL: 1315,
IFCAIRTERMINAL: 1095,
IFCMEDICALDEVICE: 1212,
IFCSPACEHEATER: 1272,
IFCAUDIOVISUALAPPLIANCE: 1099,
IFCCOMMUNICATIONSAPPLIANCE: 1127,
IFCELECTRICAPPLIANCE: 1156,
IFCLAMP: 1198,
IFCLIGHTFIXTURE: 1199,
IFCOUTLET: 1219,
IFCFLOWTREATMENTDEVICE: 425,
IFCINTERCEPTOR: 1193,
IFCDUCTSILENCER: 1155,
IFCFILTER: 1178,
IFCDISTRIBUTIONCONTROLELEMENT: 468,
IFCPROTECTIVEDEVICETRIPPINGUNIT: 1236,
IFCACTUATOR: 1091,
IFCALARM: 1098,
IFCCONTROLLER: 1139,
IFCFLOWINSTRUMENT: 1181,
IFCSENSOR: 1264,
IFCUNITARYCONTROLELEMENT: 1308,
IFCDISCRETEACCESSORY: 423,
IFCFASTENER: 535,
IFCMECHANICALFASTENER: 536,
IFCREINFORCINGBAR: 571,
IFCREINFORCINGMESH: 531,
IFCTENDON: 261,
IFCTENDONANCHOR: 675,
IFCBUILDINGELEMENTPART: 220,
IFCMECHANICALFASTENER: 536,
IFCVIBRATIONISOLATOR: 1312,
IFCCHAMFEREDGEFEATURE: 765,
IFCROUNDEDEDGEFEATURE: 766,
IFCOPENINGELEMENT: 498,
IFCOPENINGSTANDARDCASE: 1217,
IFCVOIDINGFEATURE: 1313,
IFCPROJECTIONELEMENT: 384,
IFCSURFACEFEATURE: 1287,
IFCBUILDINGELEMENTPART: 220,
IFCREINFORCINGBAR: 571,
IFCREINFORCINGMESH: 531,
IFCTENDON: 261,
IFCTENDONANCHOR: 675,
IFCFOOTING: 120,
IFCPILE: 572,
IFCBEAM: 171,
IFCBEAMSTANDARDCASE: 1104,
IFCCOLUMN: 383,
IFCCOLUMNSTANDARDCASE: 1126,
IFCCURTAINWALL: 456,
IFCDOOR: 213,
IFCDOORSTANDARDCASE: 1151,
IFCMEMBER: 310,
IFCMEMBERSTANDARDCASE: 1214,
IFCPLATE: 351,
IFCPLATESTANDARDCASE: 1224,
IFCRAILING: 350,
IFCRAMP: 414,
IFCRAMPFLIGHT: 348,
IFCROOF: 347,
IFCSLAB: 99,
IFCSLABELEMENTEDCASE: 1268,
IFCSLABSTANDARDCASE: 1269,
IFCSTAIR: 346,
IFCSTAIRFLIGHT: 25,
IFCWALL: 452,
IFCWALLSTANDARDCASE: 453,
IFCWALLELEMENTEDCASE: 1314,
IFCWINDOW: 667,
IFCWINDOWSTANDARDCASE: 1316,
IFCBUILDINGELEMENTPROXY: 560,
IFCCOVERING: 382,
IFCCHIMNEY: 1120,
IFCSHADINGDEVICE: 1265,
IFCELEMENTASSEMBLY: 18,
IFCFURNISHINGELEMENT: 253,
IFCFURNITURE: 1184,
IFCSYSTEMFURNITUREELEMENT: 1291,
IFCTRANSPORTELEMENT: 416,
IFCVIRTUALELEMENT: 168,
IFCELECTRICALELEMENT: 23,
IFCEQUIPMENTELEMENT: 212,
IFCCIVILELEMENT: 1122,
IFCGEOGRAPHICELEMENT: 1185,
IFCDISTRIBUTIONPORT: 178,
IFCPROXY: 447,
IFCSTRUCTURALLINEARACTION: 463,
IFCSTRUCTURALLINEARACTIONVARYING: 464,
IFCSTRUCTURALPLANARACTION: 39,
IFCSTRUCTURALPLANARACTIONVARYING: 357,
IFCSTRUCTURALPOINTACTION: 356,
IFCSTRUCTURALCURVEACTION: 1279,
IFCSTRUCTURALLINEARACTION: 463,
IFCSTRUCTURALSURFACEACTION: 1284,
IFCSTRUCTURALPLANARACTION: 39,
IFCSTRUCTURALPOINTREACTION: 354,
IFCSTRUCTURALCURVEREACTION: 1280,
IFCSTRUCTURALSURFACEREACTION: 1285,
IFCSTRUCTURALCURVECONNECTION: 534,
IFCSTRUCTURALPOINTCONNECTION: 533,
IFCSTRUCTURALSURFACECONNECTION: 264,
IFCSTRUCTURALCURVEMEMBER: 224,
IFCSTRUCTURALCURVEMEMBERVARYING: 227,
IFCSTRUCTURALSURFACEMEMBER: 420,
IFCSTRUCTURALSURFACEMEMBERVARYING: 421,
IFCANNOTATION: 634,
IFCBUILDING: 169,
IFCBUILDINGSTOREY: 459,
IFCSITE: 349,
IFCSPACE: 454,
IFCGRID: 564,
IFCBUILDING: 169,
IFCBUILDINGSTOREY: 459,
IFCSITE: 349,
IFCSPACE: 454,
IFCEXTERNALSPATIALELEMENT: 1174,
IFCSPATIALZONE: 1275
};
/*
* This file has been generated by spacker.exe utility. Do not change this file manualy as your changes
* will get lost when the file is regenerated. Original content is located in *.c files.
*/
if (!window.xShaders) window.xShaders = {}
xShaders.fragment_shader = " precision mediump float; uniform vec4 uClippingPlane; varying vec4 vFrontColor; varying vec4 vBackColor; varying vec3 vPosition; varying float vDiscard; void main(void) { if ( vDiscard > 0.001) discard; if (length(uClippingPlane) > 0.001) { vec4 p = uClippingPlane; vec3 x = vPosition; float distance = (dot(p.xyz, x) + p.w) / length(p.xyz); if (distance < 0.0){ discard; } } gl_FragColor = gl_FrontFacing ? vFrontColor : vBackColor; }";
xShaders.vertex_shader = " attribute highp float aVertexIndex; attribute highp float aTransformationIndex; attribute highp float aStyleIndex; attribute highp float aProduct; attribute highp vec2 aState; attribute highp vec2 aNormal; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; uniform vec4 ulightA; uniform vec4 ulightB; uniform vec4 uHighlightColour; uniform float uMeter; uniform bool uColorCoding; uniform int uRenderingMode; uniform highp sampler2D uVertexSampler; uniform int uVertexTextureSize; uniform highp sampler2D uMatrixSampler; uniform int uMatrixTextureSize; uniform highp sampler2D uStyleSampler; uniform int uStyleTextureSize; uniform highp sampler2D uStateStyleSampler; varying vec4 vFrontColor; varying vec4 vBackColor; varying vec3 vPosition; varying float vDiscard; vec3 getNormal(){ float U = aNormal[0]; float V = aNormal[1]; float PI = 3.1415926535897932384626433832795; float lon = U / 252.0 * 2.0 * PI; float lat = V / 252.0 * PI; float x = sin(lon) * sin(lat); float z = cos(lon) * sin(lat); float y = cos(lat); return normalize(vec3(x, y, z)); } vec4 getIdColor(){ float product = floor(aProduct + 0.5); float B = floor (product/(256.0*256.0)); float G = floor((product - B * 256.0*256.0)/256.0); float R = mod(product, 256.0); return vec4(R/255.0, G/255.0, B/255.0, 1.0); } vec2 getTextureCoordinates(int index, int size) { float x = float(index - (index / size) * size); float y = float(index / size); float pixelSize = 1.0 / float(size); return vec2((x + 0.5) * pixelSize, (y + 0.5) * pixelSize); } vec4 getColor(){ int restyle = int(floor(aState[1] + 0.5)); if (restyle > 224){ int index = int (floor(aStyleIndex + 0.5)); vec2 coords = getTextureCoordinates(index, uStyleTextureSize); return texture2D(uStyleSampler, coords); } vec2 coords = getTextureCoordinates(restyle, 15); return texture2D(uStateStyleSampler, coords); } vec3 getVertexPosition(){ int index = int (floor(aVertexIndex +0.5)); vec2 coords = getTextureCoordinates(index, uVertexTextureSize); vec3 point = vec3(texture2D(uVertexSampler, coords)); int tIndex = int(floor(aTransformationIndex + 0.5)); if (tIndex != 65535) { tIndex *=4; mat4 transform = mat4( texture2D(uMatrixSampler, getTextureCoordinates(tIndex, uMatrixTextureSize)), texture2D(uMatrixSampler, getTextureCoordinates(tIndex+1, uMatrixTextureSize)), texture2D(uMatrixSampler, getTextureCoordinates(tIndex+2, uMatrixTextureSize)), texture2D(uMatrixSampler, getTextureCoordinates(tIndex+3, uMatrixTextureSize)) ); return vec3(transform * vec4(point, 1.0)); } return point; } void main(void) { int state = int(floor(aState[0] + 0.5)); vDiscard = 0.0; if (state == 254) { vDiscard = 1.0; vFrontColor = vec4(0.0, 0.0, 0.0, 0.0); vBackColor = vec4(0.0, 0.0, 0.0, 0.0); vPosition = vec3(0.0, 0.0, 0.0); gl_Position = vec4(0.0, 0.0, 0.0, 1.0); return; } vec3 vertex = getVertexPosition(); vec3 normal = getNormal(); vec3 backNormal = normal * -1.0; if (uColorCoding){ vec4 idColor = getIdColor(); vFrontColor = idColor; vBackColor = idColor; } else{ float lightAIntensity = ulightA[3]; vec3