function main() {
Ab = assembleStiffnessMatrixAndLoadVector();
var solution = solveLinearSystem(Ab[0], Ab[1]);
displaySolution(solution);
}
function assembleStiffnessMatrixAndLoadVector() {
var vertex2Border = [];
for (i = 0; i < border.length; ++i) {
vertex2Border[border[i]] = 1;
}
var nbVertices = vertices.length / 2,
nbTriangles = triangles.length / 3;
var A = numeric.rep([nbVertices, nbVertices], 0);
var b = numeric.rep([nbVertices], 0);
for (var ti = 0; ti < nbTriangles; ++ti) {
var q = [];
for (i = 0; i < 3; ++i) {
var si = 3 * ti + i,
sj = 3 * ti + ((i + 1) % 3);
q[i] = [vertices[2 * triangles[si]] - vertices[2 * triangles[sj]],
vertices[2 * triangles[si] + 1] - vertices[2 * triangles[sj] + 1]];
}
var area = 0.5 * numeric.det([q[0], q[1]]);
for (i = 0; i < 3; ++i) {
var vi = triangles[3 * ti + i];
if (vertex2Border[vi] != 1) {
for (j = 0; j < 3; ++j) {
var vj = triangles[3 * ti + j];
if (vertex2Border[vj] != 1) {
var qi = (i + 1) % 3,
qj = (j + 1) % 3;
A[vi][vj] += numeric.dot(q[qi], q[qj]) / (4 * area);
}
}
b[vi] += -area / 3;
}
}
}
return [A, b];
}
function solveLinearSystem(A, b) {
return numeric.ccsLUPSolve(numeric.ccsLUP(numeric.ccsSparse(A)), b);
}
var c_w, c_h, prMatrix, mvMat, mvMatLoc, rotMat;
function displaySolution(sol) {
var solMin = sol[0],
solMax = sol[0];
for (i = 0; i < sol.length; ++i) {
if (sol[i] < solMin) {
solMin = sol[i];
} else if (sol[i] > solMax) {
solMax = sol[i];
}
}
function anim() {
drawScene();
requestAnimationFrame(anim);
}
initGL();
transl = -1.5;
c_w = window.innerWidth - 50;
c_h = window.innerHeight - 10;
canvas.width = c_w;
canvas.height = c_h;
var prog_show = gl.createProgram();
gl.attachShader(prog_show, getShader(gl, "shader-vs"));
gl.attachShader(prog_show, getShader(gl, "shader-fs"));
gl.linkProgram(prog_show);
gl.useProgram(prog_show);
var posLocation = gl.getAttribLocation(prog_show, "aPos");
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(posLocation);
var solLocation = gl.getAttribLocation(prog_show, "aSol");
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(sol), gl.STATIC_DRAW);
gl.vertexAttribPointer(solLocation, 1, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(solLocation);
gl.uniform1f(gl.getUniformLocation(prog_show, 'solMin'), solMin);
gl.uniform1f(gl.getUniformLocation(prog_show, 'solMax'), solMax);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(triangles), gl.STATIC_DRAW);
prMatrix = new CanvasMatrix4();
prMatrix.perspective(45, c_w / c_h, 0.1, 100);
gl.uniformMatrix4fv(gl.getUniformLocation(prog_show, "prMatrix"),
false, new Float32Array(prMatrix.getAsArray()));
mvMatrix = new CanvasMatrix4();
rotMat = new CanvasMatrix4();
rotMat.makeIdentity();
rotMat.rotate(-45, 1, 0, 0);
mvMatLoc = gl.getUniformLocation(prog_show, "mvMatrix");
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearDepth(1.0);
gl.clearColor(0, 0, 0, 1);
anim();
}
function drawScene() {
gl.viewport(0, 0, c_w, c_h);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
rotMat.rotate(xRot / 3, 1, 0, 0);
rotMat.rotate(yRot / 3, 0, 1, 0);
rotMat.rotate(zRot, 0, 0, 1);
yRot = xRot = zRot = 0;
mvMatrix.makeIdentity();
mvMatrix.translate(-0.5, -0.5, 0);
mvMatrix.multRight(rotMat);
mvMatrix.translate(0, 0, transl);
gl.uniformMatrix4fv(mvMatLoc, false, new Float32Array(mvMatrix.getAsArray()));
gl.drawElements(gl.TRIANGLES, triangles.length, gl.UNSIGNED_SHORT, 0);
gl.flush();
}
main();
<body>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec2 aPos;
attribute float aSol;
varying float sol;
uniform mat4 mvMatrix;
uniform mat4 prMatrix;
uniform float solMin, solMax;
void main(void) {
gl_Position = prMatrix * mvMatrix * vec4(aPos, 10. * aSol, 1.);
sol = 1. - (aSol - solMin) / (solMax - solMin);
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision highp float;
varying float sol;
vec3 heatcolor() {
float h = 4. * sol,
s = 1.,
v = 0.8,
f = h - floor(h),
p = v * (1. - s),
q = v * (1. - s * f),
t = v * (1. - s * (1. - f));
if (h <= 1.) {
return vec3(v, t, p);
}
if (h <= 2.) {
return vec3(q, v, p);
}
if (h <= 3.) {
return vec3(p, v, t);
}
return vec3(p, q, v);
}
void main(void) {
gl_FragColor = vec4(heatcolor(), 1.);
}
</script>
<canvas id="canvas" width="400" height="300"></canvas>
</body>
External resources loaded into this fiddle: