mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-10 05:09:51 +02:00
eyedropper mode, and import work
This commit is contained in:
parent
7dd217b318
commit
78fe89172a
3 changed files with 115 additions and 47 deletions
|
@ -1285,6 +1285,58 @@ void Application::chooseVoxelPaintColor() {
|
||||||
_window->activateWindow();
|
_window->activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500;
|
||||||
|
struct SendVoxelsOperataionArgs {
|
||||||
|
unsigned char* newBaseOctCode;
|
||||||
|
unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE];
|
||||||
|
int bufferInUse;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) {
|
||||||
|
SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData;
|
||||||
|
if (node->isColored()) {
|
||||||
|
unsigned char* nodeOctalCode = node->getOctalCode();
|
||||||
|
printOctalCode(nodeOctalCode);
|
||||||
|
|
||||||
|
unsigned char* codeColorBuffer = NULL;
|
||||||
|
int codeLength = 0;
|
||||||
|
int bytesInCode = 0;
|
||||||
|
int codeAndColorLength;
|
||||||
|
|
||||||
|
// If the newBase is NULL, then don't rebase
|
||||||
|
if (args->newBaseOctCode) {
|
||||||
|
codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true);
|
||||||
|
printOctalCode(codeColorBuffer);
|
||||||
|
codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer);
|
||||||
|
bytesInCode = bytesRequiredForCodeLength(codeLength);
|
||||||
|
codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA;
|
||||||
|
} else {
|
||||||
|
codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode);
|
||||||
|
bytesInCode = bytesRequiredForCodeLength(codeLength);
|
||||||
|
codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA;
|
||||||
|
codeColorBuffer = new unsigned char[codeAndColorLength];
|
||||||
|
memcpy(codeColorBuffer, nodeOctalCode, bytesInCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the colors over
|
||||||
|
codeColorBuffer[bytesInCode + RED_INDEX ] = node->getColor()[RED_INDEX ];
|
||||||
|
codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX];
|
||||||
|
codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ];
|
||||||
|
|
||||||
|
// if we have room don't have room in the buffer, then send the previously generated message first
|
||||||
|
if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
||||||
|
AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1);
|
||||||
|
args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(int); // reset to command + sequence
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy this node's code color details into our buffer.
|
||||||
|
memcpy(&args->messageBuffer[args->bufferInUse], codeColorBuffer, codeAndColorLength);
|
||||||
|
args->bufferInUse += codeAndColorLength;
|
||||||
|
}
|
||||||
|
return true; // keep going
|
||||||
|
}
|
||||||
|
|
||||||
void Application::exportVoxels() {
|
void Application::exportVoxels() {
|
||||||
QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.hio2",
|
QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.hio2",
|
||||||
tr("High Fidelity Voxel Files (*.hio2)"));
|
tr("High Fidelity Voxel Files (*.hio2)"));
|
||||||
|
@ -1303,15 +1355,45 @@ void Application::importVoxels() {
|
||||||
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), "~", tr("High Fidelity Voxel Files (*.hio2)"));
|
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), "~", tr("High Fidelity Voxel Files (*.hio2)"));
|
||||||
QByteArray fileNameAscii = fileNameString.toAscii();
|
QByteArray fileNameAscii = fileNameString.toAscii();
|
||||||
const char* fileName = fileNameAscii.data();
|
const char* fileName = fileNameAscii.data();
|
||||||
|
|
||||||
|
// Read the file into a tree
|
||||||
|
VoxelTree importVoxels;
|
||||||
|
importVoxels.readFromFileV2(fileName);
|
||||||
|
|
||||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
printf("importVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName,
|
printf("importVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName,
|
||||||
_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
|
|
||||||
|
// Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to
|
||||||
|
// the server as an set voxel message, this will also rebase the voxels to the new location
|
||||||
|
unsigned char* calculatedOctCode = NULL;
|
||||||
|
SendVoxelsOperataionArgs args;
|
||||||
|
args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE;
|
||||||
|
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)];
|
||||||
|
*sequenceAt = 0;
|
||||||
|
args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence
|
||||||
|
|
||||||
|
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
||||||
|
// voxel size/position details.
|
||||||
if (selectedNode) {
|
if (selectedNode) {
|
||||||
selectedNode->printDebugDetails("selected voxel");
|
//selectedNode->printDebugDetails("selected voxel");
|
||||||
|
args.newBaseOctCode = NULL; // selectedNode->getOctalCode();
|
||||||
|
} else {
|
||||||
|
printf("importVoxels() no voxel at current location, calculate octCode... \n");
|
||||||
|
args.newBaseOctCode = NULL; // = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
|
}
|
||||||
|
|
||||||
|
importVoxels.recurseTreeWithOperation(sendVoxelsOperataion, &args);
|
||||||
|
|
||||||
|
// If we have voxels left in the packet, then send the packet
|
||||||
|
if (args.bufferInUse > 1) {
|
||||||
|
AgentList::getInstance()->broadcastToAgents(args.messageBuffer, args.bufferInUse, &AGENT_TYPE_VOXEL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// not yet supported!!!
|
if (calculatedOctCode) {
|
||||||
_voxels.readFromFileV2(fileName,selectedNode);
|
delete calculatedOctCode;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::copyVoxels() {
|
void Application::copyVoxels() {
|
||||||
|
@ -1331,14 +1413,6 @@ void Application::copyVoxels() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE = 1500;
|
|
||||||
struct SendVoxelsOperataionArgs {
|
|
||||||
unsigned char* newBaseOctCode;
|
|
||||||
unsigned char messageBuffer[MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE];
|
|
||||||
int bufferInUse;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void Application::pasteVoxels() {
|
void Application::pasteVoxels() {
|
||||||
unsigned char* calculatedOctCode = NULL;
|
unsigned char* calculatedOctCode = NULL;
|
||||||
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
|
@ -1374,40 +1448,6 @@ void Application::pasteVoxels() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::sendVoxelsOperataion(VoxelNode* node, void* extraData) {
|
|
||||||
SendVoxelsOperataionArgs* args = (SendVoxelsOperataionArgs*)extraData;
|
|
||||||
if (node->isColored()) {
|
|
||||||
const int SIZE_OF_COLOR_DATA = 3;
|
|
||||||
const int RED_INDEX = 0;
|
|
||||||
const int GREEN_INDEX = 1;
|
|
||||||
const int BLUE_INDEX = 2;
|
|
||||||
unsigned char* nodeOctalCode = node->getOctalCode();
|
|
||||||
printOctalCode(nodeOctalCode);
|
|
||||||
unsigned char* rebasedCodeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true);
|
|
||||||
printOctalCode(rebasedCodeColorBuffer);
|
|
||||||
int rebasedCodeLength = numberOfThreeBitSectionsInCode(rebasedCodeColorBuffer);
|
|
||||||
int bytesInRebasedCode = bytesRequiredForCodeLength(rebasedCodeLength);
|
|
||||||
int codeAndColorLength = bytesInRebasedCode + SIZE_OF_COLOR_DATA;
|
|
||||||
|
|
||||||
// copy the colors over
|
|
||||||
rebasedCodeColorBuffer[bytesInRebasedCode + RED_INDEX ] = node->getColor()[RED_INDEX ];
|
|
||||||
rebasedCodeColorBuffer[bytesInRebasedCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX];
|
|
||||||
rebasedCodeColorBuffer[bytesInRebasedCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ];
|
|
||||||
|
|
||||||
// if we have room don't have room in the buffer, then send the previously generated message first
|
|
||||||
if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
|
||||||
AgentList::getInstance()->broadcastToAgents(args->messageBuffer, args->bufferInUse, &AGENT_TYPE_VOXEL, 1);
|
|
||||||
args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(int); // reset to command + sequence
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy this node's code color details into our buffer.
|
|
||||||
memcpy(&args->messageBuffer[args->bufferInUse], rebasedCodeColorBuffer, codeAndColorLength);
|
|
||||||
args->bufferInUse += codeAndColorLength;
|
|
||||||
}
|
|
||||||
return true; // keep going
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Application::initMenu() {
|
void Application::initMenu() {
|
||||||
QMenuBar* menuBar = new QMenuBar();
|
QMenuBar* menuBar = new QMenuBar();
|
||||||
_window->setMenuBar(menuBar);
|
_window->setMenuBar(menuBar);
|
||||||
|
@ -1479,6 +1519,9 @@ void Application::initMenu() {
|
||||||
(_selectVoxelMode = voxelMenu->addAction(
|
(_selectVoxelMode = voxelMenu->addAction(
|
||||||
"Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true);
|
"Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true);
|
||||||
_voxelModeActions->addAction(_selectVoxelMode);
|
_voxelModeActions->addAction(_selectVoxelMode);
|
||||||
|
(_eyedropperMode = voxelMenu->addAction(
|
||||||
|
"Eyedropper Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_E))->setCheckable(true);
|
||||||
|
_voxelModeActions->addAction(_eyedropperMode);
|
||||||
|
|
||||||
voxelMenu->addAction("Place New Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::Key_N);
|
voxelMenu->addAction("Place New Voxel", this, SLOT(addVoxelInFrontOfAvatar()), Qt::CTRL | Qt::Key_N);
|
||||||
voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut);
|
voxelMenu->addAction("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut);
|
||||||
|
@ -1486,6 +1529,7 @@ void Application::initMenu() {
|
||||||
|
|
||||||
_voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this,
|
_voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this,
|
||||||
SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C);
|
SLOT(chooseVoxelPaintColor()), Qt::META | Qt::Key_C);
|
||||||
|
voxelMenu->addAction("Use Voxel Color", this, SLOT(useVoxelPaintColor()), Qt::CTRL | Qt::Key_U);
|
||||||
QColor paintColor(128, 128, 128);
|
QColor paintColor(128, 128, 128);
|
||||||
_voxelPaintColor->setData(paintColor);
|
_voxelPaintColor->setData(paintColor);
|
||||||
_voxelPaintColor->setIcon(createSwatchIcon(paintColor));
|
_voxelPaintColor->setIcon(createSwatchIcon(paintColor));
|
||||||
|
@ -2359,6 +2403,8 @@ void Application::maybeEditVoxelUnderCursor() {
|
||||||
}
|
}
|
||||||
} else if (_deleteVoxelMode->isChecked()) {
|
} else if (_deleteVoxelMode->isChecked()) {
|
||||||
deleteVoxelUnderCursor();
|
deleteVoxelUnderCursor();
|
||||||
|
} else if (_eyedropperMode->isChecked()) {
|
||||||
|
eyedropperVoxelUnderCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2383,6 +2429,20 @@ void Application::deleteVoxelUnderCursor() {
|
||||||
_justEditedVoxel = true;
|
_justEditedVoxel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::eyedropperVoxelUnderCursor() {
|
||||||
|
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
|
||||||
|
if (selectedNode && selectedNode->isColored()) {
|
||||||
|
QColor selectedColor(selectedNode->getColor()[RED_INDEX],
|
||||||
|
selectedNode->getColor()[GREEN_INDEX],
|
||||||
|
selectedNode->getColor()[BLUE_INDEX]);
|
||||||
|
|
||||||
|
if (selectedColor.isValid()) {
|
||||||
|
_voxelPaintColor->setData(selectedColor);
|
||||||
|
_voxelPaintColor->setIcon(createSwatchIcon(selectedColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::goHome() {
|
void Application::goHome() {
|
||||||
_myAvatar.setPosition(START_LOCATION);
|
_myAvatar.setPosition(START_LOCATION);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,7 @@ private:
|
||||||
void shiftPaintingColor();
|
void shiftPaintingColor();
|
||||||
void maybeEditVoxelUnderCursor();
|
void maybeEditVoxelUnderCursor();
|
||||||
void deleteVoxelUnderCursor();
|
void deleteVoxelUnderCursor();
|
||||||
|
void eyedropperVoxelUnderCursor();
|
||||||
void goHome();
|
void goHome();
|
||||||
void resetSensors();
|
void resetSensors();
|
||||||
|
|
||||||
|
@ -225,6 +225,7 @@ private:
|
||||||
QAction* _deleteVoxelMode; // Whether delete voxel mode is enabled
|
QAction* _deleteVoxelMode; // Whether delete voxel mode is enabled
|
||||||
QAction* _colorVoxelMode; // Whether color voxel mode is enabled
|
QAction* _colorVoxelMode; // Whether color voxel mode is enabled
|
||||||
QAction* _selectVoxelMode; // Whether select voxel mode is enabled
|
QAction* _selectVoxelMode; // Whether select voxel mode is enabled
|
||||||
|
QAction* _eyedropperMode; // Whether voxel color eyedropper mode is enabled
|
||||||
QAction* _voxelPaintColor; // The color with which to paint voxels
|
QAction* _voxelPaintColor; // The color with which to paint voxels
|
||||||
QAction* _destructiveAddVoxel; // when doing voxel editing do we want them to be destructive
|
QAction* _destructiveAddVoxel; // when doing voxel editing do we want them to be destructive
|
||||||
QAction* _frustumOn; // Whether or not to display the debug view frustum
|
QAction* _frustumOn; // Whether or not to display the debug view frustum
|
||||||
|
|
|
@ -23,11 +23,18 @@ const int MAX_VOXELS_PER_SYSTEM = 200000;
|
||||||
const int VERTICES_PER_VOXEL = 24;
|
const int VERTICES_PER_VOXEL = 24;
|
||||||
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||||
const int INDICES_PER_VOXEL = 3 * 12;
|
const int INDICES_PER_VOXEL = 3 * 12;
|
||||||
const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
|
||||||
|
const int NUMBER_OF_COLORS = 3; // RGB!
|
||||||
|
const int SIZE_OF_COLOR_DATA = NUMBER_OF_COLORS * sizeof(unsigned char); // size in bytes
|
||||||
|
const int RED_INDEX = 0;
|
||||||
|
const int GREEN_INDEX = 1;
|
||||||
|
const int BLUE_INDEX = 2;
|
||||||
|
const int COLOR_VALUES_PER_VOXEL = NUMBER_OF_COLORS * VERTICES_PER_VOXEL;
|
||||||
|
|
||||||
typedef unsigned long int glBufferIndex;
|
typedef unsigned long int glBufferIndex;
|
||||||
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
||||||
|
|
||||||
const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60;
|
const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60;
|
||||||
const double VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0; // once a second is fine
|
const double VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0; // once a second is fine
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue