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