Created
          September 22, 2015 17:14 
        
      - 
      
- 
        Save lykkin/9e26ba88f627822e8025 to your computer and use it in GitHub Desktop. 
    wiggling boxes
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | var WIDTH = window.innerWidth - 20, | |
| HEIGHT = window.innerHeight - 20; | |
| var VIEW_ANGLE = 45, | |
| ASPECT = WIDTH/HEIGHT, | |
| NEAR = 0.1, | |
| FAR = 10000; | |
| var camera = | |
| new THREE.PerspectiveCamera( | |
| VIEW_ANGLE, | |
| ASPECT, | |
| NEAR, | |
| FAR); | |
| camera.position.z = 0; | |
| camera.position.x = -200; | |
| camera.position.y = 150; | |
| camera.up = new THREE.Vector3(0,0,1); | |
| var projector = new THREE.Projector(); | |
| var renderer = new THREE.SVGRenderer(); | |
| renderer.setSize(WIDTH, HEIGHT); | |
| var objects = []; | |
| var scene = new THREE.Scene(); | |
| var logoGen = function(){ | |
| var res = { | |
| newVerts: [], | |
| oldVerts: [], | |
| curVerts: [], | |
| /* | |
| 5____4 | |
| 1/___0/| | |
| | 6__|_7 | |
| 2/___3/ | |
| */ | |
| adjacentVerts : [ //0 if not connected, the axis of connection if they are | |
| [ 0 , 'x', 0 , 'y', 'z', 0 , 0 , 0 ], | |
| [ 'x', 0 , 'y', 0 , 0 , 'z', 0 , 0 ], | |
| [ 0 , 'y', 0 , 'x', 0 , 0 , 'z', 0 ], | |
| [ 'y', 0 , 'x', 0 , 0 , 0 , 0 , 'z' ], | |
| [ 'z', 0 , 0 , 0 , 0 , 'x', 0 , 'y' ], | |
| [ 0 , 'z', 0 , 0 , 'x', 0 , 'y', 0 ], | |
| [ 0 , 0 , 'z', 0 , 0 , 'y', 0 , 'x' ], | |
| [ 0 , 0 , 0 , 'z' , 'y', 0 , 'x', 0 ], | |
| ], | |
| lengthRules: { | |
| counter: 0, | |
| isValid: false, | |
| rules: 0, | |
| getRules: function(){ | |
| this.counter += 1; | |
| this.isValid = this.counter % 3 === 0; | |
| this.rules = this.isValid ? this.valid : this.invalid; | |
| return this.rules; | |
| }, | |
| invalid: [ | |
| { | |
| first:0, second:4, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:1, second:5, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:2, second:6, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:3, second:7, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:1, second:0, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:2, second:1, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:2, second:3, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first: 3, second: 0, | |
| minLen: 0, dLen: 10, | |
| locked: false | |
| }, | |
| { | |
| first:5, second:4, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:6, second:5, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:7, second:6, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| { | |
| first:7, second:4, | |
| minLen:0, dLen:10, | |
| locked: false | |
| }, | |
| ], | |
| valid: [ | |
| // { | |
| // first: int, second: int - vertices of the line, order | |
| // matters | |
| // | |
| // minLen: int, dLen: int - minimum and delta line length | |
| // | |
| // locked: bool - line length is perserved across vertex | |
| // movement | |
| // | |
| // inequality: [int] - indices to sides this side can't be | |
| // the same as -- soon to come | |
| // } | |
| { | |
| first:0, second:4, | |
| minLen:3, dLen:0, | |
| locked: true | |
| }, | |
| { | |
| first:1, second:5, | |
| minLen:4, dLen:3, | |
| locked: true | |
| }, | |
| { | |
| first:2, second:6, | |
| minLen:8, dLen:0, | |
| locked: true | |
| }, | |
| { | |
| first:3, second:7, | |
| minLen:4, dLen:3, | |
| locked: true | |
| }, | |
| { | |
| first:1, second:0, | |
| minLen:7, dLen:0, | |
| locked: false | |
| }, | |
| { | |
| first:2, second:1, | |
| minLen:2, dLen:10, | |
| locked: true | |
| }, | |
| { | |
| first:2, second:3, | |
| minLen:7, dLen:0, | |
| locked: false | |
| }, | |
| { | |
| first: 3, second: 0, | |
| minLen: 2, dLen: 10, | |
| locked: true | |
| }, | |
| { | |
| first:5, second:4, | |
| minLen:7, dLen:0, | |
| locked: false | |
| }, | |
| { | |
| first:6, second:5, | |
| minLen:7, dLen:0, | |
| locked: false | |
| }, | |
| { | |
| first:7, second:6, | |
| minLen:7, dLen:0, | |
| locked: false | |
| }, | |
| { | |
| first:7, second:4, | |
| minLen:7, dLen:0, | |
| locked: false | |
| }, | |
| ], | |
| }, | |
| templateVerts: 0, | |
| unit: 10, | |
| animationTime: 2000, | |
| cube: 0, | |
| counter: 0, | |
| scene: scene, | |
| generateCoord: function(i){ | |
| return { | |
| val: this.templateVerts[i], | |
| neighbor: false, | |
| locked: false, | |
| visited: false, | |
| }; | |
| }, | |
| generateVert: function(i){ | |
| return { | |
| x: this.generateCoord(i), | |
| y: this.generateCoord(i), | |
| z: this.generateCoord(i), | |
| move: function(dels){ | |
| this.x.visited = true; | |
| if(this.x.locked && !this.x.neighbor.x.visited){ | |
| this.x.neighbor.move(dels); | |
| } | |
| this.x.val += dels.x; | |
| this.y.visited = true; | |
| if(this.y.locked && !this.y.neighbor.y.visited){ | |
| this.y.neighbor.move(dels); | |
| } | |
| this.y.val += dels.y; | |
| this.z.visited = true; | |
| if(this.z.locked && !this.z.neighbor.z.visited){ | |
| this.z.neighbor.move(dels); | |
| } | |
| this.z.val += dels.z; | |
| } | |
| }; | |
| }, | |
| generateKeyFrame: function(){ | |
| if (this.oldVerts.length === 0){ | |
| this.primeVerts(); | |
| } | |
| this.newVerts = []; | |
| for(var i = 0; i < 43; i += 6){ | |
| this.newVerts.push(this.generateVert(i)); | |
| } | |
| for(var i = 0; i < 8; i++){ | |
| for(var j = i; j < 8; j++){ | |
| if(this.adjacentVerts[i][j] !== 0){ | |
| this.newVerts[i][this.adjacentVerts[i][j]].neighbor = this.newVerts[j]; | |
| this.newVerts[j][this.adjacentVerts[i][j]].neighbor = this.newVerts[i]; | |
| } | |
| } | |
| } | |
| this.vetKeyFrame(); | |
| this.centerFrame(); | |
| this.start = new Date(); | |
| }, | |
| centerFrame: function(){ | |
| for(var i = 0; i < 8; i++){ | |
| var v = this.newVerts[i]; | |
| var dist = 0; | |
| if(!v.x.visited){ | |
| dist = Math.abs(v.x.val - v.x.neighbor.x.val)/2; | |
| if(v.x.val < v.x.neighbor.x.val){ | |
| v.x.val = -dist; | |
| v.x.neighbor.x.val = dist; | |
| } else { | |
| v.x.val = dist; | |
| v.x.neighbor.x.val = -dist; | |
| } | |
| v.x.visited = true; | |
| v.x.neighbor.x.visited = true; | |
| } | |
| if(!v.y.visited){ | |
| dist = Math.abs(v.y.val - v.y.neighbor.y.val)/2; | |
| if(v.y.val < v.y.neighbor.y.val){ | |
| v.y.val = -dist; | |
| v.y.neighbor.y.val = dist; | |
| } else { | |
| v.y.val = dist; | |
| v.y.neighbor.y.val = -dist; | |
| } | |
| v.y.visited = true; | |
| v.y.neighbor.y.visited = true; | |
| } | |
| if(!v.z.visited){ | |
| dist = Math.abs(v.z.val - v.z.neighbor.z.val)/2; | |
| if(v.z.val < v.z.neighbor.z.val){ | |
| v.z.val = -dist; | |
| v.z.neighbor.z.val = dist; | |
| } else { | |
| v.z.val = dist; | |
| v.z.neighbor.z.val = -dist; | |
| } | |
| v.z.visited = true; | |
| v.z.neighbor.z.visited = true; | |
| } | |
| } | |
| }, | |
| generatePoint: function(x,y,z){ | |
| return { | |
| x: x, | |
| y: y, | |
| z: z | |
| }; | |
| }, | |
| getDist: function(a, b){ | |
| return Math.sqrt((a.x.val-b.x.val)*(a.x.val-b.x.val) + (a.y.val-b.y.val)*(a.y.val-b.y.val) + (a.z.val-b.z.val)*(a.z.val-b.z.val)); | |
| }, | |
| resizeSide: function(to, from, lenRule){ | |
| switch(this.adjacentVerts[lenRule.first][lenRule.second]){ | |
| case 0: | |
| console.error('attempted to lock vertices that are not adjacent\nPlease remove the rule from: ' + Number(a.first).toString() + ' to ' + Number(a.second).toString()); | |
| break; | |
| case 'x': | |
| to.move(this.generatePoint(from.x.val - to.x.val + (lenRule.minLen + Math.floor(lenRule.dLen*Math.random()))*this.unit, from.y.val - to.y.val, from.z.val - to.z.val)); | |
| to.x.locked = lenRule.locked; | |
| from.x.locked = lenRule.locked; | |
| break; | |
| case 'y': | |
| to.move(this.generatePoint(from.x.val - to.x.val, from.y.val - to.y.val + (lenRule.minLen + Math.floor(lenRule.dLen*Math.random()))*this.unit, from.z.val - to.z.val)); | |
| to.y.locked = lenRule.locked; | |
| from.y.locked = lenRule.locked; | |
| break; | |
| case 'z': | |
| to.move(this.generatePoint(from.x.val - to.x.val, from.y.val - to.y.val, from.z.val - to.z.val + (lenRule.minLen + Math.floor(lenRule.dLen*Math.random()))*this.unit)); | |
| to.z.locked = lenRule.locked; | |
| from.z.locked = lenRule.locked; | |
| break; | |
| } | |
| this.newVerts.forEach(function(vert){ | |
| vert.x.visited = false; | |
| vert.y.visited = false; | |
| vert.z.visited = false; | |
| }); | |
| }, | |
| vetKeyFrame: function(){ | |
| this.lengthRules.getRules().forEach( | |
| (function(a){ | |
| this.resizeSide(this.newVerts[a.first], this.newVerts[a.second], a); | |
| }).bind(this) | |
| ); | |
| }, | |
| animate: function(){ | |
| if(this.newVerts.length === 0){ | |
| this.generateKeyFrame(); | |
| } | |
| var delta = new Date() - this.start; | |
| if(this.counter + delta >= this.animationTime){ | |
| delta = this.animationTime - this.counter; | |
| this.counter = 0; | |
| } else { | |
| this.counter += delta; | |
| } | |
| var ratio = delta/this.animationTime; | |
| if(this.counter === 0){ | |
| this.primeVerts(); | |
| this.generateKeyFrame(); | |
| } else { | |
| //advance current verts | |
| for(var k = 0; k < 8; k++){ | |
| this.curVerts[k].x = this.curVerts[k].x + (this.newVerts[k].x.val - this.oldVerts[k].x)*ratio; | |
| this.curVerts[k].y = this.curVerts[k].y + (this.newVerts[k].y.val - this.oldVerts[k].y)*ratio; | |
| this.curVerts[k].z = this.curVerts[k].z + (this.newVerts[k].z.val - this.oldVerts[k].z)*ratio; | |
| } | |
| this.start = new Date(); | |
| } | |
| this.step(); | |
| }, | |
| step: function(){ | |
| /* | |
| there has to be a better way! | |
| taken from BoxHelper in the threejs source | |
| x,y,z pairs for start-end of the lines along the boxes | |
| 5____4 | |
| 1/___0/| | |
| | 6__|_7 | |
| 2/___3/ | |
| */ | |
| var pos = this.cube.geometry.attributes.position; | |
| var posArray = pos.array; | |
| //0 to 1 | |
| posArray[0] = this.curVerts[0].x; posArray[1] = this.curVerts[0].y; posArray[2] = this.curVerts[0].z; | |
| posArray[3] = this.curVerts[1].x; posArray[4] = this.curVerts[1].y; posArray[5] = this.curVerts[1].z; | |
| //1 to 2 | |
| posArray[6] = this.curVerts[1].x; posArray[7] = this.curVerts[1].y; posArray[8] = this.curVerts[1].z; | |
| posArray[9] = this.curVerts[2].x; posArray[10] = this.curVerts[2].y; posArray[11] = this.curVerts[2].z; | |
| //2 to 3 | |
| posArray[12] = this.curVerts[2].x; posArray[13] = this.curVerts[2].y; posArray[14] = this.curVerts[2].z; | |
| posArray[15] = this.curVerts[3].x; posArray[16] = this.curVerts[3].y; posArray[17] = this.curVerts[3].z; | |
| //3 to 0 | |
| posArray[18] = this.curVerts[3].x; posArray[19] = this.curVerts[3].y; posArray[20] = this.curVerts[3].z; | |
| posArray[21] = this.curVerts[0].x; posArray[22] = this.curVerts[0].y; posArray[23] = this.curVerts[0].z; | |
| // | |
| //4 to 5 | |
| posArray[24] = this.curVerts[4].x; posArray[25] = this.curVerts[4].y; posArray[26] = this.curVerts[4].z; | |
| posArray[27] = this.curVerts[5].x; posArray[28] = this.curVerts[5].y; posArray[29] = this.curVerts[5].z; | |
| //5 to 6 | |
| posArray[30] = this.curVerts[5].x; posArray[31] = this.curVerts[5].y; posArray[32] = this.curVerts[5].z; | |
| posArray[33] = this.curVerts[6].x; posArray[34] = this.curVerts[6].y; posArray[35] = this.curVerts[6].z; | |
| //6 to 7 | |
| posArray[36] = this.curVerts[6].x; posArray[37] = this.curVerts[6].y; posArray[38] = this.curVerts[6].z; | |
| posArray[39] = this.curVerts[7].x; posArray[40] = this.curVerts[7].y; posArray[41] = this.curVerts[7].z; | |
| //7 to 4 | |
| posArray[42] = this.curVerts[7].x; posArray[43] = this.curVerts[7].y; posArray[44] = this.curVerts[7].z; | |
| posArray[45] = this.curVerts[4].x; posArray[46] = this.curVerts[4].y; posArray[47] = this.curVerts[4].z; | |
| // | |
| //0 to 4 | |
| posArray[48] = this.curVerts[0].x; posArray[49] = this.curVerts[0].y; posArray[50] = this.curVerts[0].z; | |
| posArray[51] = this.curVerts[4].x; posArray[52] = this.curVerts[4].y; posArray[53] = this.curVerts[4].z; | |
| //1 to 5 | |
| posArray[54] = this.curVerts[1].x; posArray[55] = this.curVerts[1].y; posArray[56] = this.curVerts[1].z; | |
| posArray[57] = this.curVerts[5].x; posArray[58] = this.curVerts[5].y; posArray[59] = this.curVerts[5].z; | |
| //2 to 6 | |
| posArray[60] = this.curVerts[2].x; posArray[61] = this.curVerts[2].y; posArray[62] = this.curVerts[2].z; | |
| posArray[63] = this.curVerts[6].x; posArray[64] = this.curVerts[6].y; posArray[65] = this.curVerts[6].z; | |
| //3 to 7 | |
| posArray[66] = this.curVerts[3].x; posArray[67] = this.curVerts[3].y; posArray[68] = this.curVerts[3].z; | |
| posArray[69] = this.curVerts[7].x; posArray[70] = this.curVerts[7].y; posArray[71] = this.curVerts[7].z; | |
| }, | |
| generateCube: function(){ | |
| var x = this.unit*20; | |
| var y = this.unit*20; | |
| var z = this.unit*20; | |
| this.cube = new THREE.BoxHelper(new THREE.Mesh(new THREE.BoxGeometry(x,y,z), new THREE.MeshNormalMaterial())); | |
| this.templateVerts = new THREE.BoxHelper(new THREE.Mesh(new THREE.BoxGeometry(x, y, z), new THREE.MeshNormalMaterial())).geometry.attributes.position.array; | |
| this.cube.material.linewidth = 10; | |
| this.cube.material.color.set(0x00000000); | |
| this.scene.add(this.cube); | |
| }, | |
| primeVerts: function(){ | |
| if(this.templateVerts === 0){ | |
| this.generateCube(); | |
| } | |
| if(this.newVerts.length === 0){ | |
| for(var i = 0; i < 43; i += 6){ | |
| this.oldVerts.push({ | |
| x: this.templateVerts[i], | |
| y: this.templateVerts[i+1], | |
| z: this.templateVerts[i+2] | |
| }); | |
| this.curVerts.push({ | |
| x: this.templateVerts[i], | |
| y: this.templateVerts[i+1], | |
| z: this.templateVerts[i+2] | |
| }); | |
| } | |
| } else { | |
| //poor man's deep copy | |
| this.curVerts = []; | |
| for(var i = 0; i < 8; i++){ | |
| this.curVerts.push({ | |
| x: this.newVerts[i].x.val, | |
| y: this.newVerts[i].y.val, | |
| z: this.newVerts[i].z.val | |
| }); | |
| } | |
| this.oldVerts = []; | |
| for(var i = 0; i < 8; i++){ | |
| this.oldVerts.push({ | |
| x: this.newVerts[i].x.val, | |
| y: this.newVerts[i].y.val, | |
| z: this.newVerts[i].z.val | |
| }); | |
| } | |
| } | |
| } | |
| }; | |
| return res; | |
| }; | |
| $(document).ready(function(){ | |
| logogen = logoGen(); | |
| var render = function(){ | |
| renderer.render(scene, camera); | |
| logogen.animate(); | |
| requestAnimationFrame(render); | |
| }; | |
| render(); | |
| controls = new THREE.OrbitControls( camera ); | |
| $('body').append(renderer.domElement); | |
| }); | |
| //this is awful, get a backend for this shit | |
| //kinda only works for chrome, firefox would need another | |
| //blobbuilder | |
| var snap = function () { | |
| var XMLS, svgfile; | |
| XMLS = new XMLSerializer(); | |
| blob = new window.Blob([XMLS.serializeToString(renderer.domElement)]); | |
| saveAs(blob, 'test.svg'); | |
| }; | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment