mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 23:43:18 +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();
|
||||
}
|
||||
|
||||
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() {
|
||||
QString fileNameString = QFileDialog::getSaveFileName(_glWidget, tr("Export Voxels"), "~/voxels.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)"));
|
||||
QByteArray fileNameAscii = fileNameString.toAscii();
|
||||
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);
|
||||
printf("importVoxels() fileName: %s _mouseVoxel: %f,%f,%f-%f \n", fileName,
|
||||
_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) {
|
||||
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!!!
|
||||
_voxels.readFromFileV2(fileName,selectedNode);
|
||||
if (calculatedOctCode) {
|
||||
delete calculatedOctCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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() {
|
||||
unsigned char* calculatedOctCode = NULL;
|
||||
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() {
|
||||
QMenuBar* menuBar = new QMenuBar();
|
||||
_window->setMenuBar(menuBar);
|
||||
|
@ -1479,6 +1519,9 @@ void Application::initMenu() {
|
|||
(_selectVoxelMode = voxelMenu->addAction(
|
||||
"Select Voxel Mode", this, SLOT(updateVoxelModeActions()), Qt::CTRL | Qt::Key_S))->setCheckable(true);
|
||||
_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("Decrease Voxel Size", this, SLOT(decreaseVoxelSize()), QKeySequence::ZoomOut);
|
||||
|
@ -1486,6 +1529,7 @@ void Application::initMenu() {
|
|||
|
||||
_voxelPaintColor = voxelMenu->addAction("Voxel Paint Color", this,
|
||||
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);
|
||||
_voxelPaintColor->setData(paintColor);
|
||||
_voxelPaintColor->setIcon(createSwatchIcon(paintColor));
|
||||
|
@ -2359,6 +2403,8 @@ void Application::maybeEditVoxelUnderCursor() {
|
|||
}
|
||||
} else if (_deleteVoxelMode->isChecked()) {
|
||||
deleteVoxelUnderCursor();
|
||||
} else if (_eyedropperMode->isChecked()) {
|
||||
eyedropperVoxelUnderCursor();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2383,6 +2429,20 @@ void Application::deleteVoxelUnderCursor() {
|
|||
_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() {
|
||||
_myAvatar.setPosition(START_LOCATION);
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ private:
|
|||
void shiftPaintingColor();
|
||||
void maybeEditVoxelUnderCursor();
|
||||
void deleteVoxelUnderCursor();
|
||||
|
||||
void eyedropperVoxelUnderCursor();
|
||||
void goHome();
|
||||
void resetSensors();
|
||||
|
||||
|
@ -225,6 +225,7 @@ private:
|
|||
QAction* _deleteVoxelMode; // Whether delete voxel mode is enabled
|
||||
QAction* _colorVoxelMode; // Whether color 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* _destructiveAddVoxel; // when doing voxel editing do we want them to be destructive
|
||||
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 VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
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;
|
||||
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
||||
|
||||
const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60;
|
||||
const double VIEW_CULLING_RATE_IN_MILLISECONDS = 1000.0; // once a second is fine
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue