eyedropper mode, and import work

This commit is contained in:
ZappoMan 2013-06-03 12:23:16 -07:00
parent 7dd217b318
commit 78fe89172a
3 changed files with 115 additions and 47 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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