PageSourceSearch

https://origamisimulator.org/js/dynamic/dynamicSolver.js

js origamisimulator.org collected 2026-09-24 09:36:13 UTC 34,121 bytes, 667 lines download raw bytes

1/**
2 * Created by ghassaei on 10/7/16.
3 */
4
5function initDynamicSolver(globals){
6
7    globals.gpuMath = initGPUMath();
8
9    var nodes;
10    var edges;
11    var faces;
12    var creases;
13    var positions;
14    var colors;
15
16    var originalPosition;
17    var position;
18    var lastPosition;
19    var lastLastPosition;//for verlet integration
20    var velocity;
21    var lastVelocity;
22    var externalForces;
23    var mass;
24    var meta;//[beamMetaIndex, numBeams, nodeCreaseMetaIndex, numCreases]
25    var meta2;//[nodeFaceMetaIndex, numFaces]
26    var beamMeta;//[K, D, length, otherNodeIndex]
27
28    var normals;
29    var faceVertexIndices;//[a,b,c] textureDimFaces
30    var nominalTriangles;//[angleA, angleB, angleC]
31    var nodeFaceMeta;//[faceIndex, a, b, c] textureNodeFaces
32    var creaseMeta;//[k, d, targetTheta, -] textureDimCreases
33    var creaseMeta2;//[node1Index, node2Index, node3index, node4index]//nodes 1 and 2 are opposite crease, 3 and 4 are on crease, textureDimCreases
34    var nodeCreaseMeta;//[creaseIndex (thetaIndex), nodeIndex (1/2/3/4), -, -] textureDimNodeCreases
35    var creaseGeo;//[h1, h2, coef1, coef2]
36    var creaseVectors;//indices of crease nodes
37    var theta;//[theta, w, normalIndex1, normalIndex2]
38    var lastTheta;//[theta, w, normalIndex1, normalIndex2]
39
40    function syncNodesAndEdges(){
41        nodes = globals.model.getNodes();
42        edges = globals.model.getEdges();
43        faces = globals.model.getFaces();
44        creases = globals.model.getCreases();
45
46        positions = globals.model.getPositionsArray();
47        colors = globals.model.getColorsArray();
48
49        initTypedArrays();
50        initTexturesAndPrograms(globals.gpuMath);
51        setSolveParams();
52    }
53
54    var programsInited = false;//flag for initial setup
55
56    var textureDim = 0;
57    var textureDimEdges = 0;
58    var textureDimFaces = 0;
59    var textureDimCreases = 0;
60    var textureDimNodeCreases = 0;
61    var textureDimNodeFaces = 0;
62
63    function reset(){
64        globals.gpuMath.step("zeroTexture", [], "u_position");
65        globals.gpuMath.step("zeroTexture", [], "u_lastPosition");
66        globals.gpuMath.step("zeroTexture", [], "u_lastLastPosition");
67        globals.gpuMath.step("zeroTexture", [], "u_velocity");
68        globals.gpuMath.step("zeroTexture", [], "u_lastVelocity");
69        globals.gpuMath.step("zeroThetaTexture", ["u_lastTheta"], "u_theta");
70        globals.gpuMath.step("zeroThetaTexture", ["u_theta"], "u_lastTheta");
71        render();
72    }
73
74    function solve(_numSteps){
75
76        if (globals.shouldAnimateFoldPercent){
77            globals.creasePercent = globals.videoAnimator.nextFoldAngle(0);
78            globals.controls.updateCreasePercent();
79            setCreasePercent(globals.creasePercent);
80            globals.shouldChangeCreasePercent = true;
81        }
82
83        if (globals.forceHasChanged) {
84            updateExternalForces();
85            globals.forceHasChanged = false;
86        }
87        if (globals.fixedHasChanged) {
88            updateFixed();
89            globals.fixedHasChanged = false;
90        }
91        if (globals.nodePositionHasChanged) {
92            updateLastPosition();
93            globals.nodePositionHasChanged = false;
94        }
95        if (globals.creaseMaterialHasChanged) {
96            updateCreasesMeta();
97            globals.creaseMaterialHasChanged = false;
98        }
99        if (globals.materialHasChanged) {
100            updateMaterials();
101            globals.materialHasChanged = false;
102        }
103        if (globals.shouldChangeCreasePercent) {
104            setCreasePercent(globals.creasePercent);
105            globals.shouldChangeCreasePercent = false;
106        }
107        // if (globals.shouldZeroDynamicVelocity){
108        //     globals.gpuMath.step("zeroTexture", [], "u_velocity");
109        //     globals.gpuMath.step("zeroTexture", [], "u_lastVelocity");
110        //     globals.shouldZeroDynamicVelocity = false;
111        // }
112        if (globals.shouldCenterGeo){
113            var avgPosition = getAvgPosition();
114            globals.gpuMath.setProgram("centerTexture");
115            globals.gpuMath.setUniformForProgram("centerTexture", "u_center", [avgPosition.x, avgPosition.y, avgPosition.z], "3f");
116            globals.gpuMath.step("centerTexture", ["u_lastPosition"], "u_position");
117            if (globals.integrationType == "verlet") globals.gpuMath.step("copyTexture", ["u_position"], "u_lastLastPosition");
118            globals.gpuMath.swapTextures("u_position", "u_lastPosition");
119            globals.gpuMath.step("zeroTexture", [], "u_lastVelocity");
120            globals.gpuMath.step("zeroTexture", [], "u_velocity");
121            globals.shouldCenterGeo = false;
122        }
123
124        if (_numSteps === undefined) _numSteps = globals.numSteps;
125        for (var j=0;j<_numSteps;j++){
126            solveStep();
127        }
128        render();
129    }
130
131    function solveStep(){
132
133        var gpuMath = globals.gpuMath;
134
135        gpuMath.setProgram("normalCalc");
136        gpuMath.setSize(textureDimFaces, textureDimFaces);
137        gpuMath.step("normalCalc", ["u_faceVertexIndices", "u_lastPosition", "u_originalPosition"], "u_normals");
138
139        gpuMath.setProgram("thetaCalc");
140        gpuMath.setSize(textureDimCreases, textureDimCreases);
141        gpuMath.step("thetaCalc", ["u_normals", "u_lastTheta", "u_creaseVectors", "u_lastPosition",
142            "u_originalPosition"], "u_theta");
143
144        gpuMath.setProgram("updateCreaseGeo");
145        //already at textureDimCreasesxtextureDimCreases
146        gpuMath.step("updateCreaseGeo", ["u_lastPosition", "u_originalPosition", "u_creaseMeta2"], "u_creaseGeo");
147
148        if (globals.integrationType == "verlet"){
149            gpuMath.setProgram("positionCalcVerlet");
150            gpuMath.setSize(textureDim, textureDim);
151            gpuMath.step("positionCalcVerlet", ["u_lastPosition", "u_lastLastPosition", "u_lastVelocity", "u_originalPosition", "u_externalForces",
152                "u_mass", "u_meta", "u_beamMeta", "u_creaseMeta", "u_nodeCreaseMeta", "u_normals", "u_theta", "u_creaseGeo",
153                "u_meta2", "u_nodeFaceMeta", "u_nominalTriangles"], "u_position");
154            gpuMath.step("velocityCalcVerlet", ["u_position", "u_lastPosition", "u_mass"], "u_velocity");
155            gpuMath.swapTextures("u_lastPosition", "u_lastLastPosition");
156        } else {//euler
157            gpuMath.setProgram("velocityCalc");
158            gpuMath.setSize(textureDim, textureDim);
159            gpuMath.step("velocityCalc", ["u_lastPosition", "u_lastVelocity", "u_originalPosition", "u_externalForces",
160                "u_mass", "u_meta", "u_beamMeta", "u_creaseMeta", "u_nodeCreaseMeta", "u_normals", "u_theta", "u_creaseGeo",
161                "u_meta2", "u_nodeFaceMeta", "u_nominalTriangles"], "u_velocity");
162            gpuMath.step("positionCalc", ["u_velocity", "u_lastPosition", "u_mass"], "u_position");
163        }
164
165        gpuMath.swapTextures("u_theta", "u_lastTheta");
166        gpuMath.swapTextures("u_velocity", "u_lastVelocity");
167        gpuMath.swapTextures("u_position", "u_lastPosition");
168    }
169
170    var $errorOutput = $("#globalError");
171
172    function getAvgPosition(){
173        var xavg = 0;
174        var yavg = 0;
175        var zavg = 0;
176        for (var i=0;i<positions.length;i+=3){
177            xavg += positions[i];
178            yavg += positions[i+1];
179            zavg += positions[i+2];
180        }
181        var avgPosition = new THREE.Vector3(xavg, yavg, zavg);
182        avgPosition.multiplyScalar(3/positions.length);
183        return avgPosition;
184    }
185
186    function render(){
187
188        var vectorLength = 4;
189        globals.gpuMath.setProgram("packToBytes");
190        globals.gpuMath.setUniformForProgram("packToBytes", "u_vectorLength", vectorLength, "1f");
191        globals.gpuMath.setUniformForProgram("packToBytes", "u_floatTextureDim", [textureDim, textureDim], "2f");
192        globals.gpuMath.setSize(textureDim*vectorLength, textureDim);
193        globals.gpuMath.step("packToBytes", ["u_lastPosition"], "outputBytes");
194
195        if (globals.gpuMath.readyToRead()) {
196            var numPixels = nodes.length*vectorLength;
197            var height = Math.ceil(numPixels/(textureDim*vectorLength));
198            var pixels = new Uint8Array(height*textureDim*4*vectorLength);
199            globals.gpuMath.readPixels(0, 0, textureDim * vectorLength, height, pixels);
200            var parsedPixels = new Float32Array(pixels.buffer);
201            var globalError = 0;
202            var shouldUpdateColors = globals.colorMode == "axialStrain";
203            for (var i = 0; i < nodes.length; i++) {
204                var rgbaIndex = i * vectorLength;
205                var nodeError = parsedPixels[rgbaIndex+3]*100;
206                globalError += nodeError;
207                var nodePosition = new THREE.Vector3(parsedPixels[rgbaIndex], parsedPixels[rgbaIndex + 1], parsedPixels[rgbaIndex + 2]);
208                nodePosition.add(nodes[i]._originalPosition);
209                positions[3*i] = nodePosition.x;
210                positions[3*i+1] = nodePosition.y;
211                positions[3*i+2] = nodePosition.z;
212                if (shouldUpdateColors){
213                    if (nodeError>globals.strainClip) nodeError = globals.strainClip;
214                    var scaledVal = (1-nodeError/globals.strainClip) * 0.7;
215                    var color = new THREE.Color();
216                    color.setHSL(scaledVal, 1, 0.5);
217                    colors[3*i] = color.r;
218                    colors[3*i+1] = color.g;
219                    colors[3*i+2] = color.b;
220                }
221            }
222            $errorOutput.html((globalError/nodes.length).toFixed(7) + " %");
223        } else {
224            console.log("shouldn't be here");
225        }
226    }
227
228    function setSolveParams(){
229        var dt = calcDt();
230        $("#deltaT").html(dt);
231        globals.gpuMath.setProgram("thetaCalc");
232        globals.gpuMath.setUniformForProgram("thetaCalc", "u_dt", dt, "1f");
233        globals.gpuMath.setProgram("velocityCalc");
234        globals.gpuMath.setUniformForProgram("velocityCalc", "u_dt", dt, "1f");
235        globals.gpuMath.setProgram("positionCalcVerlet");
236        globals.gpuMath.setUniformForProgram("positionCalcVerlet", "u_dt", dt, "1f");
237        globals.gpuMath.setProgram("positionCalc");
238        globals.gpuMath.setUniformForProgram("positionCalc", "u_dt", dt, "1f");
239        globals.gpuMath.setProgram("velocityCalcVerlet");
240        globals.gpuMath.setUniformForProgram("velocityCalcVerlet", "u_dt", dt, "1f");
241        globals.controls.setDeltaT(dt);
242    }
243
244    function calcDt(){
245        var maxFreqNat = 0;
246        _.each(edges, function(beam){
247            if (beam.getNaturalFrequency()>maxFreqNat) maxFreqNat = beam.getNaturalFrequency();
248        });
249        return (1/(2*Math.PI*maxFreqNat))*0.9;//0.9 of max delta t for good measure
250    }
251
252    function initTexturesAndPrograms(gpuMath){
253
254        var vertexShader = document.getElementById("vertexShader").text;
255
256        gpuMath.initTextureFromData("u_position", textureDim, textureDim, "FLOAT", position, true);
257        gpuMath.initTextureFromData("u_lastPosition", textureDim, textureDim, "FLOAT", lastPosition, true);
258        gpuMath.initTextureFromData("u_lastLastPosition", textureDim, textureDim, "FLOAT", lastLastPosition, true);
259        gpuMath.initTextureFromData("u_velocity", textureDim, textureDim, "FLOAT", velocity, true);
260        gpuMath.initTextureFromData("u_lastVelocity", textureDim, textureDim, "FLOAT", lastVelocity, true);
261        gpuMath.initTextureFromData("u_theta", textureDimCreases, textureDimCreases, "FLOAT", theta, true);
262        gpuMath.initTextureFromData("u_lastTheta", textureDimCreases, textureDimCreases, "FLOAT", lastTheta, true);
263        gpuMath.initTextureFromData("u_normals", textureDimFaces, textureDimFaces, "FLOAT", normals, true);
264
265        gpuMath.initFrameBufferForTexture("u_position", true);
266        gpuMath.initFrameBufferForTexture("u_lastPosition", true);
267        gpuMath.initFrameBufferForTexture("u_lastLastPosition", true);
268        gpuMath.initFrameBufferForTexture("u_velocity", true);
269        gpuMath.initFrameBufferForTexture("u_lastVelocity", true);
270        gpuMath.initFrameBufferForTexture("u_theta", true);
271        gpuMath.initFrameBufferForTexture("u_lastTheta", true);
272        gpuMath.initFrameBufferForTexture("u_normals", true);
273
274        gpuMath.initTextureFromData("u_meta", textureDim, textureDim, "FLOAT", meta, true);
275        gpuMath.initTextureFromData("u_meta2", textureDim, textureDim, "FLOAT", meta2, true);
276        gpuMath.initTextureFromData("u_nominalTrinagles", textureDimFaces, textureDimFaces, "FLOAT", nominalTriangles, true);
277        gpuMath.initTextureFromData("u_nodeCreaseMeta", textureDimNodeCreases, textureDimNodeCreases, "FLOAT", nodeCreaseMeta, true);
278        gpuMath.initTextureFromData("u_creaseMeta2", textureDimCreases, textureDimCreases, "FLOAT", creaseMeta2, true);
279        gpuMath.initTextureFromData("u_nodeFaceMeta", textureDimNodeFaces, textureDimNodeFaces, "FLOAT", nodeFaceMeta, true);
280        gpuMath.initTextureFromData("u_creaseGeo", textureDimCreases, textureDimCreases, "FLOAT", creaseGeo, true);
281        gpuMath.initFrameBufferForTexture("u_creaseGeo", true);
282        gpuMath.initTextureFromData("u_faceVertexIndices", textureDimFaces, textureDimFaces, "FLOAT", faceVertexIndices, true);
283        gpuMath.initTextureFromData("u_nominalTriangles", textureDimFaces, textureDimFaces, "FLOAT", nominalTriangles, true);
284
285        gpuMath.createProgram("positionCalc", vertexShader, document.getElementById("positionCalcShader").text);
286        gpuMath.setUniformForProgram("positionCalc", "u_velocity", 0, "1i");
287        gpuMath.setUniformForProgram("positionCalc", "u_lastPosition", 1, "1i");
288        gpuMath.setUniformForProgram("positionCalc", "u_mass", 2, "1i");
289        gpuMath.setUniformForProgram("positionCalc", "u_textureDim", [textureDim, textureDim], "2f");
290
291        gpuMath.createProgram("velocityCalcVerlet", vertexShader, document.getElementById("velocityCalcVerletShader").text);
292        gpuMath.setUniformForProgram("velocityCalcVerlet", "u_position", 0, "1i");
293        gpuMath.setUniformForProgram("velocityCalcVerlet", "u_lastPosition", 1, "1i");
294        gpuMath.setUniformForProgram("velocityCalcVerlet", "u_mass", 2, "1i");
295        gpuMath.setUniformForProgram("velocityCalcVerlet", "u_textureDim", [textureDim, textureDim], "2f");
296
297        gpuMath.createProgram("velocityCalc", vertexShader, document.getElementById("velocityCalcShader").text);
298        gpuMath.setUniformForProgram("velocityCalc", "u_lastPosition", 0, "1i");
299        gpuMath.setUniformForProgram("velocityCalc", "u_lastVelocity", 1, "1i");
300        gpuMath.setUniformForProgram("velocityCalc", "u_originalPosition", 2, "1i");
301        gpuMath.setUniformForProgram("velocityCalc", "u_externalForces", 3, "1i");
302        gpuMath.setUniformForProgram("velocityCalc", "u_mass", 4, "1i");
303        gpuMath.setUniformForProgram("velocityCalc", "u_meta", 5, "1i");
304        gpuMath.setUniformForProgram("velocityCalc", "u_beamMeta", 6, "1i");
305        gpuMath.setUniformForProgram("velocityCalc", "u_creaseMeta", 7, "1i");
306        gpuMath.setUniformForProgram("velocityCalc", "u_nodeCreaseMeta", 8, "1i");
307        gpuMath.setUniformForProgram("velocityCalc", "u_normals", 9, "1i");
308        gpuMath.setUniformForProgram("velocityCalc", "u_theta", 10, "1i");
309        gpuMath.setUniformForProgram("velocityCalc", "u_creaseGeo", 11, "1i");
310        gpuMath.setUniformForProgram("velocityCalc", "u_meta2", 12, "1i");
311        gpuMath.setUniformForProgram("velocityCalc", "u_nodeFaceMeta", 13, "1i");
312        gpuMath.setUniformForProgram("velocityCalc", "u_nominalTriangles", 14, "1i");
313        gpuMath.setUniformForProgram("velocityCalc", "u_textureDim", [textureDim, textureDim], "2f");
314        gpuMath.setUniformForProgram("velocityCalc", "u_textureDimEdges", [textureDimEdges, textureDimEdges], "2f");
315        gpuMath.setUniformForProgram("velocityCalc", "u_textureDimFaces", [textureDimFaces, textureDimFaces], "2f");
316        gpuMath.setUniformForProgram("velocityCalc", "u_textureDimCreases", [textureDimCreases, textureDimCreases], "2f");
317        gpuMath.setUniformForProgram("velocityCalc", "u_textureDimNodeCreases", [textureDimNodeCreases, textureDimNodeCreases], "2f");
318        gpuMath.setUniformForProgram("velocityCalc", "u_textureDimNodeFaces", [textureDimNodeFaces, textureDimNodeFaces], "2f");
319        gpuMath.setUniformForProgram("velocityCalc", "u_creasePercent", globals.creasePercent, "1f");
320        gpuMath.setUniformForProgram("velocityCalc", "u_axialStiffness", globals.axialStiffness, "1f");
321        gpuMath.setUniformForProgram("velocityCalc", "u_faceStiffness", globals.faceStiffness, "1f");
322        gpuMath.setUniformForProgram("velocityCalc", "u_calcFaceStrain", globals.calcFaceStrain, "1f");
323
324        gpuMath.createProgram("positionCalcVerlet", vertexShader, document.getElementById("positionCalcVerletShader").text);
325        gpuMath.setUniformForProgram("positionCalcVerlet", "u_lastPosition", 0, "1i");
326        gpuMath.setUniformForProgram("positionCalcVerlet", "u_lastLastPosition", 1, "1i");
327        gpuMath.setUniformForProgram("positionCalcVerlet", "u_lastVelocity", 2, "1i");
328        gpuMath.setUniformForProgram("positionCalcVerlet", "u_originalPosition", 3, "1i");
329        gpuMath.setUniformForProgram("positionCalcVerlet", "u_externalForces", 4, "1i");
330        gpuMath.setUniformForProgram("positionCalcVerlet", "u_mass", 5, "1i");
331        gpuMath.setUniformForProgram("positionCalcVerlet", "u_meta", 6, "1i");
332        gpuMath.setUniformForProgram("positionCalcVerlet", "u_beamMeta", 7, "1i");
333        gpuMath.setUniformForProgram("positionCalcVerlet", "u_creaseMeta", 8, "1i");
334        gpuMath.setUniformForProgram("positionCalcVerlet", "u_nodeCreaseMeta", 9, "1i");
335        gpuMath.setUniformForProgram("positionCalcVerlet", "u_normals", 10, "1i");
336        gpuMath.setUniformForProgram("positionCalcVerlet", "u_theta", 11, "1i");
337        gpuMath.setUniformForProgram("positionCalcVerlet", "u_creaseGeo", 12, "1i");
338        gpuMath.setUniformForProgram("positionCalcVerlet", "u_meta2", 13, "1i");
339        gpuMath.setUniformForProgram("positionCalcVerlet", "u_nodeFaceMeta", 14, "1i");
340        gpuMath.setUniformForProgram("positionCalcVerlet", "u_nominalTriangles", 15, "1i");
341        gpuMath.setUniformForProgram("positionCalcVerlet", "u_textureDim", [textureDim, textureDim], "2f");
342        gpuMath.setUniformForProgram("positionCalcVerlet", "u_textureDimEdges", [textureDimEdges, textureDimEdges], "2f");
343        gpuMath.setUniformForProgram("positionCalcVerlet", "u_textureDimFaces", [textureDimFaces, textureDimFaces], "2f");
344        gpuMath.setUniformForProgram("positionCalcVerlet", "u_textureDimCreases", [textureDimCreases, textureDimCreases], "2f");
345        gpuMath.setUniformForProgram("positionCalcVerlet", "u_textureDimNodeCreases", [textureDimNodeCreases, textureDimNodeCreases], "2f");
346        gpuMath.setUniformForProgram("positionCalcVerlet", "u_textureDimNodeFaces", [textureDimNodeFaces, textureDimNodeFaces], "2f");
347        gpuMath.setUniformForProgram("positionCalcVerlet", "u_creasePercent", globals.creasePercent, "1f");
348        gpuMath.setUniformForProgram("positionCalcVerlet", "u_axialStiffness", globals.axialStiffness, "1f");
349        gpuMath.setUniformForProgram("positionCalcVerlet", "u_faceStiffness", globals.faceStiffness, "1f");
350        gpuMath.setUniformForProgram("positionCalcVerlet", "u_calcFaceStrain", globals.calcFaceStrain, "1f");
351
352        gpuMath.createProgram("thetaCalc", vertexShader, document.getElementById("thetaCalcShader").text);
353        gpuMath.setUniformForProgram("thetaCalc", "u_normals", 0, "1i");
354        gpuMath.setUniformForProgram("thetaCalc", "u_lastTheta", 1, "1i");
355        gpuMath.setUniformForProgram("thetaCalc", "u_creaseVectors", 2, "1i");
356        gpuMath.setUniformForProgram("thetaCalc", "u_lastPosition", 3, "1i");
357        gpuMath.setUniformForProgram("thetaCalc", "u_originalPosition", 4, "1i");
358        gpuMath.setUniformForProgram("thetaCalc", "u_textureDim", [textureDim, textureDim], "2f");
359        gpuMath.setUniformForProgram("thetaCalc", "u_textureDimFaces", [textureDimFaces, textureDimFaces], "2f");
360        gpuMath.setUniformForProgram("thetaCalc", "u_textureDimCreases", [textureDimCreases, textureDimCreases], "2f");
361
362        gpuMath.createProgram("normalCalc", vertexShader, document.getElementById("normalCalc").text);
363        gpuMath.setUniformForProgram("normalCalc", "u_faceVertexIndices", 0, "1i");
364        gpuMath.setUniformForProgram("normalCalc", "u_lastPosition", 1, "1i");
365        gpuMath.setUniformForProgram("normalCalc", "u_originalPosition", 2, "1i");
366        gpuMath.setUniformForProgram("normalCalc", "u_textureDim", [textureDim, textureDim], "2f");
367        gpuMath.setUniformForProgram("normalCalc", "u_textureDimFaces", [textureDimFaces, textureDimFaces], "2f");
368
369        gpuMath.createProgram("packToBytes", vertexShader, document.getElementById("packToBytesShader").text);
370        gpuMath.initTextureFromData("outputBytes", textureDim*4, textureDim, "UNSIGNED_BYTE"
370, null, true);
371        gpuMath.initFrameBufferForTexture("outputBytes", true);
372        gpuMath.setUniformForProgram("packToBytes", "u_floatTextureDim", [textureDim, textureDim], "2f");
373        gpuMath.setUniformForProgram("packToBytes", "u_floatTexture", 0, "1i");
374
375        gpuMath.createProgram("zeroTexture", vertexShader, document.getElementById("zeroTexture").text);
376        gpuMath.createProgram("zeroThetaTexture", vertexShader, document.getElementById("zeroThetaTexture").text);
377        gpuMath.setUniformForProgram("zeroThetaTexture", "u_theta", 0, "1i");
378        gpuMath.setUniformForProgram("zeroThetaTexture", "u_textureDimCreases", [textureDimCreases, textureDimCreases], "2f");
379
380        gpuMath.createProgram("centerTexture", vertexShader, document.getElementById("centerTexture").text);
381        gpuMath.setUniformForProgram("centerTexture", "u_lastPosition", 0, "1i");
382        gpuMath.setUniformForProgram("centerTexture", "u_textureDim", [textureDim, textureDim], "2f");
383
384        gpuMath.createProgram("copyTexture", vertexShader, document.getElementById("copyTexture").text);
385        gpuMath.setUniformForProgram("copyTexture", "u_orig", 0, "1i");
386        gpuMath.setUniformForProgram("copyTexture", "u_textureDim", [textureDim, textureDim], "2f");
387
388        gpuMath.createProgram("updateCreaseGeo", vertexShader, document.getElementById("updateCreaseGeo").text);
389        gpuMath.setUniformForProgram("updateCreaseGeo", "u_lastPosition", 0, "1i");
390        gpuMath.setUniformForProgram("updateCreaseGeo", "u_originalPosition", 1, "1i");
391        gpuMath.setUniformForProgram("updateCreaseGeo", "u_creaseMeta2", 2, "1i");
392        gpuMath.setUniformForProgram("updateCreaseGeo", "u_textureDim", [textureDim, textureDim], "2f");
393        gpuMath.setUniformForProgram("updateCreaseGeo", "u_textureDimCreases", [textureDimCreases, textureDimCreases], "2f");
394
395        gpuMath.setSize(textureDim, textureDim);
396
397        programsInited = true;
398    }
399
400    function calcTextureSize(numNodes){
401        if (numNodes == 1) return 2;
402        for (var i=0;i<numNodes;i++){
403            if (Math.pow(2, 2*i) >= numNodes){
404                return Math.pow(2, i);
405            }
406        }
407        console.warn("no texture size found for " + numNodes + " items");
408        return 2;
409    }
410
411    function updateMaterials(initing){
412        var index = 0;
413        for (var i=0;i<nodes.length;i++){
414            if (initing) {
415                meta[4*i] = index;
416                meta[4*i+1] = nodes[i].numBeams();
417            }
418            for (var j=0;j<nodes[i].beams.length;j++){
419                var beam = nodes[i].beams[j];
420                beamMeta[4*index] = beam.getK();
421                beamMeta[4*index+1] = beam.getD();
422                if (initing) {
423                    beamMeta[4*index+2] = beam.getLength();
424                    beamMeta[4*index+3] = beam.getOtherNode(nodes[i]).getIndex();
425                }
426                index+=1;
427            }
428        }
429        globals.gpuMath.initTextureFromData("u_beamMeta", textureDimEdges, textureDimEdges, "FLOAT", beamMeta, true);
430
431
432        if (programsInited) {
433            globals.gpuMath.setProgram("velocityCalc");
434            globals.gpuMath.setUniformForProgram("velocityCalc", "u_axialStiffness", globals.axialStiffness, "1f");
435            globals.gpuMath.setUniformForProgram("velocityCalc", "u_faceStiffness", globals.faceStiffness, "1f");
436            globals.gpuMath.setProgram("positionCalcVerlet");
437            globals.gpuMath.setUniformForProgram("positionCalcVerlet", "u_axialStiffness", globals.axialStiffness, "1f");
438            globals.gpuMath.setUniformForProgram("positionCalcVerlet", "u_faceStiffness", globals.faceStiffness, "1f");
439            setSolveParams();//recalc dt
440        }
441    }
442
443    function updateExternalForces(){
444        for (var i=0;i<nodes.length;i++){
445            var externalForce = nodes[i].getExternalForce();
446            externalForces[4*i] = externalForce.x;
447            externalForces[4*i+1] = externalForce.y;
448            externalForces[4*i+2] = externalForce.z;
449        }
450        globals.gpuMath.initTextureFromData("u_externalForces", textureDim, textureDim, "FLOAT", externalForces, true);
451    }
452
453    function updateFixed(){
454        for (var i=0;i<nodes.length;i++){
455            mass[4*i+1] = (nodes[i].isFixed() ? 1 : 0);
456        }
457        globals.gpuMath.initTextureFromData("u_mass", textureDim, textureDim, "FLOAT", mass, true);
458    }
459
460    function updateOriginalPosition(){
461        for (var i=0;i<nodes.length;i++){
462            var origPosition = nodes[i].getOriginalPosition();
463            originalPosition[4*i] = origPosition.x;
464            originalPosition[4*i+1] = origPosition.y;
465            originalPosition[4*i+2] = origPosition.z;
466        }
467        globals.gpuMath.initTextureFromData("u_originalPosition", textureDim, textureDim, "FLOAT", originalPosition, true);
468    }
469
470    function updateCreaseVectors(){
471        for (var i=0;i<creases.length;i++){
472            var rgbaIndex = i*4;
473            var nodes = creases[i].edge.nodes;
474            // this.vertices[1].clone().sub(this.vertices[0]);
475            creaseVectors[rgbaIndex] = nodes[0].getIndex();
476            creaseVectors[rgbaIndex+1] = nodes[1].getIndex();
477        }
478        globals.gpuMath.initTextureFromData("u_creaseVectors", textureDimCreases, textureDimCreases, "FLOAT", creaseVectors, true);
479    }
480
481    function updateCreasesMeta(initing){
482        for (var i=0;i<creases.length;i++){
483            var crease = creases[i];
484            creaseMeta[i*4] = crease.getK();
485            // creaseMeta[i*4+1] = crease.getD();
486            if (initing) creaseMeta[i*4+2] = crease.getTargetTheta();
487        }
488        globals.gpuMath.initTextureFromData("u_creaseMeta", textureDimCreases, textureDimCreases, "FLOAT", creaseMeta, true);
489    }
490
491    function updateLastPosition(){
492        for (var i=0;i<nodes.length;i++){
493            var _position = nodes[i].getRelativePosition();
494            lastPosition[4*i] = _position.x;
495            lastPosition[4*i+1] = _position.y;
496            lastPosition[4*i+2] = _position.z;
497        }
498        globals.gpuMath.initTextureFromData("u_lastPosition", textureDim, textureDim, "FLOAT", lastPosition, true);
499        globals.gpuMath.initFrameBufferForTexture("u_lastPosition", true);
500
501    }
502
503    function setCreasePercent(percent){
504        if (!programsInited) return;
505        globals.gpuMath.setProgram("velocityCalc");
506        globals.gpuMath.setUniformForProgram("velocityCalc", "u_creasePercent", percent, "1f");
507        globals.gpuMath.setProgram("positionCalcVerlet");
508        globals.gpuMath.setUniformForProgram("positionCalcVerlet", "u_creasePercent", percent, "1f");
509    }
510
511    function initTypedArrays(){
512
513        textureDim = calcTextureSize(nodes.length);
514
515        var numNodeFaces = 0;
516        var nodeFaces = [];
517        for (var i=0;i<nodes.length;i++){
518            nodeFaces.push([]);
519            for (var j=0;j<faces.length;j++){
520                if (faces[j].indexOf(i)>=0) {
521                    nodeFaces[i].push(j);
522                    numNodeFaces++;
523                }
524            }
525        }
526        textureDimNodeFaces = calcTextureSize(numNodeFaces);
527
528        var numEdges = 0;
529        for (var i=0;i<nodes.length;i++){
530            numEdges += nodes[i].numBeams();
531        }
532        textureDimEdges = calcTextureSize(numEdges);
533
534        var numCreases = creases.length;
535        textureDimCreases = calcTextureSize(numCreases);
536
537        var numNodeCreases = 0;
538        for (var i=0;i<nodes.length;i++){
539            numNodeCreases += nodes[i].numCreases();
540        }
541        numNodeCreases += numCreases*2;//reactions
542        textureDimNodeCreases = calcTextureSize(numNodeCreases);
543
544        var numFaces = faces.length;
545        textureDimFaces = calcTextureSize(numFaces);
546
547        originalPosition = new Float32Array(textureDim*textureDim*4);
548        position = new Float32Array(textureDim*textureDim*4);
549        lastPosition = new Float32Array(textureDim*textureDim*4);
550        lastLastPosition = new Float32Array(textureDim*textureDim*4);
551        velocity = new Float32Array(textureDim*textureDim*4);
552        lastVelocity = new Float32Array(textureDim*textureDim*4);
553        externalForces = new Float32Array(textureDim*textureDim*4);
554        mass = new Float32Array(textureDim*textureDim*4);
555        meta = new Float32Array(textureDim*textureDim*4);
556        meta2 = new Float32Array(textureDim*textureDim*4);
557        beamMeta = new Float32Array(textureDimEdges*textureDimEdges*4);
558
559        normals = new Float32Array(textureDimFaces*textureDimFaces*4);
560        faceVertexIndices = new Float32Array(textureDimFaces*textureDimFaces*4);
561        creaseMeta = new Float32Array(textureDimCreases*textureDimCreases*4);
562        nodeFaceMeta = new Float32Array(textureDimNodeFaces*textureDimNodeFaces*4);
563        nominalTriangles = new Float32Array(textureDimFaces*textureDimFaces*4);
564        nodeCreaseMeta = new Float32Array(textureDimNodeCreases*textureDimNodeCreases*4);
565        creaseMeta2 = new Float32Array(textureDimCreases*textureDimCreases*4);
566        creaseGeo = new Float32Array(textureDimCreases*textureDimCreases*4);
567        creaseVectors = new Float32Array(textureDimCreases*textureDimCreases*4);
568        theta = new Float32Array(textureDimCreases*textureDimCreases*4);
569        lastTheta = new Float32Array(textureDimCreases*textureDimCreases*4);
570
571        for (var i=0;i<faces.length;i++){
572            var face = faces[i];
573            faceVertexIndices[4*i] = face[0];
574            faceVertexIndices[4*i+1] = face[1];
575            faceVertexIndices[4*i+2] = face[2];
576
577            var a = nodes[face[0]].getOriginalPosition();
578            var b = nodes[face[1]].getOriginalPosition();
579            var c = nodes[face[2]].getOriginalPosition();
580            var ab = (b.clone().sub(a)).normalize();
581            var ac = (c.clone().sub(a)).normalize();
582            var bc = (c.clone().sub(b)).normalize();
583            nominalTriangles[4*i] = Math.acos(ab.dot(ac));
584            nominalTriangles[4*i+1] = Math.acos(-1*ab.dot(bc));
585            nominalTriangles[4*i+2] = Math.acos(ac.dot(bc));
586
587            if (Math.abs(nominalTriangles[4*i]+nominalTriangles[4*i+1]+nominalTriangles[4*i+2]-Math.PI)>0.1){
588                console.warn("bad angles");
589            }
590        }
591
592
593        for (var i=0;i<textureDim*textureDim;i++){
594            mass[4*i+1] = 1;//set all fixed by default
595        }
596
597        for (var i=0;i<textureDimCreases*textureDimCreases;i++){
598            if (i >= numCreases){
599                lastTheta[i*4+2] = -1;
600                lastTheta[i*4+3] = -1;
601                continue;
602            }
603            lastTheta[i*4+2] = creases[i].getNormal1Index();
604            lastTheta[i*4+3] = creases[i].getNormal2Index();
605        }
606
607        var index = 0;
608        for (var i=0;i<nodes.length;i++){
609            meta2[4*i] = index;
610            var num = nodeFaces[i].length;
611            meta2[4*i+1] = num;
612            for (var j=0;j<num;j++){
613                var _index = (index+j)*4;
614                var face = faces[nodeFaces[i][j]];
615                nodeFaceMeta[_index] = nodeFaces[i][j];
616                nodeFaceMeta[_index+1] = face[0] == i ? -1 : face[0];
617                nodeFaceMeta[_index+2] = face[1] == i ? -1 : face[1];
618                nodeFaceMeta[_index+3] = face[2] == i ? -1 : face[2];
619            }
620            index+=num;
621        }
622
623        var index = 0;
624        for (var i=0;i<nodes.length;i++){
625            mass[4*i] = nodes[i].getSimMass();
626            meta[i*4+2] = index;
627            var nodeCreases = nodes[i].creases;
628            var nodeInvCreases = nodes[i].invCreases;
628//nodes attached to crease move in opposite direction
629            // console.log(nodeInvCreases);
630            meta[i*4+3] = nodeCreases.length + nodeInvCreases.length;
631            for (var j=0;j<nodeCreases.length;j++){
632                nodeCreaseMeta[index*4] = nodeCreases[j].getIndex();
633                nodeCreaseMeta[index*4+1] = nodeCreases[j].getNodeIndex(nodes[i]);//type 1, 2, 3, 4
634                index++;
635            }
636            for (var j=0;j<nodeInvCreases.length;j++){
637                nodeCreaseMeta[index*4] = nodeInvCreases[j].getIndex();
638                nodeCreaseMeta[index*4+1] = nodeInvCreases[j].getNodeIndex(nodes[i]);//type 1, 2, 3, 4
639                index++;
640            }
641        }
642        for (var i=0;i<creases.length;i++){
643            var crease = creases[i];
644            creaseMeta2[i*4] = crease.node1.getIndex();
645            creaseMeta2[i*4+1] = crease.node2.getIndex();
646            creaseMeta2[i*4+2] = crease.edge.nodes[0].getIndex();
647            creaseMeta2[i*4+3] = crease.edge.nodes[1].getIndex();
648            index++;
649        }
650
651        updateOriginalPosition();
652        updateMaterials(true);
653        updateFixed();
654        updateExternalForces();
655        updateCreasesMeta(true);
656        updateCreaseVectors();
657        setCreasePercent(globals.creasePercent);
658    }
659
660    return {
661        syncNodesAndEdges: syncNodesAndEdges,
662        updateFixed: updateFixed,
663        solve: solve,
664        render: render,
665        reset: reset
666    }
667}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.