// VVVV.js -- Visual Web Client Programming // (c) 2011 Matthias Zauner // VVVV.js is freely distributable under the MIT license. // Additional authors of sub components are mentioned at the specific code locations. /** * The Transform Pin Type * @mixin * @property {String} typeName "Transform" * @property {Boolean} reset_on_disconnect true * @property {Function} defaultValue Function returning an identity matrix */ VVVV.PinTypes.Transform = { typeName: "Transform", reset_on_disconnect: true, defaultValue: function() { return mat4.identity(mat4.create()); } } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NODE: Rotate (Transform) Author(s): Matthias Zauner Original Node Author(s): VVVV Group ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ VVVV.Nodes.Rotate = function(id, graph) { this.constructor(id, "Rotate (Transform)", graph); this.meta = { authors: ['Matthias Zauner'], original_authors: ['VVVV Group'], credits: [], compatibility_issues: [] }; var ident = mat4.identity(mat4.create()); this.trIn = this.addInputPin("Transform In", [], VVVV.PinTypes.Transform); this.xIn = this.addInputPin("X", [0.0], VVVV.PinTypes.Value); this.yIn = this.addInputPin("Y", [0.0], VVVV.PinTypes.Value); this.zIn = this.addInputPin("Z", [0.0], VVVV.PinTypes.Value); this.trOut = this.addOutputPin("Transform Out", [], VVVV.PinTypes.Transform); this.evaluate = function() { var maxSize = this.trIn.isConnected() ? this.getMaxInputSliceCount() : Math.max(this.xIn.getSliceCount(),this.yIn.getSliceCount(),this.zIn.getSliceCount()); for (var i=0; i<maxSize; i++) { var transformin = this.inputPins["Transform In"].getValue(i); var x = parseFloat(this.inputPins["X"].getValue(i)); var y = parseFloat(this.inputPins["Y"].getValue(i)); var z = parseFloat(this.inputPins["Z"].getValue(i)); var t = mat4.create(); mat4.identity(t); mat4.rotate(t, y*Math.PI*2, [0, 1, 0]); mat4.rotate(t, x*Math.PI*2, [1, 0, 0]); mat4.rotate(t, z*Math.PI*2, [0, 0, 1]); if (this.trIn.isConnected()) mat4.multiply(transformin, t, t); this.trOut.setValue(i, t); } this.trOut.setSliceCount(maxSize); } } VVVV.Nodes.Rotate.prototype = new VVVV.Core.Node(); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NODE: Translate (Transform) Author(s): Matthias Zauner Original Node Author(s): VVVV Group ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ VVVV.Nodes.Translate = function(id, graph) { this.constructor(id, "Translate (Transform)", graph); this.meta = { authors: ['Matthias Zauner'], original_authors: ['VVVV Group'], credits: [], compatibility_issues: [] }; var ident = mat4.identity(mat4.create()); this.trIn = this.addInputPin("Transform In", [], VVVV.PinTypes.Transform); this.xIn = this.addInputPin("X", [0.0], VVVV.PinTypes.Value); this.yIn = this.addInputPin("Y", [0.0], VVVV.PinTypes.Value); this.zIn = this.addInputPin("Z", [0.0], VVVV.PinTypes.Value); this.trOut = this.addOutputPin("Transform Out", [], VVVV.PinTypes.Transform); this.evaluate = function() { var maxSize = this.trIn.isConnected() ? this.getMaxInputSliceCount() : Math.max(this.xIn.getSliceCount(),this.yIn.getSliceCount(),this.zIn.getSliceCount()); for (var i=0; i<maxSize; i++) { var x = parseFloat(this.xIn.getValue(i)); var y = parseFloat(this.yIn.getValue(i)); var z = parseFloat(this.zIn.getValue(i)); var t = mat4.create(); mat4.identity(t); mat4.translate(t, [x, y, z]); if (this.trIn.isConnected()) { var transformin = this.trIn.getValue(i); mat4.multiply(transformin, t, t); } this.trOut.setValue(i, t); } this.trOut.setSliceCount(maxSize); } } VVVV.Nodes.Translate.prototype = new VVVV.Core.Node(); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NODE: Scale (Transform) Author(s): Matthias Zauner Original Node Author(s): VVVV Group ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ VVVV.Nodes.Scale = function(id, graph) { this.constructor(id, "Scale (Transform)", graph); this.meta = { authors: ['Matthias Zauner'], original_authors: ['VVVV Group'], credits: [], compatibility_issues: [] }; var ident = mat4.identity(mat4.create()); this.trIn = this.addInputPin("Transform In", [], VVVV.PinTypes.Transform); this.xIn = this.addInputPin("X", [1.0], VVVV.PinTypes.Value); this.yIn = this.addInputPin("Y", [1.0], VVVV.PinTypes.Value); this.zIn = this.addInputPin("Z", [1.0], VVVV.PinTypes.Value); this.trOut = this.addOutputPin("Transform Out", [], VVVV.PinTypes.Transform); this.evaluate = function() { var maxSize = this.trIn.isConnected() ? this.getMaxInputSliceCount() : Math.max(this.xIn.getSliceCount(),this.yIn.getSliceCount(),this.zIn.getSliceCount()); for (var i=0; i<maxSize; i++) { var x = parseFloat(this.inputPins["X"].getValue(i)); var y = parseFloat(this.inputPins["Y"].getValue(i)); var z = parseFloat(this.inputPins["Z"].getValue(i)); var t = mat4.create(); mat4.identity(t); mat4.scale(t, [x, y, z]); if (this.inputPins["Transform In"].isConnected()) { var transformin = this.inputPins["Transform In"].getValue(i); mat4.multiply(transformin, t, t); } this.trOut.setValue(i, t); } this.trOut.setSliceCount(maxSize); } } VVVV.Nodes.Scale.prototype = new VVVV.Core.Node(); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NODE: Perspective (Transform) Author(s): Matthias Zauner Original Node Author(s): VVVV Group ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ VVVV.Nodes.Perspective = function(id, graph) { this.constructor(id, "Perspective (Transform)", graph); this.meta = { authors: ['Matthias Zauner'], original_authors: ['VVVV Group'], credits: [], compatibility_issues: ['Not spreadable'] }; var ident = mat4.identity(mat4.create()); this.addInputPin("Transform In", [], VVVV.PinTypes.Transform); this.addInputPin("FOV", [0.25], VVVV.PinTypes.Value); this.addInputPin("Near Plane", [0.05], VVVV.PinTypes.Value); this.addInputPin("Far Plane", [100.0], VVVV.PinTypes.Value); this.addOutputPin("Transform Out", [], VVVV.PinTypes.Transform); this.evaluate = function() { var fov = parseFloat(this.inputPins["FOV"].getValue(0)); var near = parseFloat(this.inputPins["Near Plane"].getValue(0)); var far = parseFloat(this.inputPins["Far Plane"].getValue(0)); var t = mat4.create(); mat4.identity(t); mat4.perspective(fov*360, 1, near, far, t); if (this.inputPins["Transform In"].isConnected()) { var transformin = this.inputPins["Transform In"].getValue(0); mat4.multiply(transformin, t, t); } this.outputPins["Transform Out"].setValue(0, t); } } VVVV.Nodes.Perspective.prototype = new VVVV.Core.Node(); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NODE: Inverse (Transform) Author(s): Matthias Zauner Original Node Author(s): VVVV Group ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ VVVV.Nodes.InverseTransform = function(id, graph) { this.constructor(id, "Inverse (Transform)", graph); this.meta = { authors: ['Matthias Zauner'], original_authors: ['VVVV Group'], credits: [], compatibility_issues: [] }; var trIn = this.addInputPin("Transform In", [], VVVV.PinTypes.Transform); var sourceIn = this.addInputPin("Source", [], VVVV.PinTypes.Transform); var trOut = this.addOutputPin("Transform Out", [], VVVV.PinTypes.Transform); this.evaluate = function() { var maxSize = this.getMaxInputSliceCount(); for (var i=0; i<maxSize; i++) { var s = mat4.create(); mat4.set(sourceIn.getValue(i), s); mat4.multiply(trIn.getValue(i), mat4.inverse(s, s), s); trOut.setValue(i, s); } trOut.setSliceCount(maxSize); } } VVVV.Nodes.InverseTransform.prototype = new VVVV.Core.Node(); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NODE: LookAt (Transform Vector) Author(s): 'Matthias Zauner' Original Node Author(s): 'VVVV Group' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ VVVV.Nodes.LookAtTransformVector = function(id, graph) { this.constructor(id, "LookAt (Transform Vector)", graph); this.meta = { authors: ['Matthias Zauner'], original_authors: ['VVVV Group'], credits: [], compatibility_issues: [] }; this.auto_evaluate = false; var transformIn = this.addInputPin('Transform In', [], VVVV.PinTypes.Transform); var positionxyzIn = this.addInputPin('Position XYZ', [0, 0, 0], VVVV.PinTypes.Value); var lookatxyzIn = this.addInputPin('LookAt XYZ', [0, 0, 1], VVVV.PinTypes.Value); var upvectorxyzIn = this.addInputPin('UpVector XYZ', [0, 1, 0], VVVV.PinTypes.Value); var transformoutOut = this.addOutputPin('Transform Out', [], VVVV.PinTypes.Transform); var mirror = mat4.create(); mat4.identity(mirror); mat4.scale(mirror, [-1, 1, -1]); this.evaluate = function() { var spreadCount = Math.max(transformIn.getSliceCount(), Math.max(positionxyzIn.getSliceCount()/3, Math.max(lookatxyzIn.getSliceCount()/3, upvectorxyzIn.getSliceCount()/3))); spreadCount = Math.ceil(spreadCount); for (var i=0; i<spreadCount; i++) { var pos = positionxyzIn.getValue(i, 3); var lookat = lookatxyzIn.getValue(i, 3); var up = upvectorxyzIn.getValue(i, 3); var t = mat4.create(); mat4.identity(t); mat4.lookAt(vec3.create(pos), vec3.create(lookat), vec3.create(up), t); mat4.multiply(mirror, t, t); if (transformIn.isConnected()) { mat4.multiply(transformIn.getValue(i), t, t); } transformoutOut.setValue(i, t); } transformoutOut.setSliceCount(spreadCount); } } VVVV.Nodes.LookAtTransformVector.prototype = new VVVV.Core.Node(); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NODE: LookAt (Transform) Author(s): 'Matthias Zauner' Original Node Author(s): 'VVVV Group' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ VVVV.Nodes.LookAtTransform = function(id, graph) { this.constructor(id, "LookAt (Transform)", graph); this.meta = { authors: ['Matthias Zauner'], original_authors: ['VVVV Group'], credits: [], compatibility_issues: [] }; this.auto_evaluate = false; // input pins var transformIn = this.addInputPin('Transform In', [], VVVV.PinTypes.Transform); var positionxIn = this.addInputPin('Position X', [0], VVVV.PinTypes.Value); var positionyIn = this.addInputPin('Position Y', [0], VVVV.PinTypes.Value); var positionzIn = this.addInputPin('Position Z', [0], VVVV.PinTypes.Value); var lookatxIn = this.addInputPin('LookAt X', [0], VVVV.PinTypes.Value); var lookatyIn = this.addInputPin('LookAt Y', [0], VVVV.PinTypes.Value); var lookatzIn = this.addInputPin('LookAt Z', [1], VVVV.PinTypes.Value); var upvectorxIn = this.addInputPin('UpVector X', [0], VVVV.PinTypes.Value); var upvectoryIn = this.addInputPin('UpVector Y', [1], VVVV.PinTypes.Value); var upvectorzIn = this.addInputPin('UpVector Z', [0], VVVV.PinTypes.Value); var transformoutOut = this.addOutputPin('Transform Out', [], VVVV.PinTypes.Transform); var mirror = mat4.create(); mat4.identity(mirror); mat4.scale(mirror, [-1, 1, -1]); this.evaluate = function() { var spreadCount = this.getMaxInputSliceCount(); for (var i=0; i<spreadCount; i++) { var t = mat4.create(); mat4.identity(t); mat4.lookAt(vec3.create([positionxIn.getValue(i), positionyIn.getValue(i), positionzIn.getValue(i)]), vec3.create([lookatxIn.getValue(i), lookatyIn.getValue(i), lookatzIn.getValue(i)]), vec3.create([upvectorxIn.getValue(i), upvectoryIn.getValue(i), upvectorzIn.getValue(i)]), t); mat4.multiply(mirror, t, t); if (transformIn.isConnected()) { mat4.multiply(transformIn.getValue(i), t, t); } transformoutOut.setValue(i, t); } transformoutOut.setSliceCount(spreadCount); } } VVVV.Nodes.LookAtTransform.prototype = new VVVV.Core.Node();