| 885 | } |
| 886 | |
| 887 | class Simulation { |
| 888 | options: SimOptions; |
| 889 | fbos: Record<string, THREE.WebGLRenderTarget | null> = { |
| 890 | vel_0: null, |
| 891 | vel_1: null, |
| 892 | vel_viscous0: null, |
| 893 | vel_viscous1: null, |
| 894 | div: null, |
| 895 | pressure_0: null, |
| 896 | pressure_1: null, |
| 897 | }; |
| 898 | fboSize = new THREE.Vector2(); |
| 899 | cellScale = new THREE.Vector2(); |
| 900 | boundarySpace = new THREE.Vector2(); |
| 901 | advection!: Advection; |
| 902 | externalForce!: ExternalForce; |
| 903 | viscous!: Viscous; |
| 904 | divergence!: Divergence; |
| 905 | poisson!: Poisson; |
| 906 | pressure!: Pressure; |
| 907 | constructor(options?: Partial<SimOptions>) { |
| 908 | this.options = { |
| 909 | iterations_poisson: 32, |
| 910 | iterations_viscous: 32, |
| 911 | mouse_force: 20, |
| 912 | resolution: 0.5, |
| 913 | cursor_size: 100, |
| 914 | viscous: 30, |
| 915 | isBounce: false, |
| 916 | dt: 0.014, |
| 917 | isViscous: false, |
| 918 | BFECC: true, |
| 919 | ...options, |
| 920 | }; |
| 921 | this.init(); |
| 922 | } |
| 923 | init() { |
| 924 | this.calcSize(); |
| 925 | this.createAllFBO(); |
| 926 | this.createShaderPass(); |
| 927 | } |
| 928 | getFloatType() { |
| 929 | const isIOS = /(iPad|iPhone|iPod)/i.test(navigator.userAgent); |
| 930 | return isIOS ? THREE.HalfFloatType : THREE.FloatType; |
| 931 | } |
| 932 | createAllFBO() { |
| 933 | const type = this.getFloatType(); |
| 934 | const opts = { |
| 935 | type, |
| 936 | depthBuffer: false, |
| 937 | stencilBuffer: false, |
| 938 | minFilter: THREE.LinearFilter, |
| 939 | magFilter: THREE.LinearFilter, |
| 940 | wrapS: THREE.ClampToEdgeWrapping, |
| 941 | wrapT: THREE.ClampToEdgeWrapping, |
| 942 | } as const; |
| 943 | for (const key in this.fbos) { |
| 944 | this.fbos[key] = new THREE.WebGLRenderTarget( |
nothing calls this directly
no outgoing calls
no test coverage detected