Merge upstream/master' into shapes branch

This commit is contained in:
Andrew Meadows 2014-03-06 12:45:43 -08:00
commit 868e92c0fa
74 changed files with 815 additions and 272 deletions

View file

@ -8,15 +8,11 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
find_package(Qt5Network REQUIRED)
find_package(Qt5Script REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5 COMPONENTS Network Script Widgets)
include("${MACRO_DIR}/SetupHifiProject.cmake")
setup_hifi_project(${TARGET_NAME} TRUE)
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
# include glm
include("${MACRO_DIR}/IncludeGLM.cmake")
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -40,3 +36,5 @@ endif (UNIX)
IF (WIN32)
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
ENDIF(WIN32)
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script)

View file

@ -36,11 +36,8 @@ public:
public slots:
void run();
void readPendingDatagrams();
signals:
void willSendAudioDataCallback();
void willSendVisualDataCallback();
private:
ScriptEngine _scriptEngine;
VoxelEditPacketSender _voxelEditSender;

View file

@ -18,8 +18,6 @@ include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE)
qt5_use_modules(${TARGET_NAME} Network)
# remove and then copy the files for the webserver
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E remove_directory
@ -36,4 +34,6 @@ link_hifi_library(embedded-webserver ${TARGET_NAME} "${ROOT_DIR}")
IF (WIN32)
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
ENDIF(WIN32)
ENDIF(WIN32)
target_link_libraries(${TARGET_NAME} Qt5::Network)

View file

@ -114,7 +114,7 @@ function sendNextCells() {
var sentFirstBoard = false;
function step() {
function step(deltaTime) {
if (sentFirstBoard) {
// we've already sent the first full board, perform a step in time
updateCells();
@ -127,5 +127,5 @@ function step() {
}
Script.willSendVisualDataCallback.connect(step);
Script.update.connect(step);
Voxels.setPacketsPerSecond(200);

View file

@ -18,7 +18,7 @@ var FACTOR = 0.75;
var countParticles = 0; // the first time around we want to create the particle and thereafter to modify it.
var particleID;
function updateParticle() {
function updateParticle(deltaTime) {
// the particle should be placed in front of the user's avatar
var avatarFront = Quat.getFront(MyAvatar.orientation);
@ -62,7 +62,7 @@ function updateParticle() {
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(updateParticle);
Script.update.connect(updateParticle);
// register our scriptEnding callback
Script.scriptEnding.connect(function scriptEnding() {});

View file

@ -18,6 +18,10 @@ function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function printVector(string, vector) {
print(string + " " + vector.x + ", " + vector.y + ", " + vector.z);
}
var CHANCE_OF_MOVING = 0.005;
var CHANCE_OF_SOUND = 0.005;
var CHANCE_OF_HEAD_TURNING = 0.05;
@ -31,6 +35,7 @@ var X_MIN = 0.0;
var X_MAX = 5.0;
var Z_MIN = 0.0;
var Z_MAX = 5.0;
var Y_PELVIS = 2.5;
var MOVE_RANGE_SMALL = 0.5;
var MOVE_RANGE_BIG = Math.max(X_MAX - X_MIN, Z_MAX - Z_MIN) / 2.0;
@ -41,7 +46,7 @@ var TURN_RATE = 0.15;
var PITCH_RATE = 0.20;
var PITCH_RANGE = 30.0;
var firstPosition = { x: getRandomFloat(X_MIN, X_MAX), y: 0, z: getRandomFloat(Z_MIN, Z_MAX) };
var firstPosition = { x: getRandomFloat(X_MIN, X_MAX), y: Y_PELVIS, z: getRandomFloat(Z_MIN, Z_MAX) };
var targetPosition = { x: 0, y: 0, z: 0 };
var targetDirection = { x: 0, y: 0, z: 0, w: 0 };
var currentDirection = { x: 0, y: 0, z: 0, w: 0 };
@ -72,9 +77,6 @@ function playRandomSound(position) {
}
}
// change the avatar's position to the random one
Avatar.position = firstPosition;
// pick an integer between 1 and 20 for the face model for this bot
botNumber = getRandomInt(1, 100);
@ -103,7 +105,11 @@ Avatar.billboardURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/me
Agent.isAvatar = true;
function updateBehavior() {
// change the avatar's position to the random one
Avatar.position = firstPosition;
printVector("New bot, position = ", Avatar.position);
function updateBehavior(deltaTime) {
if (Math.random() < CHANCE_OF_SOUND) {
playRandomSound(Avatar.position);
}
@ -132,6 +138,7 @@ function updateBehavior() {
}
targetPosition.x = clamp(targetPosition.x, X_MIN, X_MAX);
targetPosition.z = clamp(targetPosition.z, Z_MIN, Z_MAX);
targetPosition.y = Y_PELVIS;
isMoving = true;
} else {
@ -142,7 +149,7 @@ function updateBehavior() {
}
}
}
Script.willSendVisualDataCallback.connect(updateBehavior);
Script.update.connect(updateBehavior);
function loadSounds() {
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail+Party+Snippets/Raws/AB1.raw"));

View file

@ -20,9 +20,8 @@ var joysticksCaptured = false;
var THRUST_CONTROLLER = 0;
var VIEW_CONTROLLER = 1;
function checkCamera() {
function checkCamera(deltaTime) {
if (Camera.getMode() == "independent") {
var deltaTime = 1/60; // approximately our FPS - maybe better to be elapsed time since last call
var THRUST_MAG_UP = 800.0;
var THRUST_MAG_DOWN = 300.0;
var THRUST_MAG_FWD = 500.0;
@ -80,7 +79,7 @@ function checkCamera() {
}
}
Script.willSendVisualDataCallback.connect(checkCamera);
Script.update.connect(checkCamera);
function mouseMoveEvent(event) {
print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y);

View file

@ -28,7 +28,7 @@ var clapping = new Array();
clapping[0] = false;
clapping[1] = false;
function maybePlaySound() {
function maybePlaySound(deltaTime) {
// Set the location and other info for the sound to play
var palm1Position = Controller.getSpatialControlPosition(0);
var palm2Position = Controller.getSpatialControlPosition(2);
@ -62,4 +62,4 @@ function maybePlaySound() {
}
// Connect a call back that happens every frame
Script.willSendVisualDataCallback.connect(maybePlaySound);
Script.update.connect(maybePlaySound);

View file

@ -30,8 +30,9 @@ var gravity = {
var damping = 0.1;
var scriptA = " " +
" function collisionWithParticle(other) { " +
" function collisionWithParticle(other, penetration) { " +
" print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " +
" Vec3.print('penetration=', penetration); " +
" print('myID=' + Particle.getID() + '\\n'); " +
" var colorBlack = { red: 0, green: 0, blue: 0 };" +
" var otherColor = other.getColor();" +
@ -45,8 +46,9 @@ var scriptA = " " +
" ";
var scriptB = " " +
" function collisionWithParticle(other) { " +
" function collisionWithParticle(other, penetration) { " +
" print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " +
" Vec3.print('penetration=', penetration); " +
" print('myID=' + Particle.getID() + '\\n'); " +
" Particle.setScript('Particle.setShouldDie(true);'); " +
" } " +
@ -58,7 +60,7 @@ var color = {
green: 255,
blue: 0 };
function draw() {
function draw(deltaTime) {
print("hello... draw()... currentIteration=" + currentIteration + "\n");
// on the first iteration, setup a single particle that's slowly moving
@ -150,5 +152,5 @@ function draw() {
// register the call back so it fires before each data send
print("here...\n");
Particles.setPacketsPerSecond(40000);
Script.willSendVisualDataCallback.connect(draw);
Script.update.connect(draw);
print("and here...\n");

View file

@ -16,7 +16,7 @@ for (t = 0; t < numberOfTriggers; t++) {
triggerPulled[t] = false;
}
function checkController() {
function checkController(deltaTime) {
var numberOfTriggers = Controller.getNumberOfTriggers();
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers;
@ -48,7 +48,7 @@ function checkController() {
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(checkController);
Script.update.connect(checkController);
function printKeyEvent(eventName, event) {
print(eventName);

View file

@ -10,8 +10,8 @@
var count = 0;
function displayCount() {
print("count =" + count);
function displayCount(deltaTime) {
print("count =" + count + " deltaTime=" + deltaTime);
count++;
}
@ -20,7 +20,7 @@ function scriptEnding() {
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(displayCount);
Script.update.connect(displayCount);
// register our scriptEnding callback
Script.scriptEnding.connect(scriptEnding);

View file

@ -31,7 +31,7 @@ var strokeSpeed = new Array();
strokeSpeed[0] = 0.0;
strokeSpeed[1] = 0.0;
function checkSticks() {
function checkSticks(deltaTime) {
for (var palm = 0; palm < 2; palm++) {
var palmVelocity = Controller.getSpatialControlVelocity(palm * 2 + 1);
var speed = length(palmVelocity);
@ -69,4 +69,4 @@ function checkSticks() {
}
// Connect a call back that happens every frame
Script.willSendVisualDataCallback.connect(checkSticks);
Script.update.connect(checkSticks);

View file

@ -42,7 +42,7 @@ var positionDelta = { x: 0.05, y: 0, z: 0 };
var particleID = Particles.addParticle(originalProperties);
function moveParticle() {
function moveParticle(deltaTime) {
if (count >= moveUntil) {
// delete it...
@ -85,5 +85,5 @@ function moveParticle() {
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(moveParticle);
Script.update.connect(moveParticle);

View file

@ -920,7 +920,7 @@ function keyPressEvent(event) {
red: colors[color].red,
green: colors[color].green,
blue: colors[color].blue };
Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s);
Voxels.eraseVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s);
Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue);
setAudioPosition();
playRandomAddSound(audioOptions);
@ -1329,7 +1329,7 @@ function checkControllers() {
}
}
function update() {
function update(deltaTime) {
var newWindowDimensions = Controller.getViewportDimensions();
if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) {
windowDimensions = newWindowDimensions;
@ -1399,6 +1399,6 @@ function scriptEnding() {
}
Script.scriptEnding.connect(scriptEnding);
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
setupMenus();

View file

@ -60,7 +60,7 @@ function printProperties(properties) {
}
}
function findParticles() {
function findParticles(deltaTime) {
// run for a while, then clean up
// stop it...
@ -122,7 +122,7 @@ function findParticles() {
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(findParticles);
Script.update.connect(findParticles);
// register our scriptEnding callback
Script.scriptEnding.connect(scriptEnding);

464
examples/flockingBirds.js Normal file
View file

@ -0,0 +1,464 @@
//
// flockingBirds.js
// hifi
//
// Created by Brad Hefta-Gaub on 3/4/14.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
// This is an example script that generates particles that act like flocking birds
//
// All birds, even flying solo...
// birds don't like to fall too fast
// if they fall to fast, they will go into a state of thrusting up, until they reach some max upward velocity, then
// go back to gliding
// birds don't like to be below a certain altitude
// if they are below that altitude they will keep thrusting up, until they get ove
// flocking
// try to align your velocity with velocity of other birds
// try to fly toward center of flock
// but dont get too close
//
var birdsInFlock = 40;
var birdLifetime = 60; // 2 minutes
var count=0; // iterations
var enableFlyTowardPoints = true; // some birds have a point they want to fly to
var enabledClustedFlyTowardPoints = true; // the flyToward points will be generally near each other
var flyToFrames = 10; // number of frames the bird would like to attempt to fly to it's flyTo point
var PROBABILITY_OF_FLY_TOWARD_CHANGE = 0.01; // chance the bird will decide to change its flyTo point
var PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD = 0.2; // chance the bird will decide to flyTo, otherwise it follows
var flyingToCount = 0; // count of birds currently flying to someplace
var flyToCluster = { }; // the point that the cluster of flyTo points is based on when in enabledClustedFlyTowardPoints
// Bird behaviors
var enableAvoidDropping = true; // birds will resist falling too fast, and will thrust up if falling
var enableAvoidMinHeight = true; // birds will resist being below a certain height and thrust up to get above it
var enableAvoidMaxHeight = true; // birds will resist being above a certain height and will glide to get below it
var enableMatchFlockVelocity = true; // birds will thrust to match the flocks average velocity
var enableThrustTowardCenter = true; // birds will thrust to try to move toward the center of the flock
var enableAvoidOtherBirds = true; // birds will thrust away from all other birds
var startWithVelocity = true;
var flockGravity = { x: 0, y: -1, z: 0};
// NOTE: these two features don't seem to be very interesting, they cause odd behaviors
var enableRandomXZThrust = false; // leading birds randomly decide to thrust in some random direction.
var enableSomeBirdsLead = false; // birds randomly decide not fly toward flock, causing other birds to follow
var leaders = 0; // number of birds leading
var PROBABILITY_TO_LEAD = 0.1; // probabolity a bird will choose to lead
var birds = new Array(); // array of bird state data
var flockStartPosition = { x: 100, y: 10, z: 100};
var flockStartVelocity = { x: 0, y: 0, z: 0};
var flockStartThrust = { x: 0, y: 0, z: 0}; // slightly upward against gravity
var INITIAL_XY_VELOCITY_SCALE = 2;
var birdRadius = 0.0625;
var baseBirdColor = { red: 0, green: 255, blue: 255 };
var glidingColor = { red: 255, green: 0, blue: 0 };
var thrustUpwardColor = { red: 0, green: 255, blue: 0 };
var thrustXYColor = { red: 128, green: 0, blue: 128 }; // will be added to any other color
var leadingOrflyToColor = { red: 200, green: 200, blue: 255 };
var tooClose = birdRadius * 3; // how close birds are willing to be to each other
var droppingTooFast = -1; // birds don't like to fall too fast
var risingTooFast = 1; // birds don't like to climb too fast
var upwardThrustAgainstGravity = -10; // how hard a bird will attempt to thrust up to avoid downward motion
var droppingAdjustFrames = 5; // birds try to correct their min height in only a couple frames
var minHeight = 10; // meters off the ground
var maxHeight = 50; // meters off the ground
var adjustFrames = 10; // typical number of frames a bird will assume for it's adjustments
var PROBABILITY_OF_RANDOM_XZ_THRUST = 0.25;
var RANDOM_XZ_THRUST_SCALE = 5; // random -SCALE...to...+SCALE in X or Z direction
var MAX_XY_VELOCITY = 10;
// These are multiplied by every frame since a change. so after 50 frames, there's a 50% probability of change
var PROBABILITY_OF_STARTING_XZ_THRUST = 0.0025;
var PROBABILITY_OF_STOPPING_XZ_THRUST = 0.01;
var FLY_TOWARD_XZ_DISTANCE = 100;
var FLY_TOWARD_Y_DISTANCE = 0;
var FLY_TOWARD_XZ_CLUSTER_DELTA = 5;
var FLY_TOWARD_Y_CLUSTER_DELTA = 0;
function createBirds() {
if (enabledClustedFlyTowardPoints) {
flyToCluster = { x: flockStartPosition.x + Math.random() * FLY_TOWARD_XZ_DISTANCE,
y: flockStartPosition.y + Math.random() * FLY_TOWARD_Y_DISTANCE,
z: flockStartPosition.z + Math.random() * FLY_TOWARD_XZ_DISTANCE};
}
for(var i =0; i < birdsInFlock; i++) {
var velocity;
position = Vec3.sum(flockStartPosition, { x: Math.random(), y: Math.random(), z: Math.random() }); // add random
var flyingToward = position;
var isFlyingToward = false;
if (enableFlyTowardPoints) {
if (Math.random() < PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD) {
flyingToCount++;
isFlyingToward = true;
if (enabledClustedFlyTowardPoints) {
flyingToward = { x: flyToCluster.x + Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA,
y: flyToCluster.y + Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA,
z: flyToCluster.z + Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA};
} else {
flyingToward = { x: flockStartPosition.x + Math.random() * FLY_TOWARD_XZ_DISTANCE,
y: flockStartPosition.y + Math.random() * FLY_TOWARD_Y_DISTANCE,
z: flockStartPosition.z + Math.random() * FLY_TOWARD_XZ_DISTANCE};
}
}
Vec3.print("birds["+i+"].flyingToward=",flyingToward);
}
birds[i] = {
particle: {},
properties: {},
thrust: Vec3.sum(flockStartThrust, { x:0, y: 0, z: 0 }),
gliding: true,
xzThrust: { x:0, y: 0, z: 0},
xzthrustCount: 0,
isLeading: false,
flyingToward: flyingToward,
isFlyingToward: isFlyingToward,
};
if (enableSomeBirdsLead) {
if (Math.random() < PROBABILITY_TO_LEAD) {
birds[i].isLeading = true;
}
if (leaders == 0 && i == (birdsInFlock-1)) {
birds[i].isLeading = true;
}
if (birds[i].isLeading) {
leaders++;
velocity = { x: 2, y: 0, z: 2};
print(">>>>>>THIS BIRD LEADS!!!! i="+i);
}
}
if (startWithVelocity) {
velocity = Vec3.sum(flockStartVelocity, { x: (Math.random() * INITIAL_XY_VELOCITY_SCALE),
y: 0,
z: (Math.random() * INITIAL_XY_VELOCITY_SCALE) }); // add random
} else {
velocity = { x: 0, y: 0, z: 0};
}
birds[i].particle = Particles.addParticle({
position: position,
velocity: velocity,
gravity: flockGravity,
damping: 0,
radius: birdRadius,
color: baseBirdColor,
lifetime: birdLifetime
});
}
print("flyingToCount=" + flyingToCount);
}
var wantDebug = false;
function updateBirds(deltaTime) {
count++;
// get all our bird properties, and calculate the current flock velocity
var averageVelocity = { x: 0, y: 0, z: 0};
var averagePosition = { x: 0, y: 0, z: 0};
var knownBirds = 0;
for(var i =0; i < birdsInFlock; i++) {
// identifyParticle() will check to see that the particle handle we have is in sync with the domain/server
// context. If the handle is for a created particle that now has a known ID it will be updated to be a
// handle with a known ID.
birds[i].particle = Particles.identifyParticle(birds[i].particle);
if (birds[i].particle.isKnownID) {
birds[i].properties = Particles.getParticleProperties(birds[i].particle);
if (birds[i].properties.isKnownID) {
knownBirds++;
averageVelocity = Vec3.sum(averageVelocity, birds[i].properties.velocity);
averagePosition = Vec3.sum(averagePosition, birds[i].properties.position);
}
}
}
if (knownBirds == 0 && count > 100) {
Script.stop();
return;
}
averageVelocity = Vec3.multiply(averageVelocity, (1 / Math.max(1, knownBirds)));
averagePosition = Vec3.multiply(averagePosition, (1 / Math.max(1, knownBirds)));
if (wantDebug) {
Vec3.print("averagePosition=",averagePosition);
Vec3.print("averageVelocity=",averageVelocity);
print("knownBirds="+knownBirds);
}
var flyToClusterChanged = false;
if (enabledClustedFlyTowardPoints) {
if (Math.random() < PROBABILITY_OF_FLY_TOWARD_CHANGE) {
flyToClusterChanged = true;
flyToCluster = { x: averagePosition.x + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2,
y: averagePosition.y + (Math.random() * FLY_TOWARD_Y_DISTANCE) - FLY_TOWARD_Y_DISTANCE/2,
z: averagePosition.z + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2};
}
}
// iterate all birds again, adjust their thrust for various goals
for(var i =0; i < birdsInFlock; i++) {
birds[i].thrust = { x: 0, y: 0, z: 0 }; // assume no thrust...
if (birds[i].particle.isKnownID) {
if (enableFlyTowardPoints) {
// if we're flying toward clusters, and the cluster changed, and this bird is flyingToward
// then we need to update it's flyingToward
if (enabledClustedFlyTowardPoints && flyToClusterChanged && birds[i].isFlyingToward) {
flyingToward = { x: flyToCluster.x + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2,
y: flyToCluster.y + (Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA) - FLY_TOWARD_Y_CLUSTER_DELTA/2,
z: flyToCluster.z + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2};
birds[i].flyingToward = flyingToward;
}
// there a random chance this bird will decide to change it's flying toward state
if (Math.random() < PROBABILITY_OF_FLY_TOWARD_CHANGE) {
var wasFlyingTo = birds[i].isFlyingToward;
// there's some chance it will decide it should be flying toward
if (Math.random() < PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD) {
// if we're flying toward clustered points, then we randomize from the cluster, otherwise we pick
// completely random places based on flocks current averagePosition
if (enabledClustedFlyTowardPoints) {
flyingToward = { x: flyToCluster.x + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2,
y: flyToCluster.y + (Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA) - FLY_TOWARD_Y_CLUSTER_DELTA/2,
z: flyToCluster.z + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2};
} else {
flyingToward = { x: averagePosition.x + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2,
y: averagePosition.y + (Math.random() * FLY_TOWARD_Y_DISTANCE) - FLY_TOWARD_Y_DISTANCE/2,
z: averagePosition.z + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2};
}
birds[i].flyingToward = flyingToward;
birds[i].isFlyingToward = true;
} else {
birds[i].flyingToward = {};
birds[i].isFlyingToward = false;
}
// keep track of our bookkeeping
if (!wasFlyingTo && birds[i].isFlyingToward) {
flyingToCount++;
}
if (wasFlyingTo && !birds[i].isFlyingToward) {
flyingToCount--;
}
print(">>>> CHANGING flyingToCount="+flyingToCount);
if (birds[i].isFlyingToward) {
Vec3.print("... now birds["+i+"].flyingToward=", birds[i].flyingToward);
}
}
// actually apply the thrust after all that
if (birds[i].isFlyingToward) {
var flyTowardDelta = Vec3.subtract(birds[i].flyingToward, birds[i].properties.position);
var thrustTowardFlyTo = Vec3.multiply(flyTowardDelta, 1/flyToFrames);
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustTowardFlyTo);
}
}
// adjust thrust to avoid dropping to fast
if (enableAvoidDropping) {
if (birds[i].gliding) {
if (birds[i].properties.velocity.y < droppingTooFast) {
birds[i].gliding = false; // leave thrusting against gravity till it gets too high
//print("birdGliding["+i+"]=false <<<< try to conteract gravity <<<<<<<<<<<<<<<<<<<<");
}
}
}
// if the bird is currently not gliding, check to see if it's rising too fast
if (!birds[i].gliding && birds[i].properties.velocity.y > risingTooFast) {
//Vec3.print("bird rising too fast will glide bird["+i+"]=",birds[i].properties.velocity.y);
birds[i].gliding = true;
}
// adjust thrust to avoid minHeight, we don't care about rising too fast in this case, so we do it
// after the rising too fast check
if (enableAvoidMinHeight) {
if (birds[i].properties.position.y < minHeight) {
//Vec3.print("**** enableAvoidMinHeight... enable thrust against gravity... bird["+i+"].position=",birds[i].properties.position);
birds[i].gliding = false;
}
}
// adjust thrust to avoid maxHeight
if (enableAvoidMaxHeight) {
if (birds[i].properties.position.y > maxHeight) {
//Vec3.print("********************* bird above max height will glide bird["+i+"].position=",birds[i].properties.position);
birds[i].gliding = true;
}
}
// if the bird is currently not gliding, then it is applying a thrust upward against gravity
if (!birds[i].gliding) {
// as long as we're not rising too fast, keep thrusting...
if (birds[i].properties.velocity.y < risingTooFast) {
var thrustAdjust = {x: 0, y: (flockGravity.y * upwardThrustAgainstGravity), z: 0};
//Vec3.print("bird fighting gravity thrustAdjust for bird["+i+"]=",thrustAdjust);
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustAdjust);
} else {
//print("%%% non-gliding bird, thrusting too much...");
}
}
if (enableRandomXZThrust && birds[i].isLeading) {
birds[i].xzThrustCount++;
// we will randomly decide to enable XY thrust, in which case we will set the thrust and leave it
// that way till we randomly shut it off.
// if we don't have a thrust, check against probability of starting it, and create a random thrust if
// probability occurs
if (Vec3.length(birds[i].xzThrust) == 0) {
var probabilityToStart = (PROBABILITY_OF_STARTING_XZ_THRUST * birds[i].xzThrustCount);
//print("probabilityToStart=" + probabilityToStart);
if (Math.random() < probabilityToStart) {
var xThrust = (Math.random() * (RANDOM_XZ_THRUST_SCALE * 2)) - RANDOM_XZ_THRUST_SCALE;
var zThrust = (Math.random() * (RANDOM_XZ_THRUST_SCALE * 2)) - RANDOM_XZ_THRUST_SCALE;
birds[i].xzThrust = { x: zThrust, y: 0, z: zThrust };
birds[i].xzThrustCount = 0;
//Vec3.print(">>>>>>>>>> STARTING XY THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
}
}
// if we're thrusting... then check for probability of stopping
if (Vec3.length(birds[i].xzThrust)) {
var probabilityToStop = (PROBABILITY_OF_STOPPING_XZ_THRUST * birds[i].xzThrustCount);
//print("probabilityToStop=" + probabilityToStop);
if (Math.random() < probabilityToStop) {
birds[i].xzThrust = { x: 0, y: 0, z: 0};
//Vec3.print(">>>>>>>>>> STOPPING XY THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
birds[i].xzThrustCount = 0;
}
if (birds[i].properties.velocity.x > MAX_XY_VELOCITY) {
birds[i].xzThrust.x = 0;
//Vec3.print(">>>>>>>>>> CLEARING X THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
}
if (birds[i].properties.velocity.z > MAX_XY_VELOCITY) {
birds[i].xzThrust.z = 0;
//Vec3.print(">>>>>>>>>> CLEARING Y THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
}
if (Vec3.length(birds[i].xzThrust)) {
birds[i].thrust = Vec3.sum(birds[i].thrust, birds[i].xzThrust);
}
}
}
// adjust thrust to move their velocity toward average flock velocity
if (enableMatchFlockVelocity) {
if (birds[i].isLeading) {
print("this bird is leading... i="+i);
} else {
var velocityDelta = Vec3.subtract(averageVelocity, birds[i].properties.velocity);
var thrustAdjust = velocityDelta;
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustAdjust);
}
}
// adjust thrust to move their velocity toward average flock position
if (enableThrustTowardCenter) {
if (birds[i].isLeading) {
print("this bird is leading... i="+i);
} else {
var positionDelta = Vec3.subtract(averagePosition, birds[i].properties.position);
var thrustTowardCenter = Vec3.multiply(positionDelta, 1/adjustFrames);
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustTowardCenter);
}
}
// adjust thrust to avoid other birds
if (enableAvoidOtherBirds) {
var sumThrustThisBird = { x: 0, y: 0, z: 0 };
for(var j =0; j < birdsInFlock; j++) {
// if this is not me, and a known bird, then check our position
if (birds[i].properties.isKnownID && j != i) {
var positionMe = birds[i].properties.position;
var positionYou = birds[j].properties.position;
var awayFromYou = Vec3.subtract(positionMe, positionYou); // vector pointing away from "you"
var distance = Vec3.length(awayFromYou);
if (distance < tooClose) {
// NOTE: this was Philip's recommendation for "avoiding" other birds...
// Vme -= Vec3.multiply(Vme, normalize(PositionMe - PositionYou))
//
// But it doesn't seem to work... Here's my JS implementation...
//
// var velocityMe = birds[i].properties.velocity;
// var thrustAdjust = Vec3.cross(velocityMe, Vec3.normalize(awayFromYou));
// sumThrustThisBird = Vec3.sum(sumThrustThisBird, thrustAdjust);
//
// Instead I just apply a thrust equal to the vector away from all the birds
sumThrustThisBird = Vec3.sum(sumThrustThisBird, awayFromYou);
}
}
}
birds[i].thrust = Vec3.sum(birds[i].thrust, sumThrustThisBird);
}
}
}
// iterate all birds again, apply their thrust
for(var i =0; i < birdsInFlock; i++) {
if (birds[i].particle.isKnownID) {
var color;
if (birds[i].gliding) {
color = glidingColor;
} else {
color = thrustUpwardColor;
}
if (Vec3.length(birds[i].xzThrust)) {
color = Vec3.sum(color, thrustXYColor);
}
var velocityMe = birds[i].properties.velocity;
// add thrust to velocity
var newVelocity = Vec3.sum(velocityMe, Vec3.multiply(birds[i].thrust, deltaTime));
if (birds[i].isLeading || birds[i].isFlyingToward) {
Vec3.print("this bird is leading/flying toward... i="+i+" velocity=",newVelocity);
color = leadingOrflyToColor;
}
if (wantDebug) {
Vec3.print("birds["+i+"].position=", birds[i].properties.position);
Vec3.print("birds["+i+"].oldVelocity=", velocityMe);
Vec3.print("birdThrusts["+i+"]=", birds[i].thrust);
Vec3.print("birds["+i+"].newVelocity=", newVelocity);
}
birds[i].particle = Particles.editParticle(birds[i].particle,{ velocity: newVelocity, color: color });
}
}
}
createBirds();
// register the call back for simulation loop
Script.update.connect(updateBirds);

View file

@ -41,7 +41,7 @@ var position = { x: 5.0, y: 0.6, z: 5.0 };
Voxels.setVoxel(position.x, 0, position.z, 0.5, 0, 0, 255);
var totalParticles = 0;
function makeFountain() {
function makeFountain(deltaTime) {
if (Math.random() < 0.10) {
//print("Made particle!\n");
var properties = {
@ -64,4 +64,4 @@ function makeFountain() {
}
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(makeFountain);
Script.update.connect(makeFountain);

View file

@ -114,7 +114,7 @@ function sendNextCells() {
var sentFirstBoard = false;
function step() {
function step(deltaTime) {
if (sentFirstBoard) {
// we've already sent the first full board, perform a step in time
updateCells();
@ -127,6 +127,6 @@ function step() {
}
print("here");
Script.willSendVisualDataCallback.connect(step);
Script.update.connect(step);
Voxels.setPacketsPerSecond(200);
print("now here");

View file

@ -10,17 +10,23 @@
//
function particleCollisionWithVoxel(particle, voxel) {
print("hello...");
function particleCollisionWithVoxel(particle, voxel, penetration) {
print("particleCollisionWithVoxel()..");
print(" particle.getID()=" + particle.id);
print(" voxel color...=" + voxel.red + ", " + voxel.green + ", " + voxel.blue);
Vec3.print('penetration=', penetration);
}
function particleCollisionWithParticle(particleA, particleB) {
function particleCollisionWithParticle(particleA, particleB, penetration) {
print("particleCollisionWithParticle()..");
print(" particleA.getID()=" + particleA.id);
print(" particleB.getID()=" + particleB.id);
Vec3.print('penetration=', penetration);
}
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle);
print("here... hello...");

View file

@ -57,12 +57,13 @@ function shootBullet(position, velocity) {
damping: 0 });
// Play firing sounds
audioOptions.position = position;
audioOptions.position = position;
Audio.playSound(fireSound, audioOptions);
}
function particleCollisionWithVoxel(particle, voxel) {
var HOLE_SIZE = 0.25;
function particleCollisionWithVoxel(particle, voxel, penetration) {
Vec3.print('particleCollisionWithVoxel() ... penetration=', penetration);
var HOLE_SIZE = 0.125;
var particleProperties = Particles.getParticleProperties(particle);
var position = particleProperties.position;
Particles.deleteParticle(particle);
@ -73,7 +74,7 @@ function particleCollisionWithVoxel(particle, voxel) {
Audio.playSound(impactSound, audioOptions);
}
function update() {
function update(deltaTime) {
// Check for mouseLook movement, update rotation
// rotate body yaw for yaw received from mouse
@ -178,7 +179,7 @@ function scriptEnding() {
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
Script.scriptEnding.connect(scriptEnding);
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);

View file

@ -29,7 +29,6 @@ var grabbingWithLeftHand = false;
var wasGrabbingWithLeftHand = false;
var EPSILON = 0.000001;
var velocity = { x: 0, y: 0, z: 0};
var deltaTime = 1/60; // approximately our FPS - maybe better to be elapsed time since last call
var THRUST_MAG_UP = 800.0;
var THRUST_MAG_DOWN = 300.0;
var THRUST_MAG_FWD = 500.0;
@ -77,7 +76,7 @@ function getAndResetGrabRotation() {
}
// handles all the grab related behavior: position (crawl), velocity (flick), and rotate (twist)
function handleGrabBehavior() {
function handleGrabBehavior(deltaTime) {
// check for and handle grab behaviors
grabbingWithRightHand = Controller.isButtonPressed(RIGHT_BUTTON_4);
grabbingWithLeftHand = Controller.isButtonPressed(LEFT_BUTTON_4);
@ -156,7 +155,7 @@ function handleGrabBehavior() {
}
// Main update function that handles flying and grabbing behaviort
function flyWithHydra() {
function flyWithHydra(deltaTime) {
var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER);
if (thrustJoystickPosition.x != 0 || thrustJoystickPosition.y != 0) {
@ -193,10 +192,10 @@ function flyWithHydra() {
var newPitch = MyAvatar.headPitch + (viewJoystickPosition.y * JOYSTICK_PITCH_MAG * deltaTime);
MyAvatar.headPitch = newPitch;
}
handleGrabBehavior();
handleGrabBehavior(deltaTime);
}
Script.willSendVisualDataCallback.connect(flyWithHydra);
Script.update.connect(flyWithHydra);
Controller.captureJoystick(THRUST_CONTROLLER);
Controller.captureJoystick(VIEW_CONTROLLER);

View file

@ -45,13 +45,13 @@ function releaseMovementKeys() {
}
var cameraPosition = Camera.getPosition();
function moveCamera() {
function moveCamera(update) {
if (lookingAtSomething) {
Camera.setPosition(cameraPosition);
}
}
Script.willSendVisualDataCallback.connect(moveCamera);
Script.update.connect(moveCamera);
function mousePressEvent(event) {

View file

@ -49,7 +49,7 @@ function mouseMoveEvent(event) {
}
}
function update() {
function update(deltaTime) {
if (wantDebugging) {
print("update()...");
}
@ -91,5 +91,5 @@ MyAvatar.bodyPitch = 0;
MyAvatar.bodyRoll = 0;
// would be nice to change to update
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
Script.scriptEnding.connect(scriptEnding);

View file

@ -43,7 +43,7 @@ function touchUpdateEvent(event) {
lastY = event.y;
}
function update() {
function update(deltaTime) {
// rotate body yaw for yaw received from mouse
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMouse, z: 0 } ));
if (wantDebugging) {
@ -82,5 +82,5 @@ MyAvatar.bodyPitch = 0;
MyAvatar.bodyRoll = 0;
// would be nice to change to update
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
Script.scriptEnding.connect(scriptEnding);

View file

@ -12,7 +12,7 @@ var colorEdge = { r:255, g:250, b:175 };
var frame = 0;
var thisColor = color;
function moveVoxel() {
function moveVoxel(deltaTime) {
frame++;
if (frame % 3 == 0) {
// Get a new position
@ -41,4 +41,4 @@ function moveVoxel() {
Voxels.setPacketsPerSecond(300);
// Connect a call back that happens every frame
Script.willSendVisualDataCallback.connect(moveVoxel);
Script.update.connect(moveVoxel);

View file

@ -90,7 +90,7 @@ Controller.touchEndEvent.connect(touchEndEvent);
function update() {
function update(deltaTime) {
// rotate body yaw for yaw received from multitouch rotate
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMultiTouch, z: 0 } ));
if (wantDebugging) {
@ -110,7 +110,7 @@ function update() {
MyAvatar.headPitch = newPitch;
pitchFromMultiTouch = 0;
}
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
function scriptEnding() {

View file

@ -186,7 +186,7 @@ var toolAVisible = false;
var count = 0;
// Our update() function is called at approximately 60fps, and we will use it to animate our various overlays
function update() {
function update(deltaTime) {
count++;
// every second or so, toggle the visibility our our blinking tool
@ -226,7 +226,7 @@ function update() {
// update our 3D line to go from origin to our avatar's position
Overlays.editOverlay(line3d, { end: MyAvatar.position } );
}
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
// The slider is handled in the mouse event callbacks.

View file

@ -13,7 +13,7 @@ for (t = 0; t < numberOfTriggers; t++) {
triggerPulled[t] = false;
}
function checkController() {
function checkController(deltaTime) {
var numberOfTriggers = Controller.getNumberOfTriggers();
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers;
@ -62,8 +62,9 @@ function checkController() {
// This is the script for the particles that this gun shoots.
var script =
" function collisionWithVoxel(voxel) { " +
" function collisionWithVoxel(voxel, penetration) { " +
" print('collisionWithVoxel(voxel)... '); " +
" Vec3.print('penetration=', penetration); " +
" print('myID=' + Particle.getID() + '\\n'); " +
" var voxelColor = { red: voxel.red, green: voxel.green, blue: voxel.blue };" +
" var voxelAt = { x: voxel.x, y: voxel.y, z: voxel.z };" +
@ -93,4 +94,4 @@ function checkController() {
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(checkController);
Script.update.connect(checkController);

View file

@ -99,7 +99,7 @@ var properties = {
var range = 1.0; // Distance around avatar where I can move
// Create the actual bird
var particleID = Particles.addParticle(properties);
function moveBird() {
function moveBird(deltaTime) {
// check to see if we've been running long enough that our bird is dead
var nowTimeInSeconds = new Date().getTime() / 1000;
@ -194,4 +194,4 @@ function moveBird() {
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(moveBird);
Script.update.connect(moveBird);

View file

@ -47,7 +47,7 @@ var modelAParticleID = Particles.addParticle(modelPropertiesA);
var modelBParticleID = Particles.addParticle(modelPropertiesB);
var ballParticleID = Particles.addParticle(ballProperties);
function endAfterAWhile() {
function endAfterAWhile(deltaTime) {
// stop it...
if (count >= stopAfter) {
print("calling Script.stop()");
@ -60,5 +60,5 @@ function endAfterAWhile() {
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(endAfterAWhile);
Script.update.connect(endAfterAWhile);

View file

@ -5,7 +5,7 @@
// First, load the clap sound from a URL
var clap = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw");
function maybePlaySound() {
function maybePlaySound(deltaTime) {
if (Math.random() < 0.01) {
// Set the location and other info for the sound to play
var options = new AudioInjectionOptions();
@ -17,4 +17,4 @@ function maybePlaySound() {
}
// Connect a call back that happens every frame
Script.willSendVisualDataCallback.connect(maybePlaySound);
Script.update.connect(maybePlaySound);

View file

@ -122,7 +122,7 @@ var velocity;
var hueAngle = 0;
var smoothedOffset;
function step() {
function step(deltaTime) {
if (stateHistory.length === 0) {
// start at a random position within the bounds, with a random velocity
position = randomVector(BOUNDS_MIN, BOUNDS_MAX);
@ -170,4 +170,4 @@ function step() {
hueAngle = (hueAngle + 1) % MAX_HUE_ANGLE;
}
Script.willSendVisualDataCallback.connect(step);
Script.update.connect(step);

View file

@ -22,7 +22,7 @@ var particleA = Particles.addParticle(
lifetime: (lengthOfRide * 60) + 1
});
function rideWithParticle() {
function rideWithParticle(deltaTime) {
if (iteration <= lengthOfRide) {
@ -46,5 +46,5 @@ function rideWithParticle() {
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(rideWithParticle);
Script.update.connect(rideWithParticle);

View file

@ -31,7 +31,7 @@ function init() {
}
}
function keepLooking() {
function keepLooking(deltaTime) {
//print("count =" + count);
if (count == 0) {
@ -63,7 +63,7 @@ function scriptEnding() {
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(keepLooking);
Script.update.connect(keepLooking);
// register our scriptEnding callback
Script.scriptEnding.connect(scriptEnding);

View file

@ -207,7 +207,7 @@ function displayGameOver() {
print("Game over...");
}
function update() {
function update(deltaTime) {
if (!gameOver) {
//print("updating space invaders... iteration="+iteration);
iteration++;
@ -257,7 +257,7 @@ function update() {
}
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
function cleanupGame() {
print("cleaning up game...");
@ -392,8 +392,9 @@ function deleteIfInvader(possibleInvaderParticle) {
}
}
function particleCollisionWithParticle(particleA, particleB) {
function particleCollisionWithParticle(particleA, particleB, penetration) {
print("particleCollisionWithParticle() a.id="+particleA.id + " b.id=" + particleB.id);
Vec3.print('particleCollisionWithParticle() penetration=', penetration);
if (missileFired) {
myMissile = Particles.identifyParticle(myMissile);
if (myMissile.id == particleA.id) {

View file

@ -208,7 +208,7 @@ function checkControllerSide(whichSide) {
}
function checkController() {
function checkController(deltaTime) {
var numberOfButtons = Controller.getNumberOfButtons();
var numberOfTriggers = Controller.getNumberOfTriggers();
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
@ -226,4 +226,4 @@ function checkController() {
// register the call back so it fires before each data send
Script.willSendVisualDataCallback.connect(checkController);
Script.update.connect(checkController);

View file

@ -73,7 +73,7 @@ var moved = true;
var CHANCE_OF_MOVING = 0.05;
var CHANCE_OF_TWEETING = 0.05;
function moveBird() {
function moveBird(deltaTime) {
frame++;
if (frame % 3 == 0) {
// Tweeting behavior
@ -130,4 +130,4 @@ function moveBird() {
Voxels.setPacketsPerSecond(10000);
// Connect a call back that happens every frame
Script.willSendVisualDataCallback.connect(moveBird);
Script.update.connect(moveBird);

View file

@ -70,14 +70,13 @@ function clamp(valueToClamp, minValue, maxValue) {
return Math.max(minValue, Math.min(maxValue, valueToClamp));
}
function produceCollisionSound(palm, voxelDetail) {
function produceCollisionSound(deltaTime, palm, voxelDetail) {
// Collision between finger and a voxel plays sound
var palmVelocity = Controller.getSpatialControlVelocity(palm * 2);
var speed = Vec3.length(palmVelocity);
var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1);
var deltaTime = 1/60; //close enough
var LOWEST_FREQUENCY = 100.0;
var HERTZ_PER_RGB = 3.0;
var DECAY_PER_SAMPLE = 0.0005;
@ -97,9 +96,7 @@ function produceCollisionSound(palm, voxelDetail) {
Audio.startDrumSound(volume, frequency, DURATION_MAX, DECAY_PER_SAMPLE, audioOptions);
}
function update() {
var deltaTime = 1/60; //close enough
function update(deltaTime) {
// Voxel Drumming with fingertips if enabled
if (Menu.isOptionChecked("Voxel Drumming")) {
@ -111,7 +108,7 @@ function update() {
if (!isColliding[palm]) {
// Collision has just started
isColliding[palm] = true;
produceCollisionSound(palm, voxel);
produceCollisionSound(deltaTime, palm, voxel);
// Set highlight voxel
Overlays.editOverlay(highlightVoxel,
@ -156,7 +153,7 @@ function update() {
} // palm loop
} // menu item check
}
Script.willSendVisualDataCallback.connect(update);
Script.update.connect(update);
function scriptEnding() {
Overlays.deleteOverlay(highlightVoxel);

View file

@ -75,15 +75,7 @@ foreach(EXTERNAL_SOURCE_SUBDIR ${EXTERNAL_SOURCE_SUBDIRS})
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
endforeach(EXTERNAL_SOURCE_SUBDIR)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Multimedia REQUIRED)
find_package(Qt5Network REQUIRED)
find_package(Qt5OpenGL REQUIRED)
find_package(Qt5Svg REQUIRED)
find_package(Qt5WebKit REQUIRED)
find_package(Qt5WebKitWidgets REQUIRED)
find_package(Qt5Xml REQUIRED)
find_package(Qt5 COMPONENTS Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
# grab the ui files in resources/ui
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
@ -180,8 +172,6 @@ if (LIBOVR_FOUND AND NOT DISABLE_LIBOVR)
target_link_libraries(${TARGET_NAME} "${LIBOVR_LIBRARIES}")
endif (LIBOVR_FOUND AND NOT DISABLE_LIBOVR)
qt5_use_modules(${TARGET_NAME} Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
# include headers for interface and InterfaceConfig.
include_directories(
"${PROJECT_SOURCE_DIR}/src"
@ -200,6 +190,8 @@ target_link_libraries(
${TARGET_NAME}
"${FACESHIFT_LIBRARIES}"
"${ZLIB_LIBRARIES}"
Qt5::Core Qt5::Gui Qt5::Multimedia Qt5::Network Qt5::OpenGL
Qt5::Script Qt5::Svg Qt5::WebKit Qt5::WebKitWidgets Qt5::Xml Qt5::UiTools
)
if (APPLE)

View file

@ -110,9 +110,11 @@ const QString CUSTOM_URL_SCHEME = "hifi:";
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
if (message.size() > 0) {
QString messageWithNewLine = message + "\n";
fprintf(stdout, "%s", messageWithNewLine.toLocal8Bit().constData());
Application::getInstance()->getLogger()->addMessage(messageWithNewLine.toLocal8Bit().constData());
QString dateString = QDateTime::currentDateTime().toTimeSpec(Qt::LocalTime).toString(Qt::ISODate);
QString formattedMessage = QString("[%1] %2\n").arg(dateString).arg(message);
fprintf(stdout, "%s", qPrintable(formattedMessage));
Application::getInstance()->getLogger()->addMessage(qPrintable(formattedMessage));
}
}
@ -402,17 +404,17 @@ void Application::initializeGL() {
// initialize glut for shape drawing; Qt apparently initializes it on OS X
#ifndef __APPLE__
int argc = 0;
glutInit(&argc, 0);
#endif
#ifdef WIN32
static bool isInitialized = false;
if (isInitialized) {
return;
} else {
isInitialized = true;
}
int argc = 0;
glutInit(&argc, 0);
#endif
#ifdef WIN32
GLenum err = glewInit();
if (GLEW_OK != err) {
/* Problem: glewInit failed, something is seriously wrong. */
@ -1560,14 +1562,14 @@ void Application::init() {
// connect the _particleCollisionSystem to our script engine's ParticleScriptingInterface
connect(&_particleCollisionSystem,
SIGNAL(particleCollisionWithVoxel(const ParticleID&, const VoxelDetail&)),
SIGNAL(particleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&)),
ScriptEngine::getParticlesScriptingInterface(),
SLOT(forwardParticleCollisionWithVoxel(const ParticleID&, const VoxelDetail&)));
SLOT(forwardParticleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&)));
connect(&_particleCollisionSystem,
SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&)),
SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&)),
ScriptEngine::getParticlesScriptingInterface(),
SLOT(forwardParticleCollisionWithParticle(const ParticleID&, const ParticleID&)));
SLOT(forwardParticleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&)));
_pieMenu.init("./resources/images/hifi-interface-tools-v2-pie.svg",
_glWidget->width(),
@ -2381,8 +2383,8 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE_SPECULAR_COLOR);
}
bool forceRenderMyHead = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
_avatarManager.renderAvatars(forceRenderMyHead, selfAvatarOnly);
bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
_avatarManager.renderAvatars(mirrorMode, selfAvatarOnly);
if (!selfAvatarOnly) {
// Render the world box
@ -3479,7 +3481,6 @@ void Application::cleanupScriptMenuItem(const QString& scriptMenuName) {
}
void Application::loadScript(const QString& fileNameString) {
_activeScripts.append(fileNameString);
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
const char* fileName = fileNameAscii.data();
@ -3489,6 +3490,7 @@ void Application::loadScript(const QString& fileNameString) {
return;
}
qDebug("Loading file %s...", fileName);
_activeScripts.append(fileNameString);
// get file length....
unsigned long fileLength = file.tellg();

View file

@ -201,7 +201,7 @@ static TextRenderer* textRenderer(TextRendererType type) {
return displayNameRenderer;
}
void Avatar::render() {
void Avatar::render(bool forShadowMap) {
glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition();
float lengthToTarget = glm::length(toTarget);
@ -209,7 +209,7 @@ void Avatar::render() {
// glow when moving in the distance
const float GLOW_DISTANCE = 5.0f;
Glower glower(_moving && lengthToTarget > GLOW_DISTANCE ? 1.0f : 0.0f);
Glower glower(_moving && lengthToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f);
// render body
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
@ -233,7 +233,7 @@ void Avatar::render() {
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
if ((sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
if (!forShadowMap && (sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE);
glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z);
@ -243,7 +243,10 @@ void Avatar::render() {
}
}
const float DISPLAYNAME_DISTANCE = 10.0f;
setShowDisplayName(lengthToTarget < DISPLAYNAME_DISTANCE);
setShowDisplayName(!forShadowMap && lengthToTarget < DISPLAYNAME_DISTANCE);
if (forShadowMap) {
return;
}
renderDisplayName();
if (!_chatMessage.empty()) {

View file

@ -74,7 +74,7 @@ public:
void init();
void simulate(float deltaTime);
void render();
void render(bool forShadowMap = false);
//setters
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }

View file

@ -69,7 +69,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
simulateAvatarFades(deltaTime);
}
void AvatarManager::renderAvatars(bool forceRenderMyHead, bool selfAvatarOnly) {
void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly) {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::renderAvatars()");
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors);
@ -83,16 +83,16 @@ void AvatarManager::renderAvatars(bool forceRenderMyHead, bool selfAvatarOnly) {
avatar->init();
}
if (avatar == static_cast<Avatar*>(_myAvatar.data())) {
_myAvatar->render(forceRenderMyHead);
_myAvatar->render(forShadowMapOrMirror);
} else {
avatar->render();
avatar->render(forShadowMapOrMirror);
}
avatar->setDisplayingLookatVectors(renderLookAtVectors);
}
renderAvatarFades();
renderAvatarFades(forShadowMapOrMirror);
} else {
// just render myAvatar
_myAvatar->render(forceRenderMyHead, true);
_myAvatar->render(forShadowMapOrMirror);
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
}
}
@ -115,13 +115,13 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
}
}
void AvatarManager::renderAvatarFades() {
void AvatarManager::renderAvatarFades(bool forShadowMap) {
// render avatar fades
Glower glower;
Glower glower(forShadowMap ? 0.0f : 1.0f);
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
avatar->render();
avatar->render(forShadowMap);
}
}

View file

@ -29,7 +29,7 @@ public:
MyAvatar* getMyAvatar() { return _myAvatar.data(); }
void updateOtherAvatars(float deltaTime);
void renderAvatars(bool forceRenderMyHead, bool selfAvatarOnly = false);
void renderAvatars(bool forShadowMapOrMirror = false, bool selfAvatarOnly = false);
void clearOtherAvatars();
@ -45,7 +45,7 @@ private:
void processKillAvatar(const QByteArray& datagram);
void simulateAvatarFades(float deltaTime);
void renderAvatarFades();
void renderAvatarFades(bool forShadowMap);
// virtual override
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);

View file

@ -456,14 +456,14 @@ void MyAvatar::renderDebugBodyPoints() {
}
void MyAvatar::render(bool forceRenderHead, bool avatarOnly) {
void MyAvatar::render(bool forShadowMapOrMirror) {
// don't render if we've been asked to disable local rendering
if (!_shouldRender) {
return; // exit early
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
renderBody(forceRenderHead);
renderBody(forShadowMapOrMirror);
}
// render body
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
@ -472,8 +472,8 @@ void MyAvatar::render(bool forceRenderHead, bool avatarOnly) {
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) {
getHead()->getFaceModel().renderCollisionProxies(0.8f);
}
setShowDisplayName(!avatarOnly);
if (avatarOnly) {
setShowDisplayName(!forShadowMapOrMirror);
if (forShadowMapOrMirror) {
return;
}
renderDisplayName();

View file

@ -35,7 +35,7 @@ public:
void simulate(float deltaTime);
void updateFromGyros(float deltaTime);
void render(bool forceRenderHead, bool avatarOnly = false);
void render(bool forShadowMapOrMirror = false);
void renderDebugBodyPoints();
void renderHeadMouse() const;

View file

@ -343,7 +343,14 @@ QSharedPointer<NetworkGeometry> NetworkGeometry::getLODOrFallback(float distance
// if we previously selected a different distance, make sure we've moved far enough to justify switching
const float HYSTERESIS_PROPORTION = 0.1f;
if (glm::abs(distance - qMax(hysteresis, lodDistance)) / fabsf(hysteresis - lodDistance) < HYSTERESIS_PROPORTION) {
return getLODOrFallback(hysteresis, hysteresis);
lod = _lodParent;
lodDistance = 0.0f;
it = _lods.upperBound(hysteresis);
if (it != _lods.constBegin()) {
it = it - 1;
lod = it.value();
lodDistance = it.key();
}
}
}
if (lod->isLoaded()) {

View file

@ -459,6 +459,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
// if so instructed, keep the current geometry until the new one is loaded
_nextBaseGeometry = _nextGeometry = Application::getInstance()->getGeometryCache()->getGeometry(url, fallback, delayLoad);
_nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS;
if (!retainCurrent || !isActive() || _nextGeometry->isLoaded()) {
applyNextGeometry();
}
@ -842,7 +843,7 @@ void Model::applyCollision(CollisionInfo& collision) {
QVector<Model::JointState> Model::updateGeometry(bool delayLoad) {
QVector<JointState> newJointStates;
if (_nextGeometry) {
_nextGeometry = _nextGeometry->getLODOrFallback(_lodDistance, _lodHysteresis, delayLoad);
_nextGeometry = _nextGeometry->getLODOrFallback(_lodDistance, _nextLODHysteresis, delayLoad);
if (!delayLoad) {
_nextGeometry->setLoadPriority(this, -_lodDistance);
_nextGeometry->ensureLoading();
@ -885,7 +886,7 @@ void Model::applyNextGeometry() {
// delete our local geometry and custom textures
deleteGeometry();
_dilatedTextures.clear();
_lodHysteresis = NetworkGeometry::NO_HYSTERESIS;
_lodHysteresis = _nextLODHysteresis;
// we retain a reference to the base geometry so that its reference count doesn't fall to zero
_baseGeometry = _nextBaseGeometry;

View file

@ -245,6 +245,7 @@ private:
QSharedPointer<NetworkGeometry> _nextGeometry;
float _lodDistance;
float _lodHysteresis;
float _nextLODHysteresis;
float _pupilDilation;
std::vector<float> _blendshapeCoefficients;

View file

@ -113,7 +113,8 @@ GLuint TextureCache::getFileTextureID(const QString& filename) {
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 1,
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
_fileTextureIDs.insert(filename, id);
@ -335,7 +336,8 @@ void NetworkTexture::setImage(const QImage& image, const glm::vec4& averageColor
glBindTexture(GL_TEXTURE_2D, getID());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 1,
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
@ -388,7 +390,8 @@ QSharedPointer<Texture> DilatableNetworkTexture::getDilatedTexture(float dilatio
glBindTexture(GL_TEXTURE_2D, texture->getID());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dilatedImage.width(), dilatedImage.height(), 1,
GL_BGRA, GL_UNSIGNED_BYTE, dilatedImage.constBits());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}

View file

@ -13,8 +13,6 @@ find_package(Qt5Script REQUIRED)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
qt5_use_modules(${TARGET_NAME} Script)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -24,3 +22,5 @@ link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
# link in the hifi voxels library
link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
target_link_libraries(${TARGET_NAME} Qt5::Script)

View file

@ -13,4 +13,4 @@ find_package(Qt5Network REQUIRED)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
qt5_use_modules(${TARGET_NAME} Network)
target_link_libraries(${TARGET_NAME} Qt5::Network)

View file

@ -8,8 +8,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm
set(TARGET_NAME metavoxels)
find_package(Qt5Network REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5 COMPONENTS Network Script Widgets)
include(${MACRO_DIR}/AutoMTC.cmake)
auto_mtc(${TARGET_NAME} "${ROOT_DIR}")
@ -17,8 +16,8 @@ auto_mtc(${TARGET_NAME} "${ROOT_DIR}")
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME} "${AUTOMTC_SRC}")
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script)

View file

@ -13,8 +13,6 @@ find_package(Qt5Widgets REQUIRED)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
qt5_use_modules(${TARGET_NAME} Widgets)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -24,4 +22,5 @@ link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
include_directories("${ZLIB_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)

View file

@ -17,9 +17,7 @@
#include <glm/gtc/noise.hpp>
#include <QtCore/QDebug>
#include <QImage>
#include <QRgb>
#include <QDebug>
#include "CoverageMap.h"
#include <GeometryUtil.h>
@ -590,16 +588,26 @@ bool findRayIntersectionOp(OctreeElement* node, void* extraData) {
}
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElement*& node, float& distance, BoxFace& face, bool tryLock) {
OctreeElement*& node, float& distance, BoxFace& face, Octree::lockType lockType) {
RayArgs args = { origin / (float)(TREE_SCALE), direction, node, distance, face };
if (!tryLock) {
bool gotLock = false;
if (lockType == Octree::Lock) {
lockForRead();
gotLock = true;
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
}
}
if (tryLock && tryLockForRead()) {
recurseTreeWithOperation(findRayIntersectionOp, &args);
recurseTreeWithOperation(findRayIntersectionOp, &args);
if (gotLock) {
unlock();
}
return args.found;
}
@ -635,7 +643,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
}
bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
void** penetratedObject, bool tryLock) {
void** penetratedObject, Octree::lockType lockType) {
SphereArgs args = {
center / (float)(TREE_SCALE),
@ -644,17 +652,27 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v
false,
NULL };
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
if (!tryLock) {
bool gotLock = false;
if (lockType == Octree::Lock) {
lockForRead();
}
if (tryLock && tryLockForRead()) {
recurseTreeWithOperation(findSpherePenetrationOp, &args);
if (penetratedObject) {
*penetratedObject = args.penetratedObject;
gotLock = true;
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
}
}
recurseTreeWithOperation(findSpherePenetrationOp, &args);
if (penetratedObject) {
*penetratedObject = args.penetratedObject;
}
if (gotLock) {
unlock();
}
return args.found;
}
@ -689,7 +707,7 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) {
}
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
glm::vec3& penetration, bool tryLock) {
glm::vec3& penetration, Octree::lockType lockType) {
CapsuleArgs args = {
start / (float)(TREE_SCALE),
@ -699,11 +717,20 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end
false };
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
if (!tryLock) {
bool gotLock = false;
if (lockType == Octree::Lock) {
lockForRead();
gotLock = true;
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
return args.found; // if we wanted to tryLock, and we couldn't then just bail...
}
}
if (tryLock && tryLockForRead()) {
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
if (gotLock) {
unlock();
}
return args.found;
@ -732,18 +759,28 @@ bool getElementEnclosingOperation(OctreeElement* element, void* extraData) {
return true; // keep looking
}
OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, bool tryLock) {
OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType) {
GetElementEnclosingArgs args;
args.point = point;
args.element = NULL;
if (!tryLock) {
bool gotLock = false;
if (lockType == Octree::Lock) {
lockForRead();
gotLock = true;
} else if (lockType == Octree::TryLock) {
gotLock = tryLockForRead();
if (!gotLock) {
return args.element; // if we wanted to tryLock, and we couldn't then just bail...
}
}
if (tryLock && tryLockForRead()) {
recurseTreeWithOperation(getElementEnclosingOperation, (void*)&args);
recurseTreeWithOperation(getElementEnclosingOperation, (void*)&args);
if (gotLock) {
unlock();
}
return args.element;
}

View file

@ -221,16 +221,29 @@ public:
void clearDirtyBit() { _isDirty = false; }
void setDirtyBit() { _isDirty = true; }
// Octree does not currently handle its own locking, caller must use these to lock/unlock
void lockForRead() { _lock.lockForRead(); }
bool tryLockForRead() { return _lock.tryLockForRead(); }
void lockForWrite() { _lock.lockForWrite(); }
bool tryLockForWrite() { return _lock.tryLockForWrite(); }
void unlock() { _lock.unlock(); }
// output hints from the encode process
typedef enum {
Lock,
TryLock,
NoLock
} lockType;
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElement*& node, float& distance, BoxFace& face, bool tryLock = true);
OctreeElement*& node, float& distance, BoxFace& face, Octree::lockType lockType = Octree::TryLock);
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration,
void** penetratedObject = NULL, bool tryLock = true);
void** penetratedObject = NULL, Octree::lockType lockType = Octree::TryLock);
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius,
glm::vec3& penetration, bool tryLock = true);
glm::vec3& penetration, Octree::lockType lockType = Octree::TryLock);
OctreeElement* getElementEnclosingPoint(const glm::vec3& point, bool tryLock = true);
OctreeElement* getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType = Octree::TryLock);
// Note: this assumes the fileFormat is the HIO individual voxels code files
void loadOctreeFile(const char* fileName, bool wantColorRandomizer);
@ -238,13 +251,7 @@ public:
// these will read/write files that match the wireformat, excluding the 'V' leading
void writeToSVOFile(const char* filename, OctreeElement* node = NULL);
bool readFromSVOFile(const char* filename);
// Octree does not currently handle its own locking, caller must use these to lock/unlock
void lockForRead() { _lock.lockForRead(); }
bool tryLockForRead() { return _lock.tryLockForRead(); }
void lockForWrite() { _lock.lockForWrite(); }
bool tryLockForWrite() { return _lock.tryLockForWrite(); }
void unlock() { _lock.unlock(); }
unsigned long getOctreeElementsCount();

View file

@ -13,8 +13,6 @@ find_package(Qt5Widgets REQUIRED)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
qt5_use_modules(${TARGET_NAME} Widgets)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -25,4 +23,5 @@ link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
include_directories("${ZLIB_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)

View file

@ -884,25 +884,25 @@ void Particle::executeUpdateScripts() {
}
}
void Particle::collisionWithParticle(Particle* other) {
void Particle::collisionWithParticle(Particle* other, const glm::vec3& penetration) {
// Only run this particle script if there's a script attached directly to the particle.
if (!_script.isEmpty()) {
ScriptEngine engine(_script);
ParticleScriptObject particleScriptable(this);
startParticleScriptContext(engine, particleScriptable);
ParticleScriptObject otherParticleScriptable(other);
particleScriptable.emitCollisionWithParticle(&otherParticleScriptable);
particleScriptable.emitCollisionWithParticle(&otherParticleScriptable, penetration);
endParticleScriptContext(engine, particleScriptable);
}
}
void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) {
void Particle::collisionWithVoxel(VoxelDetail* voxelDetails, const glm::vec3& penetration) {
// Only run this particle script if there's a script attached directly to the particle.
if (!_script.isEmpty()) {
ScriptEngine engine(_script);
ParticleScriptObject particleScriptable(this);
startParticleScriptContext(engine, particleScriptable);
particleScriptable.emitCollisionWithVoxel(*voxelDetails);
particleScriptable.emitCollisionWithVoxel(*voxelDetails, penetration);
endParticleScriptContext(engine, particleScriptable);
}
}

View file

@ -295,8 +295,8 @@ public:
void applyHardCollision(const CollisionInfo& collisionInfo);
void update(const quint64& now);
void collisionWithParticle(Particle* other);
void collisionWithVoxel(VoxelDetail* voxel);
void collisionWithParticle(Particle* other, const glm::vec3& penetration);
void collisionWithVoxel(VoxelDetail* voxel, const glm::vec3& penetration);
void debugDump() const;
@ -371,8 +371,10 @@ public:
//~ParticleScriptObject() { qDebug() << "~ParticleScriptObject() this=" << this; }
void emitUpdate() { emit update(); }
void emitCollisionWithParticle(QObject* other) { emit collisionWithParticle(other); }
void emitCollisionWithVoxel(const VoxelDetail& voxel) { emit collisionWithVoxel(voxel); }
void emitCollisionWithParticle(QObject* other, const glm::vec3& penetration)
{ emit collisionWithParticle(other, penetration); }
void emitCollisionWithVoxel(const VoxelDetail& voxel, const glm::vec3& penetration)
{ emit collisionWithVoxel(voxel, penetration); }
public slots:
unsigned int getID() const { return _particle->getID(); }
@ -417,8 +419,8 @@ public slots:
signals:
void update();
void collisionWithVoxel(const VoxelDetail& voxel);
void collisionWithParticle(QObject* other);
void collisionWithVoxel(const VoxelDetail& voxel, const glm::vec3& penetration);
void collisionWithParticle(QObject* other, const glm::vec3& penetration);
private:
Particle* _particle;

View file

@ -58,7 +58,7 @@ bool ParticleCollisionSystem::updateOperation(OctreeElement* element, void* extr
void ParticleCollisionSystem::update() {
// update all particles
if (_particles->tryLockForWrite()) {
if (_particles->tryLockForRead()) {
_particles->recurseTreeWithOperation(updateOperation, this);
_particles->unlock();
}
@ -71,15 +71,18 @@ void ParticleCollisionSystem::checkParticle(Particle* particle) {
updateCollisionWithAvatars(particle);
}
void ParticleCollisionSystem::emitGlobalParticleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails) {
void ParticleCollisionSystem::emitGlobalParticleCollisionWithVoxel(Particle* particle,
VoxelDetail* voxelDetails, const glm::vec3& penetration) {
ParticleID particleID = particle->getParticleID();
emit particleCollisionWithVoxel(particleID, *voxelDetails);
emit particleCollisionWithVoxel(particleID, *voxelDetails, penetration);
}
void ParticleCollisionSystem::emitGlobalParticleCollisionWithParticle(Particle* particleA, Particle* particleB) {
void ParticleCollisionSystem::emitGlobalParticleCollisionWithParticle(Particle* particleA,
Particle* particleB, const glm::vec3& penetration) {
ParticleID idA = particleA->getParticleID();
ParticleID idB = particleB->getParticleID();
emit particleCollisionWithParticle(idA, idB);
emit particleCollisionWithParticle(idA, idB, penetration);
}
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
@ -95,10 +98,10 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
if (_voxels->findSpherePenetration(center, radius, collisionInfo._penetration, (void**)&voxelDetails)) {
// let the particles run their collision scripts if they have them
particle->collisionWithVoxel(voxelDetails);
particle->collisionWithVoxel(voxelDetails, collisionInfo._penetration);
// let the global script run their collision scripts for particles if they have them
emitGlobalParticleCollisionWithVoxel(particle, voxelDetails);
emitGlobalParticleCollisionWithVoxel(particle, voxelDetails, collisionInfo._penetration);
updateCollisionSound(particle, collisionInfo._penetration, COLLISION_FREQUENCY);
collisionInfo._penetration /= (float)(TREE_SCALE);
@ -117,7 +120,7 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
const float COLLISION_FREQUENCY = 0.5f;
glm::vec3 penetration;
Particle* particleB;
if (_particles->findSpherePenetration(center, radius, penetration, (void**)&particleB)) {
if (_particles->findSpherePenetration(center, radius, penetration, (void**)&particleB, Octree::NoLock)) {
// NOTE: 'penetration' is the depth that 'particleA' overlaps 'particleB'.
// That is, it points from A into B.
@ -125,9 +128,9 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
// we don't want to count this as a collision.
glm::vec3 relativeVelocity = particleA->getVelocity() - particleB->getVelocity();
if (glm::dot(relativeVelocity, penetration) > 0.0f) {
particleA->collisionWithParticle(particleB);
particleB->collisionWithParticle(particleA);
emitGlobalParticleCollisionWithParticle(particleA, particleB);
particleA->collisionWithParticle(particleB, penetration);
particleB->collisionWithParticle(particleA, penetration * -1.0f); // the penetration is reversed
emitGlobalParticleCollisionWithParticle(particleA, particleB, penetration);
glm::vec3 axis = glm::normalize(penetration);
glm::vec3 axialVelocity = glm::dot(relativeVelocity, axis) * axis;

View file

@ -53,13 +53,13 @@ public:
void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency);
signals:
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel);
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB);
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const glm::vec3& penetration);
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const glm::vec3& penetration);
private:
static bool updateOperation(OctreeElement* element, void* extraData);
void emitGlobalParticleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails);
void emitGlobalParticleCollisionWithParticle(Particle* particleA, Particle* particleB);
void emitGlobalParticleCollisionWithVoxel(Particle* particle, VoxelDetail* voxelDetails, const glm::vec3& penetration);
void emitGlobalParticleCollisionWithParticle(Particle* particleA, Particle* particleB, const glm::vec3& penetration);
ParticleEditPacketSender* _packetSender;
ParticleTree* _particles;

View file

@ -29,12 +29,13 @@ public:
private slots:
/// inbound slots for external collision systems
void forwardParticleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel) {
emit particleCollisionWithVoxel(particleID, voxel);
void forwardParticleCollisionWithVoxel(const ParticleID& particleID,
const VoxelDetail& voxel, const glm::vec3& penetration) {
emit particleCollisionWithVoxel(particleID, voxel, penetration);
}
void forwardParticleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB) {
emit particleCollisionWithParticle(idA, idB);
void forwardParticleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const glm::vec3& penetration) {
emit particleCollisionWithParticle(idA, idB, penetration);
}
public slots:
@ -65,8 +66,8 @@ public slots:
QVector<ParticleID> findParticles(const glm::vec3& center, float radius) const;
signals:
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel);
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB);
void particleCollisionWithVoxel(const ParticleID& particleID, const VoxelDetail& voxel, const glm::vec3& penetration);
void particleCollisionWithParticle(const ParticleID& idA, const ParticleID& idB, const glm::vec3& penetration);
private:
void queueParticleMessage(PacketType packetType, ParticleID particleID, const ParticleProperties& properties);

View file

@ -13,8 +13,6 @@ find_package(Qt5Widgets REQUIRED)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
qt5_use_modules(${TARGET_NAME} Widgets)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -27,4 +25,5 @@ link_hifi_library(particles ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
include_directories("${ZLIB_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets)

View file

@ -11,6 +11,8 @@
#include <glm/gtx/vector_angle.hpp>
#include <QDebug>
#include <OctreeConstants.h>
#include <SharedUtil.h>
#include "Quat.h"
@ -56,3 +58,7 @@ glm::quat Quat::mix(const glm::quat& q1, const glm::quat& q2, float alpha) {
return safeMix(q1, q2, alpha);
}
void Quat::print(const QString& lable, const glm::quat& q) {
qDebug() << qPrintable(lable) << q.x << "," << q.y << "," << q.z << "," << q.w;
}

View file

@ -13,7 +13,9 @@
#define __hifi__Quat__
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QObject>
#include <QObject>
#include <QString>
/// Scriptable interface a Quaternion helper class object. Used exclusively in the JavaScript API
class Quat : public QObject {
@ -30,6 +32,7 @@ public slots:
glm::vec3 safeEulerAngles(const glm::quat& orientation);
glm::quat angleAxis(float angle, const glm::vec3& v);
glm::quat mix(const glm::quat& q1, const glm::quat& q2, float alpha);
void print(const QString& lable, const glm::quat& q);
};
#endif /* defined(__hifi__Quat__) */

View file

@ -220,6 +220,8 @@ void ScriptEngine::run() {
int thisFrame = 0;
NodeList* nodeList = NodeList::getInstance();
qint64 lastUpdate = usecTimestampNow();
while (!_isFinished) {
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow();
@ -264,7 +266,10 @@ void ScriptEngine::run() {
nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer);
}
emit willSendVisualDataCallback();
qint64 now = usecTimestampNow();
float deltaTime = (float)(now - lastUpdate)/(float)USECS_PER_SECOND;
emit update(deltaTime);
lastUpdate = now;
if (_engine.hasUncaughtException()) {
int line = _engine.uncaughtExceptionLineNumber();

View file

@ -71,8 +71,7 @@ public slots:
void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
signals:
void willSendAudioDataCallback();
void willSendVisualDataCallback();
void update(float deltaTime);
void scriptEnding();
void finished(const QString& fileNameString);
void cleanupMenuItem(const QString& menuItemString);

View file

@ -9,10 +9,12 @@
//
//
#include <QDebug>
#include "Vec3.h"
glm::vec3 Vec3::multiply(const glm::vec3& v1, const glm::vec3& v2) {
return v1 * v2;
glm::vec3 Vec3::cross(const glm::vec3& v1, const glm::vec3& v2) {
return glm::cross(v1,v2);
}
glm::vec3 Vec3::multiply(const glm::vec3& v1, float f) {
@ -29,6 +31,15 @@ glm::vec3 Vec3::sum(const glm::vec3& v1, const glm::vec3& v2) {
glm::vec3 Vec3::subtract(const glm::vec3& v1, const glm::vec3& v2) {
return v1 - v2;
}
float Vec3::length(const glm::vec3& v) {
return glm::length(v);
}
glm::vec3 Vec3::normalize(const glm::vec3& v) {
return glm::normalize(v);
}
void Vec3::print(const QString& lable, const glm::vec3& v) {
qDebug() << qPrintable(lable) << v.x << "," << v.y << "," << v.z;
}

View file

@ -14,19 +14,23 @@
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QObject>
#include <QObject>
#include <QString>
/// Scriptable interface a Vec3ernion helper class object. Used exclusively in the JavaScript API
class Vec3 : public QObject {
Q_OBJECT
public slots:
glm::vec3 multiply(const glm::vec3& v1, const glm::vec3& v2);
glm::vec3 cross(const glm::vec3& v1, const glm::vec3& v2);
glm::vec3 multiply(const glm::vec3& v1, float f);
glm::vec3 multiplyQbyV(const glm::quat& q, const glm::vec3& v);
glm::vec3 sum(const glm::vec3& v1, const glm::vec3& v2);
glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2);
float length(const glm::vec3& v);
glm::vec3 normalize(const glm::vec3& v);
void print(const QString& lable, const glm::vec3& v);
};

View file

@ -6,14 +6,11 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
set(TARGET_NAME shared)
project(${TARGET_NAME})
find_package(Qt5Network REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5 COMPONENTS Network Widgets)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
qt5_use_modules(${TARGET_NAME} Network Widgets)
# include GLM
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -31,3 +28,5 @@ if (UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
target_link_libraries(${TARGET_NAME} "${CMAKE_THREAD_LIBS_INIT}")
endif (UNIX AND NOT APPLE)
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets)

View file

@ -8,14 +8,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm
set(TARGET_NAME voxels)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Script REQUIRED)
find_package(Qt5 COMPONENTS Widgets Script)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
qt5_use_modules(${TARGET_NAME} Widgets Script)
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -26,4 +23,5 @@ link_hifi_library(octree ${TARGET_NAME} "${ROOT_DIR}")
# link ZLIB
find_package(ZLIB)
include_directories("${ZLIB_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}" Qt5::Widgets Qt5::Script)

View file

@ -61,15 +61,7 @@ foreach(EXTERNAL_SOURCE_SUBDIR ${EXTERNAL_SOURCE_SUBDIRS})
set(APPLICATION_SRCS ${APPLICATION_SRCS} "${SUBDIR_SRCS}")
endforeach(EXTERNAL_SOURCE_SUBDIR)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Multimedia REQUIRED)
find_package(Qt5Network REQUIRED)
find_package(Qt5OpenGL REQUIRED)
find_package(Qt5Svg REQUIRED)
find_package(Qt5WebKit REQUIRED)
find_package(Qt5WebKitWidgets REQUIRED)
find_package(Qt5Xml REQUIRED)
find_package(Qt5 COMPONENTS Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
# grab the ui files in resources/ui
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
@ -122,8 +114,6 @@ link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
find_package(GLM REQUIRED)
find_package(ZLIB)
qt5_use_modules(${TARGET_NAME} Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
# include headers for interface
include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes")
@ -131,7 +121,9 @@ include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes"
# use system flag so warnings are supressed
include_directories(SYSTEM "${GLM_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}")
target_link_libraries(${TARGET_NAME} "${ZLIB_LIBRARIES}"
Qt5::Core Qt5::Gui Qt5::Multimedia Qt5::Network Qt5::OpenGL
Qt5::Script Qt5::Svg Qt5::WebKit Qt5::WebKitWidgets Qt5::Xml Qt5::UiTools)
if (APPLE)
# link in required OS X frameworks and include the right GL headers

View file

@ -8,9 +8,7 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/")
find_package(Qt5Network REQUIRED)
find_package(Qt5Script REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5 COMPONENTS Network Script Widgets)
include(${MACRO_DIR}/AutoMTC.cmake)
auto_mtc(${TARGET_NAME} "${ROOT_DIR}")
@ -18,8 +16,6 @@ auto_mtc(${TARGET_NAME} "${ROOT_DIR}")
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE "${AUTOMTC_SRC}")
qt5_use_modules(${TARGET_NAME} Network Script Widgets)
#include glm
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -33,3 +29,5 @@ IF (WIN32)
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
ENDIF(WIN32)
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Script)

View file

@ -12,12 +12,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} "${ROOT_DIR}")
find_package(Qt5Script REQUIRED)
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE)
find_package(Qt5Script REQUIRED)
qt5_use_modules(${TARGET_NAME} Script)
# link in the shared library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} "${ROOT_DIR}")
@ -31,3 +30,5 @@ link_hifi_library(voxels ${TARGET_NAME} "${ROOT_DIR}")
IF (WIN32)
target_link_libraries(${TARGET_NAME} Winmm Ws2_32)
ENDIF(WIN32)
target_link_libraries(${TARGET_NAME} Qt5::Script)