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.
191 lines
5.3 KiB
191 lines
5.3 KiB
'use strict'
|
|
|
|
var coallesceUniforms = require('./reflect')
|
|
var GLError = require("./GLError")
|
|
|
|
module.exports = createUniformWrapper
|
|
|
|
//Binds a function and returns a value
|
|
function identity(x) {
|
|
var c = new Function('y', 'return function(){return y}')
|
|
return c(x)
|
|
}
|
|
|
|
function makeVector(length, fill) {
|
|
var result = new Array(length)
|
|
for(var i=0; i<length; ++i) {
|
|
result[i] = fill
|
|
}
|
|
return result
|
|
}
|
|
|
|
//Create shims for uniforms
|
|
function createUniformWrapper(gl, wrapper, uniforms, locations) {
|
|
|
|
function makeGetter(index) {
|
|
var proc = new Function(
|
|
'gl'
|
|
, 'wrapper'
|
|
, 'locations'
|
|
, 'return function(){return gl.getUniform(wrapper.program,locations[' + index + '])}')
|
|
return proc(gl, wrapper, locations)
|
|
}
|
|
|
|
function makePropSetter(path, index, type) {
|
|
switch(type) {
|
|
case 'bool':
|
|
case 'int':
|
|
case 'sampler2D':
|
|
case 'samplerCube':
|
|
return 'gl.uniform1i(locations[' + index + '],obj' + path + ')'
|
|
case 'float':
|
|
return 'gl.uniform1f(locations[' + index + '],obj' + path + ')'
|
|
default:
|
|
var vidx = type.indexOf('vec')
|
|
if(0 <= vidx && vidx <= 1 && type.length === 4 + vidx) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid data type')
|
|
}
|
|
switch(type.charAt(0)) {
|
|
case 'b':
|
|
case 'i':
|
|
return 'gl.uniform' + d + 'iv(locations[' + index + '],obj' + path + ')'
|
|
case 'v':
|
|
return 'gl.uniform' + d + 'fv(locations[' + index + '],obj' + path + ')'
|
|
default:
|
|
throw new GLError('', 'Unrecognized data type for vector ' + name + ': ' + type)
|
|
}
|
|
} else if(type.indexOf('mat') === 0 && type.length === 4) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type)
|
|
}
|
|
return 'gl.uniformMatrix' + d + 'fv(locations[' + index + '],false,obj' + path + ')'
|
|
} else {
|
|
throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
function enumerateIndices(prefix, type) {
|
|
if(typeof type !== 'object') {
|
|
return [ [prefix, type] ]
|
|
}
|
|
var indices = []
|
|
for(var id in type) {
|
|
var prop = type[id]
|
|
var tprefix = prefix
|
|
if(parseInt(id) + '' === id) {
|
|
tprefix += '[' + id + ']'
|
|
} else {
|
|
tprefix += '.' + id
|
|
}
|
|
if(typeof prop === 'object') {
|
|
indices.push.apply(indices, enumerateIndices(tprefix, prop))
|
|
} else {
|
|
indices.push([tprefix, prop])
|
|
}
|
|
}
|
|
return indices
|
|
}
|
|
|
|
function makeSetter(type) {
|
|
var code = [ 'return function updateProperty(obj){' ]
|
|
var indices = enumerateIndices('', type)
|
|
for(var i=0; i<indices.length; ++i) {
|
|
var item = indices[i]
|
|
var path = item[0]
|
|
var idx = item[1]
|
|
if(locations[idx]) {
|
|
code.push(makePropSetter(path, idx, uniforms[idx].type))
|
|
}
|
|
}
|
|
code.push('return obj}')
|
|
var proc = new Function('gl', 'locations', code.join('\n'))
|
|
return proc(gl, locations)
|
|
}
|
|
|
|
function defaultValue(type) {
|
|
switch(type) {
|
|
case 'bool':
|
|
return false
|
|
case 'int':
|
|
case 'sampler2D':
|
|
case 'samplerCube':
|
|
return 0
|
|
case 'float':
|
|
return 0.0
|
|
default:
|
|
var vidx = type.indexOf('vec')
|
|
if(0 <= vidx && vidx <= 1 && type.length === 4 + vidx) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid data type')
|
|
}
|
|
if(type.charAt(0) === 'b') {
|
|
return makeVector(d, false)
|
|
}
|
|
return makeVector(d, 0)
|
|
} else if(type.indexOf('mat') === 0 && type.length === 4) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type)
|
|
}
|
|
return makeVector(d*d, 0)
|
|
} else {
|
|
throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
function storeProperty(obj, prop, type) {
|
|
if(typeof type === 'object') {
|
|
var child = processObject(type)
|
|
Object.defineProperty(obj, prop, {
|
|
get: identity(child),
|
|
set: makeSetter(type),
|
|
enumerable: true,
|
|
configurable: false
|
|
})
|
|
} else {
|
|
if(locations[type]) {
|
|
Object.defineProperty(obj, prop, {
|
|
get: makeGetter(type),
|
|
set: makeSetter(type),
|
|
enumerable: true,
|
|
configurable: false
|
|
})
|
|
} else {
|
|
obj[prop] = defaultValue(uniforms[type].type)
|
|
}
|
|
}
|
|
}
|
|
|
|
function processObject(obj) {
|
|
var result
|
|
if(Array.isArray(obj)) {
|
|
result = new Array(obj.length)
|
|
for(var i=0; i<obj.length; ++i) {
|
|
storeProperty(result, i, obj[i])
|
|
}
|
|
} else {
|
|
result = {}
|
|
for(var id in obj) {
|
|
storeProperty(result, id, obj[id])
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
//Return data
|
|
var coallesced = coallesceUniforms(uniforms, true)
|
|
return {
|
|
get: identity(processObject(coallesced)),
|
|
set: makeSetter(coallesced),
|
|
enumerable: true,
|
|
configurable: true
|
|
}
|
|
}
|
|
|