From 7f33762aab74f937b76c08f8788ec7622865809f Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 6 Mar 2014 01:49:27 +0100 Subject: [PATCH 01/37] fixed invalid define guard --- interface/src/starfield/Controller.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/starfield/Controller.h b/interface/src/starfield/Controller.h index c5ade48442..5403d2fb75 100755 --- a/interface/src/starfield/Controller.h +++ b/interface/src/starfield/Controller.h @@ -8,7 +8,7 @@ // #ifndef __interface__starfield__Controller__ -#define __interface__starfield__Confroller__ +#define __interface__starfield__Controller__ #include From 438b07290785f1617fa471563b5ef138f4140512 Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 6 Mar 2014 02:29:12 +0100 Subject: [PATCH 02/37] editVoxels - importing voxels --- examples/editVoxels.js | 92 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 9a014639f0..24ae2a7330 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -26,6 +26,10 @@ var PIXELS_PER_EXTRUDE_VOXEL = 16; var WHEEL_PIXELS_PER_SCALE_CHANGE = 100; var MAX_VOXEL_SCALE = 1.0; var MIN_VOXEL_SCALE = 1.0 / Math.pow(2.0, 8.0); +var WHITE_COLOR = { red: 255, green: 255, blue: 255 }; + +var MAX_PASTE_VOXEL_SCALE = 256; +var MIN_PASTE_VOXEL_SCALE = .256; var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting var previewLineWidth = 1.5; @@ -199,6 +203,8 @@ var voxelToolAt = 0; var recolorToolAt = 1; var eyedropperToolAt = 2; +var pasteModeColor = { red: 132, green: 61, blue: 255 }; + var voxelTool = Overlays.addOverlay("image", { x: 0, y: 0, width: toolWidth, height: toolHeight, subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, @@ -262,7 +268,7 @@ var thumb = Overlays.addOverlay("image", { visible: false }); -var pointerVoxelScale = 0; // this is the voxel scale used for click to add or delete +var pointerVoxelScale = Math.floor(MAX_VOXEL_SCALE + MIN_VOXEL_SCALE) / 2; // this is the voxel scale used for click to add or delete var pointerVoxelScaleSet = false; // if voxel scale has not yet been set, we use the intersection size var pointerVoxelScaleSteps = 8; // the number of slider position steps @@ -308,6 +314,23 @@ function setAudioPosition() { audioOptions.position = Vec3.sum(camera, forwardVector); } +function getNewPasteVoxel(pickRay) { + + var voxelSize = MIN_PASTE_VOXEL_SCALE + (MAX_PASTE_VOXEL_SCALE - MIN_PASTE_VOXEL_SCALE) * pointerVoxelScale - 1; + var distance = 1 + 30 * voxelSize / MAX_PASTE_VOXEL_SCALE; + var origin = { x: pickRay.direction.x * NEW_VOXEL_DISTANCE_FROM_CAMERA + voxelSize, y: pickRay.direction.y, z: pickRay.direction.z }; + + origin.x += pickRay.origin.x; + origin.y += pickRay.origin.y; + origin.z += pickRay.origin.z; + + origin.x -= voxelSize / 2; + origin.y -= voxelSize / 2; + origin.z -= voxelSize / 2; + + return {origin: origin, voxelSize: voxelSize}; +} + function getNewVoxelPosition() { var camera = Camera.getPosition(); var forwardVector = Quat.getFront(MyAvatar.orientation); @@ -337,6 +360,7 @@ var trackAsOrbitOrPan = false; var voxelToolSelected = true; var recolorToolSelected = false; var eyedropperToolSelected = false; +var pasteMode = false; function playRandomAddSound(audioOptions) { if (Math.random() < 0.33) { @@ -523,6 +547,38 @@ function showPreviewVoxel() { function showPreviewLines() { var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); + + if (pasteMode) { // free voxel pasting + + Overlays.editOverlay(voxelPreview, { visible: false }); + Overlays.editOverlay(linePreviewLeft, { visible: false }); + + var pasteVoxel = getNewPasteVoxel(pickRay); + + // X axis + Overlays.editOverlay(linePreviewBottom, { + position: pasteVoxel.origin, + end: {x: pasteVoxel.origin.x + pasteVoxel.voxelSize, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z }, + visible: true + }); + + // Y axis + Overlays.editOverlay(linePreviewRight, { + position: pasteVoxel.origin, + end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y + pasteVoxel.voxelSize, z: pasteVoxel.origin.z }, + visible: true + }); + + // Z axis + Overlays.editOverlay(linePreviewTop, { + position: pasteVoxel.origin, + end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z - pasteVoxel.voxelSize }, + visible: true + }); + + return; + } + var intersection = Voxels.findRayIntersection(pickRay); if (intersection.intersects) { @@ -617,6 +673,8 @@ function trackKeyReleaseEvent(event) { if (editToolsOn) { if (event.text == "ESC") { pointerVoxelScaleSet = false; + pasteMode = false; + moveTools(); } if (event.text == "-") { thumbX -= thumbDeltaPerStep; @@ -821,6 +879,15 @@ function mousePressEvent(event) { var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Voxels.findRayIntersection(pickRay); audioOptions.position = Vec3.sum(pickRay.origin, pickRay.direction); + + if (pasteMode) { + var pasteVoxel = getNewPasteVoxel(pickRay); + Clipboard.pasteVoxel(pasteVoxel.origin.x, pasteVoxel.origin.y, pasteVoxel.origin.z, pasteVoxel.voxelSize); + pasteMode = false; + moveTools(); + return; + } + if (intersection.intersects) { // if the user hasn't updated the if (!pointerVoxelScaleSet) { @@ -974,21 +1041,28 @@ function cleanupMenus() { function menuItemEvent(menuItem) { // handle clipboard items - if (selectToolSelected) { + if (editToolsOn) { + var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); var intersection = Voxels.findRayIntersection(pickRay); selectedVoxel = calculateVoxelFromIntersection(intersection,"select"); if (menuItem == "Copy") { print("copying..."); Clipboard.copyVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + pasteMode = true; + moveTools(); } if (menuItem == "Cut") { print("cutting..."); Clipboard.cutVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + pasteMode = true; + moveTools(); } if (menuItem == "Paste") { print("pasting..."); Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + pasteMode = false; + moveTools(); } if (menuItem == "Delete") { print("deleting..."); @@ -1002,6 +1076,8 @@ function menuItemEvent(menuItem) { if (menuItem == "Import Voxels") { print("import"); Clipboard.importVoxels(); + pasteMode = true; + moveTools(); } if (menuItem == "Nudge") { print("nudge"); @@ -1156,19 +1232,23 @@ function moveTools() { recolorToolOffset = 1, eyedropperToolOffset = 1; - if (trackAsRecolor || recolorToolSelected) { + var voxelToolColor = WHITE_COLOR; + + if (recolorToolSelected) { recolorToolOffset = 2; - } else if (trackAsEyedropper || eyedropperToolSelected) { + } else if (eyedropperToolSelected) { eyedropperToolOffset = 2; - } else if (trackAsOrbitOrPan) { - // nothing gets selected in this case... } else { + if (pasteMode) { + voxelToolColor = pasteModeColor; + } voxelToolOffset = 2; } Overlays.editOverlay(voxelTool, { subImage: { x: 0, y: toolHeight * voxelToolOffset, width: toolWidth, height: toolHeight }, x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * voxelToolAt), width: toolWidth, height: toolHeight, + color: voxelToolColor, visible: editToolsOn }); From dbef17db597bac9b735c52717492be7af28e60d8 Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 6 Mar 2014 22:42:34 +0100 Subject: [PATCH 03/37] code style --- examples/editVoxels.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index c4694df5f8..8197f4f801 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -316,19 +316,18 @@ function setAudioPosition() { function getNewPasteVoxel(pickRay) { - var voxelSize = MIN_PASTE_VOXEL_SCALE + (MAX_PASTE_VOXEL_SCALE - MIN_PASTE_VOXEL_SCALE) * pointerVoxelScale - 1; - var distance = 1 + 30 * voxelSize / MAX_PASTE_VOXEL_SCALE; - var origin = { x: pickRay.direction.x * NEW_VOXEL_DISTANCE_FROM_CAMERA + voxelSize, y: pickRay.direction.y, z: pickRay.direction.z }; + var voxelSize = MIN_PASTE_VOXEL_SCALE + (MAX_PASTE_VOXEL_SCALE - MIN_PASTE_VOXEL_SCALE) * pointerVoxelScale - 1; + var origin = { x: pickRay.direction.x, y: pickRay.direction.y, z: pickRay.direction.z }; - origin.x += pickRay.origin.x; - origin.y += pickRay.origin.y; - origin.z += pickRay.origin.z; + origin.x += pickRay.origin.x; + origin.y += pickRay.origin.y; + origin.z += pickRay.origin.z; + + origin.x -= voxelSize / 2; + origin.y -= voxelSize / 2; + origin.z += voxelSize / 2; - origin.x -= voxelSize / 2; - origin.y -= voxelSize / 2; - origin.z -= voxelSize / 2; - - return {origin: origin, voxelSize: voxelSize}; + return {origin: origin, voxelSize: voxelSize}; } function getNewVoxelPosition() { From dcaef45f2e2749f94390644d18da71cd493e3905 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 11 Mar 2014 16:01:21 -0700 Subject: [PATCH 04/37] More work on editVoxel.js --- examples/addVoxelOnMouseClickExample.js | 20 +- examples/editVoxels.js | 344 ++++++++++++------ interface/src/Application.cpp | 14 +- interface/src/Application.h | 5 +- interface/src/ClipboardScriptingInterface.cpp | 14 +- interface/src/ClipboardScriptingInterface.h | 5 +- interface/src/VoxelSystem.cpp | 2 - interface/src/ui/LocalVoxelsOverlay.cpp | 4 +- interface/src/ui/Volume3DOverlay.cpp | 3 + 9 files changed, 273 insertions(+), 138 deletions(-) diff --git a/examples/addVoxelOnMouseClickExample.js b/examples/addVoxelOnMouseClickExample.js index 244a017ae4..4450a16c22 100644 --- a/examples/addVoxelOnMouseClickExample.js +++ b/examples/addVoxelOnMouseClickExample.js @@ -15,16 +15,16 @@ function mousePressEvent(event) { 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 + ", " + 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 + ", " + 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 = { + + var newVoxel = { x: intersection.voxel.x, y: intersection.voxel.y, z: intersection.voxel.z, @@ -32,7 +32,7 @@ function mousePressEvent(event) { red: 255, green: 0, blue: 255 }; - + if (intersection.face == "MIN_X_FACE") { newVoxel.x -= newVoxel.s; } else if (intersection.face == "MAX_X_FACE") { @@ -46,11 +46,11 @@ function mousePressEvent(event) { } else if (intersection.face == "MAX_Z_FACE") { newVoxel.z += newVoxel.s; } - - print("Voxels.setVoxel("+newVoxel.x + ", " - + newVoxel.y + ", " + 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); } } diff --git a/examples/editVoxels.js b/examples/editVoxels.js index c4abfd7fff..960840b680 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -8,10 +8,10 @@ // Captures mouse clicks and edits voxels accordingly. // // click = create a new voxel on this face, same color as old (default color picker state) -// right click or control + click = delete this voxel +// right click or control + click = delete this voxel // shift + click = recolor this voxel // 1 - 8 = pick new color from palette -// 9 = create a new voxel in front of the camera +// 9 = create a new voxel in front of the camera // // Click and drag to create more new voxels in the same direction // @@ -36,19 +36,19 @@ var previewLineWidth = 1.5; var oldMode = Camera.getMode(); -var isAdding = false; -var isExtruding = false; +var isAdding = false; +var isExtruding = false; var isOrbiting = false; var isOrbitingFromTouch = false; var isPanning = false; var isPanningFromTouch = false; var touchPointsToOrbit = 2; // you can change these, but be mindful that on some track pads 2 touch points = right click+drag -var touchPointsToPan = 3; +var touchPointsToPan = 3; var orbitAzimuth = 0.0; var orbitAltitude = 0.0; var orbitCenter = { x: 0, y: 0, z: 0 }; var orbitPosition = { x: 0, y: 0, z: 0 }; -var torsoToEyeVector = { x: 0, y: 0, z: 0 }; +var torsoToEyeVector = { x: 0, y: 0, z: 0 }; var orbitRadius = 0.0; var extrudeDirection = { x: 0, y: 0, z: 0 }; var extrudeScale = 0.0; @@ -60,7 +60,7 @@ var wheelPixelsMoved = 0; var mouseX = 0; -var mouseY = 0; +var mouseY = 0; // Create a table of the different colors you can choose var colors = new Array(); @@ -76,7 +76,7 @@ colors[8] = { red: 31, green: 64, blue: 64 }; var numColors = 9; var whichColor = -1; // Starting color is 'Copy' mode -// Create sounds for adding, deleting, recoloring voxels +// Create sounds for adding, deleting, recoloring voxels var addSound1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+2.raw"); var addSound2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+3.raw"); var addSound3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+4.raw"); @@ -93,7 +93,7 @@ var editToolsOn = true; // starts out off // previewAsVoxel - by default, we will preview adds/deletes/recolors as just 4 lines on the intersecting face. But if you // the preview to show a full voxel then set this to true and the voxel will be displayed for voxel editing -var previewAsVoxel = false; +var previewAsVoxel = true; var voxelPreview = Overlays.addOverlay("cube", { position: { x: 0, y: 0, z: 0}, @@ -104,7 +104,7 @@ var voxelPreview = Overlays.addOverlay("cube", { visible: false, lineWidth: 4 }); - + var linePreviewTop = Overlays.addOverlay("line3d", { position: { x: 0, y: 0, z: 0}, end: { x: 0, y: 0, z: 0}, @@ -228,7 +228,7 @@ var eyedropperTool = Overlays.addOverlay("image", { visible: false, alpha: 0.9 }); - + // This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to // move the slider @@ -277,6 +277,88 @@ var pointerVoxelScaleMin = Math.pow(2, (1-pointerVoxelScaleOriginStep)); var pointerVoxelScaleMax = Math.pow(2, (pointerVoxelScaleSteps-pointerVoxelScaleOriginStep)); var thumbDeltaPerStep = thumbExtents / (pointerVoxelScaleSteps - 1); + + +///////////////////////////////////// IMPORT MODULE /////////////////////////////// +// Move the following code to a separate file when include will be available. +var importTree; +var importPreview; +var isImporting; +var importPosition; +var importScale; + +function initImport() { + importPreview = Overlays.addOverlay("localvoxels", { + name: "import", + position: { x: 0, y: 0, z: 0}, + scale: 0, + visible: false + }); + isImporting = false; + importPosition = { x: 0, y: 0, z: 0 }; + importScale = 0; +} + +function importVoxels() { + if (Clipboard.importVoxels() == 0) { + isImporting = true; + if (importScale <= 0) { + importScale = 1; + } + } else { + isImporting = false; + } + + return isImporting; +} + +function moveImport(position) { + if (0 < position.x && 0 < position.y && 0 < position.z) { + importPosition = position; + Overlays.editOverlay(importPreview, { + position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } + }); + } +} + +function rescaleImport(scale) { + if (0 < scale) { + importScale = scale; + Overlays.editOverlay(importPreview, { + scale: importScale + }); + } +} + +function showImport(doShow) { + Overlays.editOverlay(importPreview, { + visible: doShow + }); +} + +function placeImport() { + if (isImporting) { + Clipboard.pasteVoxel(importPosition.x, importPosition.y, importPosition.z, importScale); + isImporting = false; + } +} + +function cancelImport() { + if (isImporting) { + isImporting = false; + showImport(false); + } +} + +function cleanupImport() { + Overlays.deleteOverlay(importPreview); + isImporting = false; + importPostion = { x: 0, y: 0, z: 0 }; + importScale = 0; +} +/////////////////////////////////// END IMPORT MODULE ///////////////////////////// +initImport(); + if (editToolsOn) { moveTools(); } @@ -301,9 +383,16 @@ function calcScaleFromThumb(newThumbX) { thumbAt = newThumbX - minThumbX; thumbStep = Math.floor((thumbAt/ thumbExtents) * (pointerVoxelScaleSteps-1)) + 1; pointerVoxelScale = Math.pow(2, (thumbStep-pointerVoxelScaleOriginStep)); + + // if importing, rescale import ... + if (isImporting) { + var importScale = (pointerVoxelScale / MAX_VOXEL_SCALE) * MAX_PASTE_VOXEL_SCALE; + rescaleImport(importScale); + } + // now reset the display accordingly... calcThumbFromScale(pointerVoxelScale); - + // if the user moved the thumb, then they are fixing the voxel scale pointerVoxelScaleSet = true; } @@ -322,7 +411,7 @@ function getNewPasteVoxel(pickRay) { origin.x += pickRay.origin.x; origin.y += pickRay.origin.y; origin.z += pickRay.origin.z; - + origin.x -= voxelSize / 2; origin.y -= voxelSize / 2; origin.z += voxelSize / 2; @@ -330,7 +419,7 @@ function getNewPasteVoxel(pickRay) { return {origin: origin, voxelSize: voxelSize}; } -function getNewVoxelPosition() { +function getNewVoxelPosition() { var camera = Camera.getPosition(); var forwardVector = Quat.getFront(MyAvatar.orientation); var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, NEW_VOXEL_DISTANCE_FROM_CAMERA)); @@ -377,27 +466,27 @@ function calculateVoxelFromIntersection(intersection, operation) { var wantDebug = false; if (wantDebug) { - print(">>>>> calculateVoxelFromIntersection().... intersection voxel.red/green/blue=" + intersection.voxel.red + ", " + print(">>>>> calculateVoxelFromIntersection().... intersection voxel.red/green/blue=" + intersection.voxel.red + ", " + intersection.voxel.green + ", " + intersection.voxel.blue); - print(" intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " + 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 + ", " + print(" intersection intersection.x/y/z=" + intersection.intersection.x + ", " + intersection.intersection.y + ", " + intersection.intersection.z); } - + var voxelSize; if (pointerVoxelScaleSet) { - voxelSize = pointerVoxelScale; + voxelSize = pointerVoxelScale; } else { - voxelSize = intersection.voxel.s; + voxelSize = intersection.voxel.s; } var x; var y; var z; - + // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest // ancestor voxel of our target size that contains our intersected voxel. if (voxelSize > intersection.voxel.s) { @@ -438,7 +527,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.x -= voxelSize; } - + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; @@ -462,7 +551,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.y -= voxelSize; } - + resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; @@ -474,7 +563,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.y += voxelSize; } - + resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust}; resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; @@ -486,7 +575,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.z -= voxelSize; } - + resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; @@ -505,7 +594,7 @@ function calculateVoxelFromIntersection(intersection, operation) { resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; } - + return resultVoxel; } @@ -515,7 +604,7 @@ function showPreviewVoxel() { var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); var intersection = Voxels.findRayIntersection(pickRay); - // if the user hasn't updated the + // if the user hasn't updated the if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } @@ -548,41 +637,41 @@ function showPreviewLines() { var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); if (pasteMode) { // free voxel pasting - + Overlays.editOverlay(voxelPreview, { visible: false }); Overlays.editOverlay(linePreviewLeft, { visible: false }); var pasteVoxel = getNewPasteVoxel(pickRay); // X axis - Overlays.editOverlay(linePreviewBottom, { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x + pasteVoxel.voxelSize, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z }, - visible: true + Overlays.editOverlay(linePreviewBottom, { + position: pasteVoxel.origin, + end: {x: pasteVoxel.origin.x + pasteVoxel.voxelSize, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z }, + visible: true }); // Y axis - Overlays.editOverlay(linePreviewRight, { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y + pasteVoxel.voxelSize, z: pasteVoxel.origin.z }, - visible: true + Overlays.editOverlay(linePreviewRight, { + position: pasteVoxel.origin, + end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y + pasteVoxel.voxelSize, z: pasteVoxel.origin.z }, + visible: true }); // Z axis - Overlays.editOverlay(linePreviewTop, { - position: pasteVoxel.origin, - end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z - pasteVoxel.voxelSize }, - visible: true + Overlays.editOverlay(linePreviewTop, { + position: pasteVoxel.origin, + end: {x: pasteVoxel.origin.x, y: pasteVoxel.origin.y, z: pasteVoxel.origin.z - pasteVoxel.voxelSize }, + visible: true }); return; } var intersection = Voxels.findRayIntersection(pickRay); - + if (intersection.intersects) { - // if the user hasn't updated the + // if the user hasn't updated the if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } @@ -699,14 +788,14 @@ function trackKeyReleaseEvent(event) { trackAsOrbitOrPan = false; moveTools(); } - + // on F1 toggle the preview mode between cubes and lines if (event.text == "F1") { previewAsVoxel = !previewAsVoxel; } showPreviewGuides(); - } + } } function startOrbitMode(event) { @@ -715,7 +804,7 @@ function startOrbitMode(event) { var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Voxels.findRayIntersection(pickRay); - // start orbit camera! + // start orbit camera! var cameraPosition = Camera.getPosition(); torsoToEyeVector = Vec3.subtract(cameraPosition, MyAvatar.position); torsoToEyeVector.x = 0.0; @@ -724,12 +813,12 @@ function startOrbitMode(event) { Camera.setMode("independent"); Camera.keepLookingAt(intersection.intersection); // get position for initial azimuth, elevation - orbitCenter = intersection.intersection; + orbitCenter = intersection.intersection; var orbitVector = Vec3.subtract(cameraPosition, orbitCenter); - orbitRadius = Vec3.length(orbitVector); + orbitRadius = Vec3.length(orbitVector); orbitAzimuth = Math.atan2(orbitVector.z, orbitVector.x); orbitAltitude = Math.asin(orbitVector.y / Vec3.length(orbitVector)); - + //print("startOrbitMode..."); } @@ -737,17 +826,17 @@ function handleOrbitingMove(event) { var cameraOrientation = Camera.getOrientation(); var origEulers = Quat.safeEulerAngles(cameraOrientation); var newEulers = fixEulerAngles(Quat.safeEulerAngles(cameraOrientation)); - var dx = event.x - mouseX; + var dx = event.x - mouseX; var dy = event.y - mouseY; orbitAzimuth += dx / ORBIT_RATE_AZIMUTH; orbitAltitude += dy / ORBIT_RATE_ALTITUDE; - var orbitVector = { x:(Math.cos(orbitAltitude) * Math.cos(orbitAzimuth)) * orbitRadius, + var orbitVector = { x:(Math.cos(orbitAltitude) * Math.cos(orbitAzimuth)) * orbitRadius, y:Math.sin(orbitAltitude) * orbitRadius, - z:(Math.cos(orbitAltitude) * Math.sin(orbitAzimuth)) * orbitRadius }; + z:(Math.cos(orbitAltitude) * Math.sin(orbitAzimuth)) * orbitRadius }; orbitPosition = Vec3.sum(orbitCenter, orbitVector); Camera.setPosition(orbitPosition); - mouseX = event.x; + mouseX = event.x; mouseY = event.y; //print("handleOrbitingMove..."); } @@ -763,7 +852,7 @@ function endOrbitMode(event) { } function startPanMode(event, intersection) { - // start pan camera! + // start pan camera! print("handle PAN mode!!!"); } @@ -781,14 +870,14 @@ function mousePressEvent(event) { // if our tools are off, then don't do anything if (!editToolsOn) { - return; + return; } - - // Normally, if we're panning or orbiting from touch, ignore these... because our touch takes precedence. - // but In the case of a button="RIGHT" click, we may get some touch messages first, and we actually want to + + // Normally, if we're panning or orbiting from touch, ignore these... because our touch takes precedence. + // but In the case of a button="RIGHT" click, we may get some touch messages first, and we actually want to // cancel any touch mode, and then let the right-click through if (isOrbitingFromTouch || isPanningFromTouch) { - + // if the user is holding the ALT key AND they are clicking the RIGHT button (or on multi-touch doing a two // finger touch, then we want to let the new panning behavior take over. // if it's any other case we still want to bail @@ -805,15 +894,15 @@ function mousePressEvent(event) { } // let things fall through } else { - return; + return; } } - + // no clicking on overlays while in panning mode if (!trackAsOrbitOrPan) { var clickedOnSomething = false; var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - + // If the user clicked on the thumb, handle the slider logic if (clickedOverlay == thumb) { @@ -870,7 +959,7 @@ function mousePressEvent(event) { return; // no further processing } } - + // TODO: does any of this stuff need to execute if we're panning or orbiting? trackMouseEvent(event); // used by preview support mouseX = event.x; @@ -879,6 +968,15 @@ function mousePressEvent(event) { var intersection = Voxels.findRayIntersection(pickRay); audioOptions.position = Vec3.sum(pickRay.origin, pickRay.direction); + if (isImporting) { + print("placing import..."); + placeImport(); + showImport(false); + pasteMode = false; + moveTools(); + return; + } + if (pasteMode) { var pasteVoxel = getNewPasteVoxel(pickRay); Clipboard.pasteVoxel(pasteVoxel.origin.x, pasteVoxel.origin.y, pasteVoxel.origin.z, pasteVoxel.voxelSize); @@ -888,11 +986,11 @@ function mousePressEvent(event) { } if (intersection.intersects) { - // if the user hasn't updated the + // if the user hasn't updated the if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } - + // Note: touch and mouse events can cross paths, so we want to ignore any mouse events that would // start a pan or orbit if we're already doing a pan or orbit via touch... if ((event.isAlt || trackAsOrbitOrPan) && !(isOrbitingFromTouch || isPanningFromTouch)) { @@ -916,14 +1014,14 @@ function mousePressEvent(event) { colors[whichColor].blue = intersection.voxel.blue; moveTools(); } - + } else if (recolorToolSelected || trackAsRecolor) { // Recolor Voxel voxelDetails = calculateVoxelFromIntersection(intersection,"recolor"); // doing this erase then set will make sure we only recolor just the target voxel Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); - Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, + Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); Audio.playSound(changeColorSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); @@ -931,17 +1029,17 @@ function mousePressEvent(event) { // Add voxel on face if (whichColor == -1) { // Copy mode - use clicked voxel color - newColor = { + newColor = { red: intersection.voxel.red, green: intersection.voxel.green, blue: intersection.voxel.blue }; } else { - newColor = { + newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; } - + voxelDetails = calculateVoxelFromIntersection(intersection,"add"); Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, @@ -951,11 +1049,11 @@ function mousePressEvent(event) { lastVoxelScale = voxelDetails.s; playRandomAddSound(audioOptions); - + Overlays.editOverlay(voxelPreview, { visible: false }); dragStart = { x: event.x, y: event.y }; isAdding = true; - } + } } } @@ -974,14 +1072,14 @@ function keyPressEvent(event) { Audio.playSound(clickSound, audioOptions); moveTools(); } else if (event.text == "0") { - // Create a brand new 1 meter voxel in front of your avatar - var color = whichColor; + // Create a brand new 1 meter voxel in front of your avatar + var color = whichColor; if (color == -1) color = 0; var newPosition = getNewVoxelPosition(); - var newVoxel = { + var newVoxel = { x: newPosition.x, y: newPosition.y , - z: newPosition.z, + z: newPosition.z, s: NEW_VOXEL_SIZE, red: colors[color].red, green: colors[color].green, @@ -992,7 +1090,7 @@ function keyPressEvent(event) { playRandomAddSound(audioOptions); } } - + trackKeyPressEvent(event); // used by preview support } @@ -1051,24 +1149,36 @@ function menuItemEvent(menuItem) { moveTools(); } if (menuItem == "Paste") { - print("pasting..."); - Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + if (isImporting) { + print("placing import..."); + placeImport(); + showImport(false); + } else { + print("pasting..."); + Clipboard.pasteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } pasteMode = false; moveTools(); } if (menuItem == "Delete") { print("deleting..."); - Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + if (isImporting) { + cancelImport(); + } else { + Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); + } } - + if (menuItem == "Export Voxels") { print("export"); Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } if (menuItem == "Import Voxels") { - print("import"); - Clipboard.importVoxels(); - pasteMode = true; + print("importing..."); + if (importVoxels()) { + showImport(true); + pasteMode = true; + } moveTools(); } if (menuItem == "Nudge") { @@ -1083,11 +1193,11 @@ function mouseMoveEvent(event) { return; } - // if we're panning or orbiting from touch, ignore these... because our touch takes precedence. + // if we're panning or orbiting from touch, ignore these... because our touch takes precedence. if (isOrbitingFromTouch || isPanningFromTouch) { - return; + return; } - + // double check that we didn't accidentally miss a pan or orbit click request if (trackAsOrbitOrPan && !isPanning && !isOrbiting) { if (event.isLeftButton && !event.isRightButton) { @@ -1109,7 +1219,7 @@ function mouseMoveEvent(event) { thumbX = maxThumbX; } calcScaleFromThumb(thumbX); - + } else if (isOrbiting) { handleOrbitingMove(event); } else if (isPanning) { @@ -1118,8 +1228,8 @@ function mouseMoveEvent(event) { // Watch the drag direction to tell which way to 'extrude' this voxel if (!isExtruding) { var pickRay = Camera.computePickRay(event.x, event.y); - var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x, - y: pickRay.origin.y - lastVoxelPosition.y, + var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x, + y: pickRay.origin.y - lastVoxelPosition.y, z: pickRay.origin.z - lastVoxelPosition.z }; var distance = Vec3.length(lastVoxelDistance); var mouseSpot = { x: pickRay.direction.x * distance, y: pickRay.direction.y * distance, z: pickRay.direction.z * distance }; @@ -1138,22 +1248,22 @@ function mouseMoveEvent(event) { else if (dy < -lastVoxelScale) extrudeDirection.y = -extrudeScale; else if (dz > lastVoxelScale) extrudeDirection.z = extrudeScale; else if (dz < -lastVoxelScale) extrudeDirection.z = -extrudeScale; - else isExtruding = false; + else isExtruding = false; } else { // We have got an extrusion direction, now look for mouse move beyond threshold to add new voxel - var dx = event.x - mouseX; + var dx = event.x - mouseX; var dy = event.y - mouseY; if (Math.sqrt(dx*dx + dy*dy) > PIXELS_PER_EXTRUDE_VOXEL) { lastVoxelPosition = Vec3.sum(lastVoxelPosition, extrudeDirection); Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); - Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, extrudeScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); mouseX = event.x; mouseY = event.y; } } } - + // update the add voxel/delete voxel overlay preview trackMouseEvent(event); } @@ -1161,13 +1271,13 @@ function mouseMoveEvent(event) { function mouseReleaseEvent(event) { // if our tools are off, then don't do anything if (!editToolsOn) { - return; + return; } if (isMovingSlider) { isMovingSlider = false; } - + if (isOrbiting) { endOrbitMode(event); isOrbiting = false; @@ -1178,7 +1288,7 @@ function mouseReleaseEvent(event) { isPanning = false; } isAdding = false; - isExtruding = false; + isExtruding = false; } function moveTools() { @@ -1206,7 +1316,7 @@ function moveTools() { if (s == (numColors - 1)) { extraWidth = swatchExtraPadding; } - + Overlays.editOverlay(swatches[s], { x: swatchX, y: swatchesY, @@ -1270,16 +1380,16 @@ function touchBeginEvent(event) { if (!editToolsOn) { return; } - + // if we're already in the middle of orbiting or panning, then ignore these multi-touch events... if (isOrbiting || isPanning) { return; - } - + } + if (event.isAlt || trackAsOrbitOrPan) { if (event.touchPoints == touchPointsToOrbit) { // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (isPanningFromTouch) { print("touchBeginEvent... calling endPanMode()"); endPanMode(event); @@ -1289,7 +1399,7 @@ function touchBeginEvent(event) { isOrbitingFromTouch = true; } else if (event.touchPoints == touchPointsToPan) { // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (isOrbitingFromTouch) { endOrbitMode(event); isOrbitingFromTouch = false; @@ -1308,11 +1418,11 @@ function touchUpdateEvent(event) { // if we're already in the middle of orbiting or panning, then ignore these multi-touch events... if (isOrbiting || isPanning) { return; - } - + } + if (isOrbitingFromTouch) { // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (event.touchPoints == touchPointsToPan) { //print("we now have touchPointsToPan touches... switch to pan..."); endOrbitMode(event); @@ -1326,7 +1436,7 @@ function touchUpdateEvent(event) { if (isPanningFromTouch) { //print("touchUpdateEvent... isPanningFromTouch... event.touchPoints=" + event.touchPoints); // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (event.touchPoints == touchPointsToOrbit) { //print("we now have touchPointsToOrbit touches... switch to orbit..."); //print("touchUpdateEvent... calling endPanMode()"); @@ -1349,8 +1459,8 @@ function touchEndEvent(event) { // if we're already in the middle of orbiting or panning, then ignore these multi-touch events... if (isOrbiting || isPanning) { return; - } - + } + if (isOrbitingFromTouch) { endOrbitMode(event); isOrbitingFromTouch = false; @@ -1368,10 +1478,10 @@ var lastFingerDeleteVoxel = { x: -1, y: -1, z: -1}; // off of the build-able are function checkControllers() { var controllersPerPalm = 2; // palm and finger for (var palm = 0; palm < 2; palm++) { - var palmController = palm * controllersPerPalm; - var fingerTipController = palmController + 1; + var palmController = palm * controllersPerPalm; + var fingerTipController = palmController + 1; var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); - + var BUTTON_COUNT = 6; var BUTTON_BASE = palm * BUTTON_COUNT; var BUTTON_1 = BUTTON_BASE + 1; @@ -1389,7 +1499,7 @@ function checkControllers() { Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE); Voxels.setVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE, newColor.red, newColor.green, newColor.blue); - + lastFingerAddVoxel = fingerTipPosition; } } else if (Controller.isButtonPressed(BUTTON_2)) { @@ -1407,7 +1517,7 @@ function update(deltaTime) { windowDimensions = newWindowDimensions; moveTools(); } - + if (editToolsOn) { checkControllers(); } @@ -1425,7 +1535,7 @@ function wheelEvent(event) { pointerVoxelScale /= 2.0; if (pointerVoxelScale < MIN_VOXEL_SCALE) { pointerVoxelScale = MIN_VOXEL_SCALE; - } + } } else { pointerVoxelScale *= 2.0; if (pointerVoxelScale > MAX_VOXEL_SCALE) { @@ -1435,6 +1545,11 @@ function wheelEvent(event) { calcThumbFromScale(pointerVoxelScale); trackMouseEvent(event); wheelPixelsMoved = 0; + + if (isImporting) { + var importScale = (pointerVoxelScale / MAX_VOXEL_SCALE) * MAX_PASTE_VOXEL_SCALE; + rescaleImport(importScale); + } } } @@ -1467,6 +1582,7 @@ function scriptEnding() { Overlays.deleteOverlay(thumb); Controller.releaseKeyEvents({ text: "+" }); Controller.releaseKeyEvents({ text: "-" }); + cleanupImport(); cleanupMenus(); } Script.scriptEnding.connect(scriptEnding); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 032e849f0a..771f02750d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -140,9 +140,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _fps(120.0f), _justStarted(true), _voxelImporter(NULL), + _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), _wantToKillLocalVoxels(false), _audioScope(256, 200, true), - _myAvatar(), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _mouseX(0), _mouseY(0), @@ -1387,6 +1387,8 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) { } void Application::importVoxels() { + int result = 1; + if (!_voxelImporter) { _voxelImporter = new VoxelImporter(_window); _voxelImporter->loadSettings(_settings); @@ -1394,6 +1396,7 @@ void Application::importVoxels() { if (!_voxelImporter->exec()) { qDebug() << "[DEBUG] Import succeeded." << endl; + result = 0; } else { qDebug() << "[DEBUG] Import failed." << endl; if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) { @@ -1404,6 +1407,8 @@ void Application::importVoxels() { // restore the main window's active state _window->activateWindow(); + + emit importDone(result); } void Application::cutVoxels(const VoxelDetail& sourceVoxel) { @@ -1495,10 +1500,9 @@ void Application::init() { // Cleanup of the original shared tree _sharedVoxelSystem.init(); - VoxelTree* tmpTree = _sharedVoxelSystem.getTree(); - _sharedVoxelSystem.changeTree(&_clipboard); - delete tmpTree; - + + _voxelImporter = new VoxelImporter(_window); + _environment.init(); _glowEffect.init(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 234f264447..c6fc7140eb 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -225,6 +225,9 @@ signals: /// Fired when we're rendering in-world interface elements; allows external parties to hook in. void renderingInWorldInterface(); + /// Fired when the import window is closed with a return code. + void importDone(int); + public slots: void domainChanged(const QString& domainHostname); void updateWindowTitle(); @@ -351,13 +354,13 @@ private: glm::vec3 _gravity; // Frame Rate Measurement + int _frameCount; float _fps; timeval _applicationStartupTime; timeval _timerStart, _timerEnd; timeval _lastTimeUpdated; bool _justStarted; - Stars _stars; BuckyBalls _buckyBalls; diff --git a/interface/src/ClipboardScriptingInterface.cpp b/interface/src/ClipboardScriptingInterface.cpp index d9a8f04d90..e8a02b041b 100644 --- a/interface/src/ClipboardScriptingInterface.cpp +++ b/interface/src/ClipboardScriptingInterface.cpp @@ -9,6 +9,7 @@ #include "ClipboardScriptingInterface.h" ClipboardScriptingInterface::ClipboardScriptingInterface() { + connect(this, SIGNAL(readyToImport()), Application::getInstance(), SLOT(importVoxels())); } void ClipboardScriptingInterface::cutVoxel(const VoxelDetail& sourceVoxel) { @@ -70,12 +71,17 @@ void ClipboardScriptingInterface::exportVoxel(float x, float y, float z, float s z / (float)TREE_SCALE, s / (float)TREE_SCALE }; - QMetaObject::invokeMethod(Application::getInstance(), "exportVoxels", - Q_ARG(const VoxelDetail&, sourceVoxel)); + Application::getInstance()->exportVoxels(sourceVoxel); } -void ClipboardScriptingInterface::importVoxels() { - QMetaObject::invokeMethod(Application::getInstance(), "importVoxels"); +bool ClipboardScriptingInterface::importVoxels() { + qDebug() << "[DEBUG] Importing ... "; + QEventLoop loop; + connect(Application::getInstance(), SIGNAL(importDone(int)), &loop, SLOT(quit())); + emit readyToImport(); + int returnCode = loop.exec(); + + return returnCode; } void ClipboardScriptingInterface::nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) { diff --git a/interface/src/ClipboardScriptingInterface.h b/interface/src/ClipboardScriptingInterface.h index 99747f56f6..78e72d6de0 100644 --- a/interface/src/ClipboardScriptingInterface.h +++ b/interface/src/ClipboardScriptingInterface.h @@ -18,6 +18,9 @@ class ClipboardScriptingInterface : public QObject { public: ClipboardScriptingInterface(); +signals: + void readyToImport(); + public slots: void cutVoxel(const VoxelDetail& sourceVoxel); void cutVoxel(float x, float y, float z, float s); @@ -34,7 +37,7 @@ public slots: void exportVoxel(const VoxelDetail& sourceVoxel); void exportVoxel(float x, float y, float z, float s); - void importVoxels(); + bool importVoxels(); void nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec); void nudgeVoxel(float x, float y, float z, float s, const glm::vec3& nudgeVec); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index aa628bac7b..a8bdeb1114 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1177,8 +1177,6 @@ void VoxelSystem::init() { } void VoxelSystem::changeTree(VoxelTree* newTree) { - disconnect(_tree, 0, this, 0); - _tree = newTree; _tree->setDirtyBit(); diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/LocalVoxelsOverlay.cpp index 01a885dedc..248a5b6733 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/LocalVoxelsOverlay.cpp @@ -40,9 +40,11 @@ void LocalVoxelsOverlay::update(float deltatime) { _voxelSystem->init(); } - if (_voxelCount != _tree->getOctreeElementsCount()) { + if (_visible && _voxelCount != _tree->getOctreeElementsCount()) { _voxelCount = _tree->getOctreeElementsCount(); + _tree->lockForWrite(); _voxelSystem->forceRedrawEntireTree(); + _tree->unlock(); } } diff --git a/interface/src/ui/Volume3DOverlay.cpp b/interface/src/ui/Volume3DOverlay.cpp index dbc1582cc5..a4e6c76a12 100644 --- a/interface/src/ui/Volume3DOverlay.cpp +++ b/interface/src/ui/Volume3DOverlay.cpp @@ -31,6 +31,9 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) { if (properties.property("size").isValid()) { setSize(properties.property("size").toVariant().toFloat()); } + if (properties.property("scale").isValid()) { + setSize(properties.property("scale").toVariant().toFloat()); + } if (properties.property("isSolid").isValid()) { setIsSolid(properties.property("isSolid").toVariant().toBool()); From 12becb9d19777de3f63c2365bc81de140d853305 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 16:22:35 -0700 Subject: [PATCH 05/37] improve octree stats display --- interface/src/ui/OctreeStatsDialog.cpp | 57 ++++++----- libraries/octree/src/Octree.cpp | 2 - libraries/octree/src/OctreeSceneStats.cpp | 114 +++++++++++++++++++--- libraries/octree/src/OctreeSceneStats.h | 22 ++++- libraries/voxels/src/VoxelTree.cpp | 2 - 5 files changed, 152 insertions(+), 45 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 974964da04..92578b6b34 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -157,9 +157,9 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { statsValue.str(""); statsValue << - "Total: " << localTotalString.toLocal8Bit().constData() << " / " << - "Internal: " << localInternalString.toLocal8Bit().constData() << " / " << - "Leaves: " << localLeavesString.toLocal8Bit().constData() << ""; + "Total: " << qPrintable(localTotalString) << " / " << + "Internal: " << qPrintable(localInternalString) << " / " << + "Leaves: " << qPrintable(localLeavesString) << ""; label->setText(statsValue.str().c_str()); // iterate all the current voxel stats, and list their sending modes, total their voxels, etc... @@ -212,9 +212,9 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { label = _labels[_serverVoxels]; statsValue.str(""); statsValue << - "Total: " << serversTotalString.toLocal8Bit().constData() << " / " << - "Internal: " << serversInternalString.toLocal8Bit().constData() << " / " << - "Leaves: " << serversLeavesString.toLocal8Bit().constData() << ""; + "Total: " << qPrintable(serversTotalString) << " / " << + "Internal: " << qPrintable(serversInternalString) << " / " << + "Leaves: " << qPrintable(serversLeavesString) << ""; label->setText(statsValue.str().c_str()); showAllOctreeServers(); @@ -290,7 +290,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); serverDetails << " jurisdiction: " - << rootCodeHex.toLocal8Bit().constData() + << qPrintable(rootCodeHex) << " [" << rootDetails.x << ", " << rootDetails.y << ", " @@ -320,8 +320,8 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QString lastFullSendString = locale.toString(lastFullSend); extraDetails << "
" << "Last Full Scene... " << - "Encode Time: " << lastFullEncodeString.toLocal8Bit().constData() << " ms " << - "Send Time: " << lastFullSendString.toLocal8Bit().constData() << " ms "; + "Encode Time: " << qPrintable(lastFullEncodeString) << " ms " << + "Send Time: " << qPrintable(lastFullSendString) << " ms "; for (int i = 0; i < OctreeSceneStats::ITEM_COUNT; i++) { OctreeSceneStats::Item item = (OctreeSceneStats::Item)(i); @@ -334,42 +334,51 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QString internalString = locale.toString((uint)stats.getTotalInternal()); QString leavesString = locale.toString((uint)stats.getTotalLeaves()); - serverDetails << "
" << "Node UUID: " << - nodeUUID.toString().toLocal8Bit().constData() << " "; + serverDetails << "
" << "Node UUID: " << qPrintable(nodeUUID.toString()) << " "; serverDetails << "
" << "Voxels: " << - totalString.toLocal8Bit().constData() << " total " << - internalString.toLocal8Bit().constData() << " internal " << - leavesString.toLocal8Bit().constData() << " leaves "; + qPrintable(totalString) << " total " << + qPrintable(internalString) << " internal " << + qPrintable(leavesString) << " leaves "; QString incomingPacketsString = locale.toString((uint)stats.getIncomingPackets()); QString incomingBytesString = locale.toString((uint)stats.getIncomingBytes()); QString incomingWastedBytesString = locale.toString((uint)stats.getIncomingWastedBytes()); QString incomingOutOfOrderString = locale.toString((uint)stats.getIncomingOutOfOrder()); + QString incomingLateString = locale.toString((uint)stats.getIncomingLate()); + QString incomingReallyLateString = locale.toString((uint)stats.getIncomingReallyLate()); + QString incomingEarlyString = locale.toString((uint)stats.getIncomingEarly()); QString incomingLikelyLostString = locale.toString((uint)stats.getIncomingLikelyLost()); + QString incomingRecovered = locale.toString((uint)stats.getIncomingRecovered()); + QString incomingDuplicateString = locale.toString((uint)stats.getIncomingPossibleDuplicate()); int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC; QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage()); QString incomingPingTimeString = locale.toString(node->getPingMs()); QString incomingClockSkewString = locale.toString(clockSkewInMS); - serverDetails << "
" << "Incoming Packets: " << - incomingPacketsString.toLocal8Bit().constData() << - " Out of Order: " << incomingOutOfOrderString.toLocal8Bit().constData() << - " Likely Lost: " << incomingLikelyLostString.toLocal8Bit().constData(); + serverDetails << "
" << "Incoming Packets: " << qPrintable(incomingPacketsString) << + "/ Lost: " << qPrintable(incomingLikelyLostString) << + "/ Recovered: " << qPrintable(incomingRecovered); + + serverDetails << "
" << " Out of Order: " << qPrintable(incomingOutOfOrderString) << + "/ Early: " << qPrintable(incomingEarlyString) << + "/ Late: " << qPrintable(incomingLateString) << + "/ Really Late: " << qPrintable(incomingReallyLateString) << + "/ Duplicate: " << qPrintable(incomingDuplicateString); serverDetails << "
" << - " Average Flight Time: " << incomingFlightTimeString.toLocal8Bit().constData() << " msecs"; + " Average Flight Time: " << qPrintable(incomingFlightTimeString) << " msecs"; serverDetails << "
" << - " Average Ping Time: " << incomingPingTimeString.toLocal8Bit().constData() << " msecs"; + " Average Ping Time: " << qPrintable(incomingPingTimeString) << " msecs"; serverDetails << "
" << - " Average Clock Skew: " << incomingClockSkewString.toLocal8Bit().constData() << " msecs"; - + " Average Clock Skew: " << qPrintable(incomingClockSkewString) << " msecs"; + serverDetails << "
" << "Incoming" << - " Bytes: " << incomingBytesString.toLocal8Bit().constData() << - " Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData(); + " Bytes: " << qPrintable(incomingBytesString) << + " Wasted Bytes: " << qPrintable(incomingWastedBytesString); serverDetails << extraDetails.str(); if (_extraServerDetails[serverCount-1] == MORE) { diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index f85ed7f487..4c8ed8c9f6 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -15,8 +15,6 @@ #include #include // to load voxels from file -#include - #include #include "CoverageMap.h" diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 794884334f..7d1f3f0cec 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -30,8 +30,13 @@ OctreeSceneStats::OctreeSceneStats() : _incomingBytes(0), _incomingWastedBytes(0), _incomingLastSequence(0), - _incomingOutOfOrder(0), _incomingLikelyLost(0), + _incomingRecovered(0), + _incomingEarly(0), + _incomingLate(0), + _incomingReallyLate(0), + _incomingPossibleDuplicate(0), + _missingSequenceNumbers(), _incomingFlightTimeAverage(samples), _jurisdictionRoot(NULL) { @@ -134,8 +139,14 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) { _incomingBytes = other._incomingBytes; _incomingWastedBytes = other._incomingWastedBytes; _incomingLastSequence = other._incomingLastSequence; - _incomingOutOfOrder = other._incomingOutOfOrder; _incomingLikelyLost = other._incomingLikelyLost; + _incomingRecovered = other._incomingRecovered; + _incomingEarly = other._incomingEarly; + _incomingLate = other._incomingLate; + _incomingReallyLate = other._incomingReallyLate; + _incomingPossibleDuplicate = other._incomingPossibleDuplicate; + + _missingSequenceNumbers = other._missingSequenceNumbers; } @@ -823,18 +834,95 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, float flightTimeMsecs = flightTime / USECS_PER_MSEC; _incomingFlightTimeAverage.updateAverage(flightTimeMsecs); + // track out of order and possibly lost packets... + const bool wantExtraDebugging = false; + if (sequence == _incomingLastSequence) { + if (wantExtraDebugging) { + qDebug() << "last packet duplicate got:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; + } + } else { + OCTREE_PACKET_SEQUENCE expected = _incomingLastSequence+1; + if (sequence != expected) { + if (wantExtraDebugging) { + qDebug() << "out of order... got:" << sequence << "expected:" << expected; + } + + // if the sequence is less than our expected, then this might be a packet + // that was delayed and so we should find it in our lostSequence list + if (sequence < expected) { + if (wantExtraDebugging) { + qDebug() << "this packet is later than expected..."; + } + if (sequence < std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) { + _incomingReallyLate++; + } else { + _incomingLate++; + } + + if (_missingSequenceNumbers.contains(sequence)) { + if (wantExtraDebugging) { + qDebug() << "found it in _missingSequenceNumbers"; + } + _missingSequenceNumbers.remove(sequence); + _incomingLikelyLost--; + _incomingRecovered++; + } else { + // if we're still in our pruning window, and we didn't find it in our missing list, + // than this is really unexpected and can probably only happen if the packet was a + // duplicate + if (sequence >= std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) { + if (wantExtraDebugging) { + qDebug() << "sequence:" << sequence << "WAS NOT found in _missingSequenceNumbers, and not that old... (expected - MAX_MISSING_SEQUENCE_OLD_AGE):" << (expected - MAX_MISSING_SEQUENCE_OLD_AGE); + } + _incomingPossibleDuplicate++; + } + } + } + + if (sequence > expected) { + if (wantExtraDebugging) { + qDebug() << "this packet is earlier than expected..."; + } + _incomingEarly++; + + // hmm... so, we either didn't get some packets, or this guy came early... + unsigned int missing = sequence - expected; + if (wantExtraDebugging) { + qDebug() << ">>>>>>>> missing gap=" << missing; + } + _incomingLikelyLost += missing; + for(unsigned int missingSequence = expected; missingSequence < sequence; missingSequence++) { + _missingSequenceNumbers << missingSequence; + } + } + } + } + + // only bump the last sequence if it was greater than our previous last sequence, this will keep us from + // accidentally going backwards when an out of order (recovered) packet comes in + if (sequence > _incomingLastSequence) { + _incomingLastSequence = sequence; + } - // detect out of order packets - if (sequence < _incomingLastSequence) { - _incomingOutOfOrder++; + // do some garbage collecting on our _missingSequenceNumbers + if (_missingSequenceNumbers.size() > MAX_MISSING_SEQUENCE) { + if (wantExtraDebugging) { + qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size(); + } + foreach(unsigned int missingItem, _missingSequenceNumbers) { + if (wantExtraDebugging) { + qDebug() << "checking item:" << missingItem << "is it in need of pruning?"; + qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):" + << (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE); + } + if (missingItem <= std::max(0, (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE))) { + if (wantExtraDebugging) { + qDebug() << "pruning really old missing sequence:" << missingItem; + } + _missingSequenceNumbers.remove(missingItem); + } + } } - - // detect likely lost packets - OCTREE_PACKET_SEQUENCE expected = _incomingLastSequence+1; - if (sequence > expected) { - _incomingLikelyLost++; - } - - _incomingLastSequence = sequence; + } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index e106f53589..25bc5e2c21 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -159,8 +159,13 @@ public: unsigned int getIncomingPackets() const { return _incomingPacket; } unsigned long getIncomingBytes() const { return _incomingBytes; } unsigned long getIncomingWastedBytes() const { return _incomingWastedBytes; } - unsigned int getIncomingOutOfOrder() const { return _incomingOutOfOrder; } + unsigned int getIncomingOutOfOrder() const { return _incomingLate + _incomingEarly; } unsigned int getIncomingLikelyLost() const { return _incomingLikelyLost; } + unsigned int getIncomingRecovered() const { return _incomingRecovered; } + unsigned int getIncomingEarly() const { return _incomingEarly; } + unsigned int getIncomingLate() const { return _incomingLate; } + unsigned int getIncomingReallyLate() const { return _incomingReallyLate; } + unsigned int getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; } float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); } private: @@ -251,9 +256,18 @@ private: unsigned int _incomingPacket; unsigned long _incomingBytes; unsigned long _incomingWastedBytes; - unsigned int _incomingLastSequence; - unsigned int _incomingOutOfOrder; - unsigned int _incomingLikelyLost; + + const uint16_t MAX_MISSING_SEQUENCE = 100; /// how many items in our _missingSequenceNumbers before we start to prune them + const uint16_t MAX_MISSING_SEQUENCE_OLD_AGE = 1000; /// age we allow items in _missingSequenceNumbers to be before pruning + + uint16_t _incomingLastSequence; /// last incoming sequence number + unsigned int _incomingLikelyLost; /// count of packets likely lost, may be off by _incomingReallyLate count + unsigned int _incomingRecovered; /// packets that were late, and we had in our missing list, we consider recovered + unsigned int _incomingEarly; /// out of order earlier than expected + unsigned int _incomingLate; /// out of order later than expected + unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late + unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate + QSet _missingSequenceNumbers; SimpleMovingAverage _incomingFlightTimeAverage; // features related items diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 4c756c2257..5c48244a39 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -8,8 +8,6 @@ #include -#include - #include #include #include From 029b25ad29c73fea41c0afde61b57ecf3b370be2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 16:45:15 -0700 Subject: [PATCH 06/37] make domain server less noisy about Agent assignments --- domain-server/src/DomainServer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index e5979c561f..7e37c9b397 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -544,8 +544,15 @@ void DomainServer::readAvailableDatagrams() { // construct the requested assignment from the packet data Assignment requestAssignment(receivedPacket); - qDebug() << "Received a request for assignment type" << requestAssignment.getType() - << "from" << senderSockAddr; + // Suppress these for Assignment::AgentType to 1 per second... + static quint64 lastMessage = usecTimestampNow(); + quint64 timeNow = usecTimestampNow(); + const quint64 NOISY_TIME_ELAPSED = USECS_PER_SECOND; + if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastMessage) > NOISY_TIME_ELAPSED) { + qDebug() << "Received a request for assignment type" << requestAssignment.getType() + << "from" << senderSockAddr; + lastMessage = timeNow; + } SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); From 00176254424d0f4c75cbe4c6002ba457c821ec8a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 16:48:49 -0700 Subject: [PATCH 07/37] fix unix compiler issue --- libraries/octree/src/OctreeSceneStats.cpp | 4 ++++ libraries/octree/src/OctreeSceneStats.h | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 7d1f3f0cec..ad7f774377 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -18,6 +18,10 @@ #include "OctreeSceneStats.h" +const uint16_t MAX_MISSING_SEQUENCE = 100; /// how many items in our _missingSequenceNumbers before we start to prune them +const uint16_t MAX_MISSING_SEQUENCE_OLD_AGE = 1000; /// age we allow items in _missingSequenceNumbers to be before pruning + + const int samples = 100; OctreeSceneStats::OctreeSceneStats() : _isReadyToSend(false), diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index 25bc5e2c21..249ab376c1 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -257,9 +257,6 @@ private: unsigned long _incomingBytes; unsigned long _incomingWastedBytes; - const uint16_t MAX_MISSING_SEQUENCE = 100; /// how many items in our _missingSequenceNumbers before we start to prune them - const uint16_t MAX_MISSING_SEQUENCE_OLD_AGE = 1000; /// age we allow items in _missingSequenceNumbers to be before pruning - uint16_t _incomingLastSequence; /// last incoming sequence number unsigned int _incomingLikelyLost; /// count of packets likely lost, may be off by _incomingReallyLate count unsigned int _incomingRecovered; /// packets that were late, and we had in our missing list, we consider recovered From 3c24121f5c7953ea9d691f0af6dfe039427b700d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 16:54:03 -0700 Subject: [PATCH 08/37] more noise suppression --- domain-server/src/DomainServer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 7e37c9b397..68601fd007 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -569,8 +569,10 @@ void DomainServer::readAvailableDatagrams() { nodeList->getNodeSocket().writeDatagram(assignmentPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); } else { - qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType() - << "from" << senderSockAddr; + if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastMessage) > NOISY_TIME_ELAPSED) { + qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType() + << "from" << senderSockAddr; + } } } } From 1d17e750439659084c718f259090c5481d045722 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 16:56:41 -0700 Subject: [PATCH 09/37] more noise suppression --- domain-server/src/DomainServer.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 68601fd007..6410737594 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -547,11 +547,12 @@ void DomainServer::readAvailableDatagrams() { // Suppress these for Assignment::AgentType to 1 per second... static quint64 lastMessage = usecTimestampNow(); quint64 timeNow = usecTimestampNow(); - const quint64 NOISY_TIME_ELAPSED = USECS_PER_SECOND; + const quint64 NOISY_TIME_ELAPSED = 10 * USECS_PER_SECOND; + bool noisyMessage = false; if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastMessage) > NOISY_TIME_ELAPSED) { qDebug() << "Received a request for assignment type" << requestAssignment.getType() << "from" << senderSockAddr; - lastMessage = timeNow; + noisyMessage = true; } SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); @@ -572,8 +573,13 @@ void DomainServer::readAvailableDatagrams() { if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastMessage) > NOISY_TIME_ELAPSED) { qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType() << "from" << senderSockAddr; + noisyMessage = true; } } + + if (noisyMessage) { + lastMessage = timeNow; + } } } } From 214866414c6b21eede207a9e87c4d42f81feb062 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 17:09:44 -0700 Subject: [PATCH 10/37] tweak names --- domain-server/src/DomainServer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6410737594..8a95a25e23 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -545,11 +545,11 @@ void DomainServer::readAvailableDatagrams() { Assignment requestAssignment(receivedPacket); // Suppress these for Assignment::AgentType to 1 per second... - static quint64 lastMessage = usecTimestampNow(); + static quint64 lastNoisyMessage = usecTimestampNow(); quint64 timeNow = usecTimestampNow(); - const quint64 NOISY_TIME_ELAPSED = 10 * USECS_PER_SECOND; + const quint64 NOISY_TIME_ELAPSED = 5 * USECS_PER_SECOND; bool noisyMessage = false; - if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastMessage) > NOISY_TIME_ELAPSED) { + if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastNoisyMessage) > NOISY_TIME_ELAPSED) { qDebug() << "Received a request for assignment type" << requestAssignment.getType() << "from" << senderSockAddr; noisyMessage = true; @@ -570,7 +570,7 @@ void DomainServer::readAvailableDatagrams() { nodeList->getNodeSocket().writeDatagram(assignmentPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); } else { - if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastMessage) > NOISY_TIME_ELAPSED) { + if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastNoisyMessage) > NOISY_TIME_ELAPSED) { qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType() << "from" << senderSockAddr; noisyMessage = true; @@ -578,7 +578,7 @@ void DomainServer::readAvailableDatagrams() { } if (noisyMessage) { - lastMessage = timeNow; + lastNoisyMessage = timeNow; } } } From 6fcb802a9439ed2835c2cf4e3ce710ae551b1299 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 11 Mar 2014 18:01:38 -0700 Subject: [PATCH 11/37] Added preview deplacement + fixed locking issue --- examples/addVoxelOnMouseClickExample.js | 20 +++++++++--------- examples/editVoxels.js | 27 +++++++++++++++++-------- interface/src/ui/LocalVoxelsOverlay.cpp | 4 ++-- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/examples/addVoxelOnMouseClickExample.js b/examples/addVoxelOnMouseClickExample.js index 4450a16c22..244a017ae4 100644 --- a/examples/addVoxelOnMouseClickExample.js +++ b/examples/addVoxelOnMouseClickExample.js @@ -15,16 +15,16 @@ function mousePressEvent(event) { 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 + ", " + 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 + ", " + 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 = { + + var newVoxel = { x: intersection.voxel.x, y: intersection.voxel.y, z: intersection.voxel.z, @@ -32,7 +32,7 @@ function mousePressEvent(event) { red: 255, green: 0, blue: 255 }; - + if (intersection.face == "MIN_X_FACE") { newVoxel.x -= newVoxel.s; } else if (intersection.face == "MAX_X_FACE") { @@ -46,11 +46,11 @@ function mousePressEvent(event) { } else if (intersection.face == "MAX_Z_FACE") { newVoxel.z += newVoxel.s; } - - print("Voxels.setVoxel("+newVoxel.x + ", " - + newVoxel.y + ", " + 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); } } diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 960840b680..d78efdaad3 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -972,7 +972,6 @@ function mousePressEvent(event) { print("placing import..."); placeImport(); showImport(false); - pasteMode = false; moveTools(); return; } @@ -1177,7 +1176,6 @@ function menuItemEvent(menuItem) { print("importing..."); if (importVoxels()) { showImport(true); - pasteMode = true; } moveTools(); } @@ -1512,14 +1510,27 @@ function checkControllers() { } function update(deltaTime) { - var newWindowDimensions = Controller.getViewportDimensions(); - if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { - windowDimensions = newWindowDimensions; - moveTools(); - } - if (editToolsOn) { + var newWindowDimensions = Controller.getViewportDimensions(); + if (newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y) { + windowDimensions = newWindowDimensions; + moveTools(); + } + checkControllers(); + + // Move Import Preview + if (isImporting) { + var position = MyAvatar.position; + var forwardVector = Quat.getFront(MyAvatar.orientation); + var targetPosition = Vec3.sum(position, Vec3.multiply(forwardVector, importScale)); + var newPosition = { + x: Math.floor(targetPosition.x / importScale) * importScale, + y: Math.floor(targetPosition.y / importScale) * importScale, + z: Math.floor(targetPosition.z / importScale) * importScale + } + moveImport(newPosition); + } } } diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/LocalVoxelsOverlay.cpp index 248a5b6733..fde03b85cb 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/LocalVoxelsOverlay.cpp @@ -40,12 +40,12 @@ void LocalVoxelsOverlay::update(float deltatime) { _voxelSystem->init(); } + _tree->lockForWrite(); if (_visible && _voxelCount != _tree->getOctreeElementsCount()) { _voxelCount = _tree->getOctreeElementsCount(); - _tree->lockForWrite(); _voxelSystem->forceRedrawEntireTree(); - _tree->unlock(); } + _tree->unlock(); } void LocalVoxelsOverlay::render() { From 03d7fb147c6913945d0e0f6bda999d93c1e016e2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 11 Mar 2014 18:15:04 -0700 Subject: [PATCH 12/37] Fixed spaces added everywhere --- examples/editVoxels.js | 184 ++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index d78efdaad3..b5702dff47 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -8,10 +8,10 @@ // Captures mouse clicks and edits voxels accordingly. // // click = create a new voxel on this face, same color as old (default color picker state) -// right click or control + click = delete this voxel +// right click or control + click = delete this voxel // shift + click = recolor this voxel // 1 - 8 = pick new color from palette -// 9 = create a new voxel in front of the camera +// 9 = create a new voxel in front of the camera // // Click and drag to create more new voxels in the same direction // @@ -36,19 +36,19 @@ var previewLineWidth = 1.5; var oldMode = Camera.getMode(); -var isAdding = false; -var isExtruding = false; +var isAdding = false; +var isExtruding = false; var isOrbiting = false; var isOrbitingFromTouch = false; var isPanning = false; var isPanningFromTouch = false; var touchPointsToOrbit = 2; // you can change these, but be mindful that on some track pads 2 touch points = right click+drag -var touchPointsToPan = 3; +var touchPointsToPan = 3; var orbitAzimuth = 0.0; var orbitAltitude = 0.0; var orbitCenter = { x: 0, y: 0, z: 0 }; var orbitPosition = { x: 0, y: 0, z: 0 }; -var torsoToEyeVector = { x: 0, y: 0, z: 0 }; +var torsoToEyeVector = { x: 0, y: 0, z: 0 }; var orbitRadius = 0.0; var extrudeDirection = { x: 0, y: 0, z: 0 }; var extrudeScale = 0.0; @@ -60,7 +60,7 @@ var wheelPixelsMoved = 0; var mouseX = 0; -var mouseY = 0; +var mouseY = 0; // Create a table of the different colors you can choose var colors = new Array(); @@ -76,7 +76,7 @@ colors[8] = { red: 31, green: 64, blue: 64 }; var numColors = 9; var whichColor = -1; // Starting color is 'Copy' mode -// Create sounds for adding, deleting, recoloring voxels +// Create sounds for adding, deleting, recoloring voxels var addSound1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+2.raw"); var addSound2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+3.raw"); var addSound3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+4.raw"); @@ -93,7 +93,7 @@ var editToolsOn = true; // starts out off // previewAsVoxel - by default, we will preview adds/deletes/recolors as just 4 lines on the intersecting face. But if you // the preview to show a full voxel then set this to true and the voxel will be displayed for voxel editing -var previewAsVoxel = true; +var previewAsVoxel = false; var voxelPreview = Overlays.addOverlay("cube", { position: { x: 0, y: 0, z: 0}, @@ -104,7 +104,7 @@ var voxelPreview = Overlays.addOverlay("cube", { visible: false, lineWidth: 4 }); - + var linePreviewTop = Overlays.addOverlay("line3d", { position: { x: 0, y: 0, z: 0}, end: { x: 0, y: 0, z: 0}, @@ -228,7 +228,7 @@ var eyedropperTool = Overlays.addOverlay("image", { visible: false, alpha: 0.9 }); - + // This will create a couple of image overlays that make a "slider", we will demonstrate how to trap mouse messages to // move the slider @@ -392,7 +392,7 @@ function calcScaleFromThumb(newThumbX) { // now reset the display accordingly... calcThumbFromScale(pointerVoxelScale); - + // if the user moved the thumb, then they are fixing the voxel scale pointerVoxelScaleSet = true; } @@ -466,27 +466,27 @@ function calculateVoxelFromIntersection(intersection, operation) { var wantDebug = false; if (wantDebug) { - print(">>>>> calculateVoxelFromIntersection().... intersection voxel.red/green/blue=" + intersection.voxel.red + ", " + print(">>>>> calculateVoxelFromIntersection().... intersection voxel.red/green/blue=" + intersection.voxel.red + ", " + intersection.voxel.green + ", " + intersection.voxel.blue); - print(" intersection voxel.x/y/z/s=" + intersection.voxel.x + ", " + 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 + ", " + print(" intersection intersection.x/y/z=" + intersection.intersection.x + ", " + intersection.intersection.y + ", " + intersection.intersection.z); } - + var voxelSize; if (pointerVoxelScaleSet) { - voxelSize = pointerVoxelScale; + voxelSize = pointerVoxelScale; } else { - voxelSize = intersection.voxel.s; + voxelSize = intersection.voxel.s; } var x; var y; var z; - + // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest // ancestor voxel of our target size that contains our intersected voxel. if (voxelSize > intersection.voxel.s) { @@ -527,7 +527,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.x -= voxelSize; } - + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; @@ -551,7 +551,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.y -= voxelSize; } - + resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; @@ -563,7 +563,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.y += voxelSize; } - + resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust}; resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; @@ -575,7 +575,7 @@ function calculateVoxelFromIntersection(intersection, operation) { if (wantAddAdjust) { resultVoxel.z -= voxelSize; } - + resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; @@ -594,7 +594,7 @@ function calculateVoxelFromIntersection(intersection, operation) { resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; } - + return resultVoxel; } @@ -604,7 +604,7 @@ function showPreviewVoxel() { var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); var intersection = Voxels.findRayIntersection(pickRay); - // if the user hasn't updated the + // if the user hasn't updated the if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } @@ -668,10 +668,10 @@ function showPreviewLines() { } var intersection = Voxels.findRayIntersection(pickRay); - + if (intersection.intersects) { - // if the user hasn't updated the + // if the user hasn't updated the if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } @@ -788,14 +788,14 @@ function trackKeyReleaseEvent(event) { trackAsOrbitOrPan = false; moveTools(); } - + // on F1 toggle the preview mode between cubes and lines if (event.text == "F1") { previewAsVoxel = !previewAsVoxel; } showPreviewGuides(); - } + } } function startOrbitMode(event) { @@ -804,7 +804,7 @@ function startOrbitMode(event) { var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Voxels.findRayIntersection(pickRay); - // start orbit camera! + // start orbit camera! var cameraPosition = Camera.getPosition(); torsoToEyeVector = Vec3.subtract(cameraPosition, MyAvatar.position); torsoToEyeVector.x = 0.0; @@ -813,12 +813,12 @@ function startOrbitMode(event) { Camera.setMode("independent"); Camera.keepLookingAt(intersection.intersection); // get position for initial azimuth, elevation - orbitCenter = intersection.intersection; + orbitCenter = intersection.intersection; var orbitVector = Vec3.subtract(cameraPosition, orbitCenter); - orbitRadius = Vec3.length(orbitVector); + orbitRadius = Vec3.length(orbitVector); orbitAzimuth = Math.atan2(orbitVector.z, orbitVector.x); orbitAltitude = Math.asin(orbitVector.y / Vec3.length(orbitVector)); - + //print("startOrbitMode..."); } @@ -826,17 +826,17 @@ function handleOrbitingMove(event) { var cameraOrientation = Camera.getOrientation(); var origEulers = Quat.safeEulerAngles(cameraOrientation); var newEulers = fixEulerAngles(Quat.safeEulerAngles(cameraOrientation)); - var dx = event.x - mouseX; + var dx = event.x - mouseX; var dy = event.y - mouseY; orbitAzimuth += dx / ORBIT_RATE_AZIMUTH; orbitAltitude += dy / ORBIT_RATE_ALTITUDE; - var orbitVector = { x:(Math.cos(orbitAltitude) * Math.cos(orbitAzimuth)) * orbitRadius, + var orbitVector = { x:(Math.cos(orbitAltitude) * Math.cos(orbitAzimuth)) * orbitRadius, y:Math.sin(orbitAltitude) * orbitRadius, - z:(Math.cos(orbitAltitude) * Math.sin(orbitAzimuth)) * orbitRadius }; + z:(Math.cos(orbitAltitude) * Math.sin(orbitAzimuth)) * orbitRadius }; orbitPosition = Vec3.sum(orbitCenter, orbitVector); Camera.setPosition(orbitPosition); - mouseX = event.x; + mouseX = event.x; mouseY = event.y; //print("handleOrbitingMove..."); } @@ -852,7 +852,7 @@ function endOrbitMode(event) { } function startPanMode(event, intersection) { - // start pan camera! + // start pan camera! print("handle PAN mode!!!"); } @@ -870,14 +870,14 @@ function mousePressEvent(event) { // if our tools are off, then don't do anything if (!editToolsOn) { - return; + return; } - - // Normally, if we're panning or orbiting from touch, ignore these... because our touch takes precedence. - // but In the case of a button="RIGHT" click, we may get some touch messages first, and we actually want to + + // Normally, if we're panning or orbiting from touch, ignore these... because our touch takes precedence. + // but In the case of a button="RIGHT" click, we may get some touch messages first, and we actually want to // cancel any touch mode, and then let the right-click through if (isOrbitingFromTouch || isPanningFromTouch) { - + // if the user is holding the ALT key AND they are clicking the RIGHT button (or on multi-touch doing a two // finger touch, then we want to let the new panning behavior take over. // if it's any other case we still want to bail @@ -894,15 +894,15 @@ function mousePressEvent(event) { } // let things fall through } else { - return; + return; } } - + // no clicking on overlays while in panning mode if (!trackAsOrbitOrPan) { var clickedOnSomething = false; var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - + // If the user clicked on the thumb, handle the slider logic if (clickedOverlay == thumb) { @@ -959,7 +959,7 @@ function mousePressEvent(event) { return; // no further processing } } - + // TODO: does any of this stuff need to execute if we're panning or orbiting? trackMouseEvent(event); // used by preview support mouseX = event.x; @@ -985,11 +985,11 @@ function mousePressEvent(event) { } if (intersection.intersects) { - // if the user hasn't updated the + // if the user hasn't updated the if (!pointerVoxelScaleSet) { calcThumbFromScale(intersection.voxel.s); } - + // Note: touch and mouse events can cross paths, so we want to ignore any mouse events that would // start a pan or orbit if we're already doing a pan or orbit via touch... if ((event.isAlt || trackAsOrbitOrPan) && !(isOrbitingFromTouch || isPanningFromTouch)) { @@ -1013,14 +1013,14 @@ function mousePressEvent(event) { colors[whichColor].blue = intersection.voxel.blue; moveTools(); } - + } else if (recolorToolSelected || trackAsRecolor) { // Recolor Voxel voxelDetails = calculateVoxelFromIntersection(intersection,"recolor"); // doing this erase then set will make sure we only recolor just the target voxel Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); - Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, + Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); Audio.playSound(changeColorSound, audioOptions); Overlays.editOverlay(voxelPreview, { visible: false }); @@ -1028,17 +1028,17 @@ function mousePressEvent(event) { // Add voxel on face if (whichColor == -1) { // Copy mode - use clicked voxel color - newColor = { + newColor = { red: intersection.voxel.red, green: intersection.voxel.green, blue: intersection.voxel.blue }; } else { - newColor = { + newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; } - + voxelDetails = calculateVoxelFromIntersection(intersection,"add"); Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s, @@ -1048,11 +1048,11 @@ function mousePressEvent(event) { lastVoxelScale = voxelDetails.s; playRandomAddSound(audioOptions); - + Overlays.editOverlay(voxelPreview, { visible: false }); dragStart = { x: event.x, y: event.y }; isAdding = true; - } + } } } @@ -1071,14 +1071,14 @@ function keyPressEvent(event) { Audio.playSound(clickSound, audioOptions); moveTools(); } else if (event.text == "0") { - // Create a brand new 1 meter voxel in front of your avatar - var color = whichColor; + // Create a brand new 1 meter voxel in front of your avatar + var color = whichColor; if (color == -1) color = 0; var newPosition = getNewVoxelPosition(); - var newVoxel = { + var newVoxel = { x: newPosition.x, y: newPosition.y , - z: newPosition.z, + z: newPosition.z, s: NEW_VOXEL_SIZE, red: colors[color].red, green: colors[color].green, @@ -1089,7 +1089,7 @@ function keyPressEvent(event) { playRandomAddSound(audioOptions); } } - + trackKeyPressEvent(event); // used by preview support } @@ -1167,7 +1167,7 @@ function menuItemEvent(menuItem) { Clipboard.deleteVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); } } - + if (menuItem == "Export Voxels") { print("export"); Clipboard.exportVoxel(selectedVoxel.x, selectedVoxel.y, selectedVoxel.z, selectedVoxel.s); @@ -1191,11 +1191,11 @@ function mouseMoveEvent(event) { return; } - // if we're panning or orbiting from touch, ignore these... because our touch takes precedence. + // if we're panning or orbiting from touch, ignore these... because our touch takes precedence. if (isOrbitingFromTouch || isPanningFromTouch) { - return; + return; } - + // double check that we didn't accidentally miss a pan or orbit click request if (trackAsOrbitOrPan && !isPanning && !isOrbiting) { if (event.isLeftButton && !event.isRightButton) { @@ -1217,7 +1217,7 @@ function mouseMoveEvent(event) { thumbX = maxThumbX; } calcScaleFromThumb(thumbX); - + } else if (isOrbiting) { handleOrbitingMove(event); } else if (isPanning) { @@ -1226,8 +1226,8 @@ function mouseMoveEvent(event) { // Watch the drag direction to tell which way to 'extrude' this voxel if (!isExtruding) { var pickRay = Camera.computePickRay(event.x, event.y); - var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x, - y: pickRay.origin.y - lastVoxelPosition.y, + var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x, + y: pickRay.origin.y - lastVoxelPosition.y, z: pickRay.origin.z - lastVoxelPosition.z }; var distance = Vec3.length(lastVoxelDistance); var mouseSpot = { x: pickRay.direction.x * distance, y: pickRay.direction.y * distance, z: pickRay.direction.z * distance }; @@ -1246,22 +1246,22 @@ function mouseMoveEvent(event) { else if (dy < -lastVoxelScale) extrudeDirection.y = -extrudeScale; else if (dz > lastVoxelScale) extrudeDirection.z = extrudeScale; else if (dz < -lastVoxelScale) extrudeDirection.z = -extrudeScale; - else isExtruding = false; + else isExtruding = false; } else { // We have got an extrusion direction, now look for mouse move beyond threshold to add new voxel - var dx = event.x - mouseX; + var dx = event.x - mouseX; var dy = event.y - mouseY; if (Math.sqrt(dx*dx + dy*dy) > PIXELS_PER_EXTRUDE_VOXEL) { lastVoxelPosition = Vec3.sum(lastVoxelPosition, extrudeDirection); Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s); - Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, extrudeScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); mouseX = event.x; mouseY = event.y; } } } - + // update the add voxel/delete voxel overlay preview trackMouseEvent(event); } @@ -1269,13 +1269,13 @@ function mouseMoveEvent(event) { function mouseReleaseEvent(event) { // if our tools are off, then don't do anything if (!editToolsOn) { - return; + return; } if (isMovingSlider) { isMovingSlider = false; } - + if (isOrbiting) { endOrbitMode(event); isOrbiting = false; @@ -1286,7 +1286,7 @@ function mouseReleaseEvent(event) { isPanning = false; } isAdding = false; - isExtruding = false; + isExtruding = false; } function moveTools() { @@ -1314,7 +1314,7 @@ function moveTools() { if (s == (numColors - 1)) { extraWidth = swatchExtraPadding; } - + Overlays.editOverlay(swatches[s], { x: swatchX, y: swatchesY, @@ -1378,16 +1378,16 @@ function touchBeginEvent(event) { if (!editToolsOn) { return; } - + // if we're already in the middle of orbiting or panning, then ignore these multi-touch events... if (isOrbiting || isPanning) { return; - } - + } + if (event.isAlt || trackAsOrbitOrPan) { if (event.touchPoints == touchPointsToOrbit) { // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (isPanningFromTouch) { print("touchBeginEvent... calling endPanMode()"); endPanMode(event); @@ -1397,7 +1397,7 @@ function touchBeginEvent(event) { isOrbitingFromTouch = true; } else if (event.touchPoints == touchPointsToPan) { // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (isOrbitingFromTouch) { endOrbitMode(event); isOrbitingFromTouch = false; @@ -1416,11 +1416,11 @@ function touchUpdateEvent(event) { // if we're already in the middle of orbiting or panning, then ignore these multi-touch events... if (isOrbiting || isPanning) { return; - } - + } + if (isOrbitingFromTouch) { // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (event.touchPoints == touchPointsToPan) { //print("we now have touchPointsToPan touches... switch to pan..."); endOrbitMode(event); @@ -1434,7 +1434,7 @@ function touchUpdateEvent(event) { if (isPanningFromTouch) { //print("touchUpdateEvent... isPanningFromTouch... event.touchPoints=" + event.touchPoints); // we need to double check that we didn't start an orbit, because the touch events will sometimes - // come in as 2 then 3 touches... + // come in as 2 then 3 touches... if (event.touchPoints == touchPointsToOrbit) { //print("we now have touchPointsToOrbit touches... switch to orbit..."); //print("touchUpdateEvent... calling endPanMode()"); @@ -1457,8 +1457,8 @@ function touchEndEvent(event) { // if we're already in the middle of orbiting or panning, then ignore these multi-touch events... if (isOrbiting || isPanning) { return; - } - + } + if (isOrbitingFromTouch) { endOrbitMode(event); isOrbitingFromTouch = false; @@ -1476,10 +1476,10 @@ var lastFingerDeleteVoxel = { x: -1, y: -1, z: -1}; // off of the build-able are function checkControllers() { var controllersPerPalm = 2; // palm and finger for (var palm = 0; palm < 2; palm++) { - var palmController = palm * controllersPerPalm; - var fingerTipController = palmController + 1; + var palmController = palm * controllersPerPalm; + var fingerTipController = palmController + 1; var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); - + var BUTTON_COUNT = 6; var BUTTON_BASE = palm * BUTTON_COUNT; var BUTTON_1 = BUTTON_BASE + 1; @@ -1497,7 +1497,7 @@ function checkControllers() { Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE); Voxels.setVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE, newColor.red, newColor.green, newColor.blue); - + lastFingerAddVoxel = fingerTipPosition; } } else if (Controller.isButtonPressed(BUTTON_2)) { @@ -1546,7 +1546,7 @@ function wheelEvent(event) { pointerVoxelScale /= 2.0; if (pointerVoxelScale < MIN_VOXEL_SCALE) { pointerVoxelScale = MIN_VOXEL_SCALE; - } + } } else { pointerVoxelScale *= 2.0; if (pointerVoxelScale > MAX_VOXEL_SCALE) { From 4d0b762de3fb5f2a0436ee6c73cc71576c4e60bc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 20:33:53 -0700 Subject: [PATCH 13/37] some hacking on full scene debuggin --- .../src/octree/OctreeSendThread.cpp | 18 ++++++++++++++++-- interface/src/Application.cpp | 18 ++++++++++++++++-- interface/src/Application.h | 2 ++ libraries/octree/src/OctreeSceneStats.cpp | 3 +++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 751583960e..7a46fa3722 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -366,8 +366,20 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue } // start tracking our stats - bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) - && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged(); + qDebug() << "----"; + qDebug() << "viewFrustumChanged=" << viewFrustumChanged; + qDebug() << "nodeData->getWantDelta()=" << nodeData->getWantDelta(); + qDebug() << "nodeData->getViewFrustumJustStoppedChanging()=" << nodeData->getViewFrustumJustStoppedChanging(); + qDebug() << "nodeData->hasLodChanged()=" << nodeData->hasLodChanged(); + + + bool isFullScene = ( + (!viewFrustumChanged || !nodeData->getWantDelta()) + && nodeData->getViewFrustumJustStoppedChanging() + ) + || nodeData->hasLodChanged(); + + qDebug() << "isFullScene=" << isFullScene; // If we're starting a full scene, then definitely we want to empty the nodeBag if (isFullScene) { @@ -436,6 +448,8 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged(); + qDebug() << "SECOND CALC.... isFullScene=" << isFullScene; + EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, wantOcclusionCulling, coverageMap, boundaryLevelAdjust, voxelSizeScale, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 032e849f0a..f6cdfaa509 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -141,6 +141,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _justStarted(true), _voxelImporter(NULL), _wantToKillLocalVoxels(false), + _viewFrustum(), + _lastQueriedViewFrustum(), + _lastQueriedTime(usecTimestampNow()), _audioScope(256, 200, true), _myAvatar(), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), @@ -1917,8 +1920,19 @@ void Application::updateMyAvatar(float deltaTime) { loadViewFrustum(_myCamera, _viewFrustum); // Update my voxel servers with my current voxel query... - queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions); - queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions); + quint64 now = usecTimestampNow(); + const quint64 TOO_LONG_SINCE_LAST_QUERY = 1 * USECS_PER_SECOND; + + // if we haven't waited long enough and the frustum is similar enough, then surpress this query... + if ((now - _lastQueriedTime) > TOO_LONG_SINCE_LAST_QUERY || !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum)) { + _lastQueriedTime = now; + queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions); + queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions); + _lastQueriedViewFrustum = _viewFrustum; + //qDebug() << ">>>>>>>>>> SENDING query..."; + } else { + //qDebug() << "suppress query..."; + } } void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 234f264447..f56bb62d9f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -377,6 +377,8 @@ private: MetavoxelSystem _metavoxels; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. + ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels, particles) + quint64 _lastQueriedTime; Oscilloscope _audioScope; diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index ad7f774377..ec073c6ce5 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -167,6 +167,9 @@ void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeEleme _totalInternal = OctreeElement::getInternalNodeCount(); _totalLeaves = OctreeElement::getLeafNodeCount(); + if (isFullScene) { + qDebug() << "OctreeSceneStats::sceneStarted()... IS FULL SCENE"; + } _isFullScene = isFullScene; _isMoving = isMoving; From a95fd55172eb0ca1b1157643b56b81041f78a1a5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Mar 2014 01:11:21 -0700 Subject: [PATCH 14/37] suppress sending of extra queries when the client's view hasn't changed --- interface/src/Application.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f6cdfaa509..cf1966c585 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1921,17 +1921,17 @@ void Application::updateMyAvatar(float deltaTime) { // Update my voxel servers with my current voxel query... quint64 now = usecTimestampNow(); - const quint64 TOO_LONG_SINCE_LAST_QUERY = 1 * USECS_PER_SECOND; + quint64 sinceLastQuery = now - _lastQueriedTime; + const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; + bool queryIsDue = sinceLastQuery > TOO_LONG_SINCE_LAST_QUERY; + bool viewIsDifferentEnough = !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum); - // if we haven't waited long enough and the frustum is similar enough, then surpress this query... - if ((now - _lastQueriedTime) > TOO_LONG_SINCE_LAST_QUERY || !_lastQueriedViewFrustum.isVerySimilar(_viewFrustum)) { + // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it + if (queryIsDue || viewIsDifferentEnough) { _lastQueriedTime = now; queryOctree(NodeType::VoxelServer, PacketTypeVoxelQuery, _voxelServerJurisdictions); queryOctree(NodeType::ParticleServer, PacketTypeParticleQuery, _particleServerJurisdictions); _lastQueriedViewFrustum = _viewFrustum; - //qDebug() << ">>>>>>>>>> SENDING query..."; - } else { - //qDebug() << "suppress query..."; } } From 7e6beba4d2ff40759df35f5eebdd1dea7dac49a1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Mar 2014 01:29:41 -0700 Subject: [PATCH 15/37] removed redundant calc of isFullScene --- .../src/octree/OctreeSendThread.cpp | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 7a46fa3722..dcef7d59af 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -241,6 +241,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue int truePacketsSent = 0; int trueBytesSent = 0; int packetsSentThisInterval = 0; + bool isFullScene = false; bool somethingToSend = true; // assume we have something // FOR NOW... node tells us if it wants to receive only view frustum deltas @@ -366,20 +367,8 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue } // start tracking our stats - qDebug() << "----"; - qDebug() << "viewFrustumChanged=" << viewFrustumChanged; - qDebug() << "nodeData->getWantDelta()=" << nodeData->getWantDelta(); - qDebug() << "nodeData->getViewFrustumJustStoppedChanging()=" << nodeData->getViewFrustumJustStoppedChanging(); - qDebug() << "nodeData->hasLodChanged()=" << nodeData->hasLodChanged(); - - - bool isFullScene = ( - (!viewFrustumChanged || !nodeData->getWantDelta()) - && nodeData->getViewFrustumJustStoppedChanging() - ) - || nodeData->hasLodChanged(); - - qDebug() << "isFullScene=" << isFullScene; + isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging()) + || nodeData->hasLodChanged(); // If we're starting a full scene, then definitely we want to empty the nodeBag if (isFullScene) { @@ -444,12 +433,6 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue int boundaryLevelAdjust = boundaryLevelAdjustClient + (viewFrustumChanged && nodeData->getWantLowResMoving() ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); - - bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) && - nodeData->getViewFrustumJustStoppedChanging()) || nodeData->hasLodChanged(); - - qDebug() << "SECOND CALC.... isFullScene=" << isFullScene; - EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, wantOcclusionCulling, coverageMap, boundaryLevelAdjust, voxelSizeScale, From 86feabee99ec35becd0ab85e9fffce071988aa3c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Mar 2014 02:22:24 -0700 Subject: [PATCH 16/37] add last scene packets, bytes and pps --- interface/src/ui/OctreeStatsDialog.cpp | 16 +++++++++++++-- libraries/octree/src/OctreeSceneStats.cpp | 25 +++++++++++++---------- libraries/octree/src/OctreeSceneStats.h | 9 ++++++-- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 92578b6b34..daf5a68587 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -315,13 +315,25 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser const unsigned long USECS_PER_MSEC = 1000; float lastFullEncode = stats.getLastFullTotalEncodeTime() / USECS_PER_MSEC; float lastFullSend = stats.getLastFullElapsedTime() / USECS_PER_MSEC; + float lastFullSendInSeconds = stats.getLastFullElapsedTime() / USECS_PER_SECOND; + float lastFullPackets = stats.getLastFullTotalPackets(); + float lastFullPPS = lastFullPackets; + if (lastFullSendInSeconds > 0) { + lastFullPPS = lastFullPackets / lastFullSendInSeconds; + } QString lastFullEncodeString = locale.toString(lastFullEncode); QString lastFullSendString = locale.toString(lastFullSend); + QString lastFullPacketsString = locale.toString(lastFullPackets); + QString lastFullBytesString = locale.toString((uint)stats.getLastFullTotalBytes()); + QString lastFullPPSString = locale.toString(lastFullPPS); extraDetails << "
" << "Last Full Scene... " << - "Encode Time: " << qPrintable(lastFullEncodeString) << " ms " << - "Send Time: " << qPrintable(lastFullSendString) << " ms "; + "Encode: " << qPrintable(lastFullEncodeString) << " ms " << + "Send: " << qPrintable(lastFullSendString) << " ms " << + "Packets: " << qPrintable(lastFullPacketsString) << " " << + "Bytes: " << qPrintable(lastFullBytesString) << " " << + "Rate: " << qPrintable(lastFullPPSString) << " PPS"; for (int i = 0; i < OctreeSceneStats::ITEM_COUNT; i++) { OctreeSceneStats::Item item = (OctreeSceneStats::Item)(i); diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index ec073c6ce5..e42fe17df0 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -27,9 +27,12 @@ OctreeSceneStats::OctreeSceneStats() : _isReadyToSend(false), _isStarted(false), _lastFullElapsed(0), + _lastFullTotalEncodeTime(0), + _lastFullTotalPackets(0), + _lastFullTotalBytes(0), + _elapsedAverage(samples), _bitsPerOctreeAverage(samples), - _lastFullTotalEncodeTime(0), _incomingPacket(0), _incomingBytes(0), _incomingWastedBytes(0), @@ -62,8 +65,10 @@ OctreeSceneStats& OctreeSceneStats::operator=(const OctreeSceneStats& other) { void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) { _totalEncodeTime = other._totalEncodeTime; _elapsed = other._elapsed; - _lastFullTotalEncodeTime = other._lastFullTotalEncodeTime; _lastFullElapsed = other._lastFullElapsed; + _lastFullTotalEncodeTime = other._lastFullTotalEncodeTime; + _lastFullTotalPackets = other._lastFullTotalPackets; + _lastFullTotalBytes = other._lastFullTotalBytes; _encodeStart = other._encodeStart; _packets = other._packets; @@ -167,9 +172,6 @@ void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeEleme _totalInternal = OctreeElement::getInternalNodeCount(); _totalLeaves = OctreeElement::getLeafNodeCount(); - if (isFullScene) { - qDebug() << "OctreeSceneStats::sceneStarted()... IS FULL SCENE"; - } _isFullScene = isFullScene; _isMoving = isMoving; @@ -511,12 +513,6 @@ int OctreeSceneStats::unpackFromMessage(const unsigned char* sourceBuffer, int a memcpy(&_isFullScene, sourceBuffer, sizeof(_isFullScene)); sourceBuffer += sizeof(_isFullScene); - - if (_isFullScene) { - _lastFullElapsed = _elapsed; - _lastFullTotalEncodeTime = _totalEncodeTime; - } - memcpy(&_isMoving, sourceBuffer, sizeof(_isMoving)); sourceBuffer += sizeof(_isMoving); memcpy(&_packets, sourceBuffer, sizeof(_packets)); @@ -524,6 +520,13 @@ int OctreeSceneStats::unpackFromMessage(const unsigned char* sourceBuffer, int a memcpy(&_bytes, sourceBuffer, sizeof(_bytes)); sourceBuffer += sizeof(_bytes); + if (_isFullScene) { + _lastFullElapsed = _elapsed; + _lastFullTotalEncodeTime = _totalEncodeTime; + _lastFullTotalPackets = _packets; + _lastFullTotalBytes = _bytes; + } + memcpy(&_totalInternal, sourceBuffer, sizeof(_totalInternal)); sourceBuffer += sizeof(_totalInternal); memcpy(&_totalLeaves, sourceBuffer, sizeof(_totalLeaves)); diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index 249ab376c1..2b39b3434c 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -150,8 +150,10 @@ public: unsigned long getTotalEncodeTime() const { return _totalEncodeTime; } unsigned long getElapsedTime() const { return _elapsed; } - unsigned long getLastFullTotalEncodeTime() const { return _lastFullTotalEncodeTime; } unsigned long getLastFullElapsedTime() const { return _lastFullElapsed; } + unsigned long getLastFullTotalEncodeTime() const { return _lastFullTotalEncodeTime; } + unsigned int getLastFullTotalPackets() const { return _lastFullTotalPackets; } + unsigned long getLastFullTotalBytes() const { return _lastFullTotalBytes; } // Used in client implementations to track individual octree packets void trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec); @@ -181,13 +183,16 @@ private: quint64 _start; quint64 _end; quint64 _elapsed; + quint64 _lastFullElapsed; + quint64 _lastFullTotalEncodeTime; + unsigned int _lastFullTotalPackets; + unsigned long _lastFullTotalBytes; SimpleMovingAverage _elapsedAverage; SimpleMovingAverage _bitsPerOctreeAverage; quint64 _totalEncodeTime; - quint64 _lastFullTotalEncodeTime; quint64 _encodeStart; // scene octree related data From 6173a4d2a79bb1dc969794ab5095cb77261271f5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Mar 2014 10:19:21 -0700 Subject: [PATCH 17/37] fix isFullScene correctly --- assignment-client/src/octree/OctreeSendThread.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index dcef7d59af..ef69771607 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -241,7 +241,9 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue int truePacketsSent = 0; int trueBytesSent = 0; int packetsSentThisInterval = 0; - bool isFullScene = false; + bool isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging()) + || nodeData->hasLodChanged(); + bool somethingToSend = true; // assume we have something // FOR NOW... node tells us if it wants to receive only view frustum deltas @@ -366,10 +368,6 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue << " Wasted:" << _totalWastedBytes; } - // start tracking our stats - isFullScene = ((!viewFrustumChanged || !nodeData->getWantDelta()) && nodeData->getViewFrustumJustStoppedChanging()) - || nodeData->hasLodChanged(); - // If we're starting a full scene, then definitely we want to empty the nodeBag if (isFullScene) { nodeData->nodeBag.deleteAll(); @@ -383,6 +381,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue } ::startSceneSleepTime = _usleepTime; + // start tracking our stats nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getOctree()->getRoot(), _myServer->getJurisdiction()); // This is the start of "resending" the scene. From 8622f2d548d5e8c942aeac5c31edda3b6c1882be Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Mar 2014 10:20:33 -0700 Subject: [PATCH 18/37] fix comment --- domain-server/src/DomainServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8a95a25e23..a425052970 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -544,7 +544,7 @@ void DomainServer::readAvailableDatagrams() { // construct the requested assignment from the packet data Assignment requestAssignment(receivedPacket); - // Suppress these for Assignment::AgentType to 1 per second... + // Suppress these for Assignment::AgentType to once per 5 seconds static quint64 lastNoisyMessage = usecTimestampNow(); quint64 timeNow = usecTimestampNow(); const quint64 NOISY_TIME_ELAPSED = 5 * USECS_PER_SECOND; From 1c4051b288081ee12007f90eaecf89c5fd018f1d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 12 Mar 2014 10:35:22 -0700 Subject: [PATCH 19/37] Added importBoundaries --- examples/editVoxels.js | 40 ++++++++++++++++++++++++++++----------- interface/interface_en.ts | 4 ++-- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index b5702dff47..956b6f1d1d 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -283,17 +283,25 @@ var thumbDeltaPerStep = thumbExtents / (pointerVoxelScaleSteps - 1); // Move the following code to a separate file when include will be available. var importTree; var importPreview; +var importBoundaries; var isImporting; var importPosition; var importScale; function initImport() { importPreview = Overlays.addOverlay("localvoxels", { - name: "import", - position: { x: 0, y: 0, z: 0}, - scale: 0, - visible: false - }); + name: "import", + position: { x: 0, y: 0, z: 0}, + scale: 1, + visible: false + }); + importBoundaries = Overlays.addOverlay("cube", { + position: { x: 0, y: 0, z: 0 }, + scale: 1, + color: { red: 128, blue: 128, green: 128 }, + solid: false, + visible: false + }) isImporting = false; importPosition = { x: 0, y: 0, z: 0 }; importScale = 0; @@ -316,8 +324,11 @@ function moveImport(position) { if (0 < position.x && 0 < position.y && 0 < position.z) { importPosition = position; Overlays.editOverlay(importPreview, { - position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } - }); + position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } + }); + Overlays.editOverlay(importBoundaries, { + position: { x: importPosition.x, y: importPosition.y, z: importPosition.z } + }); } } @@ -325,15 +336,21 @@ function rescaleImport(scale) { if (0 < scale) { importScale = scale; Overlays.editOverlay(importPreview, { - scale: importScale - }); + scale: importScale + }); + Overlays.editOverlay(importBoundaries, { + scale: importScale + }); } } function showImport(doShow) { Overlays.editOverlay(importPreview, { - visible: doShow - }); + visible: doShow + }); + Overlays.editOverlay(importBoundaries, { + visible: doShow + }); } function placeImport() { @@ -352,6 +369,7 @@ function cancelImport() { function cleanupImport() { Overlays.deleteOverlay(importPreview); + Overlays.deleteOverlay(importBoundaries); isImporting = false; importPostion = { x: 0, y: 0, z: 0 }; importScale = 0; diff --git a/interface/interface_en.ts b/interface/interface_en.ts index a8f78cd36e..76a5d47101 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -14,12 +14,12 @@ - + Open Script - + JavaScript Files (*.js) From 4b60c549e77e021b43344bd7246a3c28279761e1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 12 Mar 2014 11:10:52 -0700 Subject: [PATCH 20/37] add LOD to overlay display --- interface/src/Application.cpp | 25 +++++++++++------ interface/src/Menu.cpp | 34 +++++++++++++++++++++++ interface/src/Menu.h | 1 + interface/src/ui/LodToolsDialog.cpp | 42 +++-------------------------- interface/src/ui/LodToolsDialog.h | 2 -- 5 files changed, 56 insertions(+), 48 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cf1966c585..2007b7929c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2786,8 +2786,8 @@ void Application::displayStats() { voxelStats.str(""); QString packetsString = locale.toString((int)voxelPacketsToProcess); QString maxString = locale.toString((int)_recentMaxPackets); - voxelStats << "Voxel Packets to Process: " << packetsString.toLocal8Bit().constData() - << " [Recent Max: " << maxString.toLocal8Bit().constData() << "]"; + voxelStats << "Voxel Packets to Process: " << qPrintable(packetsString) + << " [Recent Max: " << qPrintable(maxString) << "]"; verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT); } @@ -2810,7 +2810,7 @@ void Application::displayStats() { // Server Voxels voxelStats.str(""); - voxelStats << "Server voxels: " << serversTotalString.toLocal8Bit().constData(); + voxelStats << "Server voxels: " << qPrintable(serversTotalString); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT); @@ -2820,8 +2820,8 @@ void Application::displayStats() { voxelStats.str(""); voxelStats << - "Internal: " << serversInternalString.toLocal8Bit().constData() << " " << - "Leaves: " << serversLeavesString.toLocal8Bit().constData() << ""; + "Internal: " << qPrintable(serversInternalString) << " " << + "Leaves: " << qPrintable(serversLeavesString) << ""; verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT); } @@ -2831,7 +2831,7 @@ void Application::displayStats() { // Local Voxels voxelStats.str(""); - voxelStats << "Local voxels: " << localTotalString.toLocal8Bit().constData(); + voxelStats << "Local voxels: " << qPrintable(localTotalString); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT); @@ -2843,8 +2843,17 @@ void Application::displayStats() { voxelStats.str(""); voxelStats << - "Internal: " << localInternalString.toLocal8Bit().constData() << " " << - "Leaves: " << localLeavesString.toLocal8Bit().constData() << ""; + "Internal: " << qPrintable(localInternalString) << " " << + "Leaves: " << qPrintable(localLeavesString) << ""; + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT); + } + + // LOD Details + if (_statsExpanded) { + voxelStats.str(""); + QString displayLODDetails = Menu::getInstance()->getLODFeedbackText(); + voxelStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 5f6c541bc5..543694f404 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1087,6 +1087,40 @@ void Menu::octreeStatsDetailsClosed() { } } +QString Menu::getLODFeedbackText() { + // determine granularity feedback + int boundaryLevelAdjust = getBoundaryLevelAdjust(); + QString granularityFeedback; + + switch (boundaryLevelAdjust) { + case 0: { + granularityFeedback = QString("at standard granularity."); + } break; + case 1: { + granularityFeedback = QString("at half of standard granularity."); + } break; + case 2: { + granularityFeedback = QString("at a third of standard granularity."); + } break; + default: { + granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1); + } break; + } + + // distance feedback + float voxelSizeScale = getVoxelSizeScale(); + float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE; + QString result; + if (relativeToDefault > 1.01) { + result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback); + } else if (relativeToDefault > 0.99) { + result = QString("the default distance %1").arg(granularityFeedback); + } else { + result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback); + } + return result; +} + void Menu::autoAdjustLOD(float currentFPS) { // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't // really want to count them in our average, so we will ignore the real frame rates and stuff diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 380fe2d3b7..00ef51178a 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -84,6 +84,7 @@ public: void handleViewFrustumOffsetKeyModifier(int key); // User Tweakable LOD Items + QString getLODFeedbackText(); void autoAdjustLOD(float currentFPS); void setVoxelSizeScale(float sizeScale); float getVoxelSizeScale() const { return _voxelSizeScale; } diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index 4cf4a29bf1..564669757c 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -68,7 +68,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : const unsigned redish = 0xfff00000; palette.setColor(QPalette::WindowText, QColor::fromRgb(redish)); _feedback->setPalette(palette); - _feedback->setText(getFeedbackText()); + _feedback->setText(Menu::getInstance()->getLODFeedbackText()); const int FEEDBACK_WIDTH = 350; _feedback->setFixedWidth(FEEDBACK_WIDTH); form->addRow("You can see... ", _feedback); @@ -81,40 +81,6 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : this->QDialog::setLayout(form); } -QString LodToolsDialog::getFeedbackText() { - // determine granularity feedback - int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); - QString granularityFeedback; - - switch (boundaryLevelAdjust) { - case 0: { - granularityFeedback = QString("at standard granularity."); - } break; - case 1: { - granularityFeedback = QString("at half of standard granularity."); - } break; - case 2: { - granularityFeedback = QString("at a third of standard granularity."); - } break; - default: { - granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1); - } break; - } - - // distance feedback - float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale(); - float relativeToDefault = voxelSizeScale / DEFAULT_OCTREE_SIZE_SCALE; - QString result; - if (relativeToDefault > 1.01) { - result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback); - } else if (relativeToDefault > 0.99) { - result = QString("the default distance %1").arg(granularityFeedback); - } else { - result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback); - } - return result; -} - LodToolsDialog::~LodToolsDialog() { delete _feedback; delete _lodSize; @@ -124,19 +90,19 @@ LodToolsDialog::~LodToolsDialog() { void LodToolsDialog::reloadSliders() { _lodSize->setValue(Menu::getInstance()->getVoxelSizeScale() / TREE_SCALE); _boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust()); - _feedback->setText(getFeedbackText()); + _feedback->setText(Menu::getInstance()->getLODFeedbackText()); } void LodToolsDialog::sizeScaleValueChanged(int value) { float realValue = value * TREE_SCALE; Menu::getInstance()->setVoxelSizeScale(realValue); - _feedback->setText(getFeedbackText()); + _feedback->setText(Menu::getInstance()->getLODFeedbackText()); } void LodToolsDialog::boundaryLevelValueChanged(int value) { Menu::getInstance()->setBoundaryLevelAdjust(value); - _feedback->setText(getFeedbackText()); + _feedback->setText(Menu::getInstance()->getLODFeedbackText()); } void LodToolsDialog::resetClicked(bool checked) { diff --git a/interface/src/ui/LodToolsDialog.h b/interface/src/ui/LodToolsDialog.h index ee96cffd7e..98a5fce5f8 100644 --- a/interface/src/ui/LodToolsDialog.h +++ b/interface/src/ui/LodToolsDialog.h @@ -36,8 +36,6 @@ protected: void closeEvent(QCloseEvent*); private: - QString getFeedbackText(); - QSlider* _lodSize; QSlider* _boundaryLevelAdjust; QLabel* _feedback; From 4c7737443eec0e106f76a335ccd8b93281b45d5d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 12:11:30 -0700 Subject: [PATCH 21/37] Fix for OS X warning. --- libraries/metavoxels/src/MetavoxelData.cpp | 6 +++--- libraries/metavoxels/src/MetavoxelData.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 8a6b0bc16a..c31be16c7a 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -228,7 +228,7 @@ public: Spanner* getSpanner() const { return _spanner; } float getDistance() const { return _distance; } - virtual bool visit(Spanner* spanner, float distance); + virtual bool visitSpanner(Spanner* spanner, float distance); private: @@ -243,7 +243,7 @@ FirstRaySpannerIntersectionVisitor::FirstRaySpannerIntersectionVisitor( _spanner(NULL) { } -bool FirstRaySpannerIntersectionVisitor::visit(Spanner* spanner, float distance) { +bool FirstRaySpannerIntersectionVisitor::visitSpanner(Spanner* spanner, float distance) { _spanner = spanner; _distance = distance; return false; @@ -938,7 +938,7 @@ int RaySpannerIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { } qStableSort(spannerDistances); foreach (const SpannerDistance& spannerDistance, spannerDistances) { - if (!visit(spannerDistance.spanner, spannerDistance.distance)) { + if (!visitSpanner(spannerDistance.spanner, spannerDistance.distance)) { return SHORT_CIRCUIT; } } diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 7e0a863a3b..040132effa 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -302,7 +302,7 @@ public: /// Visits a spanner that the ray intersects. /// \return true to continue, false to short-circuit the tour - virtual bool visit(Spanner* spanner, float distance) = 0; + virtual bool visitSpanner(Spanner* spanner, float distance) = 0; virtual void prepare(); virtual int visit(MetavoxelInfo& info, float distance); From 9402a5852c79e9b1361afbc3337ddb0150ae9600 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 12 Mar 2014 12:20:43 -0700 Subject: [PATCH 22/37] Fixed review comments --- examples/editVoxels.js | 2 +- interface/interface_en.ts | 8 ++++---- interface/src/Application.cpp | 7 ++++--- interface/src/Application.h | 6 ++++-- interface/src/ClipboardScriptingInterface.cpp | 6 +++--- interface/src/ui/LocalVoxelsOverlay.cpp | 5 ++++- interface/src/ui/Volume3DOverlay.cpp | 3 --- 7 files changed, 20 insertions(+), 17 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 956b6f1d1d..31d483d798 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -308,7 +308,7 @@ function initImport() { } function importVoxels() { - if (Clipboard.importVoxels() == 0) { + if (Clipboard.importVoxels()) { isImporting = true; if (importScale <= 0) { importScale = 1; diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 76a5d47101..4aa920945b 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 771f02750d..bfcd7770eb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -140,6 +140,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _fps(120.0f), _justStarted(true), _voxelImporter(NULL), + _importSucceded(false), _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), _wantToKillLocalVoxels(false), _audioScope(256, 200, true), @@ -1387,7 +1388,7 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) { } void Application::importVoxels() { - int result = 1; + _importSucceded = false; if (!_voxelImporter) { _voxelImporter = new VoxelImporter(_window); @@ -1396,7 +1397,7 @@ void Application::importVoxels() { if (!_voxelImporter->exec()) { qDebug() << "[DEBUG] Import succeeded." << endl; - result = 0; + _importSucceded = true; } else { qDebug() << "[DEBUG] Import failed." << endl; if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) { @@ -1408,7 +1409,7 @@ void Application::importVoxels() { // restore the main window's active state _window->activateWindow(); - emit importDone(result); + emit importDone(); } void Application::cutVoxels(const VoxelDetail& sourceVoxel) { diff --git a/interface/src/Application.h b/interface/src/Application.h index c6fc7140eb..637a79c422 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -157,6 +157,7 @@ public: VoxelTree* getVoxelTree() { return _voxels.getTree(); } ParticleTreeRenderer* getParticles() { return &_particles; } MetavoxelSystem* getMetavoxels() { return &_metavoxels; } + bool getImportSucceded() { return _importSucceded; } VoxelSystem* getSharedVoxelSystem() { return &_sharedVoxelSystem; } VoxelTree* getClipboard() { return &_clipboard; } Environment* getEnvironment() { return &_environment; } @@ -225,8 +226,8 @@ signals: /// Fired when we're rendering in-world interface elements; allows external parties to hook in. void renderingInWorldInterface(); - /// Fired when the import window is closed with a return code. - void importDone(int); + /// Fired when the import window is closed + void importDone(); public slots: void domainChanged(const QString& domainHostname); @@ -368,6 +369,7 @@ private: VoxelSystem _voxels; VoxelTree _clipboard; // if I copy/paste VoxelImporter* _voxelImporter; + bool _importSucceded; VoxelSystem _sharedVoxelSystem; ViewFrustum _sharedVoxelSystemViewFrustum; diff --git a/interface/src/ClipboardScriptingInterface.cpp b/interface/src/ClipboardScriptingInterface.cpp index e8a02b041b..2ddef524aa 100644 --- a/interface/src/ClipboardScriptingInterface.cpp +++ b/interface/src/ClipboardScriptingInterface.cpp @@ -77,11 +77,11 @@ void ClipboardScriptingInterface::exportVoxel(float x, float y, float z, float s bool ClipboardScriptingInterface::importVoxels() { qDebug() << "[DEBUG] Importing ... "; QEventLoop loop; - connect(Application::getInstance(), SIGNAL(importDone(int)), &loop, SLOT(quit())); + connect(Application::getInstance(), SIGNAL(importDone()), &loop, SLOT(quit())); emit readyToImport(); - int returnCode = loop.exec(); + loop.exec(); - return returnCode; + return Application::getInstance()->getImportSucceded(); } void ClipboardScriptingInterface::nudgeVoxel(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec) { diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/LocalVoxelsOverlay.cpp index fde03b85cb..71ae9ec74e 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/LocalVoxelsOverlay.cpp @@ -61,8 +61,11 @@ void LocalVoxelsOverlay::render() { void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) { Volume3DOverlay::setProperties(properties); + if (properties.property("scale").isValid()) { + setSize(properties.property("scale").toVariant().toFloat()); + } + QScriptValue treeName = properties.property("name"); - // if "end" property was not there, check to see if they included aliases: endPoint, or p2 if (treeName.isValid()) { if ((_treeName = treeName.toString()) == DOMAIN_TREE_NAME) { qDebug() << "addOverlay(): Can't create overlay from domain tree"; diff --git a/interface/src/ui/Volume3DOverlay.cpp b/interface/src/ui/Volume3DOverlay.cpp index a4e6c76a12..dbc1582cc5 100644 --- a/interface/src/ui/Volume3DOverlay.cpp +++ b/interface/src/ui/Volume3DOverlay.cpp @@ -31,9 +31,6 @@ void Volume3DOverlay::setProperties(const QScriptValue& properties) { if (properties.property("size").isValid()) { setSize(properties.property("size").toVariant().toFloat()); } - if (properties.property("scale").isValid()) { - setSize(properties.property("scale").toVariant().toFloat()); - } if (properties.property("isSolid").isValid()) { setIsSolid(properties.property("isSolid").toVariant().toBool()); From 064f784db13d749296510538dbdb0414e3206117 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 12:23:23 -0700 Subject: [PATCH 23/37] More OS X warning fixes. --- .../metavoxels/src/AttributeRegistry.cpp | 26 ++++++++++--------- libraries/metavoxels/src/AttributeRegistry.h | 24 ++++++++--------- libraries/metavoxels/src/MetavoxelData.cpp | 16 ++++++------ 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index 9ec37acd80..ccb6d3970e 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -155,27 +155,27 @@ Attribute::Attribute(const QString& name) : Attribute::~Attribute() { } -void Attribute::read(MetavoxelData& data, MetavoxelStreamState& state) { +void Attribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state) { data.createRoot(state.attribute)->read(state); } -void Attribute::write(const MetavoxelNode& root, MetavoxelStreamState& state) { +void Attribute::writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state) { root.write(state); } -void Attribute::readDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state) { +void Attribute::readMetavoxelDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state) { data.createRoot(state.attribute)->readDelta(reference, state); } -void Attribute::writeDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state) { +void Attribute::writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state) { root.writeDelta(reference, state); } -void Attribute::readSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { +void Attribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { data.getRoot(state.attribute)->readSubdivision(state); } -void Attribute::writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { +void Attribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { root.writeSubdivision(state); } @@ -327,7 +327,7 @@ SpannerSetAttribute::SpannerSetAttribute(const QString& name, const QMetaObject* SharedObjectSetAttribute(name, metaObject) { } -void SpannerSetAttribute::read(MetavoxelData& data, MetavoxelStreamState& state) { +void SpannerSetAttribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state) { forever { SharedObjectPointer object; state.stream >> object; @@ -338,13 +338,14 @@ void SpannerSetAttribute::read(MetavoxelData& data, MetavoxelStreamState& state) } } -void SpannerSetAttribute::write(const MetavoxelNode& root, MetavoxelStreamState& state) { +void SpannerSetAttribute::writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state) { Spanner::incrementVisit(); root.writeSpanners(state); state.stream << SharedObjectPointer(); } -void SpannerSetAttribute::readDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state) { +void SpannerSetAttribute::readMetavoxelDelta(MetavoxelData& data, + const MetavoxelNode& reference, MetavoxelStreamState& state) { forever { SharedObjectPointer object; state.stream >> object; @@ -355,13 +356,14 @@ void SpannerSetAttribute::readDelta(MetavoxelData& data, const MetavoxelNode& re } } -void SpannerSetAttribute::writeDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state) { +void SpannerSetAttribute::writeMetavoxelDelta(const MetavoxelNode& root, + const MetavoxelNode& reference, MetavoxelStreamState& state) { Spanner::incrementVisit(); root.writeSpannerDelta(reference, state); state.stream << SharedObjectPointer(); } -void SpannerSetAttribute::readSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { +void SpannerSetAttribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { forever { SharedObjectPointer object; state.stream >> object; @@ -372,7 +374,7 @@ void SpannerSetAttribute::readSubdivision(MetavoxelData& data, MetavoxelStreamSt } } -void SpannerSetAttribute::writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { +void SpannerSetAttribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { Spanner::incrementVisit(); root.writeSpannerSubdivision(state); state.stream << SharedObjectPointer(); diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index 3405f90315..ba19a3b0d2 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -177,14 +177,14 @@ public: virtual void readDelta(Bitstream& in, void*& value, void* reference, bool isLeaf) const { read(in, value, isLeaf); } virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const { write(out, value, isLeaf); } - virtual void read(MetavoxelData& data, MetavoxelStreamState& state); - virtual void write(const MetavoxelNode& root, MetavoxelStreamState& state); + virtual void readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state); + virtual void writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state); - virtual void readDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state); - virtual void writeDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state); + virtual void readMetavoxelDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state); + virtual void writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state); - virtual void readSubdivision(MetavoxelData& data, MetavoxelStreamState& state); - virtual void writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state); + virtual void readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state); + virtual void writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state); virtual bool equal(void* first, void* second) const = 0; @@ -355,14 +355,14 @@ public: Q_INVOKABLE SpannerSetAttribute(const QString& name = QString(), const QMetaObject* metaObject = &SharedObject::staticMetaObject); - virtual void read(MetavoxelData& data, MetavoxelStreamState& state); - virtual void write(const MetavoxelNode& root, MetavoxelStreamState& state); + virtual void readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state); + virtual void writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state); - virtual void readDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state); - virtual void writeDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state); + virtual void readMetavoxelDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state); + virtual void writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state); - virtual void readSubdivision(MetavoxelData& data, MetavoxelStreamState& state); - virtual void writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state); + virtual void readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state); + virtual void writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state); }; #endif /* defined(__interface__AttributeRegistry__) */ diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index c31be16c7a..08cd62f30d 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -312,7 +312,7 @@ void MetavoxelData::read(Bitstream& in, const MetavoxelLOD& lod) { break; } MetavoxelStreamState state = { getMinimum(), _size, attribute, in, lod, lod }; - attribute->read(*this, state); + attribute->readMetavoxelRoot(*this, state); } } @@ -321,7 +321,7 @@ void MetavoxelData::write(Bitstream& out, const MetavoxelLOD& lod) const { for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { out << it.key(); MetavoxelStreamState state = { getMinimum(), _size, it.key(), out, lod, lod }; - it.key()->write(*it.value(), state); + it.key()->writeMetavoxelRoot(*it.value(), state); } out << AttributePointer(); } @@ -360,13 +360,13 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD in >> changed; if (changed) { oldRoot->incrementReferenceCount(); - attribute->readDelta(*this, *oldRoot, state); + attribute->readMetavoxelDelta(*this, *oldRoot, state); oldRoot->decrementReferenceCount(attribute); } else { - attribute->readSubdivision(*this, state); + attribute->readMetavoxelSubdivision(*this, state); } } else { - attribute->read(*this, state); + attribute->readMetavoxelRoot(*this, state); } } @@ -415,13 +415,13 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLO if (referenceRoot) { if (it.value() == referenceRoot) { out << false; - it.key()->writeSubdivision(*it.value(), state); + it.key()->writeMetavoxelSubdivision(*it.value(), state); } else { out << true; - it.key()->writeDelta(*it.value(), *referenceRoot, state); + it.key()->writeMetavoxelDelta(*it.value(), *referenceRoot, state); } } else { - it.key()->write(*it.value(), state); + it.key()->writeMetavoxelRoot(*it.value(), state); } } } From f1145272eb44900e6d86cf3f9ecb7fea26f6dcf4 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 12:29:01 -0700 Subject: [PATCH 24/37] Signed/unsigned fix. --- interface/src/devices/SixenseManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 287aa4e5f6..0482dbf84c 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -60,7 +60,7 @@ void SixenseManager::update(float deltaTime) { // Either find a palm matching the sixense controller, or make a new one PalmData* palm; bool foundHand = false; - for (int j = 0; j < hand->getNumPalms(); j++) { + for (size_t j = 0; j < hand->getNumPalms(); j++) { if (hand->getPalms()[j].getSixenseID() == data.controller_index) { palm = &(hand->getPalms()[j]); foundHand = true; @@ -128,7 +128,7 @@ void SixenseManager::update(float deltaTime) { } // if the controllers haven't been moved in a while, disable - const int MOVEMENT_DISABLE_DURATION = 30 * 1000 * 1000; + const unsigned int MOVEMENT_DISABLE_DURATION = 30 * 1000 * 1000; if (usecTimestampNow() - _lastMovement > MOVEMENT_DISABLE_DURATION) { for (vector::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) { it->setActive(false); From f088912ecfa51bc97fca3d0b6a70a0df38c1abc7 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 12:51:43 -0700 Subject: [PATCH 25/37] More GCC warning fixes. --- interface/src/avatar/Avatar.cpp | 3 --- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/renderer/FBXReader.cpp | 4 ++-- libraries/metavoxels/src/AttributeRegistry.h | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6cd7523a14..ea7ffc6f2b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -109,9 +109,6 @@ void Avatar::simulate(float deltaTime) { _shouldRenderBillboard = true; } - // copy velocity so we can use it later for acceleration - glm::vec3 oldVelocity = getVelocity(); - getHand()->simulate(deltaTime, false); _skeletonModel.setLODDistance(getLODDistance()); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 4699b360f6..f405358710 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -146,7 +146,7 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin // rotate palm according to average finger direction float directionLength = glm::length(direction); - const int MIN_ROTATION_FINGERS = 3; + const unsigned int MIN_ROTATION_FINGERS = 3; if (directionLength > EPSILON && palm.getNumFingers() >= MIN_ROTATION_FINGERS) { applyRotationDelta(jointIndex, rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction), false); getJointRotation(jointIndex, palmRotation, true); diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index cda14dc807..8bf5583a02 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -66,7 +66,7 @@ template QVariant readBinaryArray(QDataStream& in) { in >> compressedLength; QVector values; - const int DEFLATE_ENCODING = 1; + const unsigned int DEFLATE_ENCODING = 1; if (encoding == DEFLATE_ENCODING) { // preface encoded data with uncompressed length QByteArray compressed(sizeof(quint32) + compressedLength, 0); @@ -163,7 +163,7 @@ FBXNode parseBinaryFBXNode(QDataStream& in) { in >> nameLength; FBXNode node; - const int MIN_VALID_OFFSET = 40; + const unsigned int MIN_VALID_OFFSET = 40; if (endOffset < MIN_VALID_OFFSET || nameLength == 0) { // use a null name to indicate a null node return node; diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index ba19a3b0d2..16968da1b2 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -265,7 +265,7 @@ template inline bool SimpleInlineAttribute::merge(vo /// Provides appropriate averaging for RGBA values. class QRgbAttribute : public InlineAttribute { Q_OBJECT - Q_PROPERTY(int defaultValue MEMBER _defaultValue) + Q_PROPERTY(unsigned int defaultValue MEMBER _defaultValue) public: From 6fb313cc435374f5d102836177daac812349bd6f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 13:03:59 -0700 Subject: [PATCH 26/37] Allow streaming uints. --- libraries/metavoxels/src/AttributeRegistry.h | 2 +- libraries/metavoxels/src/Bitstream.cpp | 12 ++++++++++++ libraries/metavoxels/src/Bitstream.h | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index 16968da1b2..b6a415bef7 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -265,7 +265,7 @@ template inline bool SimpleInlineAttribute::merge(vo /// Provides appropriate averaging for RGBA values. class QRgbAttribute : public InlineAttribute { Q_OBJECT - Q_PROPERTY(unsigned int defaultValue MEMBER _defaultValue) + Q_PROPERTY(uint defaultValue MEMBER _defaultValue) public: diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 0af44eaae6..f80ef3aa28 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -23,6 +23,7 @@ REGISTER_SIMPLE_TYPE_STREAMER(bool) REGISTER_SIMPLE_TYPE_STREAMER(int) +REGISTER_SIMPLE_TYPE_STREAMER(uint) REGISTER_SIMPLE_TYPE_STREAMER(float) REGISTER_SIMPLE_TYPE_STREAMER(QByteArray) REGISTER_SIMPLE_TYPE_STREAMER(QColor) @@ -238,6 +239,17 @@ Bitstream& Bitstream::operator>>(int& value) { return *this; } +Bitstream& Bitstream::operator<<(uint value) { + return write(&value, 32); +} + +Bitstream& Bitstream::operator>>(uint& value) { + quint32 sizedValue; + read(&sizedValue, 32); + value = sizedValue; + return *this; +} + Bitstream& Bitstream::operator<<(float value) { return write(&value, 32); } diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 297d265d97..ca26509d60 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -254,6 +254,9 @@ public: Bitstream& operator<<(int value); Bitstream& operator>>(int& value); + Bitstream& operator<<(uint value); + Bitstream& operator>>(uint& value); + Bitstream& operator<<(float value); Bitstream& operator>>(float& value); From 800be7eef47af7795f2c7337c2dd99456228f42e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 13:38:16 -0700 Subject: [PATCH 27/37] One more degree conversion. --- interface/src/ui/MetavoxelEditor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index b1842e0619..eed8a7b6f3 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -387,7 +387,7 @@ void BoxSetTool::render() { glm::quat rotation = _editor->getGridRotation(); glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); glm::quat inverseRotation = glm::inverse(rotation); glm::vec3 rayOrigin = inverseRotation * Application::getInstance()->getMouseRayOrigin(); From f85f49caa624a0abcf102d5a6450c5ec60b05ec0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 14:03:22 -0700 Subject: [PATCH 28/37] Might as well update this. --- interface/interface_en.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 685c6e3f67..f700be655c 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) From 5941ad0dd1e791ad03bd5c9a276a72cc16c4d7d3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 12 Mar 2014 14:08:23 -0700 Subject: [PATCH 29/37] Changed lockForWrite() to lockForRead() --- interface/src/ui/LocalVoxelsOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/LocalVoxelsOverlay.cpp index 71ae9ec74e..7eaf9ed5c5 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/LocalVoxelsOverlay.cpp @@ -40,7 +40,7 @@ void LocalVoxelsOverlay::update(float deltatime) { _voxelSystem->init(); } - _tree->lockForWrite(); + _tree->lockForRead(); if (_visible && _voxelCount != _tree->getOctreeElementsCount()) { _voxelCount = _tree->getOctreeElementsCount(); _voxelSystem->forceRedrawEntireTree(); From 889c1358fc100fdd3c51d8bb15f50e2a70a840d0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 14:56:52 -0700 Subject: [PATCH 30/37] Increase the distance at which avatars glow when moving. --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ea7ffc6f2b..4ad7a90d6f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -189,7 +189,7 @@ void Avatar::render(bool forShadowMap) { { // glow when moving in the distance - const float GLOW_DISTANCE = 5.0f; + const float GLOW_DISTANCE = 10.0f; Glower glower(_moving && lengthToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f); // render body From bab74e9cd4fe0faeea5fdd8bd8df06f70b57c960 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 15:01:09 -0700 Subject: [PATCH 31/37] Push the distance back even more. --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4ad7a90d6f..b7e3d675a5 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -189,7 +189,7 @@ void Avatar::render(bool forShadowMap) { { // glow when moving in the distance - const float GLOW_DISTANCE = 10.0f; + const float GLOW_DISTANCE = 20.0f; Glower glower(_moving && lengthToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f); // render body From ffe371757343f2edabea23713c839b39ddedc61b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 12 Mar 2014 15:10:33 -0700 Subject: [PATCH 32/37] Enable back face culling on the opaque parts of avatars. --- interface/src/renderer/Model.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index f657ef01d7..21fdc80858 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -328,6 +328,8 @@ bool Model::render(float alpha) { glDisable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + // render opaque meshes with alpha testing glEnable(GL_ALPHA_TEST); @@ -339,8 +341,6 @@ bool Model::render(float alpha) { // render translucent meshes afterwards, with back face culling - glEnable(GL_CULL_FACE); - renderMeshes(alpha, true); glDisable(GL_CULL_FACE); From 6d4d61c38a1db08c2303ffc7f930b3d484e3a403 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 13 Mar 2014 00:51:04 +0200 Subject: [PATCH 33/37] Removed the double border between the sent messages and the entry. --- interface/interface_en.ts | 6 +++--- interface/ui/chatWindow.ui | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 72299befa4..175a1f4525 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -28,19 +28,19 @@ ChatWindow - + Chat - + Connecting to XMPP... - + online now: diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 18c9b3814a..d254efb71a 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -81,7 +81,7 @@ 0 0 358 - 448 + 454 @@ -122,7 +122,10 @@ - font-family: Helvetica, Arial, sans-serif; + border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; + + + QFrame::NoFrame Qt::ScrollBarAlwaysOff From 3b653ca542ca3313f3594c02182928e583b43d81 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 12 Mar 2014 17:00:12 -0700 Subject: [PATCH 34/37] add a sendAvatarAudioStream option to Agent for mixer load testing, closes #2291 --- assignment-client/src/Agent.cpp | 28 +++++++++++++++++++- assignment-client/src/Agent.h | 7 +++++ libraries/script-engine/src/ScriptEngine.cpp | 27 +++++++++++++------ libraries/script-engine/src/ScriptEngine.h | 11 ++++++-- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 13b1f2bdcf..9d4f07043d 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -25,7 +26,8 @@ Agent::Agent(const QByteArray& packet) : ThreadedAssignment(packet), _voxelEditSender(), - _particleEditSender() + _particleEditSender(), + _avatarAudioStream(NULL) { // be the parent of the script engine so it gets moved when we do _scriptEngine.setParent(this); @@ -34,6 +36,30 @@ Agent::Agent(const QByteArray& packet) : _scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); } +Agent::~Agent() { + delete _avatarAudioStream; +} + +const int SCRIPT_AUDIO_BUFFER_SAMPLES = (SCRIPT_DATA_CALLBACK_USECS * SAMPLE_RATE) / (1000 * 1000); + +void Agent::setSendAvatarAudioStream(bool sendAvatarAudioStream) { + if (sendAvatarAudioStream) { + // the agentAudioStream number of samples is related to the ScriptEngine callback rate + _avatarAudioStream = new int16_t[SCRIPT_AUDIO_BUFFER_SAMPLES]; + + // fill the _audioStream with zeroes to start + memset(_avatarAudioStream, 0, SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t)); + + _scriptEngine.setNumAvatarAudioBufferSamples(SCRIPT_AUDIO_BUFFER_SAMPLES); + _scriptEngine.setAvatarAudioBuffer(_avatarAudioStream); + } else { + delete _avatarAudioStream; + _avatarAudioStream = NULL; + + _scriptEngine.setAvatarAudioBuffer(NULL); + } +} + void Agent::readPendingDatagrams() { QByteArray receivedPacket; HifiSockAddr senderSockAddr; diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 1b41636874..a051f42faf 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -28,12 +28,17 @@ class Agent : public ThreadedAssignment { Q_OBJECT Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar) + Q_PROPERTY(bool sendAvatarAudioStream READ isSendingAvatarAudioStream WRITE setSendAvatarAudioStream) public: Agent(const QByteArray& packet); + ~Agent(); void setIsAvatar(bool isAvatar) { QMetaObject::invokeMethod(&_scriptEngine, "setIsAvatar", Q_ARG(bool, isAvatar)); } bool isAvatar() const { return _scriptEngine.isAvatar(); } + void setSendAvatarAudioStream(bool sendAvatarAudioStream); + bool isSendingAvatarAudioStream() const { return (bool) _scriptEngine.sendsAvatarAudioStream(); } + public slots: void run(); void readPendingDatagrams(); @@ -45,6 +50,8 @@ private: ParticleTreeHeadlessViewer _particleViewer; VoxelTreeHeadlessViewer _voxelViewer; + + int16_t* _avatarAudioStream; }; #endif /* defined(__hifi__Agent__) */ diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 04916687fb..9a672317ae 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -28,8 +28,6 @@ #include "LocalVoxels.h" #include "ScriptEngine.h" -const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000; - int ScriptEngine::_scriptNumber = 1; VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface; ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface; @@ -54,6 +52,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co _avatarIdentityTimer(NULL), _avatarBillboardTimer(NULL), _timerFunctionMap(), + _avatarAudioBuffer(NULL), _controllerScriptingInterface(controllerScriptingInterface), _avatarData(NULL), _wantMenuItems(wantMenuItems), @@ -77,9 +76,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co _scriptNumber++; } -ScriptEngine::~ScriptEngine() { -} - void ScriptEngine::setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; @@ -169,8 +165,8 @@ void ScriptEngine::init() { _engine.globalObject().setProperty("TREE_SCALE", treeScaleValue); // let the VoxelPacketSender know how frequently we plan to call it - _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); - _particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); + _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); + _particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); } @@ -228,7 +224,7 @@ void ScriptEngine::run() { qint64 lastUpdate = usecTimestampNow(); while (!_isFinished) { - int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * VISUAL_DATA_CALLBACK_USECS) - usecTimestampNow(); + int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - usecTimestampNow(); if (usecToSleep > 0) { usleep(usecToSleep); } @@ -268,6 +264,21 @@ void ScriptEngine::run() { avatarPacket.append(_avatarData->toByteArray()); nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); + + if (_avatarAudioBuffer && _numAvatarAudioBufferSamples > 0) { + // if have an avatar audio stream then send it out to our audio-mixer + QByteArray audioPacket = byteArrayWithPopulatedHeader(PacketTypeMicrophoneAudioNoEcho); + QDataStream packetStream(&audioPacket, QIODevice::Append); + + // use the orientation and position of this avatar for the source of this audio + packetStream.writeRawData(reinterpret_cast(&_avatarData->getPosition()), sizeof(glm::vec3)); + glm::quat headOrientation = _avatarData->getHeadOrientation(); + packetStream.writeRawData(reinterpret_cast(&headOrientation), sizeof(glm::quat)); + packetStream.writeRawData(reinterpret_cast(_avatarAudioBuffer), + _numAvatarAudioBufferSamples * sizeof(int16_t)); + + nodeList->broadcastToNodes(audioPacket, NodeSet() << NodeType::AudioMixer); + } } qint64 now = usecTimestampNow(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 186524eb7f..9a1d2172dd 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -28,6 +28,8 @@ class ParticlesScriptingInterface; const QString NO_SCRIPT(""); +const unsigned int SCRIPT_DATA_CALLBACK_USECS = roundf((1.0 / 60.0) * 1000 * 1000); + class ScriptEngine : public QObject { Q_OBJECT public: @@ -35,8 +37,6 @@ public: const QString& scriptMenuName = QString(""), AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); - ~ScriptEngine(); - /// Access the VoxelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; } @@ -56,6 +56,11 @@ public: void setAvatarData(AvatarData* avatarData, const QString& objectName); + void setAvatarAudioBuffer(int16_t* avatarAudioBuffer) { _avatarAudioBuffer = avatarAudioBuffer; } + bool sendsAvatarAudioStream() const { return (bool) _avatarAudioBuffer; } + void setNumAvatarAudioBufferSamples(int numAvatarAudioBufferSamples) + { _numAvatarAudioBufferSamples = numAvatarAudioBufferSamples; } + void init(); void run(); /// runs continuously until Agent.stop() is called void evaluate(); /// initializes the engine, and evaluates the script, but then returns control to caller @@ -86,6 +91,8 @@ protected: QTimer* _avatarIdentityTimer; QTimer* _avatarBillboardTimer; QHash _timerFunctionMap; + int16_t* _avatarAudioBuffer; + int _numAvatarAudioBufferSamples; private: void sendAvatarIdentityPacket(); From bd6c42a68505465fd1e4bc9b068dda4733c399bd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 12 Mar 2014 17:32:52 -0700 Subject: [PATCH 35/37] define roundf for use on Win from ScriptEngine --- libraries/script-engine/src/ScriptEngine.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 9a1d2172dd..7dadc17cc6 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -20,14 +20,20 @@ #include -class ParticlesScriptingInterface; - #include "AbstractControllerScriptingInterface.h" #include "Quat.h" #include "Vec3.h" +class ParticlesScriptingInterface; + const QString NO_SCRIPT(""); +#ifdef Q_OS_WIN32 +inline double roundf(double value) { + return (value > 0.0) ? floor(value + 0.5) : ceil(value - 0.5); +} +#endif + const unsigned int SCRIPT_DATA_CALLBACK_USECS = roundf((1.0 / 60.0) * 1000 * 1000); class ScriptEngine : public QObject { From 54d73d4a6458df8041459b410e7cadd2382ebb5a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 12 Mar 2014 17:50:58 -0700 Subject: [PATCH 36/37] use floor since round is missing on windows --- assignment-client/src/Agent.cpp | 2 +- libraries/script-engine/src/ScriptEngine.h | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 9d4f07043d..46f4d233c2 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -40,7 +40,7 @@ Agent::~Agent() { delete _avatarAudioStream; } -const int SCRIPT_AUDIO_BUFFER_SAMPLES = (SCRIPT_DATA_CALLBACK_USECS * SAMPLE_RATE) / (1000 * 1000); +const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * SAMPLE_RATE) / (1000 * 1000)) + 0.5); void Agent::setSendAvatarAudioStream(bool sendAvatarAudioStream) { if (sendAvatarAudioStream) { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7dadc17cc6..606d0aabf4 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -28,13 +28,7 @@ class ParticlesScriptingInterface; const QString NO_SCRIPT(""); -#ifdef Q_OS_WIN32 -inline double roundf(double value) { - return (value > 0.0) ? floor(value + 0.5) : ceil(value - 0.5); -} -#endif - -const unsigned int SCRIPT_DATA_CALLBACK_USECS = roundf((1.0 / 60.0) * 1000 * 1000); +const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 1000) + 0.5); class ScriptEngine : public QObject { Q_OBJECT From 727903b216fd82b5b47e710c70d653cf4a08980d Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 13 Mar 2014 01:55:42 +0200 Subject: [PATCH 37/37] Changed the chat window to a popup with a custom closing button. --- interface/CMakeLists.txt | 7 ++- interface/interface_en.ts | 16 ++--- interface/resources/images/close.svg | 14 +++++ interface/resources/resources.qrc | 5 ++ interface/src/Menu.cpp | 9 +-- interface/src/ui/ChatWindow.cpp | 2 +- interface/ui/chatWindow.ui | 89 ++++++++++++++++++++++------ 7 files changed, 108 insertions(+), 34 deletions(-) create mode 100644 interface/resources/images/close.svg create mode 100644 interface/resources/resources.qrc diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index d049fc0154..1cb0344f86 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -73,8 +73,13 @@ file (GLOB_RECURSE QT_UI_FILES ui/*.ui) # have qt5 wrap them and generate the appropriate header files qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") +# grab the resource files in resources +file (GLOB_RECURSE QT_RESOURCE_FILES resources/*.qrc) +# have qt5 wrap them and generate the appropriate source files +qt5_add_resources(QT_RESOURCES "${QT_RESOURCE_FILES}") + # add them to the interface source files -set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}") +set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}") set(QM ${TARGET_NAME}_en.qm) set(TS ${TARGET_NAME}_en.ts) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 175a1f4525..72e5ee3d3e 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) @@ -28,19 +28,19 @@ ChatWindow - + Chat - + Connecting to XMPP... - - + + online now: diff --git a/interface/resources/images/close.svg b/interface/resources/images/close.svg new file mode 100644 index 0000000000..8fe4bf4bdb --- /dev/null +++ b/interface/resources/images/close.svg @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/interface/resources/resources.qrc b/interface/resources/resources.qrc new file mode 100644 index 0000000000..372fa8b1d4 --- /dev/null +++ b/interface/resources/resources.qrc @@ -0,0 +1,5 @@ + + + images/close.svg + + diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f73da0400a..95b94bdcbf 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1039,15 +1039,10 @@ void Menu::showChat() { if (!_chatWindow) { _chatWindow = new ChatWindow(); QMainWindow* mainWindow = Application::getInstance()->getWindow(); - - // the height of the title bar is given by frameGeometry().height() - geometry().height() - // however, frameGeometry() is initialised after showing (Qt queries the OS windowing system) - // on the other hand, moving a window after showing it flickers; so just use some reasonable value - int titleBarHeight = 16; _chatWindow->setGeometry(mainWindow->width() - _chatWindow->width(), - mainWindow->geometry().y() + titleBarHeight, + mainWindow->geometry().y(), _chatWindow->width(), - mainWindow->height() - titleBarHeight); + mainWindow->height()); _chatWindow->show(); } _chatWindow->raise(); diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 5fc5d56430..3a1c26ee35 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -28,7 +28,7 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)"); ChatWindow::ChatWindow() : - QDialog(Application::getInstance()->getGLWidget(), Qt::Tool), + QDialog(Application::getInstance()->getGLWidget(), Qt::CustomizeWindowHint), ui(new Ui::ChatWindow), numMessagesAfterLastTimeStamp(0) { diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index d254efb71a..9959c638b2 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -46,20 +46,53 @@ - - - - 0 - 0 - - - - font-weight: bold; color: palette(shadow); margin-bottom: 4px; - - - online now: - - + + + + + + 0 + 0 + + + + font-weight: bold; color: palette(shadow); margin-bottom: 4px; + + + online now: + + + + + + + + 0 + 0 + + + + + 16 + 16 + + + + Qt::NoFocus + + + + + + + :/images/close.svg:/images/close.svg + + + true + + + + @@ -81,7 +114,7 @@ 0 0 358 - 454 + 452 @@ -133,6 +166,9 @@ QAbstractScrollArea::AdjustToContents + + true + @@ -141,6 +177,25 @@ messagePlainTextEdit messagesScrollArea - - + + + + + + closeButton + clicked() + ChatWindow + accept() + + + 342 + 42 + + + 550 + 42 + + + +