Select Git revision
tidyquestionform.php
-
Chris Sangwin authoredChris Sangwin authored
SimulationSettings.ts 12.85 KiB
import * as THREE from 'three';
import { GUI } from 'dat.gui';
import { picked, PipelineGUI } from '../core/Pipeline';
import { BendingSpring, ShearSpring, Spring, SpringConstants, StructuralSpring, } from './cgPhysix/Springs';
import { Particle } from './cgPhysix/particle';
class World {
public static readonly G = 9.807;
public static derivation(x: Array<number>): Array<number> {
let xDot = new Array<number>(x.length);
for (let i = 0; i < x.length; i += 6) {
xDot[i] = x[i + 3];
xDot[i + 1] = x[i + 4];
xDot[i + 2] = x[i + 5];
xDot[i + 3] = 0;
xDot[i + 4] = -.01;
xDot[i + 5] = 0;
}
return xDot;
}
}
class SimulationSettings implements PipelineGUI {
public static container: THREE.Group = new THREE.Group();
// cloth settings
public static readonly MAX_TOTAL_MASS = 10;
public static readonly MIN_TOTAL_MASS = 0.1;
public static readonly MAX_WIDTH = 5;
public static readonly MIN_WIDTH = 0.01;
public static readonly MAX_HEIGHT = 2;
public static readonly MIN_HEIGHT = 0.01;
public static readonly MAX_RESOLUTION = 20;
public static readonly MIN_RESOLUTION = 2;
public static totalMass: number = 1;
public static width: number = 1;
public static height: number = 1;
public static resolution: number = 5;
public static externalForce: THREE.Vector3 = new THREE.Vector3(0, 0, 0);
// particls
public static pList = new Array<Array<Particle>>();
public static pColorDefault: number = 0xffffff;
public static pColorNoPhysix: number = 0xff00ff;
// springs
public static readonly MAX_CONSTANT = 10;
public static readonly MIN_CONSTANT = 0.1;
public static sList = new Array<Spring>();
public static sConstants: SpringConstants = { structural: 1, shear: 1, bend: 1 };
public static sColorStructural: number = 0xff0000;
public static sColorShear: number = 0x00ff00;
public static sColorBend: number = 0x0000ff;
// integrator
public static readonly INTEGRATOR_TYPES = ['Euler', 'Midpoint', 'RungeKutta'];
public static readonly STEP_SIZE = ['Fixed', 'Adaptive'];
public static integratorType: string = 'Euler';
public static stepSize: string = 'Fixed';
public static generateTextile(): void {
// 1. reset pList
SimulationSettings.pList = new Array<Array<Particle>>();
// 2. generate particles
for (let i = 0; i < SimulationSettings.resolution; i++) {
SimulationSettings.pList[i] = new Array<Particle>();
for (let j = 0; j < SimulationSettings.resolution; j++) {
const p = new Particle({
position: new THREE.Vector3(
SimulationSettings.width * (i / SimulationSettings.resolution) - SimulationSettings.width / 2,
SimulationSettings.height * (j / SimulationSettings.resolution) - SimulationSettings.height / 2,
0),
velocity: new THREE.Vector3(0, 0, 0),
mass: SimulationSettings.totalMass / (SimulationSettings.resolution * SimulationSettings.resolution),
usePhysics: true,
references: [],
radius: 0,
color: SimulationSettings.pColorDefault,
wireframe: true
});
SimulationSettings.pList[i][j] = p;
}
}
for (let i = 0; i < SimulationSettings.resolution; i++) {
SimulationSettings.pList[i][SimulationSettings.resolution - 1].usePhysics = false;
}
// 3. set particle mass and color
SimulationSettings.changedParticleSize();
SimulationSettings.changedParticleColor();
// 4. add particles to container
const pLinList = new Array<THREE.Mesh>();
SimulationSettings.pList.forEach(pSub => {
pSub.forEach(p => {
pLinList.push(p.mesh);
});
});
// 5. reset sList
SimulationSettings.sList = new Array<Spring>();
// 6. generate springs
for (let i = 0; i < SimulationSettings.resolution; i++) {
for (let j = 0; j < SimulationSettings.resolution; j++) {
// structural springs (horizontal)
if (i < SimulationSettings.resolution - 1) {
const pA = SimulationSettings.pList[i][j];
const pB = SimulationSettings.pList[i + 1][j];
const s = new StructuralSpring({
positionA: pA.position,
positionB: pB.position,
constants: SimulationSettings.sConstants,
color: SimulationSettings.sColorStructural,
});
SimulationSettings.sList.push(s);
pA.references.push(s);
pB.references.push(s);
}
// structural springs (vertical)
if (j < SimulationSettings.resolution - 1) {
const pA = SimulationSettings.pList[i][j];
const pB = SimulationSettings.pList[i][j + 1];
const s = new StructuralSpring({
positionA: pA.position,
positionB: pB.position,
constants: SimulationSettings.sConstants,
color: SimulationSettings.sColorStructural,
});
SimulationSettings.sList.push(s);
pA.references.push(s);
pB.references.push(s);
}
// // shear springs
// if (j < SimulationSettings.resolution - 1) {
// const s = new ShearSpring(SimulationSettings.pList[i][j], SimulationSettings.pList[i][j + 1], SimulationSettings.sConstants.shear);
// SimulationSettings.sList.push(s);
// }
// // bending springs
// if (i < SimulationSettings.resolution - 1 && j < SimulationSettings.resolution - 1) {
// const s = new BendingSpring(SimulationSettings.pList[i][j], SimulationSettings.pList[i + 1][j + 1], SimulationSettings.sConstants.bend);
// SimulationSettings.sList.push(s);
// }
}
}
// 7. add springs to container
const sLinList = new Array<THREE.Line>();
SimulationSettings.sList.forEach(s => {
sLinList.push(s.line);
});
// 8. add particles and springs to container
while (SimulationSettings.container.children.length > 0) {
SimulationSettings.container.children.pop();
}
SimulationSettings.container.add(...pLinList, ...sLinList);
}
public static changedParticleSize(): void {
// 1. calculate current mass
const pCount = SimulationSettings.resolution * SimulationSettings.resolution;
const pMass = SimulationSettings.totalMass / pCount;
// 2. calculate max pSize
const maxSize = Math.min(SimulationSettings.width, SimulationSettings.height);
// 3. normalize pMass
const pMassNorm = (pMass + SimulationSettings.MIN_TOTAL_MASS) /
(SimulationSettings.MAX_TOTAL_MASS + SimulationSettings.MIN_TOTAL_MASS);
// 4. calculate pSize
const pSize = maxSize * pMassNorm;
// 5. set pSize
SimulationSettings.pList.forEach(pSub => { pSub.forEach(p => p.setRadius(pSize)) });
}
public static changedDimensions(): void {
// 1. reset positions of particles
for (let i = 0; i < SimulationSettings.resolution; i++) {
for (let j = 0; j < SimulationSettings.resolution; j++) {
SimulationSettings.pList[i][j].setPosition(
SimulationSettings.width * (i / SimulationSettings.resolution) - SimulationSettings.width / 2,
SimulationSettings.height * (j / SimulationSettings.resolution) - SimulationSettings.height / 2,
0);
}
}
// 2. set size based on particle mass
SimulationSettings.changedParticleSize();
}
public static changedParticleColor(): void {
// iterate over all particles and set color based on current internal state
SimulationSettings.pList.forEach(pSub => {
pSub.forEach(p => {
if (p.usePhysics) {
p.setColor(SimulationSettings.pColorDefault);
} else {
p.setColor(SimulationSettings.pColorNoPhysix);
}
})
});
}
public static changedSpringColor(): void {
// iterate over all particles and set color based on current internal state
SimulationSettings.sList.forEach(s => {
if (s instanceof StructuralSpring) {
s.setColor(SimulationSettings.sColorStructural);
} else if (s instanceof ShearSpring) {
s.setColor(SimulationSettings.sColorShear);
} else if (s instanceof BendingSpring) {
s.setColor(SimulationSettings.sColorBend);
}
});
}
public static switchParticlePhysics(): void {
// 1. is picked object not null
if (!picked) {
return;
}
// 2. compare mesh to all particles => find particle and change usePhysics
SimulationSettings.pList.forEach(pSub => {
pSub.forEach(p => {
if (p.mesh === picked) {
p.usePhysics = !p.usePhysics;
p.setColor(p.usePhysics ? SimulationSettings.pColorDefault
: SimulationSettings.pColorNoPhysix);
}
})
});
}
// callback overrides by other classes
public callbackSpringColorStructural(_value: number): void { }
public callbackSpringColorShear(_value: number): void { }
public callbackSpringColorBend(_value: number): void { }
gui(gui: GUI): void {
const general = gui.addFolder('General');
general.add(SimulationSettings, 'totalMass', SimulationSettings.MIN_TOTAL_MASS, SimulationSettings.MAX_TOTAL_MASS)
.step(0.1).name('Total Mass').onChange(SimulationSettings.changedParticleSize);
general.add(SimulationSettings, 'width', SimulationSettings.MIN_WIDTH, SimulationSettings.MAX_WIDTH)
.step(0.1).name('Width').onChange(SimulationSettings.changedDimensions);
general.add(SimulationSettings, 'height', SimulationSettings.MIN_HEIGHT, SimulationSettings.MAX_HEIGHT)
.step(0.1).name('Height').onChange(SimulationSettings.changedDimensions);
general.add(SimulationSettings, 'resolution', SimulationSettings.MIN_RESOLUTION, SimulationSettings.MAX_RESOLUTION)
.step(1).name('Resolution').onChange(SimulationSettings.generateTextile);
general.open();
const extForce = general.addFolder('External Force');
extForce.add(SimulationSettings.externalForce, 'x',).step(0.01);
extForce.add(SimulationSettings.externalForce, 'y',).step(0.01);
extForce.add(SimulationSettings.externalForce, 'z',).step(0.01);
extForce.open();
const particles = gui.addFolder('Particles');
particles.add(SimulationSettings, 'switchParticlePhysics').name('Switch Particle Physics');
particles.addColor(SimulationSettings, 'pColorDefault').name('Default').onChange(SimulationSettings.changedParticleColor);
particles.addColor(SimulationSettings, 'pColorNoPhysix').name('No Phyisx').onChange(SimulationSettings.changedParticleColor);
particles.open();
const springs = gui.addFolder('Springs');
springs.add(SimulationSettings.sConstants, 'structural', SimulationSettings.MIN_CONSTANT, SimulationSettings.MAX_CONSTANT)
.step(0.1).name('Structural');
springs.add(SimulationSettings.sConstants, 'shear', SimulationSettings.MIN_CONSTANT, SimulationSettings.MAX_CONSTANT)
.step(0.1).name('Shear');
springs.add(SimulationSettings.sConstants, 'bend', SimulationSettings.MIN_CONSTANT, SimulationSettings.MAX_CONSTANT)
.step(0.1).name('Bend');
springs.addColor(SimulationSettings, 'sColorStructural').name('Structural').onChange(SimulationSettings.changedSpringColor);
springs.addColor(SimulationSettings, 'sColorShear').name('Shear').onChange(SimulationSettings.changedSpringColor);
springs.addColor(SimulationSettings, 'sColorBend').name('Bend').onChange(SimulationSettings.changedSpringColor);
springs.open();
}
}
export { SimulationSettings };