{"version":3,"file":"index.mjs","sources":["../src/index.js"],"sourcesContent":["import * as BABYLON from 'babylonjs';\r\n\r\nconst defaultPriorities = {\r\n    avoid: 10,\r\n    queue: 9,\r\n    separation: 7,\r\n    flock: 6,\r\n    flee: 6,\r\n    seek: 5,\r\n    idle: 0\r\n};\r\n\r\nconst defaultProbabilities = {\r\n    avoid: 0.66,\r\n    queue: 0.66,\r\n    separation: 0.66,\r\n    flock: 0.66,\r\n    flee: 0.66,\r\n    seek: 0.66,\r\n    idle: 0.66\r\n};\r\n\r\nexport default class SteeringVehicle {\r\n\r\n    constructor(mesh, engine, options = {}) {\r\n\r\n        this.engine = engine;\r\n        this.mesh = mesh;\r\n        this.mesh.checkCollisions = true;\r\n        this.steeringForce = new BABYLON.Vector3(0, 0, 0);\r\n        this.maxForce = options.maxForce || 1;\r\n        this.velocity = new BABYLON.Vector3(0, 0, 0);\r\n        this.forces = [];\r\n\r\n        this.maxSpeed = options.maxSpeed || 0.2;\r\n        this.mass = options.mass || 1;\r\n\r\n        this.velocitySamples = [];\r\n        this.numSamplesForSmoothing = options.numSamplesForSmoothing || 20;\r\n\r\n        // ARRIVAL\r\n        this.arrivalThreshold = options.arrivalThreshold || 100;\r\n\r\n        // AVOID\r\n        this.avoidDistance = options.avoidDistance || 120;\r\n        this.radius = options.radius || 100;\r\n\r\n        // FOLLOWPATH\r\n        this.waypoints = [];\r\n        this.pathIndex = 0;\r\n\r\n        // WANDER\r\n        this.wanderDistance = options.wanderDistance || 10;\r\n        this.wanderAngle = options.wanderAngle || 10;\r\n        this.wanderRadius = options.wanderRadius || 5;\r\n        this.wanderRange = options.wanderRange || 20;\r\n\r\n        // QUEUE\r\n        this.inSightDistance = options.inSightDistance || 200;\r\n        this.tooCloseDistance = options.tooCloseDistance || 60;\r\n    }\r\n\r\n    get dt() {\r\n        return this.engine.getDeltaTime();\r\n    }\r\n\r\n    set dt(what) {\r\n        this.dt = what;\r\n    }\r\n\r\n    idle(target, configuration = {}) {\r\n        this.velocity.scaleInPlace(0);\r\n        this.steeringForce.setAll(0, 0, 0);\r\n        let action = { force: this.steeringForce, name: this.idle.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n    }\r\n\r\n    lookTarget(target) {\r\n        this.mesh.lookAt(target.mesh.position); // native function\r\n        return this;\r\n    }\r\n\r\n    lookWhereGoing(smoothing) {\r\n        var direction = this.mesh.position.clone().add(this.velocity); // si punta alla somma della velocità e della posizione\r\n        direction.y = this.mesh.position.y;\r\n        if (smoothing) {\r\n            if (this.velocitySamples.length == this.numSamplesForSmoothing) {\r\n                this.velocitySamples.shift();\r\n            }\r\n            let c = this.velocity.clone();\r\n            c.y = this.mesh.position.y\r\n            this.velocitySamples.push(c);\r\n            direction.setAll(0, 0, 0);\r\n            for (var v = 0; v < this.velocitySamples.length; v++) {\r\n                direction.addInPlace(this.velocitySamples[v])\r\n            }\r\n            direction.scaleInPlace(1 / this.velocitySamples.length)\r\n            direction = this.mesh.position.clone().add(direction)\r\n            direction.y = this.mesh.position.y;\r\n        }\r\n        this.mesh.lookAt(direction);\r\n        return this;\r\n    }\r\n\r\n    // se è sullo stesso lato ma non che è visibile...\r\n    // TEST: vedere se new BABYLON.Vector3(0, 0, 1) funziona meglio\r\n    inSight(target) {\r\n        if (BABYLON.Vector3.Distance(this.mesh.position, target.mesh.position) > this.inSightDistance) {\r\n            return false;\r\n        }\r\n        var heading = /* new BABYLON.Vector3(0, 0, 1); //  */target.velocity.clone().normalize().scaleInPlace(1);\r\n        var difference = target.mesh.position.clone().subtract(this.mesh.position.clone());\r\n        var dot = BABYLON.Vector3.Dot(difference, heading);\r\n        // console.log(`Dot:${dot}`)\r\n        return dot < 0 ? false : true;\r\n    }\r\n\r\n    // ACTIVE\r\n    hasInConeOfView(targets) {\r\n        for (let i = 0; i < targets.length; i++) {\r\n            const target = targets[i];\r\n\r\n            let targetPos = target.mesh.position.clone();\r\n            let actorPos = this.mesh.position.clone();\r\n            let distance = BABYLON.Vector3.Distance(targetPos, actorPos);\r\n\r\n            let v0 = this.velocity.clone().normalize();\r\n            let v1 = target.mesh.position.clone().subtract(this.mesh.position.clone());\r\n            v1.normalize();\r\n            let dot = BABYLON.Vector3.Dot(v0, v1)\r\n            let angle = Math.acos(dot);\r\n            let angleInDegree = BABYLON.Tools.ToDegrees(angle);\r\n            // console.log(`Distance: ${distance}`, `Degree: ${angleInDegree}, Dot:${dot}`);\r\n            if (distance < 170 && (angleInDegree < 60)) {\r\n                target.mesh.material.emissiveColor = new BABYLON.Color3(1, 0.5, 0);\r\n            } else {\r\n                target.mesh.material.emissiveColor = target.mesh.color; // TODO: \r\n            }\r\n        }\r\n        return this;\r\n    }\r\n\r\n    // https://forum.babylonjs.com/t/rotation-angle-of-camera-to-object/2603/21\r\n    // PASSIVA\r\n    isInConeOfViewOf(target) {\r\n\r\n        let targetPos = target.mesh.position.clone();\r\n        let actorPos = this.mesh.position.clone();\r\n        let distance = BABYLON.Vector3.Distance(targetPos, actorPos);\r\n\r\n        /* var v0 = new BABYLON.Vector3(0, 0, 1);\r\n        v0 = this.vecToLocal(v0, target);\r\n        v0.normalize(); */\r\n\r\n        let v0 = target.velocity.clone().normalize(); // new BABYLON.Vector3(0, 0, 1);\r\n        // var ray = new BABYLON.Ray(target.mesh.position, v0, 100);\r\n        // let rayHelper = new BABYLON.RayHelper(ray);\r\n        // rayHelper.show(this.mesh.getScene());\r\n\r\n        let v1 = this.mesh.position.clone().subtract(target.mesh.position.clone());\r\n        // var ray2 = new BABYLON.Ray(target.mesh.position, v1, 100);\r\n        // let rayHelper2 = new BABYLON.RayHelper(ray2);\r\n        // rayHelper2.show(this.mesh.getScene());\r\n        v1.normalize();\r\n\r\n        let dot = BABYLON.Vector3.Dot(v0, v1)\r\n        let angle = Math.acos(dot);\r\n        let angleInDegree = BABYLON.Tools.ToDegrees(angle);\r\n        // console.log(`Distance: ${distance}`, `Degree: ${angleInDegree}, Dot:${dot}`);\r\n        if (distance < 170 && (angleInDegree < 60)) {\r\n            this.mesh.material.emissiveColor = new BABYLON.Color3(1, 0.5, 0);\r\n        } else {\r\n            this.mesh.material.emissiveColor = new BABYLON.Color3(0, 0, 1);\r\n        }\r\n        return this;\r\n    }\r\n\r\n    // TODO: convert Three.js clampLength method to BABYLON\r\n    truncate(vector, max) {\r\n        let i = max / vector.length();\r\n        return vector.scaleInPlace(i < 1.0 ? i : 1.0);\r\n    }\r\n\r\n    // si aggiorna in base a sistema di riferimento GLOBALE\r\n    update() {\r\n        this.steeringForce = this.truncate(this.steeringForce, this.maxForce);\r\n        this.steeringForce.scaleInPlace(1 / this.mass);\r\n        this.velocity.addInPlace(this.steeringForce);\r\n        this.velocity = this.truncate(this.velocity, this.maxSpeed* this.dt);\r\n        this.velocity.y = 0;\r\n        this.steeringForce.setAll(0, 0, 0);\r\n        this.mesh.moveWithCollisions(this.velocity);\r\n        this.forces = [];\r\n    }\r\n\r\n    // forza generica...(ES: wind...)\r\n    applyForce(force, configuration = {}) {\r\n        let action = { force: force, name: this.applyForce.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n        return this;\r\n    }\r\n\r\n    // seek with a specific strength\r\n    // PASSIVE\r\n    attract(target, threshold = 0, strenght = 1, configuration = {}) {\r\n        let distance = BABYLON.Vector3.Distance(this.mesh.position, target.mesh.position);\r\n        if (distance < threshold && distance > 20) {\r\n            var desiredVelocity = (this.mesh.position.clone().subtract(target.mesh.position.clone())).normalize().scaleInPlace(this.maxSpeed * this.dt * strenght);\r\n            let action = { force: desiredVelocity.subtractInPlace(target.velocity), name: this.attract.name };\r\n            target.forces.push(Object.assign(configuration, action));\r\n        } else {\r\n            // senza di questo oscilla...\r\n            target.flee(this);\r\n        }\r\n        return this;\r\n    }\r\n\r\n    seek(target, threshold = 0, configuration = {}) {\r\n        let distance = BABYLON.Vector3.Distance(this.mesh.position, target.mesh.position);\r\n        if (distance > threshold) {\r\n            var desiredVelocity = (target.mesh.position.clone().subtract(this.mesh.position.clone())).normalize().scaleInPlace(this.maxSpeed * this.dt);\r\n            let action = { force: desiredVelocity.subtractInPlace(this.velocity), name: this.seek.name };\r\n            this.forces.push(Object.assign(configuration, action));\r\n        } else {\r\n            this.idle(target, configuration);\r\n        }\r\n        return this;\r\n    }\r\n\r\n    seekWithArrive(target, threshold, configuration = {}) {\r\n        var desiredVelocity = target.mesh.position.clone().subtract(this.mesh.position.clone());\r\n        desiredVelocity.normalize()\r\n        var distance = BABYLON.Vector3.Distance(target.mesh.position, this.mesh.position);\r\n        // si procede normalmente\r\n        if (distance > this.arrivalThreshold) {\r\n            desiredVelocity.scaleInPlace(this.maxSpeed * this.dt);\r\n            // si decellera\r\n        } else if (distance > threshold && distance < this.arrivalThreshold) {\r\n            desiredVelocity.scaleInPlace(this.maxSpeed * this.dt * (distance - threshold) / (this.arrivalThreshold - threshold))\r\n            // ci si ferma\r\n        } else {\r\n            this.idle(target, configuration);\r\n        }\r\n        let action = { force: desiredVelocity.subtractInPlace(this.velocity), name: this.seekWithArrive.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n        return this;\r\n    }\r\n\r\n    flee(target, threshold = 0, configuration = {}) {\r\n        let distance = BABYLON.Vector3.Distance(this.mesh.position, target.mesh.position);\r\n        if (distance < threshold) {\r\n            var desiredVelocity = (this.mesh.position.clone().subtract(target.mesh.position.clone())).normalize().scaleInPlace(this.maxSpeed * this.dt);\r\n            let action = { force: desiredVelocity.subtractInPlace(this.velocity), name: this.flee.name };\r\n            this.forces.push(Object.assign(configuration, action));\r\n        } else {\r\n            this.idle(target, configuration);\r\n        }\r\n        return this;\r\n    }\r\n\r\n    arrive(target, configuration = {}) {\r\n        var desiredVelocity = target.mesh.position.clone().subtract(this.mesh.position.clone());\r\n        desiredVelocity.normalize()\r\n        var distance = BABYLON.Vector3.Distance(target.mesh.position, this.mesh.position)\r\n        if (distance > this.arrivalThreshold) {\r\n            desiredVelocity.scaleInPlace(this.maxSpeed * this.dt);\r\n        } else {\r\n            desiredVelocity.scaleInPlace(this.maxSpeed * this.dt * distance / this.arrivalThreshold)\r\n        }\r\n        let action = { force: desiredVelocity.subtractInPlace(this.velocity), name: this.flee.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n        return this;\r\n    }\r\n\r\n    pursue(target, threshold = 0) {\r\n        var lookAheadTime = BABYLON.Vector3.Distance(this.mesh.position, target.mesh.position) / (this.maxSpeed * this.dt);\r\n        var predictedTarget = target.mesh.position.clone().add(target.velocity.clone().scaleInPlace(lookAheadTime));\r\n        this.seek({\r\n            mesh: {\r\n                position: predictedTarget\r\n            }\r\n        }, threshold);\r\n    }\r\n\r\n    evade(target, threshold = 0) {\r\n        var lookAheadTime = BABYLON.Vector3.Distance(this.mesh.position, target.mesh.position) / (this.maxSpeed * this.dt);\r\n        var predictedTarget = target.mesh.position.clone().subtract(target.velocity.clone().scaleInPlace(lookAheadTime));\r\n        this.flee({\r\n            mesh: {\r\n                position: predictedTarget\r\n            }\r\n        }, threshold);\r\n    }\r\n\r\n    // tramite un ray casting si vede se il target è visibile (non ci stanno ostacoli che lo nascondono)\r\n    canSee(target) {\r\n        var forward = target.mesh.position.clone();\r\n        var direction = forward.subtract(this.mesh.position).normalize();\r\n        var length = 350;\r\n        let start = BABYLON.Vector3.Lerp(target.mesh.position.clone(), this.mesh.position.clone(), 0.66);\r\n        var ray = new BABYLON.Ray(start, direction, length);\r\n        // let rayHelper = new BABYLON.RayHelper(ray);\r\n        // rayHelper.show(this.mesh.getScene());\r\n        var hit = target.mesh.getScene().pickWithRay(ray);\r\n        let output = hit.pickedMesh && hit.pickedMesh.uniqueId === target.mesh.uniqueId ? true : false;\r\n        // console.log('Can see: ', output);\r\n        return output;\r\n    }\r\n\r\n    hide(target, obstacles, threshold = 250) {\r\n        if (this.canSee(target)) {\r\n            this.lookTarget(target);\r\n            // si sceglie l'ostacolo più vicino all'elemento da nascondere\r\n            let closestObstacle = new BABYLON.Vector3(0, 0, 0);\r\n            let closestDistance = 10000;\r\n            for (let i = 0; i < obstacles.length; i++) {\r\n                const obstacle = obstacles[i];\r\n                let distance = BABYLON.Vector3.Distance(this.mesh.position, obstacle.mesh.position);\r\n                if (distance < closestDistance) {\r\n                    closestObstacle = obstacle.mesh.position.clone();\r\n                    closestDistance = distance;\r\n                }\r\n            }\r\n            // si calcola il punto dove si andrà a nasconderci\r\n            let distanceWithTarget = BABYLON.Vector3.Distance(this.mesh.position, target.mesh.position);\r\n            var pointToReach = BABYLON.Vector3.Lerp(target.mesh.position.clone(), closestObstacle.clone(), 2);\r\n            pointToReach.y = this.mesh.position.y;\r\n            // ci si nasconde solo se il target non è troppo lontano\r\n            if (distanceWithTarget < threshold) {\r\n                this.seek({\r\n                    mesh: {\r\n                        position: pointToReach\r\n                    }\r\n                }, 10);\r\n            } else {\r\n                this.flee(target)\r\n            }\r\n        } else {\r\n            this.lookWhereGoing(true);\r\n            this.idle();\r\n        }\r\n        return this;\r\n    }\r\n\r\n    // FIXME: NOT WORKING PROPERLY ???\r\n    wander(configuration = {}) {\r\n        var center = this.velocity.clone().normalize().scaleInPlace(this.wanderDistance);\r\n        var offset = new BABYLON.Vector3(1, 1, 1).scaleInPlace(this.wanderRadius);\r\n        offset.x = Math.sin(this.wanderAngle) * offset.length();\r\n        offset.z = - Math.cos(this.wanderAngle) * offset.length();\r\n        offset.y = 0;\r\n        this.wanderAngle = Math.random() * this.wanderRange - this.wanderRange * .5;\r\n        center.addInPlace(offset);\r\n        center.y = this.mesh.position.y;\r\n        let action = { force: center, name: this.wander.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n        return this;\r\n    }\r\n\r\n    separation(entities, separationRadius = 50, maxSeparation = 40, configuration = {}) {\r\n        var force = new BABYLON.Vector3(0, 0, 0);\r\n        var neighborCount = 0\r\n        for (var i = 0; i < entities.length; i++) {\r\n            if (entities[i] != this && BABYLON.Vector3.Distance(this.mesh.position, entities[i].mesh.position) <= separationRadius) {\r\n                force.addInPlace(entities[i].mesh.position.clone().subtractInPlace(this.mesh.position));\r\n                neighborCount++;\r\n            }\r\n        }\r\n        if (neighborCount != 0) {\r\n            force.scaleInPlace(1 / neighborCount)\r\n            force.negateInPlace();\r\n        }\r\n        force.normalize().scaleInPlace(maxSeparation);\r\n        let action = { force: force, name: this.separation.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n        return this;\r\n    }\r\n\r\n    interpose(targetA, targetB) {\r\n        var midPoint = targetA.mesh.position.clone().addInPlace(targetB.mesh.position.clone()).scaleInPlace(.5);\r\n        var timeToMidPoint = BABYLON.Vector3.Distance(this.mesh.position, midPoint) / (this.maxSpeed * this.dt);\r\n        var pointA = targetA.mesh.position.clone().addInPlace(targetA.velocity.clone().scaleInPlace(timeToMidPoint))\r\n        var pointB = targetB.mesh.position.clone().addInPlace(targetB.velocity.clone().scaleInPlace(timeToMidPoint))\r\n        midPoint = pointA.addInPlace(pointB).scaleInPlace(.5);\r\n        this.seek({\r\n            mesh: {\r\n                position: midPoint\r\n            }\r\n        }, 10);\r\n    }\r\n\r\n    avoid(obstacles, configuration = {}) {\r\n        var dynamic_length = this.velocity.length() / (this.maxSpeed * this.dt);\r\n        var ahead = this.mesh.position.clone().addInPlace(this.velocity.clone().normalize().scaleInPlace(dynamic_length))\r\n        var ahead2 = this.mesh.position.clone().addInPlace(this.velocity.clone().normalize().scaleInPlace(this.avoidDistance * .5));\r\n        var mostThreatening = null;\r\n        for (var i = 0; i < obstacles.length; i++) {\r\n            if (obstacles[i] === this)\r\n                continue;\r\n            var collision = BABYLON.Vector3.Distance(obstacles[i].mesh.position, ahead) <= this.radius || BABYLON.Vector3.Distance(obstacles[i].mesh.position, ahead2) <= this.radius;\r\n            if (collision && (mostThreatening == null || BABYLON.Vector3.Distance(this.mesh.position, obstacles[i].mesh.position) < BABYLON.Vector3.Distance(this.mesh.position, mostThreatening.mesh.position))) {\r\n                mostThreatening = obstacles[i];\r\n            }\r\n        }\r\n        var avoidance = new BABYLON.Vector3(0, 0, 0);\r\n        if (mostThreatening != null) {\r\n            avoidance = ahead.clone().subtractInPlace(mostThreatening.mesh.position.clone()).normalize().scaleInPlace(this.maxSpeed * this.dt * .75); // MAX AVOID FORCE (<= maxSpeed)\r\n        } else {\r\n            avoidance.scaleInPlace(0); // nullify the avoidance force\r\n        }\r\n        let action = { force: avoidance, name: this.avoid.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n        return this;\r\n    }\r\n\r\n    followPath(path, loop, thresholdRadius = 10) {\r\n        var wayPoint = path[this.pathIndex]\r\n        if (wayPoint == null)\r\n            return;\r\n        if (BABYLON.Vector3.Distance(this.mesh.position, wayPoint) < thresholdRadius) {\r\n            if (this.pathIndex >= path.length - 1) {\r\n                if (loop)\r\n                    this.pathIndex = 0;\r\n            } else {\r\n                this.pathIndex++\r\n            }\r\n        }\r\n        if (this.pathIndex >= path.length - 1 && !loop) {\r\n            this.arrive({\r\n                mesh: {\r\n                    position: wayPoint\r\n                }\r\n            });\r\n        } else {\r\n            this.seek({\r\n                mesh: {\r\n                    position: wayPoint\r\n                }\r\n            });\r\n        }\r\n    }\r\n\r\n    isOnLeaderSight(leader, ahead, leaderSightRadius) {\r\n        return (BABYLON.Vector3.Distance(ahead, this.mesh.position) <= leaderSightRadius ||\r\n            BABYLON.Vector3.Distance(leader.mesh.position, this.mesh.position) <= leaderSightRadius);\r\n    }\r\n\r\n    followLeader(leader, entities, distance = 20, separationRadius = 40, maxSeparation = 10, leaderSightRadius = 50, arrivalThreshold = 100) {\r\n        var tv = leader.velocity.clone();\r\n        tv.normalize().scaleInPlace(distance)\r\n        var ahead = leader.mesh.position.clone().add(tv);\r\n        tv.negateInPlace()\r\n        var behind = leader.mesh.position.clone().add(tv);\r\n\r\n        if (this.isOnLeaderSight(leader, ahead, leaderSightRadius)) {\r\n            this.flee(leader);\r\n        }\r\n        this.arrivalThreshold = arrivalThreshold;\r\n        this.arrive({\r\n            mesh: {\r\n                position: behind\r\n            }\r\n        });\r\n        this.separation(entities, separationRadius, maxSeparation);\r\n        return this;\r\n    }\r\n\r\n    getNeighborAhead(entities) {\r\n        var maxQueueAhead = 100;\r\n        var maxQueueRadius = 100;\r\n        var res;\r\n        var qa = this.velocity.clone().normalize().scaleInPlace(maxQueueAhead);\r\n        var ahead = this.mesh.position.clone().add(qa);\r\n        for (var i = 0; i < entities.length; i++) {\r\n            var distance = BABYLON.Vector3.Distance(ahead, entities[i].mesh.position);\r\n            if (entities[i] != this && distance <= maxQueueRadius) {\r\n                res = entities[i]\r\n                break;\r\n            }\r\n        }\r\n        return res;\r\n    }\r\n\r\n    queue(entities, maxQueueRadius = 50, configuration = {}) {\r\n        var neighbor = this.getNeighborAhead(entities);\r\n        var brake = new BABYLON.Vector3(0, 0, 0);\r\n        var v = this.velocity.clone()\r\n        if (neighbor != null) {\r\n            brake = this.steeringForce.clone().negateInPlace().scaleInPlace(0.8);\r\n            v.negateInPlace().normalize();\r\n            brake.add(v)\r\n            if (BABYLON.Vector3.Distance(this.mesh.position, neighbor.mesh.position) <= maxQueueRadius) {\r\n                this.velocity.scaleInPlace(0.3)\r\n            }\r\n        }\r\n        let action = { force: brake, name: this.queue.name };\r\n        this.forces.push(Object.assign(configuration, action));\r\n        return this;\r\n    }\r\n\r\n    // NOT WORKING !!!\r\n    flock(entities, configuration = {}) {\r\n        var averageVelocity = this.velocity.clone();\r\n        var averagePosition = new BABYLON.Vector3(0, 0, 0);\r\n        var inSightCount = 0;\r\n        for (var i = 0; i < entities.length; i++) {\r\n            if (entities[i] != this && this.inSight(entities[i])) {\r\n                averageVelocity.add(entities[i].velocity)\r\n                averagePosition.add(entities[i].mesh.position)\r\n                if (BABYLON.Vector3.Distance(this.mesh.position, entities[i].mesh.position) < this.tooCloseDistance) {\r\n                    this.flee(entities[i] /* .mesh.position */);\r\n                }\r\n                inSightCount++;\r\n            }\r\n        }\r\n        if (inSightCount > 0) {\r\n            averageVelocity.scaleInPlace(1 / inSightCount);\r\n            averagePosition.scaleInPlace(1 / inSightCount);\r\n            this.seek({\r\n                mesh: {\r\n                    position: averagePosition\r\n                }\r\n            });\r\n            let action = { force: averageVelocity.subtractInPlace(this.velocity), name: this.flock.name };\r\n            this.forces.push(Object.assign(configuration, action));\r\n        }\r\n        return this;\r\n    }\r\n\r\n    sortByPriority(arr) {\r\n        return arr.sort(function (a, b) {\r\n            return (b.priority || defaultPriorities[b.name]) - (a.priority || defaultPriorities[a.name]);\r\n        });\r\n    }\r\n\r\n    animate(mode) {\r\n        if (mode === \"blend\") {\r\n            this.forces.forEach(a => {\r\n                this.steeringForce = this.steeringForce.add(a.force).scaleInPlace(a.weigth || 0.5);\r\n            });\r\n        } else if (mode === \"priority\") {\r\n            // order for priority\r\n            this.forces = this.sortByPriority(this.forces);\r\n            let output = this.forces[0].force;\r\n            this.steeringForce = this.steeringForce.add(output);\r\n        } else if (mode === \"probability\") {\r\n            let output = new BABYLON.Vector3(0, 0, 0);\r\n            this.forces = this.sortByPriority(this.forces);\r\n            for (let i = 0; i < this.forces.length; i++) {\r\n                let ele = this.forces[i];\r\n                if ((ele.probability || defaultProbabilities[ele.name]) > Math.random()) {\r\n                    output = ele.force;\r\n                    break;\r\n                }\r\n            }\r\n            this.steeringForce = this.steeringForce.add(output);\r\n        } else if (mode === \"truncated\") {\r\n            this.forces = this.sortByPriority(this.forces);\r\n            for (let i = 0; i < this.forces.length; i++) {\r\n                let ele = this.forces[i];\r\n                this.steeringForce = this.steeringForce.add(ele.force).scaleInPlace(ele.weigth || 0.5);\r\n                if (this.steeringForce.length() > 0.005) {\r\n                    break;\r\n                }\r\n            }\r\n        } else {\r\n            this.forces.forEach(a => {\r\n                this.steeringForce = this.steeringForce.add(a.force)\r\n            });\r\n        }\r\n        this.update();\r\n    }\r\n\r\n}\r\n"],"names":["const","defaultPriorities","avoid","queue","separation","flock","flee","seek","idle","defaultProbabilities","SteeringVehicle","constructor","mesh","engine","options","checkCollisions","steeringForce","BABYLON","maxForce","velocity","forces","maxSpeed","mass","velocitySamples","numSamplesForSmoothing","arrivalThreshold","avoidDistance","radius","waypoints","pathIndex","wanderDistance","wanderAngle","wanderRadius","wanderRange","inSightDistance","tooCloseDistance","dt","this","getDeltaTime","what","target","configuration","scaleInPlace","setAll","push","Object","assign","force","name","lookTarget","lookAt","position","lookWhereGoing","smoothing","direction","clone","add","y","length","shift","c","v","addInPlace","inSight","Distance","heading","normalize","difference","subtract","Dot","hasInConeOfView","targets","let","i","targetPos","actorPos","distance","v0","v1","dot","angle","Math","acos","angleInDegree","ToDegrees","material","emissiveColor","color","isInConeOfViewOf","truncate","vector","max","update","moveWithCollisions","applyForce","attract","threshold","strenght","action","subtractInPlace","seekWithArrive","desiredVelocity","arrive","pursue","lookAheadTime","predictedTarget","evade","canSee","start","Lerp","ray","hit","getScene","pickWithRay","pickedMesh","uniqueId","hide","obstacles","closestObstacle","closestDistance","obstacle","distanceWithTarget","pointToReach","wander","center","offset","x","sin","z","cos","random","entities","separationRadius","maxSeparation","neighborCount","negateInPlace","interpose","targetA","targetB","midPoint","timeToMidPoint","pointA","pointB","dynamic_length","ahead","ahead2","mostThreatening","avoidance","followPath","path","loop","thresholdRadius","wayPoint","isOnLeaderSight","leader","leaderSightRadius","followLeader","tv","behind","getNeighborAhead","res","qa","maxQueueRadius","neighbor","brake","averageVelocity","averagePosition","inSightCount","sortByPriority","arr","sort","a","b","priority","animate","mode","forEach","weigth","output","ele","probability"],"mappings":"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"}