Commit 2a9f4cde authored by amandaghassaei's avatar amandaghassaei
Browse files

adding in static solver

parent 3c7d3cb8
...@@ -531,10 +531,9 @@ ...@@ -531,10 +531,9 @@
<input value="" placeholder="" class="form-control" type="text"> <input value="" placeholder="" class="form-control" type="text">
</div> </div>
<br/><br/> <br/><br/>
<b>Error:</b><br/> <b>Error:</b><a class="about floatRight" href="#" id="aboutError"><span class="fui-question-circle"></span></a><br/>
<div class="indent"> <div class="indent">
<label>Average node error: <span id="globalError"></span></label> <label>Average node error: <span id="globalError"></span></label>
<a class="about floatRight" href="#" id="aboutError"><span class="fui-question-circle"></span></a>
</div><br/> </div><br/>
<b>Animation Settings:</b><a class="about floatRight" href="#" id="aboutAnimation"><span class="fui-question-circle"></span></a><br/> <b>Animation Settings:</b><a class="about floatRight" href="#" id="aboutAnimation"><span class="fui-question-circle"></span></a><br/>
<div class="indent"> <div class="indent">
...@@ -710,7 +709,7 @@ ...@@ -710,7 +709,7 @@
</div><!-- /.modal-dialog --> </div><!-- /.modal-dialog -->
</div><!-- /.modal --> </div><!-- /.modal -->
<div class="modal fade" id="aboutVRmodal" tabindex="-1" role="dialog"> <div class="modal fade" id="aboutVRmodal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-med"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
...@@ -733,14 +732,14 @@ ...@@ -733,14 +732,14 @@
</div><!-- /.modal-dialog --> </div><!-- /.modal-dialog -->
</div><!-- /.modal --> </div><!-- /.modal -->
<div class="modal fade" id="aboutAnimationModal" tabindex="-1" role="dialog"> <div class="modal fade" id="aboutAnimationModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-med"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
<p><b>Animation Settings</b><br/><br/> <p><b>Animation Settings</b><br/><br/>
The dynamic simulation is calculated by moving time forward in small <b>&Delta; t</b> steps, solving the system, and moving the The dynamic simulation is calculated by moving time forward in small <b>&Delta;t</b> steps, solving the system, and moving the
vertices of the origami incrementally. The time step size for this animation is calculated automatically vertices of the origami incrementally. The time step size for this animation is calculated automatically
based on the material stiffnesses set in the <b>Stiffness Settings</b> section: more stiff settings based on the material stiffnesses set in the <b>Stiffness Settings</b> section: more stiff settings
require shorter time steps to solve and will slow down the simulation.<br/> require shorter time steps to solve and will slow down the simulation.<br/>
...@@ -872,7 +871,7 @@ ...@@ -872,7 +871,7 @@
</div><!-- /.modal-dialog --> </div><!-- /.modal-dialog -->
</div><!-- /.modal --> </div><!-- /.modal -->
<div class="modal fade" id="aboutErrorModal" tabindex="-1" role="dialog"> <div class="modal fade" id="aboutErrorModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-med"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
......
...@@ -38,6 +38,9 @@ Beam.prototype.getLength = function(){ ...@@ -38,6 +38,9 @@ Beam.prototype.getLength = function(){
Beam.prototype.getOriginalLength = function(){ Beam.prototype.getOriginalLength = function(){
return this.originalLength; return this.originalLength;
}; };
Beam.prototype.recalcOriginalLength = function(){
this.originalLength = this.getVector().length();
};
Beam.prototype.isFixed = function(){ Beam.prototype.isFixed = function(){
return this.nodes[0].fixed && this.nodes[1].fixed; return this.nodes[0].fixed && this.nodes[1].fixed;
......
...@@ -121,17 +121,13 @@ function initControls(globals){ ...@@ -121,17 +121,13 @@ function initControls(globals){
$("#svgViewer").hide(); $("#svgViewer").hide();
}); });
setCheckbox("#dynamic", globals.simType == "dynamic", function(val){
globals.simType = val;
});
setCheckbox("#static", globals.simType == "static", function(val){
globals.simType = val;
});
setCheckbox("#schematic", globals.schematicVisible, function(val){
globals.schematicVisible = val;
});
setRadio("simType", globals.simType, function(val){ setRadio("simType", globals.simType, function(val){
if (val == "static"){
globals.staticSolver.syncNodesAndEdges();
} else if (val == "dynamic"){
globals.dynamicSolver.syncNodesAndEdges();
}
globals.simType = val; globals.simType = val;
}); });
......
...@@ -10,7 +10,7 @@ function Crease(edge, face1Index, face2Index, targetTheta, type, node1, node2, i ...@@ -10,7 +10,7 @@ function Crease(edge, face1Index, face2Index, targetTheta, type, node1, node2, i
for (var i=0;i<edge.nodes.length;i++){ for (var i=0;i<edge.nodes.length;i++){
edge.nodes[i].addInvCrease(this); edge.nodes[i].addInvCrease(this);
} }
this.face1Index = face1Index; this.face1Index = face1Index;//todo this is useless
this.face2Index = face2Index; this.face2Index = face2Index;
this.targetTheta = targetTheta; this.targetTheta = targetTheta;
this.type = type; this.type = type;
...@@ -38,8 +38,6 @@ Crease.prototype.getNormal2Index = function(){ ...@@ -38,8 +38,6 @@ Crease.prototype.getNormal2Index = function(){
}; };
Crease.prototype.getTargetTheta = function(){ Crease.prototype.getTargetTheta = function(){
// if (this.targetTheta<0) this.edge.setMountain();
// else this.edge.setValley();
return this.targetTheta; return this.targetTheta;
}; };
......
...@@ -24,7 +24,7 @@ function initModel(globals){ ...@@ -24,7 +24,7 @@ function initModel(globals){
var vertices = []; var vertices = [];
function setMeshMaterial() { function setMeshMaterial() {
var polygonOffset = 2; var polygonOffset = 0.5;
if (globals.colorMode == "normal") { if (globals.colorMode == "normal") {
material = new THREE.MeshNormalMaterial({ material = new THREE.MeshNormalMaterial({
shading:THREE.FlatShading, side: THREE.DoubleSide, shading:THREE.FlatShading, side: THREE.DoubleSide,
...@@ -168,7 +168,6 @@ function initModel(globals){ ...@@ -168,7 +168,6 @@ function initModel(globals){
function setGeoUpdates(){ function setGeoUpdates(){
geometry.attributes.position.needsUpdate = true; geometry.attributes.position.needsUpdate = true;
if (globals.colorMode == "axialStrain") geometry.attributes.color.needsUpdate = true; if (globals.colorMode == "axialStrain") geometry.attributes.color.needsUpdate = true;
else geometry.computeVertexNormals();
if (globals.userInteractionEnabled || globals.vrEnabled) geometry.computeBoundingBox(); if (globals.userInteractionEnabled || globals.vrEnabled) geometry.computeBoundingBox();
// geometry.computeBoundingSphere(); // geometry.computeBoundingSphere();
...@@ -330,10 +329,13 @@ function initModel(globals){ ...@@ -330,10 +329,13 @@ function initModel(globals){
vertices[i].multiplyScalar(scale); vertices[i].multiplyScalar(scale);
} }
//update vertices //update vertices and edges
for (var i=0;i<vertices.length;i++){ for (var i=0;i<vertices.length;i++){
nodes[i].setOriginalPosition(positions[3*i], positions[3*i+1], positions[3*i+2]); nodes[i].setOriginalPosition(positions[3*i], positions[3*i+1], positions[3*i+2]);
} }
for (var i=0;i<edges.length;i++){
edges[i].recalcOriginalLength();
}
if (!globals.threeView.running()) reset(); if (!globals.threeView.running()) reset();
} }
......
...@@ -333,8 +333,6 @@ function initPattern(globals){ ...@@ -333,8 +333,6 @@ function initPattern(globals){
var edge1 = set1[i]; var edge1 = set1[i];
var edge2 = set2[j]; var edge2 = set2[j];
if ((edge2[0] == edge1[0] || edge2[0] == edge1[1]) && (edge2[1] == edge1[0] || edge2[1] == edge1[1])){ if ((edge2[0] == edge1[0] || edge2[0] == edge1[1]) && (edge2[1] == edge1[0] || edge2[1] == edge1[1])){
console.log(edge1);
console.log(edge2);
set2.splice(j, 1); set2.splice(j, 1);
if (set2 == set1) i--; if (set2 == set1) i--;
j--; j--;
......
...@@ -9,6 +9,7 @@ function initStaticSolver(){ ...@@ -9,6 +9,7 @@ function initStaticSolver(){
var edges; var edges;
var faces; var faces;
var creases; var creases;
var positions;
var Q, C, Ctrans, F, F_rxn; var Q, C, Ctrans, F, F_rxn;
var Ctrans_Q, Ctrans_Q_C; var Ctrans_Q, Ctrans_Q_C;
...@@ -21,29 +22,34 @@ function initStaticSolver(){ ...@@ -21,29 +22,34 @@ function initStaticSolver(){
faces = globals.model.getFaces(); faces = globals.model.getFaces();
creases = globals.model.getCreases(); creases = globals.model.getCreases();
positions = globals.model.getPositionsArray();
setUpParams(); setUpParams();
} }
function solve(){ function solve(){
updateMatrices();
solveStep();
} }
function reset(){ function reset(){
} }
function solveStep(){ function solveStep(){
console.log("static solve"); console.log("static solve");
if (fixedIndicesMapping.length == 0){//no boundary conditions // if (fixedIndicesMapping.length == 0){//no boundary conditions
var X = initEmptyArray(numVerticesFree*3); // var X = initEmptyArray(numVerticesFree*3);
render(X); // render(X);
console.warn("no boundary conditions"); // console.warn("no boundary conditions");
return; // return;
} // }
var _F = F.slice(); var _F = F.slice();
for (var i=0;i<_F.length;i++) { for (var i=0;i<_F.length;i++) {
_F[i] += F_rxn[i]; _F[i] += F_rxn[i];
} }
X = numeric.dot(numeric.inv(Ctrans_Q_C), _F); var X = numeric.dot(numeric.inv(Ctrans_Q_C), _F);
console.log(_F);
render(X); render(X);
} }
...@@ -51,21 +57,24 @@ function initStaticSolver(){ ...@@ -51,21 +57,24 @@ function initStaticSolver(){
function render(X){ function render(X){
for (var i=0;i<numVerticesFree;i++){ for (var i=0;i<numVerticesFree;i++){
var index = indicesMapping[i];
var nodePosition = new THREE.Vector3(X[3*i],X[3*i+1],X[3*i+2]); var nodePosition = new THREE.Vector3(X[3*i], X[3*i+1], X[3*i+2]);
var node = nodes[indicesMapping[i]]; var nexPos = nodes[index].render(nodePosition);
node.renderChange(nodePosition); positions[3*index] = nexPos.x;
positions[3*index+1] = nexPos.y;
positions[3*index+2] = nexPos.z;
} }
for (var i=0;i<numVerticesFixed;i++){ for (var i=0;i<numVerticesFixed;i++){//todo necessary?
nodes[fixedIndicesMapping[i]].render(new THREE.Vector3(0,0,0)); var index = fixedIndicesMapping[i];
var nodePosition = new THREE.Vector3(0, 0, 0);
var nexPos = nodes[index].render(nodePosition);
positions[3*index] = nexPos.x;
positions[3*index+1] = nexPos.y;
positions[3*index+2] = nexPos.z;
} }
for (var i=0;i<edges.length;i++){ for (var i=0;i<edges.length;i++){
edges[i].render(true); edges[i].render();
} }
geometry.verticesNeedUpdate = true;
geometry.computeFaceNormals();
updateMatrices();
} }
function initEmptyArray(dim1, dim2, dim3){ function initEmptyArray(dim1, dim2, dim3){
...@@ -109,7 +118,7 @@ function initStaticSolver(){ ...@@ -109,7 +118,7 @@ function initStaticSolver(){
freeEdgesMapping.push(i); freeEdgesMapping.push(i);
} }
for (var i=0;i<creases.length;i++){ for (var i=0;i<creases.length;i++){
freeCreasesMapping.push(i);//todo check for locked creases freeCreasesMapping.push(i);
} }
numVerticesFree = indicesMapping.length; numVerticesFree = indicesMapping.length;
...@@ -136,8 +145,6 @@ function initStaticSolver(){ ...@@ -136,8 +145,6 @@ function initStaticSolver(){
} }
updateMatrices(); updateMatrices();
startSolver();
} }
function calcCsAndRxns(){ function calcCsAndRxns(){
...@@ -157,60 +164,94 @@ function initStaticSolver(){ ...@@ -157,60 +164,94 @@ function initStaticSolver(){
C[j][3*i] = edgeVector0.x; C[j][3*i] = edgeVector0.x;
C[j][3*i+1] = edgeVector0.y; C[j][3*i+1] = edgeVector0.y;
C[j][3*i+2] = edgeVector0.z; C[j][3*i+2] = edgeVector0.z;
F_rxn[3*i] += edgeVector0.x*rxnForceScale; F_rxn[3*i] -= edgeVector0.x*rxnForceScale;
F_rxn[3*i+1] += edgeVector0.y*rxnForceScale; F_rxn[3*i+1] -= edgeVector0.y*rxnForceScale;
F_rxn[3*i+2] += edgeVector0.z*rxnForceScale; F_rxn[3*i+2] -= edgeVector0.z*rxnForceScale;
} }
if (!_nodes[1].fixed) { if (!_nodes[1].fixed) {
var i = indicesMapping.indexOf(_nodes[1].getIndex()); var i = indicesMapping.indexOf(_nodes[1].getIndex());
C[j][3*i] = -edgeVector0.x; C[j][3*i] = -edgeVector0.x;
C[j][3*i+1] = -edgeVector0.y; C[j][3*i+1] = -edgeVector0.y;
C[j][3*i+2] = -edgeVector0.z; C[j][3*i+2] = -edgeVector0.z;
F_rxn[3*i] -= edgeVector0.x*rxnForceScale; F_rxn[3*i] += edgeVector0.x*rxnForceScale;
F_rxn[3*i+1] -= edgeVector0.y*rxnForceScale; F_rxn[3*i+1] += edgeVector0.y*rxnForceScale;
F_rxn[3*i+2] -= edgeVector0.z*rxnForceScale; F_rxn[3*i+2] += edgeVector0.z*rxnForceScale;
} }
} }
var geometry = globals.model.getGeometry();
var indices = geometry.index.array;
var normals = [];
//compute all normals
var cb = new THREE.Vector3(), ab = new THREE.Vector3();
for (var j=0;j<indices.length;j+=3){
var index = 3*indices[j];
var vA = new THREE.Vector3(positions[index], positions[index+1], positions[index+2]);
index = 3*indices[j+1];
var vB = new THREE.Vector3(positions[index], positions[index+1], positions[index+2]);
index = 3*indices[j+2];
var vC = new THREE.Vector3(positions[index], positions[index+1], positions[index+2]);
cb.subVectors( vC, vB );
ab.subVectors( vA, vB );
cb.cross( ab );
cb.normalize();
normals.push(cb.clone());
}
for (var j=0;j<numFreeCreases;j++){ for (var j=0;j<numFreeCreases;j++){
var crease = creases[freeCreasesMapping[j]]; var crease = creases[freeCreasesMapping[j]];
var normal1 = normals[crease.face1Index];
var normal1 = geometry.faces[crease.face1Index].normal; var normal2 = normals[crease.face2Index];
var normal2 = geometry.faces[crease.face2Index].normal;
var dotNormals = normal1.dot(normal2); var dotNormals = normal1.dot(normal2);
if (dotNormals < -1.0) dotNormals = -1.0; if (dotNormals < -1.0) dotNormals = -1.0;
else if (dotNormals > 1.0) dotNormals = 1.0; else if (dotNormals > 1.0) dotNormals = 1.0;
var theta = Math.acos(dotNormals);
var creaseVector = crease.getVector(); var creaseVector = crease.getVector().normalize();
var sign = (normal1.clone().cross(normal2)).dot(creaseVector); //https://math.stackexchange.com/questions/47059/how-do-i-calculate-a-dihedral-angle-given-cartesian-coordinates
if (sign < 0.0) theta *= -1.0; var theta = Math.atan2((normal1.clone().cross(creaseVector)).dot(normal2), dotNormals);
// if (theta > 2.0 && lastTheta[0] < -2.0) theta -= TWO_PI*(1.0+floor(-lastTheta[0]/TWO_PI));
// if (theta < -2.0 && lastTheta[0] > 2.0) theta += TWO_PI*(1.0+floor(lastTheta[0]/TWO_PI));
var diff = theta - globals.creasePercent*crease.targetTheta; var diff = theta - globals.creasePercent*crease.targetTheta;
var rxnForceScale = crease.getK()*diff;
var partial1, partial2;
if (!crease.node1.fixed){ if (!crease.node1.fixed){
var i = indicesMapping.indexOf(crease.node1.getIndex()); var i = indicesMapping.indexOf(crease.node1.getIndex());
var dist = crease.getLengthToNode1(); var dist = crease.getLengthToNode1();
C[j+numFreeEdges][3*i] = -normal1.x/dist; var partial1 = normal1.clone().divideScalar(dist);
C[j+numFreeEdges][3*i+1] = -normal1.y/dist; C[j+numFreeEdges][3*i] = partial1.x;
C[j+numFreeEdges][3*i+2] = -normal1.z/dist; C[j+numFreeEdges][3*i+1] = partial1.y;
rxnForceScale = crease.getK()*diff/dist; C[j+numFreeEdges][3*i+2] = partial1.z;
F_rxn[3*i] += normal1.x*rxnForceScale; F_rxn[3*i] -= partial1.x*rxnForceScale;
F_rxn[3*i+1] += normal1.y*rxnForceScale; F_rxn[3*i+1] -= partial1.y*rxnForceScale;
F_rxn[3*i+2] += normal1.z*rxnForceScale; F_rxn[3*i+2] -= partial1.z*rxnForceScale;
} }
if (!crease.node2.fixed){ if (!crease.node2.fixed){
var i = indicesMapping.indexOf(crease.node2.getIndex()); var i = indicesMapping.indexOf(crease.node2.getIndex());
var dist = crease.getLengthToNode2(); var dist = crease.getLengthToNode2();
C[j+numFreeEdges][3*i] = -normal2.x/dist; var partial2 = normal2.clone().divideScalar(dist);
C[j+numFreeEdges][3*i+1] = -normal2.y/dist; C[j+numFreeEdges][3*i] = partial2.x;
C[j+numFreeEdges][3*i+2] = -normal2.z/dist; C[j+numFreeEdges][3*i+1] = partial2.y;
rxnForceScale = crease.getK()*diff/dist; C[j+numFreeEdges][3*i+2] = partial2.z;
F_rxn[3*i] += normal2.x*rxnForceScale; F_rxn[3*i] -= partial2.x*rxnForceScale;
F_rxn[3*i+1] += normal2.y*rxnForceScale; F_rxn[3*i+1] -= partial2.y*rxnForceScale;
F_rxn[3*i+2] += normal2.z*rxnForceScale; F_rxn[3*i+2] -= partial2.z*rxnForceScale;
}
var creaseNodes = crease.edge.nodes;
for (var k=0;k<creaseNodes.length;k++){
var node = creaseNodes[k];
if (node.fixed) continue;
var i = indicesMapping.indexOf(node.getIndex());
C[j+numFreeEdges][3*i] = -(partial1.x+partial2.x)/2;
C[j+numFreeEdges][3*i+1] = -(partial1.y+partial2.y)/2;
C[j+numFreeEdges][3*i+2] = -(partial1.z+partial2.z)/2;
F_rxn[3*i] += (partial1.x+partial2.x)/2*rxnForceScale;
F_rxn[3*i+1] += (partial1.y+partial2.y)/2*rxnForceScale;
F_rxn[3*i+2] += (partial1.z+partial2.z)/2*rxnForceScale;
} }
} }
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment