Ver código fonte

Radial impulse/force

Borut 7 anos atrás
pai
commit
4699709e9b
2 arquivos alterados com 2612 adições e 2435 exclusões
  1. 2467 2435
      dist/preview release/babylon.d.ts
  2. 145 0
      src/Physics/babylon.physicsEngine.ts

Diferenças do arquivo suprimidas por serem muito extensas
+ 2467 - 2435
dist/preview release/babylon.d.ts


+ 145 - 0
src/Physics/babylon.physicsEngine.ts

@@ -166,6 +166,145 @@
 
             return null;
         }
+
+        public applyRadialImpulse(origin: Vector3, radius: number, strength: number, falloff: PhysicsRadialImpulseFallof = PhysicsRadialImpulseFallof.Constant) {
+            if (this._impostors.length === 0) {
+                return null;
+            }
+
+            for (var i = 0; i < this._impostors.length; ++i) {
+                var impostor = this._impostors[i];
+                var impostorForceAndContactPoint = this.getImpostorForceAndContactPoint(
+                    impostor,
+                    origin,
+                    radius,
+                    strength,
+                    falloff
+                );
+                if (impostorForceAndContactPoint === false) {
+                    continue;
+                }
+
+                impostor.applyImpulse(
+                    impostorForceAndContactPoint.force,
+                    impostorForceAndContactPoint.contactPoint
+                );
+            }
+
+            return null;
+        }
+
+        public applyRadialForce(origin: Vector3, radius: number, strength: number, falloff: PhysicsRadialImpulseFallof = PhysicsRadialImpulseFallof.Constant) {
+            if (this._impostors.length === 0) {
+                return null;
+            }
+
+            for (var i = 0; i < this._impostors.length; ++i) {
+                var impostor = this._impostors[i];
+                var impostorForceAndContactPoint = this.getImpostorForceAndContactPoint(
+                    impostor,
+                    origin,
+                    radius,
+                    strength,
+                    falloff
+                );
+                if (impostorForceAndContactPoint === false) {
+                    continue;
+                }
+
+                impostor.applyForce(
+                    impostorForceAndContactPoint.force,
+                    impostorForceAndContactPoint.contactPoint
+                );
+            }
+
+            return null;
+        }
+
+        private getImpostorForceAndContactPoint(impostor: PhysicsImpostor, origin: Vector3, radius: number, strength: number, falloff: PhysicsRadialImpulseFallof) {
+            if (impostor.mass === 0) {
+                return false;
+            }
+
+            if (!this.intersectsWithRadialSphere(impostor, origin, radius)) {
+                return false;
+            }
+
+            var impostorObject = (<Mesh>impostor.object);
+            var impostorObjectCenter = impostor.getObjectCenter();
+            var direction = impostorObjectCenter.subtract(origin);
+
+            var ray = new Ray(origin, direction, radius);
+            var hit = ray.intersectsMesh(impostorObject);
+
+            var contactPoint = hit.pickedPoint;
+            if (!contactPoint) {
+                return false;
+            }
+
+            var distanceFromOrigin = BABYLON.Vector3.Distance(origin, contactPoint);
+            if (distanceFromOrigin > radius) {
+                return false;
+            }
+            
+            var multiplier = falloff === PhysicsRadialImpulseFallof.Constant
+                ? strength
+                : strength * (1 - (distanceFromOrigin / radius));
+
+            var force = direction.multiplyByFloats(multiplier, multiplier, multiplier);
+
+            return { force: force, contactPoint: contactPoint };
+        }
+
+        private _radialSphere: Mesh;
+        private _prepareRadialSphere(scene: Scene) {
+            if (!this._radialSphere) {
+                this._radialSphere = BABYLON.Mesh.CreateSphere(
+                    "radialSphere",
+                    32,
+                    1,
+                    scene
+                );
+                this._radialSphere.isVisible = false;
+            }
+        }
+
+        private intersectsWithRadialSphere(impostor: PhysicsImpostor, origin: Vector3, radius: number): boolean {
+            var impostorObject = <Mesh>impostor.object;
+
+            this._prepareRadialSphere(impostorObject.getScene());
+
+            this._radialSphere.position = origin;
+            this._radialSphere.scaling = new Vector3(radius * 2, radius * 2, radius * 2);
+            this._radialSphere._updateBoundingInfo();
+            this._radialSphere.computeWorldMatrix(true);
+  
+            if (this._radialSphere.intersectsMesh(
+                impostorObject,
+                true
+            )) {
+                return true;
+            }
+
+            return false;
+        }
+
+        public showRadialSphere(scene: Scene) {
+            this._prepareRadialSphere(scene);
+
+            this._radialSphere.isVisible = true;
+            if (!this._radialSphere.material) {
+                var radialSphereMaterial = new StandardMaterial("radialSphereMaterial", scene);
+                radialSphereMaterial.alpha = 0.5;
+                this._radialSphere.material = radialSphereMaterial;
+            }
+        }
+
+        public hideRadialSphere() {
+            if (this._radialSphere) {
+                this._radialSphere.isVisible = false;
+            }
+        }
     }
 
     export interface IPhysicsEnginePlugin {
@@ -205,4 +344,10 @@
         syncMeshWithImpostor(mesh:AbstractMesh, impostor:PhysicsImpostor): void;
         dispose(): void;
     }
+    
+    export enum PhysicsRadialImpulseFallof {
+        Constant, // impulse is constant in strength across it's whole radius
+        Linear // impulse getgets weaker if it's further from the origin
+    }
+    
 }