mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 21:36:12 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
This commit is contained in:
commit
d48b7b8ede
35 changed files with 1351 additions and 291 deletions
|
@ -13,7 +13,6 @@ include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||||
|
|
||||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||||
|
|
||||||
# link in the shared library
|
# link in the shared library
|
||||||
|
|
|
@ -171,7 +171,7 @@ void DomainServer::createStaticAssignmentsForTypeGivenConfigString(Assignment::T
|
||||||
|
|
||||||
QStringList multiConfigList = configString.split(";", QString::SkipEmptyParts);
|
QStringList multiConfigList = configString.split(";", QString::SkipEmptyParts);
|
||||||
|
|
||||||
const QString ASSIGNMENT_CONFIG_POOL_REGEX = "--pool\\s*(\\w+)";
|
const QString ASSIGNMENT_CONFIG_POOL_REGEX = "--pool\\s*([\\w-]+)";
|
||||||
QRegExp poolRegex(ASSIGNMENT_CONFIG_POOL_REGEX);
|
QRegExp poolRegex(ASSIGNMENT_CONFIG_POOL_REGEX);
|
||||||
|
|
||||||
// read each config to a payload for this type of assignment
|
// read each config to a payload for this type of assignment
|
||||||
|
|
62
examples/addVoxelOnMouseClickExample.js
Normal file
62
examples/addVoxelOnMouseClickExample.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
//
|
||||||
|
// addVoxelOnMouseClickExample.js
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/6/14.
|
||||||
|
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// This is an example script that demonstrates use of the Camera and Voxels class to implement
|
||||||
|
// clicking on a voxel and adding a new voxel on the clicked on face
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
function mousePressEvent(event) {
|
||||||
|
print("mousePressEvent event.x,y=" + event.x + ", " + event.y);
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
var intersection = Voxels.findRayIntersection(pickRay);
|
||||||
|
if (intersection.intersects) {
|
||||||
|
|
||||||
|
// Note: due to the current C++ "click on voxel" behavior, these values may be the animated color for the voxel
|
||||||
|
print("clicked on voxel.red/green/blue=" + intersection.voxel.red + ", "
|
||||||
|
+ intersection.voxel.green + ", " + intersection.voxel.blue);
|
||||||
|
print("clicked on voxel.x/y/z/s=" + intersection.voxel.x + ", "
|
||||||
|
+ intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s);
|
||||||
|
print("clicked on face=" + intersection.face);
|
||||||
|
print("clicked on distance=" + intersection.distance);
|
||||||
|
|
||||||
|
var newVoxel = {
|
||||||
|
x: intersection.voxel.x,
|
||||||
|
y: intersection.voxel.y,
|
||||||
|
z: intersection.voxel.z,
|
||||||
|
s: intersection.voxel.s,
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 255 };
|
||||||
|
|
||||||
|
if (intersection.face == "MIN_X_FACE") {
|
||||||
|
newVoxel.x -= newVoxel.s;
|
||||||
|
} else if (intersection.face == "MAX_X_FACE") {
|
||||||
|
newVoxel.x += newVoxel.s;
|
||||||
|
} else if (intersection.face == "MIN_Y_FACE") {
|
||||||
|
newVoxel.y -= newVoxel.s;
|
||||||
|
} else if (intersection.face == "MAX_Y_FACE") {
|
||||||
|
newVoxel.y += newVoxel.s;
|
||||||
|
} else if (intersection.face == "MIN_Z_FACE") {
|
||||||
|
newVoxel.z -= newVoxel.s;
|
||||||
|
} else if (intersection.face == "MAX_Z_FACE") {
|
||||||
|
newVoxel.z += newVoxel.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Voxels.setVoxel("+newVoxel.x + ", "
|
||||||
|
+ newVoxel.y + ", " + newVoxel.z + ", " + newVoxel.s + ", "
|
||||||
|
+ newVoxel.red + ", " + newVoxel.green + ", " + newVoxel.blue + ")" );
|
||||||
|
|
||||||
|
Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
}
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
|
@ -20,6 +20,7 @@ function checkController() {
|
||||||
var numberOfTriggers = Controller.getNumberOfTriggers();
|
var numberOfTriggers = Controller.getNumberOfTriggers();
|
||||||
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
|
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
|
||||||
var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers;
|
var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers;
|
||||||
|
var triggerToggled = false;
|
||||||
|
|
||||||
// this is expected for hydras
|
// this is expected for hydras
|
||||||
if (numberOfTriggers == 2 && controllersPerTrigger == 2) {
|
if (numberOfTriggers == 2 && controllersPerTrigger == 2) {
|
||||||
|
@ -46,157 +47,150 @@ function checkController() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// register the call back so it fires before each data send
|
||||||
|
Script.willSendVisualDataCallback.connect(checkController);
|
||||||
|
|
||||||
|
function printKeyEvent(eventName, event) {
|
||||||
|
print(eventName);
|
||||||
|
print(" event.key=" + event.key);
|
||||||
|
print(" event.text=" + event.text);
|
||||||
|
print(" event.isShifted=" + event.isShifted);
|
||||||
|
print(" event.isControl=" + event.isControl);
|
||||||
|
print(" event.isMeta=" + event.isMeta);
|
||||||
|
print(" event.isAlt=" + event.isAlt);
|
||||||
|
print(" event.isKeypad=" + event.isKeypad);
|
||||||
|
}
|
||||||
function keyPressEvent(event) {
|
function keyPressEvent(event) {
|
||||||
print("keyPressEvent event.key=" + event.key);
|
printKeyEvent("keyPressEvent", event);
|
||||||
print("keyPressEvent event.text=" + event.text);
|
|
||||||
|
|
||||||
print("keyPressEvent event.isShifted=" + event.isShifted);
|
if (event.text == "A") {
|
||||||
print("keyPressEvent event.isControl=" + event.isControl);
|
|
||||||
print("keyPressEvent event.isMeta=" + event.isMeta);
|
|
||||||
print("keyPressEvent event.isAlt=" + event.isAlt);
|
|
||||||
print("keyPressEvent event.isKeypad=" + event.isKeypad);
|
|
||||||
|
|
||||||
|
|
||||||
if (event.key == "A".charCodeAt(0)) {
|
|
||||||
print("the A key was pressed");
|
print("the A key was pressed");
|
||||||
}
|
}
|
||||||
if (event.key == " ".charCodeAt(0)) {
|
if (event.text == " ") {
|
||||||
print("the <space> key was pressed");
|
print("the <space> key was pressed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseMoveEvent(event) {
|
function keyReleaseEvent(event) {
|
||||||
print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y);
|
printKeyEvent("keyReleaseEvent", event);
|
||||||
}
|
|
||||||
|
|
||||||
function touchBeginEvent(event) {
|
if (event.text == "A") {
|
||||||
print("touchBeginEvent event.x,y=" + event.x + ", " + event.y);
|
print("the A key was released");
|
||||||
}
|
}
|
||||||
|
if (event.text == " ") {
|
||||||
function touchUpdateEvent(event) {
|
print("the <space> key was pressed");
|
||||||
print("touchUpdateEvent event.x,y=" + event.x + ", " + event.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function touchEndEvent(event) {
|
|
||||||
print("touchEndEvent event.x,y=" + event.x + ", " + event.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// register the call back so it fires before each data send
|
|
||||||
Script.willSendVisualDataCallback.connect(checkController);
|
|
||||||
|
|
||||||
// Map keyPress and mouse move events to our callbacks
|
// Map keyPress and mouse move events to our callbacks
|
||||||
Controller.keyPressEvent.connect(keyPressEvent);
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
var KeyEvent_A = {
|
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||||
key: "A".charCodeAt(0),
|
|
||||||
text: "A",
|
|
||||||
isShifted: false,
|
|
||||||
isMeta: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_a = {
|
|
||||||
text: "a",
|
|
||||||
isShifted: false,
|
|
||||||
isMeta: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_a2 = {
|
|
||||||
key: "a".charCodeAt(0),
|
|
||||||
isShifted: false,
|
|
||||||
isMeta: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_a3 = {
|
|
||||||
text: "a"
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_A2 = {
|
|
||||||
text: "A"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var KeyEvent_9 = {
|
|
||||||
text: "9"
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_Num = {
|
|
||||||
text: "#"
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_At = {
|
|
||||||
text: "@"
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_MetaAt = {
|
|
||||||
text: "@",
|
|
||||||
isMeta: true
|
|
||||||
};
|
|
||||||
|
|
||||||
var KeyEvent_Up = {
|
|
||||||
text: "up"
|
|
||||||
};
|
|
||||||
var KeyEvent_Down = {
|
|
||||||
text: "down"
|
|
||||||
};
|
|
||||||
var KeyEvent_Left = {
|
|
||||||
text: "left"
|
|
||||||
};
|
|
||||||
var KeyEvent_Right = {
|
|
||||||
text: "right"
|
|
||||||
};
|
|
||||||
|
|
||||||
// prevent the A key from going through to the application
|
// prevent the A key from going through to the application
|
||||||
print("KeyEvent_A");
|
Controller.captureKeyEvents({ text: "A" });
|
||||||
Controller.captureKeyEvents(KeyEvent_A);
|
Controller.captureKeyEvents({ key: "A".charCodeAt(0) }); // same as above, just another example of how to capture the key
|
||||||
|
Controller.captureKeyEvents({ text: " " });
|
||||||
print("KeyEvent_A2");
|
Controller.captureKeyEvents({ text: "@", isMeta: true });
|
||||||
Controller.captureKeyEvents(KeyEvent_A2);
|
Controller.captureKeyEvents({ text: "page up" });
|
||||||
|
Controller.captureKeyEvents({ text: "page down" });
|
||||||
print("KeyEvent_a");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_a);
|
|
||||||
|
|
||||||
print("KeyEvent_a2");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_a2);
|
|
||||||
|
|
||||||
print("KeyEvent_a3");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_a3);
|
|
||||||
|
|
||||||
print("KeyEvent_9");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_9);
|
|
||||||
|
|
||||||
print("KeyEvent_Num");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_Num);
|
|
||||||
|
|
||||||
print("KeyEvent_At");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_At);
|
|
||||||
|
|
||||||
print("KeyEvent_MetaAt");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_MetaAt);
|
|
||||||
|
|
||||||
print("KeyEvent_Up");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_Up);
|
|
||||||
print("KeyEvent_Down");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_Down);
|
|
||||||
print("KeyEvent_Left");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_Left);
|
|
||||||
print("KeyEvent_Right");
|
|
||||||
Controller.captureKeyEvents(KeyEvent_Right);
|
|
||||||
|
|
||||||
|
|
||||||
|
function printMouseEvent(eventName, event) {
|
||||||
|
print(eventName);
|
||||||
|
print(" event.x,y=" + event.x + ", " + event.y);
|
||||||
|
print(" event.button=" + event.button);
|
||||||
|
print(" event.isLeftButton=" + event.isLeftButton);
|
||||||
|
print(" event.isRightButton=" + event.isRightButton);
|
||||||
|
print(" event.isMiddleButton=" + event.isMiddleButton);
|
||||||
|
print(" event.isShifted=" + event.isShifted);
|
||||||
|
print(" event.isControl=" + event.isControl);
|
||||||
|
print(" event.isMeta=" + event.isMeta);
|
||||||
|
print(" event.isAlt=" + event.isAlt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseMoveEvent(event) {
|
||||||
|
printMouseEvent("mouseMoveEvent", event);
|
||||||
|
}
|
||||||
|
function mousePressEvent(event) {
|
||||||
|
printMouseEvent("mousePressEvent", event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseReleaseEvent(event) {
|
||||||
|
printMouseEvent("mouseReleaseEvent", event);
|
||||||
|
}
|
||||||
|
|
||||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
|
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||||
|
|
||||||
|
function printTouchEvent(eventName, event) {
|
||||||
|
print(eventName);
|
||||||
|
|
||||||
|
print(" event.x,y=" + event.x + ", " + event.y);
|
||||||
|
print(" event.isPressed=" + event.isPressed);
|
||||||
|
print(" event.isMoved=" + event.isMoved);
|
||||||
|
print(" event.isStationary=" + event.isStationary);
|
||||||
|
print(" event.isReleased=" + event.isReleased);
|
||||||
|
print(" event.isShifted=" + event.isShifted);
|
||||||
|
print(" event.isControl=" + event.isControl);
|
||||||
|
print(" event.isMeta=" + event.isMeta);
|
||||||
|
print(" event.isAlt=" + event.isAlt);
|
||||||
|
for (var i = 0; i < event.points.length; i++) {
|
||||||
|
print(" event.points[" + i + "].x.y:" + event.points[i].x + ", " + event.points[i].y);
|
||||||
|
}
|
||||||
|
print(" event.radius=" + event.radius);
|
||||||
|
print(" event.isPinching=" + event.isPinching);
|
||||||
|
print(" event.isPinchOpening=" + event.isPinchOpening);
|
||||||
|
|
||||||
|
print(" event.angle=" + event.angle);
|
||||||
|
for (var i = 0; i < event.points.length; i++) {
|
||||||
|
print(" event.angles[" + i + "]:" + event.angles[i]);
|
||||||
|
}
|
||||||
|
print(" event.isRotating=" + event.isRotating);
|
||||||
|
print(" event.rotating=" + event.rotating);
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchBeginEvent(event) {
|
||||||
|
printTouchEvent("touchBeginEvent", event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchUpdateEvent(event) {
|
||||||
|
printTouchEvent("touchUpdateEvent", event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchEndEvent(event) {
|
||||||
|
printTouchEvent("touchEndEvent", event);
|
||||||
|
}
|
||||||
// Map touch events to our callbacks
|
// Map touch events to our callbacks
|
||||||
Controller.touchBeginEvent.connect(touchBeginEvent);
|
Controller.touchBeginEvent.connect(touchBeginEvent);
|
||||||
Controller.touchUpdateEvent.connect(touchUpdateEvent);
|
Controller.touchUpdateEvent.connect(touchUpdateEvent);
|
||||||
Controller.touchEndEvent.connect(touchEndEvent);
|
Controller.touchEndEvent.connect(touchEndEvent);
|
||||||
|
|
||||||
// disable the standard application for touch events
|
|
||||||
Controller.captureTouchEvents();
|
function wheelEvent(event) {
|
||||||
|
print("wheelEvent");
|
||||||
|
print(" event.x,y=" + event.x + ", " + event.y);
|
||||||
|
print(" event.delta=" + event.delta);
|
||||||
|
print(" event.orientation=" + event.orientation);
|
||||||
|
print(" event.isLeftButton=" + event.isLeftButton);
|
||||||
|
print(" event.isRightButton=" + event.isRightButton);
|
||||||
|
print(" event.isMiddleButton=" + event.isMiddleButton);
|
||||||
|
print(" event.isShifted=" + event.isShifted);
|
||||||
|
print(" event.isControl=" + event.isControl);
|
||||||
|
print(" event.isMeta=" + event.isMeta);
|
||||||
|
print(" event.isAlt=" + event.isAlt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.wheelEvent.connect(wheelEvent);
|
||||||
|
|
||||||
function scriptEnding() {
|
function scriptEnding() {
|
||||||
// re-enabled the standard application for touch events
|
// re-enabled the standard application for touch events
|
||||||
Controller.releaseTouchEvents();
|
Controller.releaseKeyEvents({ text: "A" });
|
||||||
|
Controller.releaseKeyEvents({ key: "A".charCodeAt(0) }); // same as above, just another example of how to capture the key
|
||||||
|
Controller.releaseKeyEvents({ text: " " });
|
||||||
|
Controller.releaseKeyEvents({ text: "@", isMeta: true });
|
||||||
|
Controller.releaseKeyEvents({ text: "page up" });
|
||||||
|
Controller.releaseKeyEvents({ text: "page down" });
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
170
examples/editVoxels.js
Normal file
170
examples/editVoxels.js
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
//
|
||||||
|
// editVoxels.js
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on February 8, 2014
|
||||||
|
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Captures mouse clicks and edits voxels accordingly.
|
||||||
|
//
|
||||||
|
// click = create a new voxel on this face, same color as old
|
||||||
|
// Alt + click = delete this voxel
|
||||||
|
// shift + click = recolor this voxel
|
||||||
|
//
|
||||||
|
// Click and drag to create more new voxels in the same direction
|
||||||
|
//
|
||||||
|
|
||||||
|
function vLength(v) {
|
||||||
|
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
var key_alt = false;
|
||||||
|
var key_shift = false;
|
||||||
|
var isAdding = false;
|
||||||
|
|
||||||
|
var lastVoxelPosition = { x: 0, y: 0, z: 0 };
|
||||||
|
var lastVoxelColor = { red: 0, green: 0, blue: 0 };
|
||||||
|
var lastVoxelScale = 0;
|
||||||
|
var dragStart = { x: 0, y: 0 };
|
||||||
|
|
||||||
|
// Create a table of the different colors you can choose
|
||||||
|
var colors = new Array();
|
||||||
|
colors[0] = { red: 237, green: 175, blue: 0 };
|
||||||
|
colors[1] = { red: 61, green: 211, blue: 72 };
|
||||||
|
colors[2] = { red: 51, green: 204, blue: 204 };
|
||||||
|
colors[3] = { red: 63, green: 169, blue: 245 };
|
||||||
|
colors[4] = { red: 193, green: 99, blue: 122 };
|
||||||
|
colors[5] = { red: 255, green: 54, blue: 69 };
|
||||||
|
colors[6] = { red: 124, green: 36, blue: 36 };
|
||||||
|
colors[7] = { red: 63, green: 35, blue: 19 };
|
||||||
|
var numColors = 6;
|
||||||
|
var whichColor = 0;
|
||||||
|
|
||||||
|
// Create sounds for adding, deleting, recoloring voxels
|
||||||
|
var addSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst1.raw");
|
||||||
|
var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Bubbles/bubbles1.raw");
|
||||||
|
var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst6.raw");
|
||||||
|
var audioOptions = new AudioInjectionOptions();
|
||||||
|
|
||||||
|
function mousePressEvent(event) {
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
var intersection = Voxels.findRayIntersection(pickRay);
|
||||||
|
audioOptions.volume = 1.0;
|
||||||
|
audioOptions.position = { x: intersection.voxel.x, y: intersection.voxel.y, z: intersection.voxel.z };
|
||||||
|
|
||||||
|
if (intersection.intersects) {
|
||||||
|
if (key_alt) {
|
||||||
|
// Delete voxel
|
||||||
|
Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s);
|
||||||
|
Audio.playSound(deleteSound, audioOptions);
|
||||||
|
|
||||||
|
} else if (key_shift) {
|
||||||
|
// Recolor Voxel
|
||||||
|
whichColor++;
|
||||||
|
if (whichColor == numColors) whichColor = 0;
|
||||||
|
Voxels.setVoxel(intersection.voxel.x,
|
||||||
|
intersection.voxel.y,
|
||||||
|
intersection.voxel.z,
|
||||||
|
intersection.voxel.s,
|
||||||
|
colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue);
|
||||||
|
Audio.playSound(changeColorSound, audioOptions);
|
||||||
|
} else {
|
||||||
|
// Add voxel on face
|
||||||
|
var newVoxel = {
|
||||||
|
x: intersection.voxel.x,
|
||||||
|
y: intersection.voxel.y,
|
||||||
|
z: intersection.voxel.z,
|
||||||
|
s: intersection.voxel.s,
|
||||||
|
red: intersection.voxel.red,
|
||||||
|
green: intersection.voxel.green,
|
||||||
|
blue: intersection.voxel.blue };
|
||||||
|
|
||||||
|
if (intersection.face == "MIN_X_FACE") {
|
||||||
|
newVoxel.x -= newVoxel.s;
|
||||||
|
} else if (intersection.face == "MAX_X_FACE") {
|
||||||
|
newVoxel.x += newVoxel.s;
|
||||||
|
} else if (intersection.face == "MIN_Y_FACE") {
|
||||||
|
newVoxel.y -= newVoxel.s;
|
||||||
|
} else if (intersection.face == "MAX_Y_FACE") {
|
||||||
|
newVoxel.y += newVoxel.s;
|
||||||
|
} else if (intersection.face == "MIN_Z_FACE") {
|
||||||
|
newVoxel.z -= newVoxel.s;
|
||||||
|
} else if (intersection.face == "MAX_Z_FACE") {
|
||||||
|
newVoxel.z += newVoxel.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue);
|
||||||
|
lastVoxelPosition = { x: newVoxel.x, y: newVoxel.y, z: newVoxel.z };
|
||||||
|
lastVoxelColor = { red: newVoxel.red, green: newVoxel.green, blue: newVoxel.blue };
|
||||||
|
lastVoxelScale = newVoxel.s;
|
||||||
|
|
||||||
|
Audio.playSound(addSound, audioOptions);
|
||||||
|
dragStart = { x: event.x, y: event.y };
|
||||||
|
isAdding = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyPressEvent(event) {
|
||||||
|
key_alt = event.isAlt;
|
||||||
|
key_shift = event.isShifted;
|
||||||
|
}
|
||||||
|
function keyReleaseEvent(event) {
|
||||||
|
key_alt = false;
|
||||||
|
key_shift = false;
|
||||||
|
}
|
||||||
|
function mouseMoveEvent(event) {
|
||||||
|
if (isAdding) {
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x,
|
||||||
|
y: pickRay.origin.y - lastVoxelPosition.y,
|
||||||
|
z: pickRay.origin.z - lastVoxelPosition.z };
|
||||||
|
var distance = vLength(lastVoxelDistance);
|
||||||
|
var mouseSpot = { x: pickRay.direction.x * distance, y: pickRay.direction.y * distance, z: pickRay.direction.z * distance };
|
||||||
|
mouseSpot.x += pickRay.origin.x;
|
||||||
|
mouseSpot.y += pickRay.origin.y;
|
||||||
|
mouseSpot.z += pickRay.origin.z;
|
||||||
|
var dx = mouseSpot.x - lastVoxelPosition.x;
|
||||||
|
var dy = mouseSpot.y - lastVoxelPosition.y;
|
||||||
|
var dz = mouseSpot.z - lastVoxelPosition.z;
|
||||||
|
if (dx > lastVoxelScale) {
|
||||||
|
lastVoxelPosition.x += lastVoxelScale;
|
||||||
|
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||||
|
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||||
|
} else if (dx < -lastVoxelScale) {
|
||||||
|
lastVoxelPosition.x -= lastVoxelScale;
|
||||||
|
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||||
|
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||||
|
} else if (dy > lastVoxelScale) {
|
||||||
|
lastVoxelPosition.y += lastVoxelScale;
|
||||||
|
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||||
|
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||||
|
} else if (dy < -lastVoxelScale) {
|
||||||
|
lastVoxelPosition.y -= lastVoxelScale;
|
||||||
|
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||||
|
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||||
|
} else if (dz > lastVoxelScale) {
|
||||||
|
lastVoxelPosition.z += lastVoxelScale;
|
||||||
|
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||||
|
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||||
|
} else if (dz < -lastVoxelScale) {
|
||||||
|
lastVoxelPosition.z -= lastVoxelScale;
|
||||||
|
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||||
|
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseReleaseEvent(event) {
|
||||||
|
isAdding = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
|
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||||
|
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||||
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
|
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
}
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
122
examples/lookAtExample.js
Normal file
122
examples/lookAtExample.js
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
//
|
||||||
|
// lookAtExample.js
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/6/14.
|
||||||
|
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// This is an example script that demonstrates use of the Camera class's lookAt(), keepLookingAt(), and stopLookingAt()
|
||||||
|
// features.
|
||||||
|
//
|
||||||
|
// To use the script, click on a voxel, and the camera will switch into independent mode and fix it's lookAt on the point
|
||||||
|
// on the face of the voxel that you clicked. Click again and it will stop looking at that point. While in this fixed mode
|
||||||
|
// you can use the arrow keys to change the position of the camera.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
var lookingAtSomething = false;
|
||||||
|
var oldMode = Camera.getMode();
|
||||||
|
|
||||||
|
function cancelLookAt() {
|
||||||
|
if (lookingAtSomething) {
|
||||||
|
lookingAtSomething = false;
|
||||||
|
Camera.stopLooking();
|
||||||
|
Camera.setMode(oldMode);
|
||||||
|
releaseMovementKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function captureMovementKeys() {
|
||||||
|
Controller.captureKeyEvents({ text: "up" }); // Z-
|
||||||
|
Controller.captureKeyEvents({ text: "down" }); // Z+
|
||||||
|
Controller.captureKeyEvents({ text: "UP" }); // Y+
|
||||||
|
Controller.captureKeyEvents({ text: "DOWN" }); // Y-
|
||||||
|
Controller.captureKeyEvents({ text: "left" }); // X+
|
||||||
|
Controller.captureKeyEvents({ text: "right" }); // X-
|
||||||
|
}
|
||||||
|
|
||||||
|
function releaseMovementKeys() {
|
||||||
|
Controller.releaseKeyEvents({ text: "up" }); // Z-
|
||||||
|
Controller.releaseKeyEvents({ text: "down" }); // Z+
|
||||||
|
Controller.releaseKeyEvents({ text: "UP" }); // Y+
|
||||||
|
Controller.releaseKeyEvents({ text: "DOWN" }); // Y-
|
||||||
|
Controller.releaseKeyEvents({ text: "left" }); // X+
|
||||||
|
Controller.releaseKeyEvents({ text: "right" }); // X-
|
||||||
|
}
|
||||||
|
|
||||||
|
var cameraPosition = Camera.getPosition();
|
||||||
|
function moveCamera() {
|
||||||
|
if (lookingAtSomething) {
|
||||||
|
Camera.setPosition(cameraPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.willSendVisualDataCallback.connect(moveCamera);
|
||||||
|
|
||||||
|
|
||||||
|
function mousePressEvent(event) {
|
||||||
|
if (lookingAtSomething) {
|
||||||
|
cancelLookAt();
|
||||||
|
} else {
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
var intersection = Voxels.findRayIntersection(pickRay);
|
||||||
|
if (intersection.intersects) {
|
||||||
|
|
||||||
|
// remember the old mode we were in
|
||||||
|
oldMode = Camera.getMode();
|
||||||
|
|
||||||
|
print("looking at intersection point: " + intersection.intersection.x + ", "
|
||||||
|
+ intersection.intersection.y + ", " + intersection.intersection.z);
|
||||||
|
|
||||||
|
// switch to independent mode
|
||||||
|
Camera.setMode("independent");
|
||||||
|
|
||||||
|
// tell the camera to fix it's look at on the point we clicked
|
||||||
|
Camera.keepLookingAt(intersection.intersection);
|
||||||
|
|
||||||
|
// keep track of the fact that we're in this looking at mode
|
||||||
|
lookingAtSomething = true;
|
||||||
|
|
||||||
|
captureMovementKeys();
|
||||||
|
cameraPosition = Camera.getPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
|
|
||||||
|
function keyPressEvent(event) {
|
||||||
|
if (lookingAtSomething) {
|
||||||
|
|
||||||
|
if (event.text == "ESC") {
|
||||||
|
cancelLookAt();
|
||||||
|
}
|
||||||
|
|
||||||
|
var MOVE_DELTA = 0.5;
|
||||||
|
|
||||||
|
if (event.text == "UP" && !event.isShifted) {
|
||||||
|
cameraPosition.z -= MOVE_DELTA;
|
||||||
|
}
|
||||||
|
if (event.text == "DOWN" && !event.isShifted) {
|
||||||
|
cameraPosition.z += MOVE_DELTA;
|
||||||
|
}
|
||||||
|
if (event.text == "LEFT" && !event.isShifted) {
|
||||||
|
cameraPosition.x += MOVE_DELTA;
|
||||||
|
}
|
||||||
|
if (event.text == "RIGHT" && !event.isShifted) {
|
||||||
|
cameraPosition.x -= MOVE_DELTA;
|
||||||
|
}
|
||||||
|
if (event.text == "UP" && event.isShifted) {
|
||||||
|
cameraPosition.y += MOVE_DELTA;
|
||||||
|
}
|
||||||
|
if (event.text == "DOWN" && event.isShifted) {
|
||||||
|
cameraPosition.y -= MOVE_DELTA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
cancelLookAt();
|
||||||
|
}
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
120
examples/multitouchExample.js
Normal file
120
examples/multitouchExample.js
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
//
|
||||||
|
// multitouchExample.js
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/9/14.
|
||||||
|
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// This is an example script that demonstrates use of the Controller class's multi-touch features
|
||||||
|
//
|
||||||
|
// When this script is running:
|
||||||
|
// * Four finger rotate gesture will rotate your avatar.
|
||||||
|
// * Three finger swipe up/down will adjust the pitch of your avatars head.
|
||||||
|
//
|
||||||
|
|
||||||
|
var lastX = 0;
|
||||||
|
var lastY = 0;
|
||||||
|
var lastAngle = 0;
|
||||||
|
var yawFromMultiTouch = 0;
|
||||||
|
var pitchFromMultiTouch = 0;
|
||||||
|
var wantDebugging = false;
|
||||||
|
var ROTATE_YAW_SCALE = 0.15;
|
||||||
|
var MOUSE_PITCH_SCALE = -12.5;
|
||||||
|
var FIXED_MOUSE_TIMESTEP = 0.016;
|
||||||
|
|
||||||
|
var ROTATE_TOUCH_POINTS = 4;
|
||||||
|
var PITCH_TOUCH_POINTS = 3;
|
||||||
|
|
||||||
|
|
||||||
|
function printTouchEvent(eventName, event) {
|
||||||
|
print(eventName);
|
||||||
|
print(" event.x,y=" + event.x + ", " + event.y);
|
||||||
|
print(" event.isPressed=" + event.isPressed);
|
||||||
|
print(" event.isMoved=" + event.isMoved);
|
||||||
|
print(" event.isStationary=" + event.isStationary);
|
||||||
|
print(" event.isReleased=" + event.isReleased);
|
||||||
|
print(" event.isShifted=" + event.isShifted);
|
||||||
|
print(" event.isControl=" + event.isControl);
|
||||||
|
print(" event.isMeta=" + event.isMeta);
|
||||||
|
print(" event.isAlt=" + event.isAlt);
|
||||||
|
print(" event.touchPoints=" + event.touchPoints);
|
||||||
|
for (var i = 0; i < event.points.length; i++) {
|
||||||
|
print(" event.points[" + i + "].x.y:" + event.points[i].x + ", " + event.points[i].y);
|
||||||
|
}
|
||||||
|
print(" event.radius=" + event.radius);
|
||||||
|
print(" event.isPinching=" + event.isPinching);
|
||||||
|
print(" event.isPinchOpening=" + event.isPinchOpening);
|
||||||
|
|
||||||
|
print(" event.angle=" + event.angle);
|
||||||
|
print(" event.deltaAngle=" + event.deltaAngle);
|
||||||
|
for (var i = 0; i < event.points.length; i++) {
|
||||||
|
print(" event.angles[" + i + "]:" + event.angles[i]);
|
||||||
|
}
|
||||||
|
print(" event.isRotating=" + event.isRotating);
|
||||||
|
print(" event.rotating=" + event.rotating);
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchBeginEvent(event) {
|
||||||
|
printTouchEvent("touchBeginEvent", event);
|
||||||
|
lastX = event.x;
|
||||||
|
lastY = event.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchUpdateEvent(event) {
|
||||||
|
printTouchEvent("touchUpdateEvent", event);
|
||||||
|
|
||||||
|
if (event.isRotating && event.touchPoints == ROTATE_TOUCH_POINTS) {
|
||||||
|
// it's possible for the multitouch rotate gesture to generate angle changes which are faster than comfortable to
|
||||||
|
// view, so we will scale this change in angle to make it more comfortable
|
||||||
|
var scaledRotate = event.deltaAngle * ROTATE_YAW_SCALE;
|
||||||
|
print(">>> event.deltaAngle=" + event.deltaAngle);
|
||||||
|
print(">>> scaledRotate=" + scaledRotate);
|
||||||
|
yawFromMultiTouch += scaledRotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.touchPoints == PITCH_TOUCH_POINTS) {
|
||||||
|
pitchFromMultiTouch += ((event.y - lastY) * MOUSE_PITCH_SCALE * FIXED_MOUSE_TIMESTEP);
|
||||||
|
}
|
||||||
|
lastX = event.x;
|
||||||
|
lastY = event.y;
|
||||||
|
lastAngle = event.angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchEndEvent(event) {
|
||||||
|
printTouchEvent("touchEndEvent", event);
|
||||||
|
}
|
||||||
|
// Map touch events to our callbacks
|
||||||
|
Controller.touchBeginEvent.connect(touchBeginEvent);
|
||||||
|
Controller.touchUpdateEvent.connect(touchUpdateEvent);
|
||||||
|
Controller.touchEndEvent.connect(touchEndEvent);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
// 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) {
|
||||||
|
print("changing orientation"
|
||||||
|
+ " [old]MyAvatar.orientation="+MyAvatar.orientation.x + "," + MyAvatar.orientation.y + ","
|
||||||
|
+ MyAvatar.orientation.z + "," + MyAvatar.orientation.w
|
||||||
|
+ " newOrientation="+newOrientation.x + "," + newOrientation.y + "," + newOrientation.z + "," + newOrientation.w);
|
||||||
|
}
|
||||||
|
MyAvatar.orientation = newOrientation;
|
||||||
|
yawFromMultiTouch = 0;
|
||||||
|
|
||||||
|
// apply pitch from mouse
|
||||||
|
var newPitch = MyAvatar.headPitch + pitchFromMultiTouch;
|
||||||
|
if (wantDebugging) {
|
||||||
|
print("changing pitch [old]MyAvatar.headPitch="+MyAvatar.headPitch+ " newPitch="+newPitch);
|
||||||
|
}
|
||||||
|
MyAvatar.headPitch = newPitch;
|
||||||
|
pitchFromMultiTouch = 0;
|
||||||
|
}
|
||||||
|
Script.willSendVisualDataCallback.connect(update);
|
||||||
|
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
// handle any shutdown logic here
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
|
@ -4,6 +4,7 @@
|
||||||
//
|
//
|
||||||
// This sample script moves a voxel around like a bird and sometimes makes tweeting noises
|
// This sample script moves a voxel around like a bird and sometimes makes tweeting noises
|
||||||
//
|
//
|
||||||
|
|
||||||
function vLength(v) {
|
function vLength(v) {
|
||||||
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||||
}
|
}
|
||||||
|
@ -15,20 +16,24 @@ function randVector(a, b) {
|
||||||
var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) };
|
var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) };
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
function vMinus(a, b) {
|
function vMinus(a, b) {
|
||||||
var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
|
var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
function vPlus(a, b) {
|
function vPlus(a, b) {
|
||||||
var rval = { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
|
var rval = { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
function vCopy(a, b) {
|
function vCopy(a, b) {
|
||||||
a.x = b.x;
|
a.x = b.x;
|
||||||
a.y = b.y;
|
a.y = b.y;
|
||||||
a.z = b.z;
|
a.z = b.z;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a vector which is fraction of the way between a and b
|
// Returns a vector which is fraction of the way between a and b
|
||||||
function vInterpolate(a, b, fraction) {
|
function vInterpolate(a, b, fraction) {
|
||||||
var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction };
|
var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction };
|
||||||
|
@ -62,6 +67,7 @@ if (which < 0.2) {
|
||||||
size = 0.15;
|
size = 0.15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var startTimeInSeconds = new Date().getTime() / 1000;
|
var startTimeInSeconds = new Date().getTime() / 1000;
|
||||||
|
|
||||||
var birdLifetime = 20; // lifetime of the bird in seconds!
|
var birdLifetime = 20; // lifetime of the bird in seconds!
|
||||||
|
@ -72,15 +78,19 @@ var frame = 0;
|
||||||
var moving = false;
|
var moving = false;
|
||||||
var tweeting = 0;
|
var tweeting = 0;
|
||||||
var moved = false;
|
var moved = false;
|
||||||
var CHANCE_OF_MOVING = 0.05;
|
|
||||||
|
var CHANCE_OF_MOVING = 0.00;
|
||||||
|
var CHANCE_OF_FLAPPING = 0.05;
|
||||||
var CHANCE_OF_TWEETING = 0.05;
|
var CHANCE_OF_TWEETING = 0.05;
|
||||||
var START_HEIGHT_ABOVE_ME = 1.5;
|
var START_HEIGHT_ABOVE_ME = 1.5;
|
||||||
|
var BIRD_GRAVITY = -0.1;
|
||||||
|
var BIRD_FLAP = 1.0;
|
||||||
var myPosition = MyAvatar.position;
|
var myPosition = MyAvatar.position;
|
||||||
var properties = {
|
var properties = {
|
||||||
lifetime: birdLifetime,
|
lifetime: birdLifetime,
|
||||||
position: { x: myPosition.x, y: myPosition.y + START_HEIGHT_ABOVE_ME, z: myPosition.z },
|
position: { x: myPosition.x, y: myPosition.y + START_HEIGHT_ABOVE_ME, z: myPosition.z },
|
||||||
velocity: { x: 0, y: 0, z: 0 },
|
velocity: { x: 0, y: Math.random() * BIRD_FLAP, z: 0 },
|
||||||
gravity: { x: 0, y: 0, z: 0 },
|
gravity: { x: 0, y: BIRD_GRAVITY, z: 0 },
|
||||||
radius : 0.1,
|
radius : 0.1,
|
||||||
color: { red: 0,
|
color: { red: 0,
|
||||||
green: 255,
|
green: 255,
|
||||||
|
@ -94,6 +104,7 @@ function moveBird() {
|
||||||
// check to see if we've been running long enough that our bird is dead
|
// check to see if we've been running long enough that our bird is dead
|
||||||
var nowTimeInSeconds = new Date().getTime() / 1000;
|
var nowTimeInSeconds = new Date().getTime() / 1000;
|
||||||
if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) {
|
if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) {
|
||||||
|
|
||||||
print("our bird is dying, stop our script");
|
print("our bird is dying, stop our script");
|
||||||
Script.stop();
|
Script.stop();
|
||||||
return;
|
return;
|
||||||
|
@ -115,11 +126,22 @@ function moveBird() {
|
||||||
} else {
|
} else {
|
||||||
tweeting -= 1;
|
tweeting -= 1;
|
||||||
}
|
}
|
||||||
|
if (Math.random() < CHANCE_OF_FLAPPING) {
|
||||||
|
// Add a little upward impulse to our bird
|
||||||
|
// TODO: Get velocity
|
||||||
|
//
|
||||||
|
var newProperties = {
|
||||||
|
velocity: { x:0.0, y: Math.random() * BIRD_FLAP, z: 0.0 }
|
||||||
|
};
|
||||||
|
Particles.editParticle(particleID, newProperties);
|
||||||
|
print("flap!");
|
||||||
|
}
|
||||||
// Moving behavior
|
// Moving behavior
|
||||||
if (moving == false) {
|
if (moving == false) {
|
||||||
if (Math.random() < CHANCE_OF_MOVING) {
|
if (Math.random() < CHANCE_OF_MOVING) {
|
||||||
targetPosition = randVector(-range, range);
|
targetPosition = randVector(-range, range);
|
||||||
targetPosition = vPlus(targetPosition, myPosition);
|
targetPosition = vPlus(targetPosition, myPosition);
|
||||||
|
|
||||||
if (targetPosition.x < 0) {
|
if (targetPosition.x < 0) {
|
||||||
targetPosition.x = 0;
|
targetPosition.x = 0;
|
||||||
}
|
}
|
||||||
|
@ -170,5 +192,6 @@ function moveBird() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// register the call back so it fires before each data send
|
// register the call back so it fires before each data send
|
||||||
Script.willSendVisualDataCallback.connect(moveBird);
|
Script.willSendVisualDataCallback.connect(moveBird);
|
||||||
|
|
37
examples/rayPickExample.js
Normal file
37
examples/rayPickExample.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// rayPickExample.js
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 2/6/14.
|
||||||
|
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// This is an example script that demonstrates use of the Camera class
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
function mouseMoveEvent(event) {
|
||||||
|
print("mouseMoveEvent event.x,y=" + event.x + ", " + event.y);
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
print("called Camera.computePickRay()");
|
||||||
|
print("computePickRay origin=" + pickRay.origin.x + ", " + pickRay.origin.y + ", " + pickRay.origin.z);
|
||||||
|
print("computePickRay direction=" + pickRay.direction.x + ", " + pickRay.direction.y + ", " + pickRay.direction.z);
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
var intersection = Voxels.findRayIntersection(pickRay);
|
||||||
|
if (intersection.intersects) {
|
||||||
|
print("intersection voxel.red/green/blue=" + intersection.voxel.red + ", "
|
||||||
|
+ intersection.voxel.green + ", " + intersection.voxel.blue);
|
||||||
|
print("intersection voxel.x/y/z/s=" + intersection.voxel.x + ", "
|
||||||
|
+ intersection.voxel.y + ", " + intersection.voxel.z+ ": " + intersection.voxel.s);
|
||||||
|
print("intersection face=" + intersection.face);
|
||||||
|
print("intersection distance=" + intersection.distance);
|
||||||
|
print("intersection intersection.x/y/z=" + intersection.intersection.x + ", "
|
||||||
|
+ intersection.intersection.y + ", " + intersection.intersection.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
}
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
|
@ -135,7 +135,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
_isTouchPressed(false),
|
_isTouchPressed(false),
|
||||||
_mousePressed(false),
|
_mousePressed(false),
|
||||||
_isHoverVoxel(false),
|
_isHoverVoxel(false),
|
||||||
_isHoverVoxelSounding(false),
|
|
||||||
_mouseVoxelScale(1.0f / 1024.0f),
|
_mouseVoxelScale(1.0f / 1024.0f),
|
||||||
_mouseVoxelScaleInitialized(false),
|
_mouseVoxelScaleInitialized(false),
|
||||||
_justEditedVoxel(false),
|
_justEditedVoxel(false),
|
||||||
|
@ -448,7 +447,7 @@ void Application::paintGL() {
|
||||||
_myCamera.setTargetRotation(_myAvatar->getHead().getOrientation());
|
_myCamera.setTargetRotation(_myAvatar->getHead().getOrientation());
|
||||||
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
_myCamera.setTightness(0.0f); // In first person, camera follows head exactly without delay
|
_myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay
|
||||||
_myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition());
|
_myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition());
|
||||||
_myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation());
|
_myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation());
|
||||||
|
|
||||||
|
@ -1199,7 +1198,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_isHoverVoxel) {
|
if (_isHoverVoxel) {
|
||||||
_myAvatar->orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY);
|
//_myAvatar->orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1219,11 +1218,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool MAKE_SOUND_ON_VOXEL_HOVER = false;
|
|
||||||
const bool MAKE_SOUND_ON_VOXEL_CLICK = true;
|
|
||||||
const float HOVER_VOXEL_FREQUENCY = 7040.f;
|
|
||||||
const float HOVER_VOXEL_DECAY = 0.999f;
|
|
||||||
|
|
||||||
void Application::mousePressEvent(QMouseEvent* event) {
|
void Application::mousePressEvent(QMouseEvent* event) {
|
||||||
_controllerScriptingInterface.emitMousePressEvent(event); // send events to any registered scripts
|
_controllerScriptingInterface.emitMousePressEvent(event); // send events to any registered scripts
|
||||||
|
|
||||||
|
@ -1263,37 +1257,6 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
||||||
pasteVoxels();
|
pasteVoxels();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) &&
|
|
||||||
MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) {
|
|
||||||
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
|
|
||||||
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
|
|
||||||
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
|
|
||||||
_hoverVoxelOriginalColor[3] = 1;
|
|
||||||
const float RED_CLICK_FREQUENCY = 1000.f;
|
|
||||||
const float GREEN_CLICK_FREQUENCY = 1250.f;
|
|
||||||
const float BLUE_CLICK_FREQUENCY = 1330.f;
|
|
||||||
const float MIDDLE_A_FREQUENCY = 440.f;
|
|
||||||
float frequency = MIDDLE_A_FREQUENCY +
|
|
||||||
(_hoverVoxel.red / 255.f * RED_CLICK_FREQUENCY +
|
|
||||||
_hoverVoxel.green / 255.f * GREEN_CLICK_FREQUENCY +
|
|
||||||
_hoverVoxel.blue / 255.f * BLUE_CLICK_FREQUENCY) / 3.f;
|
|
||||||
|
|
||||||
_audio.startCollisionSound(1.0, frequency, 0.0, HOVER_VOXEL_DECAY, false);
|
|
||||||
_isHoverVoxelSounding = true;
|
|
||||||
|
|
||||||
const float PERCENTAGE_TO_MOVE_TOWARD = 0.90f;
|
|
||||||
glm::vec3 newTarget = getMouseVoxelWorldCoordinates(_hoverVoxel);
|
|
||||||
glm::vec3 myPosition = _myAvatar->getPosition();
|
|
||||||
|
|
||||||
// If there is not an action tool set (add, delete, color), move to this voxel
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ClickToFly) &&
|
|
||||||
!(Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) ||
|
|
||||||
Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) ||
|
|
||||||
Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode))) {
|
|
||||||
_myAvatar->setMoveTarget(myPosition + (newTarget - myPosition) * PERCENTAGE_TO_MOVE_TOWARD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) {
|
} else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) {
|
||||||
deleteVoxelUnderCursor();
|
deleteVoxelUnderCursor();
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1287,9 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::touchUpdateEvent(QTouchEvent* event) {
|
void Application::touchUpdateEvent(QTouchEvent* event) {
|
||||||
_controllerScriptingInterface.emitTouchUpdateEvent(event); // send events to any registered scripts
|
TouchEvent thisEvent(*event, _lastTouchEvent);
|
||||||
|
_controllerScriptingInterface.emitTouchUpdateEvent(thisEvent); // send events to any registered scripts
|
||||||
|
_lastTouchEvent = thisEvent;
|
||||||
|
|
||||||
// if one of our scripts have asked to capture this event, then stop processing it
|
// if one of our scripts have asked to capture this event, then stop processing it
|
||||||
if (_controllerScriptingInterface.isTouchCaptured()) {
|
if (_controllerScriptingInterface.isTouchCaptured()) {
|
||||||
|
@ -1355,8 +1320,10 @@ void Application::touchUpdateEvent(QTouchEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::touchBeginEvent(QTouchEvent* event) {
|
void Application::touchBeginEvent(QTouchEvent* event) {
|
||||||
_controllerScriptingInterface.emitTouchBeginEvent(event); // send events to any registered scripts
|
TouchEvent thisEvent(*event); // on touch begin, we don't compare to last event
|
||||||
|
_controllerScriptingInterface.emitTouchBeginEvent(thisEvent); // send events to any registered scripts
|
||||||
|
|
||||||
|
_lastTouchEvent = thisEvent; // and we reset our last event to this event before we call our update
|
||||||
touchUpdateEvent(event);
|
touchUpdateEvent(event);
|
||||||
|
|
||||||
// if one of our scripts have asked to capture this event, then stop processing it
|
// if one of our scripts have asked to capture this event, then stop processing it
|
||||||
|
@ -1371,7 +1338,9 @@ void Application::touchBeginEvent(QTouchEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::touchEndEvent(QTouchEvent* event) {
|
void Application::touchEndEvent(QTouchEvent* event) {
|
||||||
_controllerScriptingInterface.emitTouchEndEvent(event); // send events to any registered scripts
|
TouchEvent thisEvent(*event, _lastTouchEvent);
|
||||||
|
_controllerScriptingInterface.emitTouchEndEvent(thisEvent); // send events to any registered scripts
|
||||||
|
_lastTouchEvent = thisEvent;
|
||||||
|
|
||||||
// if one of our scripts have asked to capture this event, then stop processing it
|
// if one of our scripts have asked to capture this event, then stop processing it
|
||||||
if (_controllerScriptingInterface.isTouchCaptured()) {
|
if (_controllerScriptingInterface.isTouchCaptured()) {
|
||||||
|
@ -2039,46 +2008,10 @@ void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& f
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels()");
|
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels()");
|
||||||
|
|
||||||
// If we have clicked on a voxel, update it's color
|
|
||||||
if (_isHoverVoxelSounding) {
|
|
||||||
VoxelTreeElement* hoveredNode = _voxels.getVoxelAt(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
|
|
||||||
if (hoveredNode) {
|
|
||||||
float bright = _audio.getCollisionSoundMagnitude();
|
|
||||||
nodeColor clickColor = { 255 * bright + _hoverVoxelOriginalColor[0] * (1.f - bright),
|
|
||||||
_hoverVoxelOriginalColor[1] * (1.f - bright),
|
|
||||||
_hoverVoxelOriginalColor[2] * (1.f - bright), 1 };
|
|
||||||
hoveredNode->setColor(clickColor);
|
|
||||||
if (bright < 0.01f) {
|
|
||||||
hoveredNode->setColor(_hoverVoxelOriginalColor);
|
|
||||||
_isHoverVoxelSounding = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Voxel is not found, clear all
|
|
||||||
_isHoverVoxelSounding = false;
|
|
||||||
_isHoverVoxel = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Check for a new hover voxel
|
|
||||||
glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
|
|
||||||
// only do this work if MAKE_SOUND_ON_VOXEL_HOVER or MAKE_SOUND_ON_VOXEL_CLICK is enabled,
|
|
||||||
// and make sure the tree is not already busy... because otherwise you'll have to wait.
|
|
||||||
if (!_mousePressed) {
|
if (!_mousePressed) {
|
||||||
{
|
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()");
|
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()");
|
||||||
_isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face);
|
_isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face);
|
||||||
}
|
}
|
||||||
if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel &&
|
|
||||||
glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) {
|
|
||||||
|
|
||||||
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
|
|
||||||
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
|
|
||||||
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
|
|
||||||
_hoverVoxelOriginalColor[3] = 1;
|
|
||||||
_audio.startCollisionSound(1.0, HOVER_VOXEL_FREQUENCY * _hoverVoxel.s * TREE_SCALE, 0.0, HOVER_VOXEL_DECAY, false);
|
|
||||||
_isHoverVoxelSounding = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateMouseVoxels(float deltaTime, float& distance, BoxFace& face) {
|
void Application::updateMouseVoxels(float deltaTime, float& distance, BoxFace& face) {
|
||||||
|
@ -4101,6 +4034,7 @@ void Application::loadScript(const QString& fileNameString) {
|
||||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||||
// we can use the same ones from the application.
|
// we can use the same ones from the application.
|
||||||
scriptEngine->getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender);
|
scriptEngine->getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender);
|
||||||
|
scriptEngine->getVoxelsScriptingInterface()->setVoxelTree(_voxels.getTree());
|
||||||
scriptEngine->getParticlesScriptingInterface()->setPacketSender(&_particleEditSender);
|
scriptEngine->getParticlesScriptingInterface()->setPacketSender(&_particleEditSender);
|
||||||
scriptEngine->getParticlesScriptingInterface()->setParticleTree(_particles.getTree());
|
scriptEngine->getParticlesScriptingInterface()->setParticleTree(_particles.getTree());
|
||||||
|
|
||||||
|
|
|
@ -419,8 +419,6 @@ private:
|
||||||
|
|
||||||
VoxelDetail _hoverVoxel; // Stuff about the voxel I am hovering or clicking
|
VoxelDetail _hoverVoxel; // Stuff about the voxel I am hovering or clicking
|
||||||
bool _isHoverVoxel;
|
bool _isHoverVoxel;
|
||||||
bool _isHoverVoxelSounding;
|
|
||||||
nodeColor _hoverVoxelOriginalColor;
|
|
||||||
|
|
||||||
VoxelDetail _mouseVoxel; // details of the voxel to be edited
|
VoxelDetail _mouseVoxel; // details of the voxel to be edited
|
||||||
float _mouseVoxelScale; // the scale for adding/removing voxels
|
float _mouseVoxelScale; // the scale for adding/removing voxels
|
||||||
|
@ -490,6 +488,8 @@ private:
|
||||||
void displayUpdateDialog();
|
void displayUpdateDialog();
|
||||||
bool shouldSkipVersion(QString latestVersion);
|
bool shouldSkipVersion(QString latestVersion);
|
||||||
void takeSnapshot();
|
void takeSnapshot();
|
||||||
|
|
||||||
|
TouchEvent _lastTouchEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__interface__Application__) */
|
#endif /* defined(__interface__Application__) */
|
||||||
|
|
|
@ -65,6 +65,10 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
|
||||||
_measuredJitter(0),
|
_measuredJitter(0),
|
||||||
_jitterBufferSamples(initialJitterBufferSamples),
|
_jitterBufferSamples(initialJitterBufferSamples),
|
||||||
_lastInputLoudness(0),
|
_lastInputLoudness(0),
|
||||||
|
_averageInputLoudness(0),
|
||||||
|
_noiseGateOpen(false),
|
||||||
|
_noiseGateEnabled(true),
|
||||||
|
_noiseGateFramesToClose(0),
|
||||||
_lastVelocity(0),
|
_lastVelocity(0),
|
||||||
_lastAcceleration(0),
|
_lastAcceleration(0),
|
||||||
_totalPacketsReceived(0),
|
_totalPacketsReceived(0),
|
||||||
|
@ -348,12 +352,40 @@ void Audio::handleAudioInput() {
|
||||||
_inputFormat, _desiredInputFormat);
|
_inputFormat, _desiredInputFormat);
|
||||||
|
|
||||||
float loudness = 0;
|
float loudness = 0;
|
||||||
|
float thisSample = 0;
|
||||||
|
int samplesOverNoiseGate = 0;
|
||||||
|
|
||||||
|
const float NOISE_GATE_HEIGHT = 3.f;
|
||||||
|
const int NOISE_GATE_WIDTH = 5;
|
||||||
|
const int NOISE_GATE_CLOSE_FRAME_DELAY = 30;
|
||||||
|
|
||||||
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
||||||
loudness += fabsf(monoAudioSamples[i]);
|
thisSample = fabsf(monoAudioSamples[i]);
|
||||||
|
loudness += thisSample;
|
||||||
|
// Noise Reduction: Count peaks above the average loudness
|
||||||
|
if (thisSample > (_averageInputLoudness * NOISE_GATE_HEIGHT)) {
|
||||||
|
samplesOverNoiseGate++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastInputLoudness = loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
_lastInputLoudness = loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||||
|
const float LOUDNESS_AVERAGING_FRAMES = 1000.f; // This will be about 10 seconds
|
||||||
|
_averageInputLoudness = (1.f - 1.f / LOUDNESS_AVERAGING_FRAMES) * _averageInputLoudness + (1.f / LOUDNESS_AVERAGING_FRAMES) * _lastInputLoudness;
|
||||||
|
|
||||||
|
if (_noiseGateEnabled) {
|
||||||
|
if (samplesOverNoiseGate > NOISE_GATE_WIDTH) {
|
||||||
|
_noiseGateOpen = true;
|
||||||
|
_noiseGateFramesToClose = NOISE_GATE_CLOSE_FRAME_DELAY;
|
||||||
|
} else {
|
||||||
|
if (--_noiseGateFramesToClose == 0) {
|
||||||
|
_noiseGateOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_noiseGateOpen) {
|
||||||
|
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
||||||
|
monoAudioSamples[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add input data just written to the scope
|
// add input data just written to the scope
|
||||||
QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection,
|
||||||
|
@ -524,6 +556,10 @@ void Audio::toggleMute() {
|
||||||
muteToggled();
|
muteToggled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Audio::toggleAudioNoiseReduction() {
|
||||||
|
_noiseGateEnabled = !_noiseGateEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
void Audio::render(int screenWidth, int screenHeight) {
|
void Audio::render(int screenWidth, int screenHeight) {
|
||||||
if (_audioInput && _audioOutput) {
|
if (_audioInput && _audioOutput) {
|
||||||
glLineWidth(2.0);
|
glLineWidth(2.0);
|
||||||
|
|
|
@ -45,7 +45,9 @@ public:
|
||||||
|
|
||||||
void render(int screenWidth, int screenHeight);
|
void render(int screenWidth, int screenHeight);
|
||||||
|
|
||||||
float getLastInputLoudness() const { return _lastInputLoudness; }
|
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _averageInputLoudness, 0.f); }
|
||||||
|
|
||||||
|
void setNoiseGateEnabled(bool noiseGateEnabled) { _noiseGateEnabled = noiseGateEnabled; }
|
||||||
|
|
||||||
void setLastAcceleration(const glm::vec3 lastAcceleration) { _lastAcceleration = lastAcceleration; }
|
void setLastAcceleration(const glm::vec3 lastAcceleration) { _lastAcceleration = lastAcceleration; }
|
||||||
void setLastVelocity(const glm::vec3 lastVelocity) { _lastVelocity = lastVelocity; }
|
void setLastVelocity(const glm::vec3 lastVelocity) { _lastVelocity = lastVelocity; }
|
||||||
|
@ -73,6 +75,7 @@ public slots:
|
||||||
void handleAudioInput();
|
void handleAudioInput();
|
||||||
void reset();
|
void reset();
|
||||||
void toggleMute();
|
void toggleMute();
|
||||||
|
void toggleAudioNoiseReduction();
|
||||||
|
|
||||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
|
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
|
||||||
|
|
||||||
|
@ -106,6 +109,10 @@ private:
|
||||||
float _measuredJitter;
|
float _measuredJitter;
|
||||||
int16_t _jitterBufferSamples;
|
int16_t _jitterBufferSamples;
|
||||||
float _lastInputLoudness;
|
float _lastInputLoudness;
|
||||||
|
float _averageInputLoudness;
|
||||||
|
bool _noiseGateOpen;
|
||||||
|
bool _noiseGateEnabled;
|
||||||
|
int _noiseGateFramesToClose;
|
||||||
glm::vec3 _lastVelocity;
|
glm::vec3 _lastVelocity;
|
||||||
glm::vec3 _lastAcceleration;
|
glm::vec3 _lastAcceleration;
|
||||||
int _totalPacketsReceived;
|
int _totalPacketsReceived;
|
||||||
|
|
|
@ -58,7 +58,9 @@ Camera::Camera() :
|
||||||
_modeShift(1.0f),
|
_modeShift(1.0f),
|
||||||
_linearModeShift(0.0f),
|
_linearModeShift(0.0f),
|
||||||
_modeShiftRate(1.0f),
|
_modeShiftRate(1.0f),
|
||||||
_scale(1.0f)
|
_scale(1.0f),
|
||||||
|
_lookingAt(0.0f, 0.0f, 0.0f),
|
||||||
|
_isKeepLookingAt(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +96,12 @@ void Camera::updateFollowMode(float deltaTime) {
|
||||||
t = 1.0;
|
t = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update position and rotation, setting directly if tightness is 0.0
|
// handle keepLookingAt
|
||||||
|
if (_isKeepLookingAt) {
|
||||||
|
lookAt(_lookingAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update position and rotation, setting directly if tightness is 0.0
|
||||||
if (_needsToInitialize || (_tightness == 0.0f)) {
|
if (_needsToInitialize || (_tightness == 0.0f)) {
|
||||||
_rotation = _targetRotation;
|
_rotation = _targetRotation;
|
||||||
_idealPosition = _targetPosition + _scale * (_rotation * glm::vec3(0.0f, _upShift, _distance));
|
_idealPosition = _targetPosition + _scale * (_rotation * glm::vec3(0.0f, _upShift, _distance));
|
||||||
|
@ -155,6 +161,15 @@ void Camera::setMode(CameraMode m) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::setTargetPosition(const glm::vec3& t) {
|
||||||
|
_targetPosition = t;
|
||||||
|
|
||||||
|
// handle keepLookingAt
|
||||||
|
if (_isKeepLookingAt) {
|
||||||
|
lookAt(_lookingAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Camera::setTargetRotation( const glm::quat& targetRotation ) {
|
void Camera::setTargetRotation( const glm::quat& targetRotation ) {
|
||||||
_targetRotation = targetRotation;
|
_targetRotation = targetRotation;
|
||||||
|
@ -222,6 +237,19 @@ void Camera::setFrustumWasReshaped() {
|
||||||
_frustumNeedsReshape = false;
|
_frustumNeedsReshape = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Camera::lookAt(const glm::vec3& lookAt) {
|
||||||
|
glm::vec3 up = IDENTITY_UP;
|
||||||
|
glm::mat4 lookAtMatrix = glm::lookAt(_targetPosition, lookAt, up);
|
||||||
|
glm::quat rotation = glm::quat_cast(lookAtMatrix);
|
||||||
|
rotation.w = -rotation.w; // Rosedale approved
|
||||||
|
setTargetRotation(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::keepLookingAt(const glm::vec3& point) {
|
||||||
|
lookAt(point);
|
||||||
|
_isKeepLookingAt = true;
|
||||||
|
_lookingAt = point;
|
||||||
|
}
|
||||||
|
|
||||||
CameraScriptableObject::CameraScriptableObject(Camera* camera, ViewFrustum* viewFrustum) :
|
CameraScriptableObject::CameraScriptableObject(Camera* camera, ViewFrustum* viewFrustum) :
|
||||||
_camera(camera), _viewFrustum(viewFrustum)
|
_camera(camera), _viewFrustum(viewFrustum)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ public:
|
||||||
void setUpShift(float u) { _upShift = u; }
|
void setUpShift(float u) { _upShift = u; }
|
||||||
void setDistance(float d) { _distance = d; }
|
void setDistance(float d) { _distance = d; }
|
||||||
void setPosition(const glm::vec3& p) { _position = p; }
|
void setPosition(const glm::vec3& p) { _position = p; }
|
||||||
void setTargetPosition(const glm::vec3& t) { _targetPosition = t; }
|
void setTargetPosition(const glm::vec3& t);
|
||||||
void setTightness(float t) { _tightness = t; }
|
void setTightness(float t) { _tightness = t; }
|
||||||
void setTargetRotation(const glm::quat& rotation);
|
void setTargetRotation(const glm::quat& rotation);
|
||||||
|
|
||||||
|
@ -69,6 +70,17 @@ public:
|
||||||
bool getFrustumNeedsReshape() const; // call to find out if the view frustum needs to be reshaped
|
bool getFrustumNeedsReshape() const; // call to find out if the view frustum needs to be reshaped
|
||||||
void setFrustumWasReshaped(); // call this after reshaping the view frustum.
|
void setFrustumWasReshaped(); // call this after reshaping the view frustum.
|
||||||
|
|
||||||
|
// These only work on independent cameras
|
||||||
|
/// one time change to what the camera is looking at
|
||||||
|
void lookAt(const glm::vec3& value);
|
||||||
|
|
||||||
|
/// fix what the camera is looking at, and keep the camera looking at this even if position changes
|
||||||
|
void keepLookingAt(const glm::vec3& value);
|
||||||
|
|
||||||
|
/// stops the keep looking at feature, doesn't change what's being looked at, but will stop camera from
|
||||||
|
/// continuing to update it's orientation to keep looking at the item
|
||||||
|
void stopLooking() { _isKeepLookingAt = false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool _needsToInitialize;
|
bool _needsToInitialize;
|
||||||
|
@ -100,6 +112,9 @@ private:
|
||||||
float _modeShiftRate;
|
float _modeShiftRate;
|
||||||
float _scale;
|
float _scale;
|
||||||
|
|
||||||
|
glm::vec3 _lookingAt;
|
||||||
|
bool _isKeepLookingAt;
|
||||||
|
|
||||||
void updateFollowMode(float deltaTime);
|
void updateFollowMode(float deltaTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,6 +134,17 @@ public slots:
|
||||||
void setOrientation(const glm::quat& value) { _camera->setTargetRotation(value); }
|
void setOrientation(const glm::quat& value) { _camera->setTargetRotation(value); }
|
||||||
glm::quat getOrientation() const { return _camera->getRotation(); }
|
glm::quat getOrientation() const { return _camera->getRotation(); }
|
||||||
|
|
||||||
|
// These only work on independent cameras
|
||||||
|
/// one time change to what the camera is looking at
|
||||||
|
void lookAt(const glm::vec3& value) { _camera->lookAt(value);}
|
||||||
|
|
||||||
|
/// fix what the camera is looking at, and keep the camera looking at this even if position changes
|
||||||
|
void keepLookingAt(const glm::vec3& value) { _camera->keepLookingAt(value);}
|
||||||
|
|
||||||
|
/// stops the keep looking at feature, doesn't change what's being looked at, but will stop camera from
|
||||||
|
/// continuing to update it's orientation to keep looking at the item
|
||||||
|
void stopLooking() { _camera->stopLooking();}
|
||||||
|
|
||||||
PickRay computePickRay(float x, float y);
|
PickRay computePickRay(float x, float y);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -28,9 +28,10 @@ public:
|
||||||
void emitMousePressEvent(QMouseEvent* event) { emit mousePressEvent(MouseEvent(*event)); }
|
void emitMousePressEvent(QMouseEvent* event) { emit mousePressEvent(MouseEvent(*event)); }
|
||||||
void emitMouseReleaseEvent(QMouseEvent* event) { emit mouseReleaseEvent(MouseEvent(*event)); }
|
void emitMouseReleaseEvent(QMouseEvent* event) { emit mouseReleaseEvent(MouseEvent(*event)); }
|
||||||
|
|
||||||
void emitTouchBeginEvent(QTouchEvent* event) { emit touchBeginEvent(*event); }
|
void emitTouchBeginEvent(const TouchEvent& event) { emit touchBeginEvent(event); }
|
||||||
void emitTouchEndEvent(QTouchEvent* event) { emit touchEndEvent(*event); }
|
void emitTouchEndEvent(const TouchEvent& event) { emit touchEndEvent(event); }
|
||||||
void emitTouchUpdateEvent(QTouchEvent* event) { emit touchUpdateEvent(*event); }
|
void emitTouchUpdateEvent(const TouchEvent& event) { emit touchUpdateEvent(event); }
|
||||||
|
|
||||||
void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); }
|
void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); }
|
||||||
|
|
||||||
bool isKeyCaptured(QKeyEvent* event) const;
|
bool isKeyCaptured(QKeyEvent* event) const;
|
||||||
|
|
|
@ -457,6 +457,11 @@ Menu::Menu() :
|
||||||
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P);
|
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P);
|
||||||
|
|
||||||
QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools");
|
QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools");
|
||||||
|
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
appInstance->getAudio(),
|
||||||
|
SLOT(toggleAudioNoiseReduction()));
|
||||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio);
|
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio);
|
||||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio);
|
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio);
|
||||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio,
|
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio,
|
||||||
|
|
|
@ -187,6 +187,7 @@ namespace MenuOption {
|
||||||
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
||||||
const QString EnableOcclusionCulling = "Enable Occlusion Culling";
|
const QString EnableOcclusionCulling = "Enable Occlusion Culling";
|
||||||
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
|
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
|
||||||
|
const QString AudioNoiseReduction = "Audio Noise Reduction";
|
||||||
const QString EchoServerAudio = "Echo Server Audio";
|
const QString EchoServerAudio = "Echo Server Audio";
|
||||||
const QString EchoLocalAudio = "Echo Local Audio";
|
const QString EchoLocalAudio = "Echo Local Audio";
|
||||||
const QString MuteAudio = "Mute Microphone";
|
const QString MuteAudio = "Mute Microphone";
|
||||||
|
|
|
@ -82,7 +82,6 @@ public:
|
||||||
//getters
|
//getters
|
||||||
bool isInitialized() const { return _initialized; }
|
bool isInitialized() const { return _initialized; }
|
||||||
SkeletonModel& getSkeletonModel() { return _skeletonModel; }
|
SkeletonModel& getSkeletonModel() { return _skeletonModel; }
|
||||||
float getHeadYawRate() const { return _head.yawRate; }
|
|
||||||
glm::vec3 getChestPosition() const;
|
glm::vec3 getChestPosition() const;
|
||||||
float getScale() const { return _scale; }
|
float getScale() const { return _scale; }
|
||||||
const glm::vec3& getVelocity() const { return _velocity; }
|
const glm::vec3& getVelocity() const { return _velocity; }
|
||||||
|
|
|
@ -59,15 +59,15 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX
|
||||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) *
|
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) *
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation)));
|
joint.preTransform * glm::mat4_cast(joint.preRotation)));
|
||||||
state.rotation = glm::angleAxis(-_owningHead->getRoll(), glm::normalize(inverse * axes[2])) *
|
state.rotation = glm::angleAxis(-_owningHead->getRoll(), glm::normalize(inverse * axes[2])) *
|
||||||
glm::angleAxis(_owningHead->getYaw(), glm::normalize(inverse * axes[1])) *
|
glm::angleAxis(_owningHead->getTweakedYaw(), glm::normalize(inverse * axes[1])) *
|
||||||
glm::angleAxis(-_owningHead->getPitch(), glm::normalize(inverse * axes[0])) * joint.rotation;
|
glm::angleAxis(-_owningHead->getTweakedPitch(), glm::normalize(inverse * axes[0])) * joint.rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||||
// likewise with the eye joints
|
// likewise with the eye joints
|
||||||
glm::mat4 inverse = glm::inverse(parentState.transform * glm::translate(state.translation) *
|
glm::mat4 inverse = glm::inverse(parentState.transform * glm::translate(state.translation) *
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
||||||
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getOrientation() * IDENTITY_FRONT, 0.0f));
|
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getTweakedOrientation() * IDENTITY_FRONT, 0.0f));
|
||||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
||||||
_owningHead->getSaccade() - _translation, 1.0f));
|
_owningHead->getSaccade() - _translation, 1.0f));
|
||||||
glm::quat between = rotationBetween(front, lookAt);
|
glm::quat between = rotationBetween(front, lookAt);
|
||||||
|
|
|
@ -18,7 +18,6 @@ using namespace std;
|
||||||
|
|
||||||
Head::Head(Avatar* owningAvatar) :
|
Head::Head(Avatar* owningAvatar) :
|
||||||
HeadData((AvatarData*)owningAvatar),
|
HeadData((AvatarData*)owningAvatar),
|
||||||
yawRate(0.0f),
|
|
||||||
_returnHeadToCenter(false),
|
_returnHeadToCenter(false),
|
||||||
_position(0.0f, 0.0f, 0.0f),
|
_position(0.0f, 0.0f, 0.0f),
|
||||||
_rotation(0.0f, 0.0f, 0.0f),
|
_rotation(0.0f, 0.0f, 0.0f),
|
||||||
|
@ -37,6 +36,9 @@ Head::Head(Avatar* owningAvatar) :
|
||||||
_leftEyeBlinkVelocity(0.0f),
|
_leftEyeBlinkVelocity(0.0f),
|
||||||
_rightEyeBlinkVelocity(0.0f),
|
_rightEyeBlinkVelocity(0.0f),
|
||||||
_timeWithoutTalking(0.0f),
|
_timeWithoutTalking(0.0f),
|
||||||
|
_tweakedPitch(0.f),
|
||||||
|
_tweakedYaw(0.f),
|
||||||
|
_tweakedRoll(0.f),
|
||||||
_isCameraMoving(false),
|
_isCameraMoving(false),
|
||||||
_faceModel(this)
|
_faceModel(this)
|
||||||
{
|
{
|
||||||
|
@ -186,9 +188,14 @@ glm::quat Head::getOrientation() const {
|
||||||
return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(glm::vec3(_pitch, _yaw, _roll)));
|
return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(glm::vec3(_pitch, _yaw, _roll)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::quat Head::getTweakedOrientation() const {
|
||||||
|
return glm::quat(glm::radians(_bodyRotation)) * glm::quat(glm::radians(glm::vec3(getTweakedPitch(), getTweakedYaw(), getTweakedRoll() )));
|
||||||
|
}
|
||||||
|
|
||||||
glm::quat Head::getCameraOrientation () const {
|
glm::quat Head::getCameraOrientation () const {
|
||||||
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);
|
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);
|
||||||
return owningAvatar->getWorldAlignedOrientation();
|
return owningAvatar->getWorldAlignedOrientation()
|
||||||
|
* glm::quat(glm::radians(glm::vec3(_pitch, 0.f, 0.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const {
|
glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const {
|
||||||
|
@ -200,6 +207,18 @@ glm::vec3 Head::getScalePivot() const {
|
||||||
return _faceModel.isActive() ? _faceModel.getTranslation() : _position;
|
return _faceModel.isActive() ? _faceModel.getTranslation() : _position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Head::getTweakedYaw() const {
|
||||||
|
return glm::clamp(_yaw + _tweakedYaw, MIN_HEAD_YAW, MAX_HEAD_YAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Head::getTweakedPitch() const {
|
||||||
|
return glm::clamp(_pitch + _tweakedPitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Head::getTweakedRoll() const {
|
||||||
|
return glm::clamp(_roll + _tweakedRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL);
|
||||||
|
}
|
||||||
|
|
||||||
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
||||||
|
|
||||||
Application::getInstance()->getGlowEffect()->begin();
|
Application::getInstance()->getGlowEffect()->begin();
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include <AvatarData.h>
|
#include <HeadData.h>
|
||||||
|
|
||||||
#include <VoxelConstants.h>
|
#include <VoxelConstants.h>
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ public:
|
||||||
void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; }
|
void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; }
|
||||||
|
|
||||||
glm::quat getOrientation() const;
|
glm::quat getOrientation() const;
|
||||||
|
glm::quat getTweakedOrientation() const;
|
||||||
glm::quat getCameraOrientation () const;
|
glm::quat getCameraOrientation () const;
|
||||||
const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
|
const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
|
||||||
void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; }
|
void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; }
|
||||||
|
@ -71,7 +72,13 @@ public:
|
||||||
/// Returns the point about which scaling occurs.
|
/// Returns the point about which scaling occurs.
|
||||||
glm::vec3 getScalePivot() const;
|
glm::vec3 getScalePivot() const;
|
||||||
|
|
||||||
float yawRate;
|
void tweakPitch(float pitch) { _tweakedPitch = pitch; }
|
||||||
|
void tweakYaw(float yaw) { _tweakedYaw = yaw; }
|
||||||
|
void tweakRoll(float roll) { _tweakedRoll = roll; }
|
||||||
|
|
||||||
|
float getTweakedPitch() const;
|
||||||
|
float getTweakedYaw() const;
|
||||||
|
float getTweakedRoll() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// disallow copies of the Head, copy of owning Avatar is disallowed too
|
// disallow copies of the Head, copy of owning Avatar is disallowed too
|
||||||
|
@ -96,6 +103,12 @@ private:
|
||||||
float _leftEyeBlinkVelocity;
|
float _leftEyeBlinkVelocity;
|
||||||
float _rightEyeBlinkVelocity;
|
float _rightEyeBlinkVelocity;
|
||||||
float _timeWithoutTalking;
|
float _timeWithoutTalking;
|
||||||
|
|
||||||
|
// tweaked angles affect the rendered head, but not the camera
|
||||||
|
float _tweakedPitch;
|
||||||
|
float _tweakedYaw;
|
||||||
|
float _tweakedRoll;
|
||||||
|
|
||||||
bool _isCameraMoving;
|
bool _isCameraMoving;
|
||||||
FaceModel _faceModel;
|
FaceModel _faceModel;
|
||||||
|
|
||||||
|
|
|
@ -396,9 +396,9 @@ void MyAvatar::updateFromGyros(bool turnWithHead) {
|
||||||
const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f;
|
const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f;
|
||||||
const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f;
|
const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f;
|
||||||
const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f;
|
const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f;
|
||||||
_head.setPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
|
_head.tweakPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
|
||||||
_head.setYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
|
_head.tweakYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
|
||||||
_head.setRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
|
_head.tweakRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
|
||||||
|
|
||||||
// Update torso lean distance based on accelerometer data
|
// Update torso lean distance based on accelerometer data
|
||||||
const float TORSO_LENGTH = 0.5f;
|
const float TORSO_LENGTH = 0.5f;
|
||||||
|
|
|
@ -107,7 +107,6 @@ QByteArray AvatarData::toByteArray() {
|
||||||
destinationBuffer += sizeof(_headData->_lookAtPosition);
|
destinationBuffer += sizeof(_headData->_lookAtPosition);
|
||||||
|
|
||||||
// Instantaneous audio loudness (used to drive facial animation)
|
// Instantaneous audio loudness (used to drive facial animation)
|
||||||
//destinationBuffer += packFloatToByte(destinationBuffer, std::min(MAX_AUDIO_LOUDNESS, _audioLoudness), MAX_AUDIO_LOUDNESS);
|
|
||||||
memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float));
|
memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float));
|
||||||
destinationBuffer += sizeof(float);
|
destinationBuffer += sizeof(float);
|
||||||
|
|
||||||
|
@ -215,7 +214,6 @@ int AvatarData::parseData(const QByteArray& packet) {
|
||||||
sourceBuffer += sizeof(_headData->_lookAtPosition);
|
sourceBuffer += sizeof(_headData->_lookAtPosition);
|
||||||
|
|
||||||
// Instantaneous audio loudness (used to drive facial animation)
|
// Instantaneous audio loudness (used to drive facial animation)
|
||||||
//sourceBuffer += unpackFloatFromByte(sourceBuffer, _audioLoudness, MAX_AUDIO_LOUDNESS);
|
|
||||||
memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float));
|
memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float));
|
||||||
sourceBuffer += sizeof(float);
|
sourceBuffer += sizeof(float);
|
||||||
|
|
||||||
|
|
|
@ -9,18 +9,29 @@
|
||||||
// scripting engine
|
// scripting engine
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <RegisteredMetaTypes.h>
|
||||||
#include "EventTypes.h"
|
#include "EventTypes.h"
|
||||||
|
|
||||||
|
|
||||||
KeyEvent::KeyEvent() {
|
void registerEventTypes(QScriptEngine* engine) {
|
||||||
key = 0;
|
qScriptRegisterMetaType(engine, keyEventToScriptValue, keyEventFromScriptValue);
|
||||||
text = QString("");
|
qScriptRegisterMetaType(engine, mouseEventToScriptValue, mouseEventFromScriptValue);
|
||||||
isShifted = false;
|
qScriptRegisterMetaType(engine, touchEventToScriptValue, touchEventFromScriptValue);
|
||||||
isMeta = false;
|
qScriptRegisterMetaType(engine, wheelEventToScriptValue, wheelEventFromScriptValue);
|
||||||
isControl = false;
|
|
||||||
isValid = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyEvent::KeyEvent() :
|
||||||
|
key(0),
|
||||||
|
text(""),
|
||||||
|
isShifted(false),
|
||||||
|
isControl(false),
|
||||||
|
isMeta(false),
|
||||||
|
isAlt(false),
|
||||||
|
isKeypad(false),
|
||||||
|
isValid(false)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
KeyEvent::KeyEvent(const QKeyEvent& event) {
|
KeyEvent::KeyEvent(const QKeyEvent& event) {
|
||||||
key = event.key();
|
key = event.key();
|
||||||
|
@ -73,43 +84,34 @@ KeyEvent::KeyEvent(const QKeyEvent& event) {
|
||||||
text = "DELETE";
|
text = "DELETE";
|
||||||
} else if (key == Qt::Key_Backspace) {
|
} else if (key == Qt::Key_Backspace) {
|
||||||
text = "BACKSPACE";
|
text = "BACKSPACE";
|
||||||
|
} else if (key == Qt::Key_Shift) {
|
||||||
|
text = "SHIFT";
|
||||||
|
} else if (key == Qt::Key_Alt) {
|
||||||
|
text = "ALT";
|
||||||
|
} else if (key == Qt::Key_Control) {
|
||||||
|
text = "CONTROL";
|
||||||
|
} else if (key == Qt::Key_Meta) {
|
||||||
|
text = "META";
|
||||||
|
} else if (key == Qt::Key_PageDown) {
|
||||||
|
text = "PAGE DOWN";
|
||||||
|
} else if (key == Qt::Key_PageUp) {
|
||||||
|
text = "PAGE UP";
|
||||||
|
} else if (key == Qt::Key_Home) {
|
||||||
|
text = "HOME";
|
||||||
|
} else if (key == Qt::Key_End) {
|
||||||
|
text = "END";
|
||||||
|
} else if (key == Qt::Key_Help) {
|
||||||
|
text = "HELP";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseEvent::MouseEvent(const QMouseEvent& event) {
|
bool KeyEvent::operator==(const KeyEvent& other) const {
|
||||||
x = event.x();
|
return other.key == key
|
||||||
y = event.y();
|
&& other.isShifted == isShifted
|
||||||
}
|
&& other.isControl == isControl
|
||||||
|
&& other.isMeta == isMeta
|
||||||
TouchEvent::TouchEvent(const QTouchEvent& event) {
|
&& other.isAlt == isAlt
|
||||||
// convert the touch points into an average
|
&& other.isKeypad == isKeypad;
|
||||||
const QList<QTouchEvent::TouchPoint>& tPoints = event.touchPoints();
|
|
||||||
float touchAvgX = 0.0f;
|
|
||||||
float touchAvgY = 0.0f;
|
|
||||||
int numTouches = tPoints.count();
|
|
||||||
if (numTouches > 1) {
|
|
||||||
for (int i = 0; i < numTouches; ++i) {
|
|
||||||
touchAvgX += tPoints[i].pos().x();
|
|
||||||
touchAvgY += tPoints[i].pos().y();
|
|
||||||
}
|
|
||||||
touchAvgX /= (float)(numTouches);
|
|
||||||
touchAvgY /= (float)(numTouches);
|
|
||||||
}
|
|
||||||
x = touchAvgX;
|
|
||||||
y = touchAvgY;
|
|
||||||
}
|
|
||||||
|
|
||||||
WheelEvent::WheelEvent(const QWheelEvent& event) {
|
|
||||||
x = event.x();
|
|
||||||
y = event.y();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void registerEventTypes(QScriptEngine* engine) {
|
|
||||||
qScriptRegisterMetaType(engine, keyEventToScriptValue, keyEventFromScriptValue);
|
|
||||||
qScriptRegisterMetaType(engine, mouseEventToScriptValue, mouseEventFromScriptValue);
|
|
||||||
qScriptRegisterMetaType(engine, touchEventToScriptValue, touchEventFromScriptValue);
|
|
||||||
qScriptRegisterMetaType(engine, wheelEventToScriptValue, wheelEventFromScriptValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue keyEventToScriptValue(QScriptEngine* engine, const KeyEvent& event) {
|
QScriptValue keyEventToScriptValue(QScriptEngine* engine, const KeyEvent& event) {
|
||||||
|
@ -188,6 +190,24 @@ void keyEventFromScriptValue(const QScriptValue& object, KeyEvent& event) {
|
||||||
event.key = Qt::Key_Delete;
|
event.key = Qt::Key_Delete;
|
||||||
} else if (event.text.toUpper() == "BACKSPACE") {
|
} else if (event.text.toUpper() == "BACKSPACE") {
|
||||||
event.key = Qt::Key_Backspace;
|
event.key = Qt::Key_Backspace;
|
||||||
|
} else if (event.text.toUpper() == "SHIFT") {
|
||||||
|
event.key = Qt::Key_Shift;
|
||||||
|
} else if (event.text.toUpper() == "ALT") {
|
||||||
|
event.key = Qt::Key_Alt;
|
||||||
|
} else if (event.text.toUpper() == "CONTROL") {
|
||||||
|
event.key = Qt::Key_Control;
|
||||||
|
} else if (event.text.toUpper() == "META") {
|
||||||
|
event.key = Qt::Key_Meta;
|
||||||
|
} else if (event.text.toUpper() == "PAGE DOWN") {
|
||||||
|
event.key = Qt::Key_PageDown;
|
||||||
|
} else if (event.text.toUpper() == "PAGE UP") {
|
||||||
|
event.key = Qt::Key_PageUp;
|
||||||
|
} else if (event.text.toUpper() == "HOME") {
|
||||||
|
event.key = Qt::Key_Home;
|
||||||
|
} else if (event.text.toUpper() == "END") {
|
||||||
|
event.key = Qt::Key_End;
|
||||||
|
} else if (event.text.toUpper() == "HELP") {
|
||||||
|
event.key = Qt::Key_Help;
|
||||||
} else {
|
} else {
|
||||||
event.key = event.text.at(0).unicode();
|
event.key = event.text.at(0).unicode();
|
||||||
}
|
}
|
||||||
|
@ -224,10 +244,67 @@ void keyEventFromScriptValue(const QScriptValue& object, KeyEvent& event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MouseEvent::MouseEvent() :
|
||||||
|
x(0.0f),
|
||||||
|
y(0.0f),
|
||||||
|
isLeftButton(false),
|
||||||
|
isRightButton(false),
|
||||||
|
isMiddleButton(false),
|
||||||
|
isShifted(false),
|
||||||
|
isControl(false),
|
||||||
|
isMeta(false),
|
||||||
|
isAlt(false)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MouseEvent::MouseEvent(const QMouseEvent& event) {
|
||||||
|
x = event.x();
|
||||||
|
y = event.y();
|
||||||
|
|
||||||
|
// single button that caused the event
|
||||||
|
switch (event.button()) {
|
||||||
|
case Qt::LeftButton:
|
||||||
|
button = "LEFT";
|
||||||
|
isLeftButton = true;
|
||||||
|
break;
|
||||||
|
case Qt::RightButton:
|
||||||
|
button = "RIGHT";
|
||||||
|
isRightButton = true;
|
||||||
|
break;
|
||||||
|
case Qt::MiddleButton:
|
||||||
|
button = "MIDDLE";
|
||||||
|
isMiddleButton = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
button = "NONE";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// button pressed state
|
||||||
|
isLeftButton = isLeftButton || (event.buttons().testFlag(Qt::LeftButton));
|
||||||
|
isRightButton = isRightButton || (event.buttons().testFlag(Qt::RightButton));
|
||||||
|
isMiddleButton = isMiddleButton || (event.buttons().testFlag(Qt::MiddleButton));
|
||||||
|
|
||||||
|
// keyboard modifiers
|
||||||
|
isShifted = event.modifiers().testFlag(Qt::ShiftModifier);
|
||||||
|
isMeta = event.modifiers().testFlag(Qt::MetaModifier);
|
||||||
|
isControl = event.modifiers().testFlag(Qt::ControlModifier);
|
||||||
|
isAlt = event.modifiers().testFlag(Qt::AltModifier);
|
||||||
|
}
|
||||||
|
|
||||||
QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& event) {
|
QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& event) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("x", event.x);
|
obj.setProperty("x", event.x);
|
||||||
obj.setProperty("y", event.y);
|
obj.setProperty("y", event.y);
|
||||||
|
obj.setProperty("button", event.button);
|
||||||
|
obj.setProperty("isLeftButton", event.isLeftButton);
|
||||||
|
obj.setProperty("isRightButton", event.isRightButton);
|
||||||
|
obj.setProperty("isMiddleButton", event.isMiddleButton);
|
||||||
|
obj.setProperty("isShifted", event.isShifted);
|
||||||
|
obj.setProperty("isMeta", event.isMeta);
|
||||||
|
obj.setProperty("isControl", event.isControl);
|
||||||
|
obj.setProperty("isAlt", event.isAlt);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,10 +312,192 @@ void mouseEventFromScriptValue(const QScriptValue& object, MouseEvent& event) {
|
||||||
// nothing for now...
|
// nothing for now...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TouchEvent::TouchEvent() :
|
||||||
|
x(0.0f),
|
||||||
|
y(0.0f),
|
||||||
|
isPressed(false),
|
||||||
|
isMoved(false),
|
||||||
|
isStationary(false),
|
||||||
|
isReleased(false),
|
||||||
|
isShifted(false),
|
||||||
|
isControl(false),
|
||||||
|
isMeta(false),
|
||||||
|
isAlt(false),
|
||||||
|
touchPoints(0),
|
||||||
|
points(),
|
||||||
|
radius(0.0f),
|
||||||
|
isPinching(false),
|
||||||
|
isPinchOpening(false),
|
||||||
|
angles(),
|
||||||
|
angle(0.0f),
|
||||||
|
deltaAngle(0.0f),
|
||||||
|
isRotating(false),
|
||||||
|
rotating("none")
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
TouchEvent::TouchEvent(const QTouchEvent& event) :
|
||||||
|
// these values are not set by initWithQTouchEvent() because they only apply to comparing to other events
|
||||||
|
isPinching(false),
|
||||||
|
isPinchOpening(false),
|
||||||
|
deltaAngle(0.0f),
|
||||||
|
isRotating(false),
|
||||||
|
rotating("none")
|
||||||
|
{
|
||||||
|
initWithQTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
TouchEvent::TouchEvent(const QTouchEvent& event, const TouchEvent& other) {
|
||||||
|
initWithQTouchEvent(event);
|
||||||
|
calculateMetaAttributes(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the degrees between two points (note: 0 degrees is 'east')
|
||||||
|
float angleBetweenPoints(const glm::vec2& a, const glm::vec2& b ) {
|
||||||
|
glm::vec2 length = b - a;
|
||||||
|
float radian = std::atan2(length.y, length.x);
|
||||||
|
float angle = radian * 180.0f / PIE;
|
||||||
|
if (angle < 0) {
|
||||||
|
angle += 360.0f;
|
||||||
|
};
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchEvent::initWithQTouchEvent(const QTouchEvent& event) {
|
||||||
|
// convert the touch points into an average
|
||||||
|
const QList<QTouchEvent::TouchPoint>& tPoints = event.touchPoints();
|
||||||
|
float touchAvgX = 0.0f;
|
||||||
|
float touchAvgY = 0.0f;
|
||||||
|
touchPoints = tPoints.count();
|
||||||
|
if (touchPoints > 1) {
|
||||||
|
for (int i = 0; i < touchPoints; ++i) {
|
||||||
|
touchAvgX += tPoints[i].pos().x();
|
||||||
|
touchAvgY += tPoints[i].pos().y();
|
||||||
|
|
||||||
|
// add it to our points vector
|
||||||
|
glm::vec2 thisPoint(tPoints[i].pos().x(), tPoints[i].pos().y());
|
||||||
|
points << thisPoint;
|
||||||
|
}
|
||||||
|
touchAvgX /= (float)(touchPoints);
|
||||||
|
touchAvgY /= (float)(touchPoints);
|
||||||
|
} else {
|
||||||
|
// I'm not sure this should ever happen, why would Qt send us a touch event for only one point?
|
||||||
|
// maybe this happens in the case of a multi-touch where all but the last finger is released?
|
||||||
|
touchAvgX = tPoints[0].pos().x();
|
||||||
|
touchAvgY = tPoints[0].pos().y();
|
||||||
|
}
|
||||||
|
x = touchAvgX;
|
||||||
|
y = touchAvgY;
|
||||||
|
|
||||||
|
// after calculating the center point (average touch point), determine the maximum radius
|
||||||
|
// also calculate the rotation angle for each point
|
||||||
|
float maxRadius = 0.0f;
|
||||||
|
glm::vec2 center(x,y);
|
||||||
|
for (int i = 0; i < touchPoints; ++i) {
|
||||||
|
glm::vec2 touchPoint(tPoints[i].pos().x(), tPoints[i].pos().y());
|
||||||
|
float thisRadius = glm::distance(center,touchPoint);
|
||||||
|
if (thisRadius > maxRadius) {
|
||||||
|
maxRadius = thisRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate the angle for this point
|
||||||
|
float thisAngle = angleBetweenPoints(center,touchPoint);
|
||||||
|
angles << thisAngle;
|
||||||
|
}
|
||||||
|
radius = maxRadius;
|
||||||
|
|
||||||
|
// after calculating the angles for each touch point, determine the average angle
|
||||||
|
float totalAngle = 0.0f;
|
||||||
|
for (int i = 0; i < touchPoints; ++i) {
|
||||||
|
totalAngle += angles[i];
|
||||||
|
}
|
||||||
|
angle = totalAngle/(float)touchPoints;
|
||||||
|
|
||||||
|
isPressed = event.touchPointStates().testFlag(Qt::TouchPointPressed);
|
||||||
|
isMoved = event.touchPointStates().testFlag(Qt::TouchPointMoved);
|
||||||
|
isStationary = event.touchPointStates().testFlag(Qt::TouchPointStationary);
|
||||||
|
isReleased = event.touchPointStates().testFlag(Qt::TouchPointReleased);
|
||||||
|
|
||||||
|
// keyboard modifiers
|
||||||
|
isShifted = event.modifiers().testFlag(Qt::ShiftModifier);
|
||||||
|
isMeta = event.modifiers().testFlag(Qt::MetaModifier);
|
||||||
|
isControl = event.modifiers().testFlag(Qt::ControlModifier);
|
||||||
|
isAlt = event.modifiers().testFlag(Qt::AltModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchEvent::calculateMetaAttributes(const TouchEvent& other) {
|
||||||
|
// calculate comparative event attributes...
|
||||||
|
if (other.radius > radius) {
|
||||||
|
isPinching = true;
|
||||||
|
isPinchOpening = false;
|
||||||
|
} else if (other.radius < radius) {
|
||||||
|
isPinchOpening = true;
|
||||||
|
isPinching = false;
|
||||||
|
} else {
|
||||||
|
isPinching = other.isPinching;
|
||||||
|
isPinchOpening = other.isPinchOpening;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if the points are rotating...
|
||||||
|
// note: if the number of touch points change between events, then we don't consider ourselves to be rotating
|
||||||
|
if (touchPoints == other.touchPoints) {
|
||||||
|
deltaAngle = angle - other.angle;
|
||||||
|
if (other.angle < angle) {
|
||||||
|
isRotating = true;
|
||||||
|
rotating = "clockwise";
|
||||||
|
} else if (other.angle > angle) {
|
||||||
|
isRotating = true;
|
||||||
|
rotating = "counterClockwise";
|
||||||
|
} else {
|
||||||
|
isRotating = false;
|
||||||
|
rotating = "none";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deltaAngle = 0.0f;
|
||||||
|
isRotating = false;
|
||||||
|
rotating = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QScriptValue touchEventToScriptValue(QScriptEngine* engine, const TouchEvent& event) {
|
QScriptValue touchEventToScriptValue(QScriptEngine* engine, const TouchEvent& event) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("x", event.x);
|
obj.setProperty("x", event.x);
|
||||||
obj.setProperty("y", event.y);
|
obj.setProperty("y", event.y);
|
||||||
|
obj.setProperty("isPressed", event.isPressed);
|
||||||
|
obj.setProperty("isMoved", event.isMoved);
|
||||||
|
obj.setProperty("isStationary", event.isStationary);
|
||||||
|
obj.setProperty("isReleased", event.isReleased);
|
||||||
|
obj.setProperty("isShifted", event.isShifted);
|
||||||
|
obj.setProperty("isMeta", event.isMeta);
|
||||||
|
obj.setProperty("isControl", event.isControl);
|
||||||
|
obj.setProperty("isAlt", event.isAlt);
|
||||||
|
obj.setProperty("touchPoints", event.touchPoints);
|
||||||
|
|
||||||
|
QScriptValue pointsObj = engine->newArray();
|
||||||
|
int index = 0;
|
||||||
|
foreach (glm::vec2 point, event.points) {
|
||||||
|
QScriptValue thisPoint = vec2toScriptValue(engine, point);
|
||||||
|
pointsObj.setProperty(index, thisPoint);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
obj.setProperty("points", pointsObj);
|
||||||
|
obj.setProperty("radius", event.radius);
|
||||||
|
obj.setProperty("isPinching", event.isPinching);
|
||||||
|
obj.setProperty("isPinchOpening", event.isPinchOpening);
|
||||||
|
|
||||||
|
obj.setProperty("angle", event.angle);
|
||||||
|
obj.setProperty("deltaAngle", event.deltaAngle);
|
||||||
|
QScriptValue anglesObj = engine->newArray();
|
||||||
|
index = 0;
|
||||||
|
foreach (float angle, event.angles) {
|
||||||
|
anglesObj.setProperty(index, angle);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
obj.setProperty("angles", anglesObj);
|
||||||
|
|
||||||
|
obj.setProperty("isRotating", event.isRotating);
|
||||||
|
obj.setProperty("rotating", event.rotating);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,10 +505,58 @@ void touchEventFromScriptValue(const QScriptValue& object, TouchEvent& event) {
|
||||||
// nothing for now...
|
// nothing for now...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WheelEvent::WheelEvent() :
|
||||||
|
x(0.0f),
|
||||||
|
y(0.0f),
|
||||||
|
delta(0.0f),
|
||||||
|
orientation("UNKNOwN"),
|
||||||
|
isLeftButton(false),
|
||||||
|
isRightButton(false),
|
||||||
|
isMiddleButton(false),
|
||||||
|
isShifted(false),
|
||||||
|
isControl(false),
|
||||||
|
isMeta(false),
|
||||||
|
isAlt(false)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
WheelEvent::WheelEvent(const QWheelEvent& event) {
|
||||||
|
x = event.x();
|
||||||
|
y = event.y();
|
||||||
|
|
||||||
|
delta = event.delta();
|
||||||
|
if (event.orientation() == Qt::Horizontal) {
|
||||||
|
orientation = "HORIZONTAL";
|
||||||
|
} else {
|
||||||
|
orientation = "VERTICAL";
|
||||||
|
}
|
||||||
|
|
||||||
|
// button pressed state
|
||||||
|
isLeftButton = (event.buttons().testFlag(Qt::LeftButton));
|
||||||
|
isRightButton = (event.buttons().testFlag(Qt::RightButton));
|
||||||
|
isMiddleButton = (event.buttons().testFlag(Qt::MiddleButton));
|
||||||
|
|
||||||
|
// keyboard modifiers
|
||||||
|
isShifted = event.modifiers().testFlag(Qt::ShiftModifier);
|
||||||
|
isMeta = event.modifiers().testFlag(Qt::MetaModifier);
|
||||||
|
isControl = event.modifiers().testFlag(Qt::ControlModifier);
|
||||||
|
isAlt = event.modifiers().testFlag(Qt::AltModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QScriptValue wheelEventToScriptValue(QScriptEngine* engine, const WheelEvent& event) {
|
QScriptValue wheelEventToScriptValue(QScriptEngine* engine, const WheelEvent& event) {
|
||||||
QScriptValue obj = engine->newObject();
|
QScriptValue obj = engine->newObject();
|
||||||
obj.setProperty("x", event.x);
|
obj.setProperty("x", event.x);
|
||||||
obj.setProperty("y", event.y);
|
obj.setProperty("y", event.y);
|
||||||
|
obj.setProperty("delta", event.delta);
|
||||||
|
obj.setProperty("orientation", event.orientation);
|
||||||
|
obj.setProperty("isLeftButton", event.isLeftButton);
|
||||||
|
obj.setProperty("isRightButton", event.isRightButton);
|
||||||
|
obj.setProperty("isMiddleButton", event.isMiddleButton);
|
||||||
|
obj.setProperty("isShifted", event.isShifted);
|
||||||
|
obj.setProperty("isMeta", event.isMeta);
|
||||||
|
obj.setProperty("isControl", event.isControl);
|
||||||
|
obj.setProperty("isAlt", event.isAlt);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,7 @@ class KeyEvent {
|
||||||
public:
|
public:
|
||||||
KeyEvent();
|
KeyEvent();
|
||||||
KeyEvent(const QKeyEvent& event);
|
KeyEvent(const QKeyEvent& event);
|
||||||
inline bool operator==(const KeyEvent& other) const {
|
bool operator==(const KeyEvent& other) const;
|
||||||
return other.key == key
|
|
||||||
&& other.isShifted == isShifted
|
|
||||||
&& other.isControl == isControl
|
|
||||||
&& other.isMeta == isMeta
|
|
||||||
&& other.isAlt == isAlt
|
|
||||||
&& other.isKeypad == isKeypad; }
|
|
||||||
int key;
|
int key;
|
||||||
QString text;
|
QString text;
|
||||||
bool isShifted;
|
bool isShifted;
|
||||||
|
@ -43,26 +37,67 @@ public:
|
||||||
|
|
||||||
class MouseEvent {
|
class MouseEvent {
|
||||||
public:
|
public:
|
||||||
MouseEvent() : x(0), y(0) { };
|
MouseEvent();
|
||||||
MouseEvent(const QMouseEvent& event);
|
MouseEvent(const QMouseEvent& event);
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
QString button;
|
||||||
|
bool isLeftButton;
|
||||||
|
bool isRightButton;
|
||||||
|
bool isMiddleButton;
|
||||||
|
bool isShifted;
|
||||||
|
bool isControl;
|
||||||
|
bool isMeta;
|
||||||
|
bool isAlt;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TouchEvent {
|
class TouchEvent {
|
||||||
public:
|
public:
|
||||||
TouchEvent() : x(0), y(0) { };
|
TouchEvent();
|
||||||
TouchEvent(const QTouchEvent& event);
|
TouchEvent(const QTouchEvent& event);
|
||||||
|
TouchEvent(const QTouchEvent& event, const TouchEvent& other);
|
||||||
|
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
bool isPressed;
|
||||||
|
bool isMoved;
|
||||||
|
bool isStationary;
|
||||||
|
bool isReleased;
|
||||||
|
bool isShifted;
|
||||||
|
bool isControl;
|
||||||
|
bool isMeta;
|
||||||
|
bool isAlt;
|
||||||
|
int touchPoints;
|
||||||
|
QVector<glm::vec2> points;
|
||||||
|
float radius;
|
||||||
|
bool isPinching;
|
||||||
|
bool isPinchOpening;
|
||||||
|
QVector<float> angles; // angle from center to each point
|
||||||
|
float angle; // the average of the angles
|
||||||
|
float deltaAngle; // the change in average angle from last event
|
||||||
|
bool isRotating;
|
||||||
|
QString rotating;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initWithQTouchEvent(const QTouchEvent& event);
|
||||||
|
void calculateMetaAttributes(const TouchEvent& other);
|
||||||
};
|
};
|
||||||
|
|
||||||
class WheelEvent {
|
class WheelEvent {
|
||||||
public:
|
public:
|
||||||
WheelEvent() : x(0), y(0) { };
|
WheelEvent();
|
||||||
WheelEvent(const QWheelEvent& event);
|
WheelEvent(const QWheelEvent& event);
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
int delta;
|
||||||
|
QString orientation;
|
||||||
|
bool isLeftButton;
|
||||||
|
bool isRightButton;
|
||||||
|
bool isMiddleButton;
|
||||||
|
bool isShifted;
|
||||||
|
bool isControl;
|
||||||
|
bool isMeta;
|
||||||
|
bool isAlt;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(KeyEvent)
|
Q_DECLARE_METATYPE(KeyEvent)
|
||||||
|
|
|
@ -125,6 +125,7 @@ void ScriptEngine::init() {
|
||||||
qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue);
|
qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue);
|
||||||
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
||||||
qScriptRegisterSequenceMetaType<QVector<ParticleID> >(&_engine);
|
qScriptRegisterSequenceMetaType<QVector<ParticleID> >(&_engine);
|
||||||
|
qScriptRegisterSequenceMetaType<QVector<glm::vec2> >(&_engine);
|
||||||
|
|
||||||
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
|
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
|
||||||
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||||
|
|
|
@ -81,7 +81,6 @@ QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay)
|
||||||
QScriptValue direction = vec3toScriptValue(engine, pickRay.direction);
|
QScriptValue direction = vec3toScriptValue(engine, pickRay.direction);
|
||||||
obj.setProperty("direction", direction);
|
obj.setProperty("direction", direction);
|
||||||
return obj;
|
return obj;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay) {
|
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay) {
|
||||||
|
|
|
@ -46,5 +46,4 @@ Q_DECLARE_METATYPE(PickRay)
|
||||||
QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay);
|
QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay);
|
||||||
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
|
void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,11 +9,12 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm
|
||||||
set(TARGET_NAME voxels)
|
set(TARGET_NAME voxels)
|
||||||
|
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
find_package(Qt5Script REQUIRED)
|
||||||
|
|
||||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||||
setup_hifi_library(${TARGET_NAME})
|
setup_hifi_library(${TARGET_NAME})
|
||||||
|
|
||||||
qt5_use_modules(${TARGET_NAME} Widgets)
|
qt5_use_modules(${TARGET_NAME} Widgets Script)
|
||||||
|
|
||||||
include(${MACRO_DIR}/IncludeGLM.cmake)
|
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
|
@ -5,10 +5,13 @@
|
||||||
// Created by Brad Hefta-Gaub on 1/29/2014
|
// Created by Brad Hefta-Gaub on 1/29/2014
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <RegisteredMetaTypes.h>
|
||||||
#include "VoxelDetail.h"
|
#include "VoxelDetail.h"
|
||||||
|
|
||||||
void registerVoxelMetaTypes(QScriptEngine* engine) {
|
void registerVoxelMetaTypes(QScriptEngine* engine) {
|
||||||
qScriptRegisterMetaType(engine, voxelDetailToScriptValue, voxelDetailFromScriptValue);
|
qScriptRegisterMetaType(engine, voxelDetailToScriptValue, voxelDetailFromScriptValue);
|
||||||
|
qScriptRegisterMetaType(engine, rayToVoxelIntersectionResultToScriptValue, rayToVoxelIntersectionResultFromScriptValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& voxelDetail) {
|
QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& voxelDetail) {
|
||||||
|
@ -33,5 +36,78 @@ void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& voxelDe
|
||||||
voxelDetail.blue = object.property("blue").toVariant().toInt();
|
voxelDetail.blue = object.property("blue").toVariant().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RayToVoxelIntersectionResult::RayToVoxelIntersectionResult() :
|
||||||
|
intersects(false),
|
||||||
|
voxel(),
|
||||||
|
distance(0),
|
||||||
|
face()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, const RayToVoxelIntersectionResult& value) {
|
||||||
|
QScriptValue obj = engine->newObject();
|
||||||
|
obj.setProperty("intersects", value.intersects);
|
||||||
|
QScriptValue voxelValue = voxelDetailToScriptValue(engine, value.voxel);
|
||||||
|
obj.setProperty("voxel", voxelValue);
|
||||||
|
obj.setProperty("distance", value.distance);
|
||||||
|
|
||||||
|
QString faceName = "";
|
||||||
|
// handle BoxFace
|
||||||
|
switch (value.face) {
|
||||||
|
case MIN_X_FACE:
|
||||||
|
faceName = "MIN_X_FACE";
|
||||||
|
break;
|
||||||
|
case MAX_X_FACE:
|
||||||
|
faceName = "MAX_X_FACE";
|
||||||
|
break;
|
||||||
|
case MIN_Y_FACE:
|
||||||
|
faceName = "MIN_Y_FACE";
|
||||||
|
break;
|
||||||
|
case MAX_Y_FACE:
|
||||||
|
faceName = "MAX_Y_FACE";
|
||||||
|
break;
|
||||||
|
case MIN_Z_FACE:
|
||||||
|
faceName = "MIN_Z_FACE";
|
||||||
|
break;
|
||||||
|
case MAX_Z_FACE:
|
||||||
|
faceName = "MAX_Z_FACE";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
obj.setProperty("face", faceName);
|
||||||
|
|
||||||
|
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
|
||||||
|
obj.setProperty("intersection", intersection);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rayToVoxelIntersectionResultFromScriptValue(const QScriptValue& object, RayToVoxelIntersectionResult& value) {
|
||||||
|
value.intersects = object.property("intersects").toVariant().toBool();
|
||||||
|
QScriptValue voxelValue = object.property("voxel");
|
||||||
|
if (voxelValue.isValid()) {
|
||||||
|
voxelDetailFromScriptValue(voxelValue, value.voxel);
|
||||||
|
}
|
||||||
|
value.distance = object.property("distance").toVariant().toFloat();
|
||||||
|
|
||||||
|
QString faceName = object.property("face").toVariant().toString();
|
||||||
|
if (faceName == "MIN_X_FACE") {
|
||||||
|
value.face = MIN_X_FACE;
|
||||||
|
} else if (faceName == "MAX_X_FACE") {
|
||||||
|
value.face = MAX_X_FACE;
|
||||||
|
} else if (faceName == "MIN_Y_FACE") {
|
||||||
|
value.face = MIN_Y_FACE;
|
||||||
|
} else if (faceName == "MAX_Y_FACE") {
|
||||||
|
value.face = MAX_Y_FACE;
|
||||||
|
} else if (faceName == "MIN_Z_FACE") {
|
||||||
|
value.face = MIN_Z_FACE;
|
||||||
|
} else {
|
||||||
|
value.face = MAX_Z_FACE;
|
||||||
|
};
|
||||||
|
QScriptValue intersection = object.property("intersection");
|
||||||
|
if (intersection.isValid()) {
|
||||||
|
vec3FromScriptValue(intersection, value.intersection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
|
#include <AABox.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include "VoxelConstants.h"
|
#include "VoxelConstants.h"
|
||||||
|
|
||||||
|
@ -32,5 +33,19 @@ void registerVoxelMetaTypes(QScriptEngine* engine);
|
||||||
QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& color);
|
QScriptValue voxelDetailToScriptValue(QScriptEngine* engine, const VoxelDetail& color);
|
||||||
void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& color);
|
void voxelDetailFromScriptValue(const QScriptValue &object, VoxelDetail& color);
|
||||||
|
|
||||||
|
class RayToVoxelIntersectionResult {
|
||||||
|
public:
|
||||||
|
RayToVoxelIntersectionResult();
|
||||||
|
bool intersects;
|
||||||
|
VoxelDetail voxel;
|
||||||
|
float distance;
|
||||||
|
BoxFace face;
|
||||||
|
glm::vec3 intersection;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(RayToVoxelIntersectionResult)
|
||||||
|
|
||||||
|
QScriptValue rayToVoxelIntersectionResultToScriptValue(QScriptEngine* engine, const RayToVoxelIntersectionResult& results);
|
||||||
|
void rayToVoxelIntersectionResultFromScriptValue(const QScriptValue& object, RayToVoxelIntersectionResult& results);
|
||||||
|
|
||||||
#endif /* defined(__hifi__VoxelDetail__) */
|
#endif /* defined(__hifi__VoxelDetail__) */
|
|
@ -41,3 +41,26 @@ void VoxelsScriptingInterface::eraseVoxel(float x, float y, float z, float scale
|
||||||
getVoxelPacketSender()->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &deleteVoxelDetail);
|
getVoxelPacketSender()->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &deleteVoxelDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RayToVoxelIntersectionResult VoxelsScriptingInterface::findRayIntersection(const PickRay& ray) {
|
||||||
|
RayToVoxelIntersectionResult result;
|
||||||
|
if (_tree) {
|
||||||
|
if (_tree->tryLockForRead()) {
|
||||||
|
OctreeElement* element;
|
||||||
|
result.intersects = _tree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face);
|
||||||
|
if (result.intersects) {
|
||||||
|
VoxelTreeElement* voxel = (VoxelTreeElement*)element;
|
||||||
|
result.voxel.x = voxel->getCorner().x;
|
||||||
|
result.voxel.y = voxel->getCorner().y;
|
||||||
|
result.voxel.z = voxel->getCorner().z;
|
||||||
|
result.voxel.s = voxel->getScale();
|
||||||
|
result.voxel.red = voxel->getColor()[0];
|
||||||
|
result.voxel.green = voxel->getColor()[1];
|
||||||
|
result.voxel.blue = voxel->getColor()[2];
|
||||||
|
result.intersection = ray.origin + (ray.direction * result.distance);
|
||||||
|
}
|
||||||
|
_tree->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -12,18 +12,22 @@
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
#include <OctreeScriptingInterface.h>
|
#include <OctreeScriptingInterface.h>
|
||||||
|
#include <RegisteredMetaTypes.h>
|
||||||
|
|
||||||
#include "VoxelConstants.h"
|
#include "VoxelConstants.h"
|
||||||
#include "VoxelEditPacketSender.h"
|
#include "VoxelEditPacketSender.h"
|
||||||
|
#include "VoxelTree.h"
|
||||||
|
|
||||||
/// handles scripting of voxel commands from JS passed to assigned clients
|
/// handles scripting of voxel commands from JS passed to assigned clients
|
||||||
class VoxelsScriptingInterface : public OctreeScriptingInterface {
|
class VoxelsScriptingInterface : public OctreeScriptingInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
VoxelsScriptingInterface() : _tree(NULL) {};
|
||||||
VoxelEditPacketSender* getVoxelPacketSender() { return (VoxelEditPacketSender*)getPacketSender(); }
|
VoxelEditPacketSender* getVoxelPacketSender() { return (VoxelEditPacketSender*)getPacketSender(); }
|
||||||
|
|
||||||
virtual NodeType_t getServerNodeType() const { return NodeType::VoxelServer; }
|
virtual NodeType_t getServerNodeType() const { return NodeType::VoxelServer; }
|
||||||
virtual OctreeEditPacketSender* createPacketSender() { return new VoxelEditPacketSender(); }
|
virtual OctreeEditPacketSender* createPacketSender() { return new VoxelEditPacketSender(); }
|
||||||
|
void setVoxelTree(VoxelTree* tree) { _tree = tree; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// queues the creation of a voxel which will be sent by calling process on the PacketSender
|
/// queues the creation of a voxel which will be sent by calling process on the PacketSender
|
||||||
|
@ -53,8 +57,12 @@ public slots:
|
||||||
/// \param scale the scale of the voxel (in meter units)
|
/// \param scale the scale of the voxel (in meter units)
|
||||||
void eraseVoxel(float x, float y, float z, float scale);
|
void eraseVoxel(float x, float y, float z, float scale);
|
||||||
|
|
||||||
|
/// If the scripting context has visible voxels, this will determine a ray intersection
|
||||||
|
RayToVoxelIntersectionResult findRayIntersection(const PickRay& ray);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails);
|
void queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails);
|
||||||
|
VoxelTree* _tree;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__VoxelsScriptingInterface__) */
|
#endif /* defined(__hifi__VoxelsScriptingInterface__) */
|
||||||
|
|
|
@ -13,9 +13,11 @@ include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||||
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||||
|
|
||||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||||
|
|
||||||
|
find_package(Qt5Script REQUIRED)
|
||||||
|
qt5_use_modules(${TARGET_NAME} Script)
|
||||||
|
|
||||||
# link in the shared library
|
# link in the shared library
|
||||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
Loading…
Reference in a new issue