JSFiddle - React, Tailwind, and code Playground
HTML
<script src="//s3-us-west-2.amazonaws.com/s.cdpn.io/98205/simutil.js"></script>
<script type="text/x-vertex-shader" id="vs">
attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;
varying vec3 v_view;
varying vec3 v_light;
varying vec3 v_normal;
varying vec2 v_texcoord;
void main() {
vec4 p = u_modelView * vec4(a_position, 1.0);
v_normal = mat3(u_modelView) * a_normal;
v_view = -p.xyz;
v_light = u_lightPos - p.xyz;
v_texcoord = a_texcoord;
gl_Position = u_proj * p;
}
</script>
<script type="text/x-fragment-shader" id="fs">
varying vec3 v_view;
varying vec3 v_light;
varying vec3 v_normal;
varying vec2 v_texcoord;
uniform sampler2D u_albedo;
void main() {
vec3 n = normalize(v_normal);
vec3 l = normalize(v_light);
vec3 v = normalize(v_view);
vec3 r = reflect(-l, n);
vec3 albedo = pow(texture2D(u_albedo, v_texcoord).xyz, vec3(2.2));
vec3 diffuse = max(dot(n, l), 0.0)*albedo;
vec3 specular = vec3(0.0);//pow(max(dot(r, v), 0.0), 30.0) * u_lightColor;
vec3 color = saturate(u_ambient + diffuse + specular);
gl_FragColor = vec4(pow(color, vec3(1.0/2.2)), 1.0);
}
</script>
<div class="info">
click+drag to interact
<div id="fps"></div>
</div>
<canvas></canvas>
CSS
/* Styles go here */
body, html, canvas { width: 100%; height: 100%; margin: 0; padding: 0; border: none; overflow: hidden; }
.info {
position:absolute;
top: 0;
left: 0;
width: 400px;
font-family: sans-serif;
padding: 10px;
color: rgb(200, 110, 0);
-webkit-user-select: none;
user-select: none;
}
Babel + JSX
let DEBUG = false;
Sim.DEBUG = DEBUG;
let Options = {
gravity: -9.8,
structK: 100000,
shearK: 5000,
bendK: 1000,
dampSpring: 10,
dampAir: 5,
clothWidth: 20,
clothHeight: 20,
mass: 1.0,
sleepThreshold: 0.001,
sleepCount: 100,
tension: 1.0,
timeStep: 0.016,
pinned: {
bottomLeft: false,
bottomRight: false,
topLeft: true,
topRight: true
},
dynamicWind: true,
wind: [0.0, 0.0, 0.0] // if not dynamic
};
const StructSpring = 0;
const ShearSpring = 1;
const BendSpring = 2;
const SpringConstants = [Options.structK, Options.shearK, Options.bendK];
class Spring {
constructor(type, a, b, rest) {
this.type = type; // index into SpringConstants -- probably should just store k value here...
this.rest = rest;
this.a = a;
this.b = b;
this.iab = -1;
this.iba = -1;
}
}
// big array of 3d vectors. only treated as 3d for convenience --
// math is the same as if it was a big 1d vector
class BigVec3D {
constructor(initSize, tight=true) {
this.size = initSize;
this.data = new Float32Array(initSize*3);
}
nanCheck() {
if (DEBUG) {
for (let i = 0; i < this.size*3; ++i) {
let x = this.data[i];
if (+x !== x) { console.assert("NaNCheck failed"); debugger; }
}
}
}
copy(other) {
console.assert(this.size === other.size);
for (let i = 0; i < this.size*3; ++i) {
this.data[i] = other.data[i];
}
}
forEach(fn, self) {
for (let i = 0, ii = 0; i < this.size; ++i, ii += 3) {
fn.call(self, this.data[ii], this.data[ii+1], this.data[ii+2], i,this);
}
}
init(x, y, z) {
for (let i = 0; i < this.data.length; i += 3) {
this.data[i+0] = x;
this.data[i+1] = y;
this.data[i+2] = z;
}
}
zero() {
for (let i = 0, l = this.size*3; i < l; ++i) {
this.data[i] = 0.0;
}
}
}
function dot(a, b) {
let r = 0.0, sz = a.size;
console.assert(a.size === b.size);
for (let i = 0, size = a.size*3; i < size; ++i) r += a.data[i]*b.data[i];
return r;
}
class BigMat3D {
constructor(diagSize) {
this.size...