(function(global){ var LiteGraph = global.LiteGraph; //Converter function Converter() { this.addInput("in","*"); this.size = [60,20]; } Converter.title = "Converter"; Converter.desc = "type A to type B"; Converter.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; if(this.outputs) for(var i = 0; i < this.outputs.length; i++) { var output = this.outputs[i]; if(!output.links || !output.links.length) continue; var result = null; switch( output.name ) { case "number": result = v.length ? v[0] : parseFloat(v); break; case "vec2": case "vec3": case "vec4": var result = null; var count = 1; switch(output.name) { case "vec2": count = 2; break; case "vec3": count = 3; break; case "vec4": count = 4; break; } var result = new Float32Array( count ); if( v.length ) { for(var j = 0; j < v.length && j < result.length; j++) result[j] = v[j]; } else result[0] = parseFloat(v); break; } this.setOutputData(i, result); } } Converter.prototype.onGetOutputs = function() { return [["number","number"],["vec2","vec2"],["vec3","vec3"],["vec4","vec4"]]; } LiteGraph.registerNodeType("math/converter", Converter ); //Bypass function Bypass() { this.addInput("in"); this.addOutput("out"); this.size = [60,20]; } Bypass.title = "Bypass"; Bypass.desc = "removes the type"; Bypass.prototype.onExecute = function() { var v = this.getInputData(0); this.setOutputData(0, v); } LiteGraph.registerNodeType("math/bypass", Bypass ); function ToNumber() { this.addInput("in"); this.addOutput("out"); } ToNumber.title = "to Number"; ToNumber.desc = "Cast to number"; ToNumber.prototype.onExecute = function() { var v = this.getInputData(0); this.setOutputData(0, Number(v) ); } LiteGraph.registerNodeType("math/to_number", ToNumber ); function MathRange() { this.addInput("in","number",{locked:true}); this.addOutput("out","number",{locked:true}); this.addProperty( "in", 0 ); this.addProperty( "in_min", 0 ); this.addProperty( "in_max", 1 ); this.addProperty( "out_min", 0 ); this.addProperty( "out_max", 1 ); this.size = [80,20]; } MathRange.title = "Range"; MathRange.desc = "Convert a number from one range to another"; MathRange.prototype.getTitle = function() { if(this.flags.collapsed) return (this._last_v || 0).toFixed(2); return this.title; } MathRange.prototype.onExecute = function() { if(this.inputs) for(var i = 0; i < this.inputs.length; i++) { var input = this.inputs[i]; var v = this.getInputData(i); if(v === undefined) continue; this.properties[ input.name ] = v; } var v = this.properties["in"]; if(v === undefined || v === null || v.constructor !== Number) v = 0; var in_min = this.properties.in_min; var in_max = this.properties.in_max; var out_min = this.properties.out_min; var out_max = this.properties.out_max; this._last_v = ((v - in_min) / (in_max - in_min)) * (out_max - out_min) + out_min; this.setOutputData(0, this._last_v ); } MathRange.prototype.onDrawBackground = function(ctx) { //show the current value if(this._last_v) this.outputs[0].label = this._last_v.toFixed(3); else this.outputs[0].label = "?"; } MathRange.prototype.onGetInputs = function() { return [["in_min","number"],["in_max","number"],["out_min","number"],["out_max","number"]]; } LiteGraph.registerNodeType("math/range", MathRange); function MathRand() { this.addOutput("value","number"); this.addProperty( "min", 0 ); this.addProperty( "max", 1 ); this.size = [60,20]; } MathRand.title = "Rand"; MathRand.desc = "Random number"; MathRand.prototype.onExecute = function() { if(this.inputs) for(var i = 0; i < this.inputs.length; i++) { var input = this.inputs[i]; var v = this.getInputData(i); if(v === undefined) continue; this.properties[input.name] = v; } var min = this.properties.min; var max = this.properties.max; this._last_v = Math.random() * (max-min) + min; this.setOutputData(0, this._last_v ); } MathRand.prototype.onDrawBackground = function(ctx) { //show the current value this.outputs[0].label = ( this._last_v || 0 ).toFixed(3); } MathRand.prototype.onGetInputs = function() { return [["min","number"],["max","number"]]; } LiteGraph.registerNodeType("math/rand", MathRand); //basic continuous noise function MathNoise() { this.addInput("in","number"); this.addOutput("out","number"); this.addProperty( "min", 0 ); this.addProperty( "max", 1 ); this.addProperty( "smooth", true ); this.size = [90,20]; } MathNoise.title = "Noise"; MathNoise.desc = "Random number with temporal continuity"; MathNoise.data = null; MathNoise.getValue = function(f,smooth) { if( !MathNoise.data ) { MathNoise.data = new Float32Array(1024); for(var i = 0; i < MathNoise.data.length; ++i) MathNoise.data[i] = Math.random(); } f = f % 1024; if(f < 0) f += 1024; var f_min = Math.floor(f); var f = f - f_min; var r1 = MathNoise.data[ f_min ]; var r2 = MathNoise.data[ f_min == 1023 ? 0 : f_min + 1 ]; if(smooth) f = f*f*f*(f*(f*6.0-15.0)+10.0); return r1 * (1-f) + r2 * f; } MathNoise.prototype.onExecute = function() { var f = (this.getInputData(0) || 0); var r = MathNoise.getValue( f, this.properties.smooth ); var min = this.properties.min; var max = this.properties.max; this._last_v = r * (max-min) + min; this.setOutputData(0, this._last_v ); } MathNoise.prototype.onDrawBackground = function(ctx) { //show the current value this.outputs[0].label = ( this._last_v || 0 ).toFixed(3); } LiteGraph.registerNodeType("math/noise", MathNoise); //generates spikes every random time function MathSpikes() { this.addOutput("out","number"); this.addProperty( "min_time", 1 ); this.addProperty( "max_time", 2 ); this.addProperty( "duration", 0.2 ); this.size = [90,20]; this._remaining_time = 0; this._blink_time = 0; } MathSpikes.title = "Spikes"; MathSpikes.desc = "spike every random time"; MathSpikes.prototype.onExecute = function() { var dt = this.graph.elapsed_time; //in secs this._remaining_time -= dt; this._blink_time -= dt; var v = 0; if(this._blink_time > 0) { var f = this._blink_time / this.properties.duration; v = 1/(Math.pow(f*8-4,4)+1); } if( this._remaining_time < 0) { this._remaining_time = Math.random() * (this.properties.max_time-this.properties.min_time) + this.properties.min_time; this._blink_time = this.properties.duration; this.boxcolor = "#FFF"; } else this.boxcolor = "#000"; this.setOutputData( 0, v ); } LiteGraph.registerNodeType("math/spikes", MathSpikes); //Math clamp function MathClamp() { this.addInput("in","number"); this.addOutput("out","number"); this.size = [60,20]; this.addProperty( "min", 0 ); this.addProperty( "max", 1 ); } MathClamp.title = "Clamp"; MathClamp.desc = "Clamp number between min and max"; MathClamp.filter = "shader"; MathClamp.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; v = Math.max(this.properties.min,v); v = Math.min(this.properties.max,v); this.setOutputData(0, v ); } MathClamp.prototype.getCode = function(lang) { var code = ""; if(this.isInputConnected(0)) code += "clamp({{0}}," + this.properties.min + "," + this.properties.max + ")"; return code; } LiteGraph.registerNodeType("math/clamp", MathClamp ); //Math ABS function MathLerp() { this.properties = { f: 0.5 }; this.addInput("A","number"); this.addInput("B","number"); this.addOutput("out","number"); } MathLerp.title = "Lerp"; MathLerp.desc = "Linear Interpolation"; MathLerp.prototype.onExecute = function() { var v1 = this.getInputData(0); if(v1 == null) v1 = 0; var v2 = this.getInputData(1); if(v2 == null) v2 = 0; var f = this.properties.f; var _f = this.getInputData(2); if(_f !== undefined) f = _f; this.setOutputData(0, v1 * (1-f) + v2 * f ); } MathLerp.prototype.onGetInputs = function() { return [["f","number"]]; } LiteGraph.registerNodeType("math/lerp", MathLerp); //Math ABS function MathAbs() { this.addInput("in","number"); this.addOutput("out","number"); this.size = [60,20]; } MathAbs.title = "Abs"; MathAbs.desc = "Absolute"; MathAbs.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; this.setOutputData(0, Math.abs(v) ); } LiteGraph.registerNodeType("math/abs", MathAbs); //Math Floor function MathFloor() { this.addInput("in","number"); this.addOutput("out","number"); this.size = [80,30]; } MathFloor.title = "Floor"; MathFloor.desc = "Floor number to remove fractional part"; MathFloor.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; this.setOutputData(0, Math.floor(v) ); } LiteGraph.registerNodeType("math/floor", MathFloor ); //Math frac function MathFrac() { this.addInput("in","number"); this.addOutput("out","number"); this.size = [80,30]; } MathFrac.title = "Frac"; MathFrac.desc = "Returns fractional part"; MathFrac.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; this.setOutputData(0, v%1 ); } LiteGraph.registerNodeType("math/frac",MathFrac); //Math Floor function MathSmoothStep() { this.addInput("in","number"); this.addOutput("out","number"); this.size = [80,30]; this.properties = { A: 0, B: 1 }; } MathSmoothStep.title = "Smoothstep"; MathSmoothStep.desc = "Smoothstep"; MathSmoothStep.prototype.onExecute = function() { var v = this.getInputData(0); if(v === undefined) return; var edge0 = this.properties.A; var edge1 = this.properties.B; // Scale, bias and saturate x to 0..1 range v = Math.clamp((v - edge0)/(edge1 - edge0), 0.0, 1.0); // Evaluate polynomial v = v*v*(3 - 2*v); this.setOutputData(0, v ); } LiteGraph.registerNodeType("math/smoothstep", MathSmoothStep ); //Math scale function MathScale() { this.addInput("in","number",{label:""}); this.addOutput("out","number",{label:""}); this.size = [80,30]; this.addProperty( "factor", 1 ); } MathScale.title = "Scale"; MathScale.desc = "v * factor"; MathScale.prototype.onExecute = function() { var value = this.getInputData(0); if(value != null) this.setOutputData(0, value * this.properties.factor ); } LiteGraph.registerNodeType("math/scale", MathScale ); //Math Average function MathAverageFilter() { this.addInput("in","number"); this.addOutput("out","number"); this.size = [80,30]; this.addProperty( "samples", 10 ); this._values = new Float32Array(10); this._current = 0; } MathAverageFilter.title = "Average"; MathAverageFilter.desc = "Average Filter"; MathAverageFilter.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) v = 0; var num_samples = this._values.length; this._values[ this._current % num_samples ] = v; this._current += 1; if(this._current > num_samples) this._current = 0; var avr = 0; for(var i = 0; i < num_samples; ++i) avr += this._values[i]; this.setOutputData( 0, avr / num_samples ); } MathAverageFilter.prototype.onPropertyChanged = function( name, value ) { if(value < 1) value = 1; this.properties.samples = Math.round(value); var old = this._values; this._values = new Float32Array( this.properties.samples ); if(old.length <= this._values.length ) this._values.set(old); else this._values.set( old.subarray( 0, this._values.length ) ); } LiteGraph.registerNodeType("math/average", MathAverageFilter ); //Math function MathTendTo() { this.addInput("in","number"); this.addOutput("out","number"); this.addProperty( "factor", 0.1 ); this.size = [80,30]; this._value = null; } MathTendTo.title = "TendTo"; MathTendTo.desc = "moves the output value always closer to the input"; MathTendTo.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) v = 0; var f = this.properties.factor; if(this._value == null) this._value = v; else this._value = this._value * (1 - f) + v * f; this.setOutputData( 0, this._value ); } LiteGraph.registerNodeType("math/tendTo", MathTendTo ); //Math operation function MathOperation() { this.addInput("A","number"); this.addInput("B","number"); this.addOutput("=","number"); this.addProperty( "A", 1 ); this.addProperty( "B", 1 ); this.addProperty( "OP", "+", "enum", { values: MathOperation.values } ); } MathOperation.values = ["+","-","*","/","%","^"]; MathOperation.title = "Operation"; MathOperation.desc = "Easy math operators"; MathOperation["@OP"] = { type:"enum", title: "operation", values: MathOperation.values }; MathOperation.size = [100,60]; MathOperation.prototype.getTitle = function() { return "A " + this.properties.OP + " B"; } MathOperation.prototype.setValue = function(v) { if( typeof(v) == "string") v = parseFloat(v); this.properties["value"] = v; } MathOperation.prototype.onExecute = function() { var A = this.getInputData(0); var B = this.getInputData(1); if(A!=null) this.properties["A"] = A; else A = this.properties["A"]; if(B!=null) this.properties["B"] = B; else B = this.properties["B"]; var result = 0; switch(this.properties.OP) { case '+': result = A+B; break; case '-': result = A-B; break; case 'x': case 'X': case '*': result = A*B; break; case '/': result = A/B; break; case '%': result = A%B; break; case '^': result = Math.pow(A,B); break; default: console.warn("Unknown operation: " + this.properties.OP); } this.setOutputData(0, result ); } MathOperation.prototype.onDrawBackground = function(ctx) { if(this.flags.collapsed) return; ctx.font = "40px Arial"; ctx.fillStyle = "#666"; ctx.textAlign = "center"; ctx.fillText(this.properties.OP, this.size[0] * 0.5, ( this.size[1] + LiteGraph.NODE_TITLE_HEIGHT ) * 0.5 ); ctx.textAlign = "left"; } LiteGraph.registerNodeType("math/operation", MathOperation ); //Math compare function MathCompare() { this.addInput( "A","number" ); this.addInput( "B","number" ); this.addOutput("A==B","boolean"); this.addOutput("A!=B","boolean"); this.addProperty( "A", 0 ); this.addProperty( "B", 0 ); } MathCompare.title = "Compare"; MathCompare.desc = "compares between two values"; MathCompare.prototype.onExecute = function() { var A = this.getInputData(0); var B = this.getInputData(1); if(A !== undefined) this.properties["A"] = A; else A = this.properties["A"]; if(B !== undefined) this.properties["B"] = B; else B = this.properties["B"]; for(var i = 0, l = this.outputs.length; i < l; ++i) { var output = this.outputs[i]; if(!output.links || !output.links.length) continue; switch( output.name ) { case "A==B": value = A==B; break; case "A!=B": value = A!=B; break; case "A>B": value = A>B; break; case "A=B": value = A>=B; break; } this.setOutputData(i, value ); } }; MathCompare.prototype.onGetOutputs = function() { return [["A==B","boolean"],["A!=B","boolean"],["A>B","boolean"],["A=B","boolean"],["A<=B","boolean"]]; } LiteGraph.registerNodeType("math/compare",MathCompare); LiteGraph.registerSearchboxExtra("math/compare","==", { outputs:[["A==B","boolean"]], title: "A==B" }); LiteGraph.registerSearchboxExtra("math/compare","!=", { outputs:[["A!=B","boolean"]], title: "A!=B" }); LiteGraph.registerSearchboxExtra("math/compare",">", { outputs:[["A>B","boolean"]], title: "A>B" }); LiteGraph.registerSearchboxExtra("math/compare","<", { outputs:[["A=", { outputs:[["A>=B","boolean"]], title: "A>=B" }); LiteGraph.registerSearchboxExtra("math/compare","<=", { outputs:[["A<=B","boolean"]], title: "A<=B" }); function MathCondition() { this.addInput("A","number"); this.addInput("B","number"); this.addOutput("out","boolean"); this.addProperty( "A", 1 ); this.addProperty( "B", 1 ); this.addProperty( "OP", ">", "string", { values: MathCondition.values } ); this.size = [80,60]; } MathCondition.values = [">","<","==","!=","<=",">="]; MathCondition["@OP"] = { type:"enum", title: "operation", values: MathCondition.values }; MathCondition.title = "Condition"; MathCondition.desc = "evaluates condition between A and B"; MathCondition.prototype.onExecute = function() { var A = this.getInputData(0); if(A === undefined) A = this.properties.A; else this.properties.A = A; var B = this.getInputData(1); if(B === undefined) B = this.properties.B; else this.properties.B = B; var result = true; switch(this.properties.OP) { case ">": result = A>B; break; case "<": result = A=": result = A>=B; break; } this.setOutputData(0, result ); } LiteGraph.registerNodeType("math/condition", MathCondition); function MathAccumulate() { this.addInput("inc","number"); this.addOutput("total","number"); this.addProperty( "increment", 1 ); this.addProperty( "value", 0 ); } MathAccumulate.title = "Accumulate"; MathAccumulate.desc = "Increments a value every time"; MathAccumulate.prototype.onExecute = function() { if(this.properties.value === null) this.properties.value = 0; var inc = this.getInputData(0); if(inc !== null) this.properties.value += inc; else this.properties.value += this.properties.increment; this.setOutputData(0, this.properties.value ); } LiteGraph.registerNodeType("math/accumulate", MathAccumulate); //Math Trigonometry function MathTrigonometry() { this.addInput("v","number"); this.addOutput("sin","number"); this.addProperty( "amplitude", 1 ); this.addProperty( "offset", 0 ); this.bgImageUrl = "nodes/imgs/icon-sin.png"; } MathTrigonometry.title = "Trigonometry"; MathTrigonometry.desc = "Sin Cos Tan"; MathTrigonometry.filter = "shader"; MathTrigonometry.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) v = 0; var amplitude = this.properties["amplitude"]; var slot = this.findInputSlot("amplitude"); if(slot != -1) amplitude = this.getInputData(slot); var offset = this.properties["offset"]; slot = this.findInputSlot("offset"); if(slot != -1) offset = this.getInputData(slot); for(var i = 0, l = this.outputs.length; i < l; ++i) { var output = this.outputs[i]; switch( output.name ) { case "sin": value = Math.sin(v); break; case "cos": value = Math.cos(v); break; case "tan": value = Math.tan(v); break; case "asin": value = Math.asin(v); break; case "acos": value = Math.acos(v); break; case "atan": value = Math.atan(v); break; } this.setOutputData(i, amplitude * value + offset); } } MathTrigonometry.prototype.onGetInputs = function() { return [["v","number"],["amplitude","number"],["offset","number"]]; } MathTrigonometry.prototype.onGetOutputs = function() { return [["sin","number"],["cos","number"],["tan","number"],["asin","number"],["acos","number"],["atan","number"]]; } LiteGraph.registerNodeType("math/trigonometry", MathTrigonometry ); LiteGraph.registerSearchboxExtra("math/trigonometry","SIN()", { outputs:[["sin","number"]], title: "SIN()" }); LiteGraph.registerSearchboxExtra("math/trigonometry","COS()", { outputs:[["cos","number"]], title: "COS()" }); LiteGraph.registerSearchboxExtra("math/trigonometry","TAN()", { outputs:[["tan","number"]], title: "TAN()" }); //math library for safe math operations without eval function MathFormula() { this.addInput("x","number"); this.addInput("y","number"); this.addOutput("","number"); this.properties = {x:1.0, y:1.0, formula:"x+y"}; this.code_widget = this.addWidget("text","F(x,y)",this.properties.formula,function(v,canvas,node){ node.properties.formula = v; }); this.addWidget("toggle","allow",LiteGraph.allow_scripts,function(v){ LiteGraph.allow_scripts = v; }); this._func = null; } MathFormula.title = "Formula"; MathFormula.desc = "Compute formula"; MathFormula.size = [160,100]; MathAverageFilter.prototype.onPropertyChanged = function( name, value ) { if(name == "formula") this.code_widget.value = value; } MathFormula.prototype.onExecute = function() { if(!LiteGraph.allow_scripts) return; var x = this.getInputData(0); var y = this.getInputData(1); if(x != null) this.properties["x"] = x; else x = this.properties["x"]; if(y!=null) this.properties["y"] = y; else y = this.properties["y"]; var f = this.properties["formula"]; var value; try { if(!this._func || this._func_code != this.properties.formula) { this._func = new Function( "x","y","TIME", "return " + this.properties.formula ); this._func_code = this.properties.formula; } value = this._func(x,y,this.graph.globaltime); this.boxcolor = null; } catch (err) { this.boxcolor = "red"; } this.setOutputData(0, value ); } MathFormula.prototype.getTitle = function() { return this._func_code || "Formula"; } MathFormula.prototype.onDrawBackground = function() { var f = this.properties["formula"]; if(this.outputs && this.outputs.length) this.outputs[0].label = f; } LiteGraph.registerNodeType("math/formula", MathFormula ); function Math3DVec2ToXYZ() { this.addInput("vec2","vec2"); this.addOutput("x","number"); this.addOutput("y","number"); } Math3DVec2ToXYZ.title = "Vec2->XY"; Math3DVec2ToXYZ.desc = "vector 2 to components"; Math3DVec2ToXYZ.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; this.setOutputData( 0, v[0] ); this.setOutputData( 1, v[1] ); } LiteGraph.registerNodeType("math3d/vec2-to-xyz", Math3DVec2ToXYZ ); function Math3DXYToVec2() { this.addInputs([["x","number"],["y","number"]]); this.addOutput("vec2","vec2"); this.properties = {x:0, y:0}; this._data = new Float32Array(2); } Math3DXYToVec2.title = "XY->Vec2"; Math3DXYToVec2.desc = "components to vector2"; Math3DXYToVec2.prototype.onExecute = function() { var x = this.getInputData(0); if(x == null) x = this.properties.x; var y = this.getInputData(1); if(y == null) y = this.properties.y; var data = this._data; data[0] = x; data[1] = y; this.setOutputData( 0, data ); } LiteGraph.registerNodeType("math3d/xy-to-vec2", Math3DXYToVec2 ); function Math3DVec3ToXYZ() { this.addInput("vec3","vec3"); this.addOutput("x","number"); this.addOutput("y","number"); this.addOutput("z","number"); } Math3DVec3ToXYZ.title = "Vec3->XYZ"; Math3DVec3ToXYZ.desc = "vector 3 to components"; Math3DVec3ToXYZ.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; this.setOutputData( 0, v[0] ); this.setOutputData( 1, v[1] ); this.setOutputData( 2, v[2] ); } LiteGraph.registerNodeType("math3d/vec3-to-xyz", Math3DVec3ToXYZ ); function Math3DXYZToVec3() { this.addInputs([["x","number"],["y","number"],["z","number"]]); this.addOutput("vec3","vec3"); this.properties = {x:0, y:0, z:0}; this._data = new Float32Array(3); } Math3DXYZToVec3.title = "XYZ->Vec3"; Math3DXYZToVec3.desc = "components to vector3"; Math3DXYZToVec3.prototype.onExecute = function() { var x = this.getInputData(0); if(x == null) x = this.properties.x; var y = this.getInputData(1); if(y == null) y = this.properties.y; var z = this.getInputData(2); if(z == null) z = this.properties.z; var data = this._data; data[0] = x; data[1] = y; data[2] = z; this.setOutputData( 0, data ); } LiteGraph.registerNodeType("math3d/xyz-to-vec3", Math3DXYZToVec3 ); function Math3DVec4ToXYZW() { this.addInput("vec4","vec4"); this.addOutput("x","number"); this.addOutput("y","number"); this.addOutput("z","number"); this.addOutput("w","number"); } Math3DVec4ToXYZW.title = "Vec4->XYZW"; Math3DVec4ToXYZW.desc = "vector 4 to components"; Math3DVec4ToXYZW.prototype.onExecute = function() { var v = this.getInputData(0); if(v == null) return; this.setOutputData( 0, v[0] ); this.setOutputData( 1, v[1] ); this.setOutputData( 2, v[2] ); this.setOutputData( 3, v[3] ); } LiteGraph.registerNodeType("math3d/vec4-to-xyzw", Math3DVec4ToXYZW ); function Math3DXYZWToVec4() { this.addInputs([["x","number"],["y","number"],["z","number"],["w","number"]]); this.addOutput("vec4","vec4"); this.properties = {x:0, y:0, z:0, w:0}; this._data = new Float32Array(4); } Math3DXYZWToVec4.title = "XYZW->Vec4"; Math3DXYZWToVec4.desc = "components to vector4"; Math3DXYZWToVec4.prototype.onExecute = function() { var x = this.getInputData(0); if(x == null) x = this.properties.x; var y = this.getInputData(1); if(y == null) y = this.properties.y; var z = this.getInputData(2); if(z == null) z = this.properties.z; var w = this.getInputData(3); if(w == null) w = this.properties.w; var data = this._data; data[0] = x; data[1] = y; data[2] = z; data[3] = w; this.setOutputData( 0, data ); } LiteGraph.registerNodeType("math3d/xyzw-to-vec4", Math3DXYZWToVec4 ); //if glMatrix is installed... if(global.glMatrix) { function Math3DQuaternion() { this.addOutput("quat","quat"); this.properties = { x:0, y:0, z:0, w: 1 }; this._value = quat.create(); } Math3DQuaternion.title = "Quaternion"; Math3DQuaternion.desc = "quaternion"; Math3DQuaternion.prototype.onExecute = function() { this._value[0] = this.properties.x; this._value[1] = this.properties.y; this._value[2] = this.properties.z; this._value[3] = this.properties.w; this.setOutputData( 0, this._value ); } LiteGraph.registerNodeType("math3d/quaternion", Math3DQuaternion ); function Math3DRotation() { this.addInputs([["degrees","number"],["axis","vec3"]]); this.addOutput("quat","quat"); this.properties = { angle:90.0, axis: vec3.fromValues(0,1,0) }; this._value = quat.create(); } Math3DRotation.title = "Rotation"; Math3DRotation.desc = "quaternion rotation"; Math3DRotation.prototype.onExecute = function() { var angle = this.getInputData(0); if(angle == null) angle = this.properties.angle; var axis = this.getInputData(1); if(axis == null) axis = this.properties.axis; var R = quat.setAxisAngle( this._value, axis, angle * 0.0174532925 ); this.setOutputData( 0, R ); } LiteGraph.registerNodeType("math3d/rotation", Math3DRotation ); //Math3D rotate vec3 function Math3DRotateVec3() { this.addInputs([["vec3","vec3"],["quat","quat"]]); this.addOutput("result","vec3"); this.properties = { vec: [0,0,1] }; } Math3DRotateVec3.title = "Rot. Vec3"; Math3DRotateVec3.desc = "rotate a point"; Math3DRotateVec3.prototype.onExecute = function() { var vec = this.getInputData(0); if(vec == null) vec = this.properties.vec; var quat = this.getInputData(1); if(quat == null) this.setOutputData(vec); else this.setOutputData( 0, vec3.transformQuat( vec3.create(), vec, quat ) ); } LiteGraph.registerNodeType("math3d/rotate_vec3", Math3DRotateVec3); function Math3DMultQuat() { this.addInputs( [["A","quat"],["B","quat"]] ); this.addOutput( "A*B","quat" ); this._value = quat.create(); } Math3DMultQuat.title = "Mult. Quat"; Math3DMultQuat.desc = "rotate quaternion"; Math3DMultQuat.prototype.onExecute = function() { var A = this.getInputData(0); if(A == null) return; var B = this.getInputData(1); if(B == null) return; var R = quat.multiply( this._value, A, B ); this.setOutputData( 0, R ); } LiteGraph.registerNodeType("math3d/mult-quat", Math3DMultQuat ); function Math3DQuatSlerp() { this.addInputs( [["A","quat"],["B","quat"],["factor","number"]] ); this.addOutput( "slerp","quat" ); this.addProperty( "factor", 0.5 ); this._value = quat.create(); } Math3DQuatSlerp.title = "Quat Slerp"; Math3DQuatSlerp.desc = "quaternion spherical interpolation"; Math3DQuatSlerp.prototype.onExecute = function() { var A = this.getInputData(0); if(A == null) return; var B = this.getInputData(1); if(B == null) return; var factor = this.properties.factor; if( this.getInputData(2) != null ) factor = this.getInputData(2); var R = quat.slerp( this._value, A, B, factor ); this.setOutputData( 0, R ); } LiteGraph.registerNodeType("math3d/quat-slerp", Math3DQuatSlerp ); } //glMatrix })(this);