mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 20:34:07 +02:00
overlay fish
This commit is contained in:
parent
b10592b98d
commit
f745a3f06d
3 changed files with 167 additions and 2 deletions
|
@ -0,0 +1,166 @@
|
|||
//
|
||||
// entityLocalFish.js
|
||||
// examples
|
||||
//
|
||||
// Philip Rosedale
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Fish smimming around in a space in front of you
|
||||
// These fish are overlays, meaning they can only be seen by you.
|
||||
// Attach this entity script to an object to create fish that stay within the
|
||||
// dimensions of the object.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
(function(){
|
||||
|
||||
var NUM_FISH = 25;
|
||||
var FISH_SCALE = 0.45;
|
||||
var MAX_SIGHT_DISTANCE = 0.5;
|
||||
var MIN_SEPARATION = 0.08;
|
||||
var AVOIDANCE_FORCE = 0.05;
|
||||
var COHESION_FORCE = 0.025;
|
||||
var ALIGNMENT_FORCE = 0.025;
|
||||
var SWIMMING_FORCE = 0.025;
|
||||
var SWIMMING_SPEED = 0.5;
|
||||
var VELOCITY_FOLLOW_RATE = 0.25;
|
||||
var FISH_MODEL_URL = "http://hifi-content.s3.amazonaws.com/DomainContent/Home/fishTank/goodfish5.fbx";
|
||||
|
||||
var fishLoaded = false;
|
||||
var fish = [];
|
||||
|
||||
var lowerCorner = { x: 0, y: 0, z: 0 };
|
||||
var upperCorner = { x: 0, y: 0, z: 0 };
|
||||
|
||||
var entityID;
|
||||
|
||||
function update(deltaTime) {
|
||||
|
||||
var averageVelocity = { x: 0, y: 0, z: 0 };
|
||||
var averagePosition = { x: 0, y: 0, z: 0 };
|
||||
|
||||
for (var i = 0; i < fish.length; i++) {
|
||||
|
||||
// Update position by velocity
|
||||
fish[i].position = Vec3.sum(fish[i].position, Vec3.multiply(deltaTime, fish[i].velocity));
|
||||
|
||||
averageVelocity = { x: 0, y: 0, z: 0 };
|
||||
averagePosition = { x: 0, y: 0, z: 0 };
|
||||
|
||||
var othersCounted = 0;
|
||||
for (var j = 0; j < fish.length; j++) {
|
||||
if (i != j) {
|
||||
// Get only the properties we need, because that is faster
|
||||
var separation = Vec3.distance(fish[i].position, fish[j].position);
|
||||
if (separation < MAX_SIGHT_DISTANCE) {
|
||||
averageVelocity = Vec3.sum(averageVelocity, fish[j].velocity);
|
||||
averagePosition = Vec3.sum(averagePosition, fish[j].position);
|
||||
othersCounted++;
|
||||
}
|
||||
if (separation < MIN_SEPARATION) {
|
||||
// Separation: Push away if you are too close to someone else
|
||||
var pushAway = Vec3.multiply(Vec3.normalize(Vec3.subtract(fish[i].position, fish[j].position)), AVOIDANCE_FORCE);
|
||||
fish[i].velocity = Vec3.sum(fish[i].velocity, pushAway);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (othersCounted > 0) {
|
||||
averageVelocity = Vec3.multiply(averageVelocity, 1.0 / othersCounted);
|
||||
averagePosition = Vec3.multiply(averagePosition, 1.0 / othersCounted);
|
||||
// Alignment: Follow group's direction and speed
|
||||
fish[i].velocity = Vec3.mix(fish[i].velocity, Vec3.multiply(Vec3.normalize(averageVelocity), Vec3.length(fish[i].velocity)), ALIGNMENT_FORCE);
|
||||
// Cohesion: Steer towards center of flock
|
||||
var towardCenter = Vec3.subtract(averagePosition, fish[i].position);
|
||||
fish[i].velocity = Vec3.mix(fish[i].velocity, Vec3.multiply(Vec3.normalize(towardCenter), Vec3.length(fish[i].velocity)), COHESION_FORCE);
|
||||
}
|
||||
|
||||
// Try to swim at a constant speed
|
||||
fish[i].velocity = Vec3.mix(fish[i].velocity, Vec3.multiply(Vec3.normalize(fish[i].velocity), SWIMMING_SPEED), SWIMMING_FORCE);
|
||||
|
||||
// Keep fish in their 'tank'
|
||||
if (fish[i].position.x < lowerCorner.x) {
|
||||
fish[i].position.x = lowerCorner.x;
|
||||
fish[i].velocity.x *= -1.0;
|
||||
} else if (fish[i].position.x > upperCorner.x) {
|
||||
fish[i].position.x = upperCorner.x;
|
||||
fish[i].velocity.x *= -1.0;
|
||||
}
|
||||
if (fish[i].position.y < lowerCorner.y) {
|
||||
fish[i].position.y = lowerCorner.y;
|
||||
fish[i].velocity.y *= -1.0;
|
||||
} else if (fish[i].position.y > upperCorner.y) {
|
||||
fish[i].position.y = upperCorner.y;
|
||||
fish[i].velocity.y *= -1.0;
|
||||
}
|
||||
if (fish[i].position.z < lowerCorner.z) {
|
||||
fish[i].position.z = lowerCorner.z;
|
||||
fish[i].velocity.z *= -1.0;
|
||||
} else if (fish[i].position.z > upperCorner.z) {
|
||||
fish[i].position.z = upperCorner.z;
|
||||
fish[i].velocity.z *= -1.0;
|
||||
}
|
||||
|
||||
// Orient in direction of velocity
|
||||
var rotation = Quat.rotationBetween(Vec3.UNIT_NEG_Z, fish[i].velocity);
|
||||
fish[i].rotation = Quat.slerp(fish[i].rotation, rotation, VELOCITY_FOLLOW_RATE);
|
||||
|
||||
// Update the actual 3D overlay
|
||||
Overlays.editOverlay(fish[i].overlayID, { position: fish[i].position,
|
||||
velocity: fish[i].velocity,
|
||||
rotation: fish[i].rotation });
|
||||
}
|
||||
}
|
||||
|
||||
function randomVector(scale) {
|
||||
return { x: Math.random() * scale - scale / 2.0, y: Math.random() * scale - scale / 2.0, z: Math.random() * scale - scale / 2.0 };
|
||||
}
|
||||
|
||||
function loadFish(entityID, howMany) {
|
||||
var STARTING_FRACTION = 0.25;
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
lowerCorner = { x: properties.position.x - properties.dimensions.x / 2,
|
||||
y: properties.position.y - properties.dimensions.y / 2,
|
||||
z: properties.position.z - properties.dimensions.z / 2 };
|
||||
upperCorner = { x: properties.position.x + properties.dimensions.x / 2,
|
||||
y: properties.position.y + properties.dimensions.y / 2,
|
||||
z: properties.position.z + properties.dimensions.z / 2 };
|
||||
|
||||
for (var i = 0; i < howMany; i++) {
|
||||
var position = {
|
||||
x: lowerCorner.x + (upperCorner.x - lowerCorner.x) / 2.0 + (Math.random() - 0.5) * (upperCorner.x - lowerCorner.x) * STARTING_FRACTION,
|
||||
y: lowerCorner.y + (upperCorner.y - lowerCorner.y) / 2.0 + (Math.random() - 0.5) * (upperCorner.y - lowerCorner.y) * STARTING_FRACTION,
|
||||
z: lowerCorner.z + (upperCorner.z - lowerCorner.x) / 2.0 + (Math.random() - 0.5) * (upperCorner.z - lowerCorner.z) * STARTING_FRACTION
|
||||
};
|
||||
var rotation = { x: 0, y: 0, z: 0, w: 1 };
|
||||
fish.push({
|
||||
overlayID: Overlays.addOverlay("model", {
|
||||
url: FISH_MODEL_URL,
|
||||
position: position,
|
||||
rotation: rotation,
|
||||
scale: FISH_SCALE,
|
||||
visible: true }),
|
||||
position: position,
|
||||
rotation: rotation,
|
||||
velocity: randomVector(SWIMMING_SPEED)
|
||||
});
|
||||
}
|
||||
print("Fish loaded");
|
||||
}
|
||||
|
||||
this.preload = function(entityID) {
|
||||
print("Fish Preload v3");
|
||||
loadFish(entityID, NUM_FISH);
|
||||
fishLoaded = true;
|
||||
Script.update.connect(update);
|
||||
|
||||
};
|
||||
|
||||
this.unload = function() {
|
||||
Script.update.disconnect(update);
|
||||
print("Fish Unload");
|
||||
for (var i = 0; i < fish.length; i++) {
|
||||
Overlays.deleteOverlay(fish[i].overlayID);
|
||||
}
|
||||
};
|
||||
})
|
|
@ -11,6 +11,6 @@
|
|||
z: 0
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function(){
|
||||
Script.scriptEnding.connect(function() {
|
||||
fishtank.cleanup()
|
||||
})
|
|
@ -22,7 +22,6 @@ FishTank = function(spawnPosition, spawnRotation) {
|
|||
z: 2.1404
|
||||
};
|
||||
|
||||
|
||||
var INNER_TANK_SCALE = 0.7;
|
||||
var INNER_TANK_DIMENSIONS = Vec3.multiply(INNER_TANK_SCALE, TANK_DIMENSIONS);
|
||||
INNER_TANK_DIMENSIONS.y = INNER_TANK_DIMENSIONS.y - 0.4;
|
||||
|
|
Loading…
Reference in a new issue