UNPKG

marching

Version:

Marching.js is a JavaScript library that compiles GLSL ray marchers.

208 lines (178 loc) 5.3 kB
const { param_wrap, MaterialID } = require( './utils.js' ) const { Var, float_var_gen, vec2_var_gen, vec3_var_gen, vec4_var_gen, int_var_gen, VarAlloc } = require( './var.js' ) const Matrix = require( './external/matrix.js' ) window.Matrix = Matrix const MatrixWrap = function ( shouldInvert = false ) { const m = Object.create( MatrixWrap.prototype ) m.dirty = true m.translation = {} m.scale = {} m.shouldInvert = shouldInvert m.rotation = { axis: {} } m.parent = null let tx = 0, ty = 0, tz = 0 Object.defineProperties( m.translation, { x: { get() { return tx }, set(v){ tx = v //m.__data = m.__data.multiply( Matrix.translate( tx, ty, tz ) ) m.dirty = true } }, y: { get() { return ty }, set(v){ ty = v //m.__data = m.__data.multiply( Matrix.translate( tx, ty, tz ) ) m.dirty = true } }, z: { get() { return tz }, set(v){ tz = v //m.__data = m.__data.multiply( Matrix.translate( tx, ty, tz ) ) m.dirty = true } }, }) // scaling must be sent as separate uniform to avoid sdf over estimation let scale = 1 Object.defineProperty( m,'scale', { get() { return scale }, set(v){ scale = v //m.__data = m.__data.multiply( Matrix.rotate( angle, rx, ry, rz ) ) m.dirty = true } }) /* FOR NON-UNIFORM SCALING: * * 1. comment out scale property above * 2. uncomment scale property below * 3. change emit_decl to use a vec3 for scale * 4. change upload_data to upload a 3f * 5. In "primitives.js", replace line 155 (part of emit) to use compensated scaling */ //let sx = 1, sy = 1, sz = 1 //Object.defineProperties( m.scale, { // x: { // get() { return sx }, // set(v){ // sx = v // //m.__data = m.__data.multiply( Matrix.scale( sx, sy, sz ) ) // m.dirty = true // } // }, // y: { // get() { return sy }, // set(v){ // sy = v // //m.__data = m.__data.multiply( Matrix.scale( sx, sy, sz ) ) // m.dirty = true // } // }, // z: { // get() { return sz }, // set(v){ // sz = v // //m.__data = m.__data.multiply( Matrix.scale( sx, sy, sz ) ) // m.dirty = true // } // }, //}) let angle = 0 Object.defineProperty( m.rotation, 'angle', { get() { return angle }, set(v){ angle = v //m.__data = m.__data.multiply( Matrix.rotate( angle, rx, ry, rz ) ) m.dirty = true } }) let rx = 0, ry = 0, rz = 0 Object.defineProperties( m.rotation.axis, { x: { get() { return rx }, set(v){ rx = v //m.__data = m.__data = Matrix.rotate( angle, rx, ry, rz, m.__data ) m.dirty = true } }, y: { get() { return ry }, set(v){ ry = v //m.__data = m.__data = Matrix.rotate( angle, rx, ry, rz, m.__data ) m.dirty = true } }, z: { get() { return rz }, set(v){ rz = v //m.__data = m.__data = Matrix.rotate( angle, rx, ry, rz, m.__data ) m.dirty = true } }, }) m.__rotations = [] m.__id = VarAlloc.alloc() m.__dirty = function() {} m.__data = Matrix.identity() m.__Matrix = Matrix m.varName = 'transform' + m.__id return m } MatrixWrap.prototype = { type: 'matrix', emit() { return this.varName }, emit_scale() { return this.varName + '_scale' }, emit_decl() { const decl = ` uniform mat4 ${this.varName}; uniform float ${this.varName}_scale; ` return decl }, update_location(gl, program) { this.loc = gl.getUniformLocation( program, this.varName ) this.loc_scale = gl.getUniformLocation( program, this.varName+'_scale' ) }, upload_data(gl) { if( !this.dirty ) return this.internal() if( this.shouldInvert === true ) { const inverse = Matrix.inverse( this.__data ) gl.uniformMatrix4fv( this.loc, false, inverse.m ) }else{ gl.uniformMatrix4fv( this.loc, false, this.__data.m ) } //gl.uniform3f(this.loc_scale, this.scale.x, this.scale.y, this.scale.z ) // scaling must be sent as separate uniform to avoid sdf over-estimation gl.uniform1f(this.loc_scale, this.scale ) this.dirty = false }, internal() { this.__data = Matrix.identity() if( this.parent != null ) this.__data = this.parent.__data this.__data = this.__data.multiply( Matrix.translate( this.translation.x, this.translation.y, this.translation.z ) ) // handle cumulative rotations via .rotateBy() method this.__rotations.forEach( r => this.__data = this.__data.multiply( r ) ) // handle absolute rotations via .rotate() method... should this be aliased to rotateTo() ? this.__data = this.__data.multiply( Matrix.rotate( this.rotation.angle, this.rotation.axis.x, this.rotation.axis.y, this.rotation.axis.z ) ) this.__data = this.__data.multiply( Matrix.scale( this.scale, this.scale, this.scale ) ) }, invert( shouldInvert = true) { this.shouldInvert = shouldInvert this.dirty = true }, apply( transform = null, shouldInvert = false ) { this.parent = transform this.dirty = true } } module.exports = MatrixWrap