StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
5.1 KiB
194 lines
5.1 KiB
4 years ago
|
'use strict'
|
||
|
|
||
|
const isPlainObject = require('is-plain-obj');
|
||
|
const extend = require('object-assign');
|
||
|
const getProgram = require('./program')
|
||
|
const WeakMap = require('weak-map');
|
||
|
|
||
|
let attributesCache = setAttribute.cache = new WeakMap();
|
||
|
let attributesIdx = new WeakMap();
|
||
|
|
||
|
module.exports = setAttribute;
|
||
|
|
||
|
function setAttribute (gl, name, options, program) {
|
||
|
if (!gl) throw Error('WebGL context is not provided');
|
||
|
|
||
|
if (options instanceof WebGLProgram) {
|
||
|
program = options;
|
||
|
options = null;
|
||
|
}
|
||
|
else if (!program) {
|
||
|
program = getProgram(gl, program);
|
||
|
}
|
||
|
|
||
|
if (!program) throw Error('Context has no active program');
|
||
|
|
||
|
//object with attributes passed
|
||
|
if (name && typeof name != 'string') {
|
||
|
let result = {};
|
||
|
let attributes = name;
|
||
|
|
||
|
for (let name in attributes) {
|
||
|
result[name] = setAttribute(gl, name, attributes[name], program);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
let attributes = attributesCache.has(program) ? attributesCache.get(program) : attributesCache.set(program, {}).get(program);
|
||
|
|
||
|
//return all attribs if no name provided
|
||
|
if (!name) return attributes;
|
||
|
|
||
|
let attribute = attributes[name];
|
||
|
|
||
|
//if attribute exists and ony the data passed - just update buffer data
|
||
|
if (attribute) {
|
||
|
if (options && attribute.data && !isPlainObject(options) && options.length <= attribute.data.length) {
|
||
|
|
||
|
if (attribute.target === gl.ELEMENT_ARRAY_BUFFER) {
|
||
|
attribute.data = new Uint16Array(options);
|
||
|
}
|
||
|
else if (attribute.type === gl.FLOAT) {
|
||
|
attribute.data = new Float32Array(options);
|
||
|
}
|
||
|
else if (attribute.type === gl.UNSIGNED_BYTE) {
|
||
|
attribute.data = new Uint8Array(options);
|
||
|
}
|
||
|
|
||
|
gl.bindBuffer(attribute.target, attribute.buffer);
|
||
|
gl.bufferSubData(attribute.target, 0, attribute.data);
|
||
|
|
||
|
//FIXME: sort out why do we need to set pointer every program switch
|
||
|
// gl.enableVertexAttribArray(attribute.index);
|
||
|
gl.vertexAttribPointer(attribute.index, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset);
|
||
|
// gl.bindAttribLocation(program, attribute.index, attribute.name);
|
||
|
|
||
|
return attribute;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//autoinit attribute(s)
|
||
|
else {
|
||
|
let count = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
|
||
|
|
||
|
for (var i=0; i < count; ++i) {
|
||
|
let info = gl.getActiveAttrib(program, i);
|
||
|
if (!info) continue;
|
||
|
let type = info.type, size = info.size;
|
||
|
switch (info.type) {
|
||
|
case gl.FLOAT_VEC2:
|
||
|
case gl.FLOAT_VEC3:
|
||
|
case gl.FLOAT_VEC4:
|
||
|
case gl.FLOAT_MAT2:
|
||
|
case gl.FLOAT_MAT3:
|
||
|
case gl.FLOAT_MAT4:
|
||
|
type = gl.FLOAT;
|
||
|
break;
|
||
|
case gl.INT_VEC2:
|
||
|
case gl.INT_VEC3:
|
||
|
case gl.INT_VEC4:
|
||
|
case gl.INT_MAT2:
|
||
|
case gl.INT_MAT3:
|
||
|
case gl.INT_MAT4:
|
||
|
type = gl.UNSIGNED_INT;
|
||
|
break;
|
||
|
}
|
||
|
switch (info.type) {
|
||
|
case gl.FLOAT_VEC2:
|
||
|
case gl.INT_VEC2:
|
||
|
size = 2;
|
||
|
break;
|
||
|
case gl.FLOAT_VEC3:
|
||
|
case gl.INT_VEC3:
|
||
|
size = 3;
|
||
|
break;
|
||
|
case gl.FLOAT_VEC4:
|
||
|
case gl.INT_VEC4:
|
||
|
case gl.FLOAT_MAT2:
|
||
|
size = 4;
|
||
|
break;
|
||
|
case gl.FLOAT_MAT3:
|
||
|
size = 9;
|
||
|
break;
|
||
|
case gl.FLOAT_MAT4:
|
||
|
size = 16;
|
||
|
break;
|
||
|
}
|
||
|
attributes[info.name] = {name: info.name, type: type, size: size, data: []}
|
||
|
}
|
||
|
|
||
|
if (!attributes[name]) attributes[name] = {name: name, data: [], type: null, size: null}
|
||
|
|
||
|
attribute = attributes[name];
|
||
|
}
|
||
|
|
||
|
//if no options passed - just return known attribute info
|
||
|
if (options == null) return attribute;
|
||
|
|
||
|
if (!isPlainObject(options)) options = {data: options};
|
||
|
extend(attribute, options);
|
||
|
|
||
|
//detect target
|
||
|
if (!attribute.target) {
|
||
|
attribute.target = gl.ARRAY_BUFFER;
|
||
|
}
|
||
|
|
||
|
if (!attribute.buffer) {
|
||
|
attribute.buffer = gl.createBuffer();
|
||
|
}
|
||
|
|
||
|
if (!attribute.usage) {
|
||
|
attribute.usage = gl.STATIC_DRAW;
|
||
|
}
|
||
|
|
||
|
//set index if undefined
|
||
|
if (attribute.index == null) {
|
||
|
let topIndex = attributesIdx.get(program) || 0;
|
||
|
attribute.index = topIndex++;
|
||
|
topIndex = Math.max(topIndex, attribute.index);
|
||
|
attributesIdx.set(program, topIndex);
|
||
|
}
|
||
|
|
||
|
if (!attribute.size) {
|
||
|
attribute.size = 2;
|
||
|
}
|
||
|
|
||
|
if (!attribute.type) {
|
||
|
attribute.type = attribute.target === gl.ELEMENT_ARRAY_BUFFER ? gl.UNSIGNED_SHORT : gl.FLOAT;
|
||
|
}
|
||
|
|
||
|
if (Array.isArray(attribute.data)) {
|
||
|
if (attribute.type === gl.FLOAT) {
|
||
|
attribute.data = new Float32Array(attribute.data);
|
||
|
}
|
||
|
else if (attribute.type === gl.UNSIGNED_BYTE) {
|
||
|
attribute.data = new Uint8Array(attribute.data);
|
||
|
}
|
||
|
else if (attribute.type === gl.UNSIGNED_SHORT) {
|
||
|
attribute.data = new Uint16Array(attribute.data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (attribute.normalized == null) {
|
||
|
attribute.normalized = false;
|
||
|
}
|
||
|
|
||
|
if (attribute.stride == null) {
|
||
|
attribute.stride = 0;
|
||
|
}
|
||
|
|
||
|
if (attribute.offset == null) {
|
||
|
attribute.offset = 0;
|
||
|
}
|
||
|
|
||
|
gl.bindBuffer(attribute.target, attribute.buffer);
|
||
|
gl.bufferData(attribute.target, attribute.data, attribute.usage);
|
||
|
|
||
|
gl.enableVertexAttribArray(attribute.index);
|
||
|
gl.vertexAttribPointer(attribute.index, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset);
|
||
|
gl.bindAttribLocation(program, attribute.index, attribute.name);
|
||
|
|
||
|
return attribute;
|
||
|
}
|