From 8116a7f9e5dcf8c0ff4c8ec65bceeb82756e494c Mon Sep 17 00:00:00 2001 From: Darrell Huffman Date: Sun, 14 Jan 2024 21:18:48 +0100 Subject: [PATCH] feat: cast and use non null operator less --- src/physics/integrators/euler.ts | 28 +++--- src/physics/integrators/rk4.ts | 48 +++++----- src/scene/manifestations/index.ts | 4 + src/scene/manifestations/manifestation.ts | 106 +++++++++++++++++----- src/scene/particles/particles.ts | 17 ++-- tsconfig.json | 10 +- 6 files changed, 137 insertions(+), 76 deletions(-) diff --git a/src/physics/integrators/euler.ts b/src/physics/integrators/euler.ts index 9bafbd4f7..7153dc15c 100644 --- a/src/physics/integrators/euler.ts +++ b/src/physics/integrators/euler.ts @@ -46,9 +46,9 @@ class Euler { for (let i = 0; i < massesLength; i++) { let massI = masses[i]; - positionVectors[i] = massI!.position; + positionVectors[i] = massI.position; - velocityVectors[i] = massI!.velocity; + velocityVectors[i] = massI.velocity; } return { positionVectors, velocityVectors }; @@ -58,13 +58,13 @@ class Euler { const massesLength = p.length; for (let i = 0; i < massesLength; i++) { - const positionVectorI = p[i]!; - const velocityVectorI = v[i]!; + const positionVectorI = p[i]; + const velocityVectorI = v[i]; const mass = this.masses[i]; - mass!.position = positionVectorI; - mass!.velocity = velocityVectorI; + mass.position = positionVectorI; + mass.velocity = velocityVectorI; } } @@ -73,11 +73,11 @@ class Euler { const massesLength = velocityVectors.length; for (let i = 0; i < massesLength; i++) { - let velocityVectorI = velocityVectors[i]!; + let velocityVectorI = velocityVectors[i]; let mass = this.masses[i]; positionVectors[i] = this.positionVector - .set(mass!.position) + .set(mass.position) .addScaledVector(dt, velocityVectorI) .toObject(); } @@ -92,11 +92,11 @@ class Euler { for (let i = 0; i < massesLength; i++) { this.accelerationVector.set({ x: 0, y: 0, z: 0 }); - let positionVectorI = positionVectors[i]!; + let positionVectorI = positionVectors[i]; for (let j = 0; j < massesLength; j++) { - if (i !== j && this.masses[j]!.m > 0) { - let positionVectorJ = positionVectors[j]!; + if (i !== j && this.masses[j].m > 0) { + let positionVectorJ = positionVectors[j]; let distanceParams = this.getDistanceParams( positionVectorI, @@ -105,7 +105,7 @@ class Euler { let distance = Math.sqrt(distanceParams.dSquared); let fact = - (this.g * this.masses[j]!.m) / (distanceParams.dSquared * distance); + (this.g * this.masses[j].m) / (distanceParams.dSquared * distance); this.accelerationVector.addScaledVector(fact, { x: distanceParams.dx, @@ -126,11 +126,11 @@ class Euler { const massesLength = accelerationVectors.length; for (let i = 0; i < massesLength; i++) { - let accelerationVectorI = accelerationVectors[i]!; + let accelerationVectorI = accelerationVectors[i]; let mass = this.masses[i]; velocityVectors[i] = this.velocityVector - .set(mass!.velocity) + .set(mass.velocity) .addScaledVector(dt, accelerationVectorI) .toObject(); } diff --git a/src/physics/integrators/rk4.ts b/src/physics/integrators/rk4.ts index e1652ecbb..b3aea1a67 100644 --- a/src/physics/integrators/rk4.ts +++ b/src/physics/integrators/rk4.ts @@ -48,38 +48,38 @@ class RK4 extends Euler { for (let i = 0; i < massesLength; i++) { accelerationVectors[i] = { x: - accelerationVectors1[i]!.x / 6 + - accelerationVectors2[i]!.x / 3 + - accelerationVectors3[i]!.x / 3 + - accelerationVectors4[i]!.x / 6, + accelerationVectors1[i].x / 6 + + accelerationVectors2[i].x / 3 + + accelerationVectors3[i].x / 3 + + accelerationVectors4[i].x / 6, y: - accelerationVectors1[i]!.y / 6 + - accelerationVectors2[i]!.y / 3 + - accelerationVectors3[i]!.y / 3 + - accelerationVectors4[i]!.y / 6, + accelerationVectors1[i].y / 6 + + accelerationVectors2[i].y / 3 + + accelerationVectors3[i].y / 3 + + accelerationVectors4[i].y / 6, z: - accelerationVectors1[i]!.z / 6 + - accelerationVectors2[i]!.z / 3 + - accelerationVectors3[i]!.z / 3 + - accelerationVectors4[i]!.z / 6, + accelerationVectors1[i].z / 6 + + accelerationVectors2[i].z / 3 + + accelerationVectors3[i].z / 3 + + accelerationVectors4[i].z / 6, }; velocityVectors[i] = { x: - stateVectors.velocityVectors[i]!.x / 6 + - velocityVectors2[i]!.x / 3 + - velocityVectors3[i]!.x / 3 + - velocityVectors4[i]!.x / 6, + stateVectors.velocityVectors[i].x / 6 + + velocityVectors2[i].x / 3 + + velocityVectors3[i].x / 3 + + velocityVectors4[i].x / 6, y: - stateVectors.velocityVectors[i]!.y / 6 + - velocityVectors2[i]!.y / 3 + - velocityVectors3[i]!.y / 3 + - velocityVectors4[i]!.y / 6, + stateVectors.velocityVectors[i].y / 6 + + velocityVectors2[i].y / 3 + + velocityVectors3[i].y / 3 + + velocityVectors4[i].y / 6, z: - stateVectors.velocityVectors[i]!.z / 6 + - velocityVectors2[i]!.z / 3 + - velocityVectors3[i]!.z / 3 + - velocityVectors4[i]!.z / 6, + stateVectors.velocityVectors[i].z / 6 + + velocityVectors2[i].z / 3 + + velocityVectors3[i].z / 3 + + velocityVectors4[i].z / 6, }; } diff --git a/src/scene/manifestations/index.ts b/src/scene/manifestations/index.ts index 7bd0f8434..63a0c8fb4 100644 --- a/src/scene/manifestations/index.ts +++ b/src/scene/manifestations/index.ts @@ -65,6 +65,10 @@ class ManifestationManager { this.scene.remove(massToBeDeleted); + this.manifestations[i]?.dispose(); + if (this.manifestations[i]!.object3D) { + this.manifestations[i]!.object3D = undefined; + } this.manifestations.splice(i, 1); } } diff --git a/src/scene/manifestations/manifestation.ts b/src/scene/manifestations/manifestation.ts index cc5de4be1..690c861e5 100644 --- a/src/scene/manifestations/manifestation.ts +++ b/src/scene/manifestations/manifestation.ts @@ -8,8 +8,8 @@ class Manifestation { public mass: ScenarioMassType; protected textureLoader: THREE.TextureLoader; protected trailVertices: number; - public object3D: THREE.Object3D; - public orbit: EllipseCurve | null; + public object3D: THREE.Object3D | undefined; + public orbit: EllipseCurve | undefined; constructor(mass: ScenarioMassType, textureLoader: THREE.TextureLoader) { this.mass = mass; @@ -19,7 +19,7 @@ class Manifestation { this.object3D = new THREE.Object3D(); this.object3D.name = this.mass.name; - this.orbit = null; + this.orbit = undefined; this.trailVertices = 3000; } @@ -40,7 +40,9 @@ class Manifestation { const sphere = new THREE.Mesh(geometry, material); sphere.name = "sphere"; - this.object3D.add(sphere); + if (this.object3D) { + this.object3D.add(sphere); + } return this; } @@ -59,17 +61,20 @@ class Manifestation { "green", ); - this.object3D.add(this.orbit.object3D); + this.object3D!.add(this.orbit.object3D!); return this; } public removeOrbit() { - this.object3D.remove(this.orbit!.object3D); + if (this.orbit) { + this.orbit.dispose(); - this.orbit!.dispose(); + this.object3D!.remove(this.orbit.object3D!); + this.orbit.object3D = undefined; - this.orbit = null; + this.orbit = undefined; + } } public updateOrbit( @@ -87,7 +92,7 @@ class Manifestation { const ellipse = getEllipse(a, e); - const orbit = this.object3D.getObjectByName("ellipse") as THREE.Object3D; + const orbit = this.object3D!.getObjectByName("ellipse") as THREE.Object3D; orbit.position.z = (rotatingReferenceFrame.z - primaryPosition.z) * scale; @@ -109,7 +114,7 @@ class Manifestation { const points = []; - const spherePosition = this.object3D.getObjectByName("sphere")!.position; + const spherePosition = this.object3D!.getObjectByName("sphere")!.position; for (let i = 0; i < verticesLength; i++) { points.push(spherePosition); @@ -127,32 +132,45 @@ class Manifestation { mesh.frustumCulled = false; - this.object3D.add(mesh); + this.object3D!.add(mesh); } public removeTrail() { - const trail = this.object3D.getObjectByName("trail"); + let trail = this.object3D!.getObjectByName("trail") as + | THREE.Line + | undefined; if (trail) { - // @ts-ignore - trail.geometry.dispose(); + let geometry = trail.geometry as + | THREE.BufferGeometry + | undefined; + + if (geometry) { + geometry.dispose(); + geometry = undefined; + } + + let material = trail.material as THREE.Material | undefined; + + if (material) { + material.dispose(); + material = undefined; + } - // @ts-ignore - trail.material.dispose(); + this.object3D!.remove(trail); - this.object3D.remove(trail); + trail = undefined; } } public drawTrail() { - const trail = this.object3D.getObjectByName("trail"); + const trail = this.object3D!.getObjectByName("trail") as THREE.Line; - // @ts-ignore const geometry = trail.geometry; - const positions = geometry.attributes.position.array; + const positions = geometry.attributes["position"]!.array; for (let i = positions.length - 1; i > 2; i--) { - positions[i] = positions[i - 3]; + positions[i] = positions[i - 3] as number; } const { x, y, z } = this.mass.rotatedPosition as VectorType; @@ -165,15 +183,53 @@ class Manifestation { } public setPosition() { - const object3D = this.object3D; - const { x, y, z } = this.mass.rotatedPosition as VectorType; - const sphere = object3D.getObjectByName("sphere"); - sphere?.position.set(x, y, z); + const sphere = this.object3D!.getObjectByName("sphere") as THREE.Mesh; + sphere.position.set(x, y, z); return this; } + + public dispose() { + this.removeOrbit(); + + this.removeTrail(); + + let sphereMesh = this.object3D!.getObjectByName("sphere") as + | THREE.Mesh + | undefined; + + if (sphereMesh) { + let sphereMaterial = sphereMesh.material as THREE.Material | undefined; + + if (sphereMaterial) { + //@ts-ignore + let sphereMaterialMap = sphereMesh.material.map; + + if (sphereMaterialMap) { + sphereMaterialMap.dispose(); + sphereMaterialMap = undefined; + } + + sphereMaterial.dispose(); + sphereMaterial = undefined; + } + + let sphereGeometry = sphereMesh.geometry as + | THREE.BufferGeometry + | undefined; + + if (sphereGeometry) { + sphereGeometry.dispose(); + sphereGeometry = undefined; + } + + this.object3D!.remove(sphereMesh); + + sphereMesh = undefined; + } + } } export default Manifestation; diff --git a/src/scene/particles/particles.ts b/src/scene/particles/particles.ts index fa137706c..9fe15e00e 100644 --- a/src/scene/particles/particles.ts +++ b/src/scene/particles/particles.ts @@ -1,11 +1,11 @@ import * as THREE from "three"; -import { ParticlesType, VectorType, ParticleType } from "../../types/physics"; +import { ParticlesType, VectorType } from "../../types/physics"; class Particles { particles: ParticlesType; scale: number; textureLoader: THREE.TextureLoader; - mesh: THREE.Points | null; + mesh: THREE.Points; constructor( particles: ParticlesType, @@ -18,7 +18,7 @@ class Particles { this.textureLoader = textureLoader; - this.mesh = null; + this.mesh = this.createParticleSystem(); } public createParticleSystem() { @@ -31,7 +31,7 @@ class Particles { const particles = this.particles; for (let i = 0; i < particlesLength; i++) { - const particlePosition = particles[i]!.position; + const particlePosition = particles[i].position; const x = particlePosition.x * scale; const y = particlePosition.y * scale; @@ -60,7 +60,7 @@ class Particles { const mesh = new THREE.Points(geometry, material); mesh.name = "particles"; - this.mesh = mesh; + return mesh; } public setPositions( @@ -69,17 +69,17 @@ class Particles { ) { const particlesLength = particles.length; - const geometry = this.mesh!.geometry; + const geometry = this.mesh.geometry; geometry.setDrawRange(0, particlesLength); - const positions = geometry.attributes.position!.array; + const positions = geometry.attributes["position"].array; let j = 0; const scale = this.scale; for (let i = 0; i < particlesLength; i++) { - const particle = particles[i] as ParticleType; + const particle = particles[i]; let x = (rotatingReferenceFrame.x - particle.position.x) * scale; let y = (rotatingReferenceFrame.y - particle.position.y) * scale; @@ -91,6 +91,7 @@ class Particles { j += 3; } + geometry.getAttribute("position").needsUpdate = true; } } diff --git a/tsconfig.json b/tsconfig.json index 118e4125d..480040fad 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -84,16 +84,16 @@ "strictBindCallApply": true /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */, "strictPropertyInitialization": true /* Check for class properties that are declared but not set in the constructor. */, "noImplicitThis": true /* Enable error reporting when `this` is given the type `any`. */, - "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ - "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + "useUnknownInCatchVariables": true /* Type catch clause variables as 'unknown' instead of 'any'. */, + "alwaysStrict": true /* Ensure 'use strict' is always emitted. */, "noUnusedLocals": true /* Enable error reporting when a local variables aren't read. */, "noUnusedParameters": true /* Raise an error when a function parameter isn't read */, - "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + "exactOptionalPropertyTypes": true /* Interpret optional property types as written, rather than adding 'undefined'. */, "noImplicitReturns": true /* Enable error reporting for codepaths that do not explicitly return in a function. */, "noFallthroughCasesInSwitch": true /* Enable error reporting for fallthrough cases in switch statements. */, - "noUncheckedIndexedAccess": true /* Include 'undefined' in index signature results */, + "noUncheckedIndexedAccess": false /* Include 'undefined' in index signature results */, "noImplicitOverride": true /* Ensure overriding members in derived classes are marked with an override modifier. */, - "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + "noPropertyAccessFromIndexSignature": true /* Enforces using indexed accessors for keys declared using an indexed type */, // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */