Merge branch 'master' of https://github.com/worklist/hifi into animation_server_jurisdictions

This commit is contained in:
ZappoMan 2013-08-21 12:16:09 -07:00
commit 4bdaf7589f
23 changed files with 995 additions and 399 deletions

View file

@ -4,6 +4,9 @@ project(hifi)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{QT_CMAKE_PREFIX_PATH})
# set our Base SDK to 10.7
set(CMAKE_OSX_SYSROOT /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk)
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.

View file

@ -59,7 +59,7 @@ void main(void) {
vec3 offset = center + rotation * (radius * sampleKernel[i]);
vec4 projected = gl_ProjectionMatrix * vec4(offset, 1.0);
float depth = texCoordToViewSpaceZ(projected.xy * 0.5 / projected.w + vec2(0.5, 0.5));
occlusion += 1.0 - step(offset.z, depth); // * step(abs(center.z - depth), radius);
occlusion += 1.0 - step(offset.z, depth);
}
gl_FragColor = vec4(occlusion, occlusion, occlusion, 0.0) / 16.0;

View file

@ -14,15 +14,14 @@ uniform sampler2D originalTexture;
// the texture containing the diffused color
uniform sampler2D diffusedTexture;
// the scale of diffusion
uniform vec2 diffusionScale;
void main(void) {
float ds = dFdx(gl_TexCoord[0].s);
float dt = dFdy(gl_TexCoord[0].t);
gl_FragColor = (texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(-ds, -dt)) +
texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(0.0, -dt)) +
texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(ds, -dt)) +
texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(ds, 0.0)) +
texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(ds, dt)) +
texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(0.0, dt)) +
texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(-ds, dt)) +
texture2D(diffusedTexture, gl_TexCoord[0].st + vec2(-ds, 0.0))) / 8.5 + texture2D(originalTexture, gl_TexCoord[0].st) * 0.1;
vec2 minExtents = gl_TexCoord[0].st + diffusionScale * vec2(-1.5, -1.5);
vec2 maxExtents = gl_TexCoord[0].st + diffusionScale * vec2(1.5, 1.5);
gl_FragColor = (texture2D(diffusedTexture, minExtents) +
texture2D(diffusedTexture, vec2(maxExtents.s, minExtents.t)) +
texture2D(diffusedTexture, vec2(minExtents.s, maxExtents.t)) +
texture2D(diffusedTexture, maxExtents)) * 0.235 + texture2D(originalTexture, gl_TexCoord[0].st) * 0.1;
}

View file

@ -11,15 +11,14 @@
// the original texture
uniform sampler2D originalTexture;
// the scale for the blur kernel
uniform vec2 blurScale;
void main(void) {
float ds = dFdx(gl_TexCoord[0].s);
float dt = dFdy(gl_TexCoord[0].t);
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
sum += texture2D(originalTexture, gl_TexCoord[0].st +
vec2(ds, dt) * vec2(-2.0 + float(i), -2.0 + float(j)));
}
}
gl_FragColor = sum / 16.0;
vec2 minExtents = gl_TexCoord[0].st + blurScale * vec2(-0.5, -0.5);
vec2 maxExtents = gl_TexCoord[0].st + blurScale * vec2(1.5, 1.5);
gl_FragColor = (texture2D(originalTexture, minExtents) +
texture2D(originalTexture, vec2(maxExtents.s, minExtents.t)) +
texture2D(originalTexture, vec2(minExtents.s, maxExtents.t)) +
texture2D(originalTexture, maxExtents)) * 0.25;
}

View file

@ -81,6 +81,8 @@ const int STARTUP_JITTER_SAMPLES = PACKET_LENGTH_SAMPLES_PER_CHANNEL / 2;
// Startup optimistically with small jitter buffer that
// will start playback on the second received audio packet.
static const float CLIPBOARD_TREE_SCALE = 1.0f;
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) {
fprintf(stdout, "%s", message.toLocal8Bit().constData());
LogDisplay::instance.addMessage(message.toLocal8Bit().constData());
@ -94,6 +96,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_frameCount(0),
_fps(120.0f),
_justStarted(true),
_clipboard(CLIPBOARD_TREE_SCALE),
_voxelImporter(_window),
_wantToKillLocalVoxels(false),
_audioScope(256, 200, true),
_mouseX(0),
@ -125,7 +129,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_packetsPerSecond(0),
_bytesPerSecond(0),
_bytesCount(0),
_swatch(NULL)
_swatch(NULL),
_pasteMode(false)
{
_applicationStartupTime = startup_time;
_window->setWindowTitle("Interface");
@ -813,6 +818,10 @@ void Application::mousePressEvent(QMouseEvent* event) {
_pieMenu.mousePressEvent(_mouseX, _mouseY);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode) && _pasteMode) {
pasteVoxels();
}
if (MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) {
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
@ -1191,185 +1200,27 @@ void Application::exportVoxels() {
_window->activateWindow();
}
const char* IMPORT_FILE_TYPES = "Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)";
void Application::importVoxelsToClipboard() {
QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels to Clipboard"), desktopLocation,
tr(IMPORT_FILE_TYPES));
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
const char* fileName = fileNameAscii.data();
_clipboardTree.eraseAllVoxels();
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
QImage pngImage = QImage(fileName);
if (pngImage.height() != pngImage.width()) {
qDebug("ERROR: Bad PNG size: height != width.\n");
return;
}
const uint32_t* pixels;
if (pngImage.format() == QImage::Format_ARGB32) {
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits());
} else {
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
}
_clipboardTree.readFromSquareARGB32Pixels(pixels, pngImage.height());
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
_clipboardTree.readFromSVOFile(fileName);
} else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) {
_clipboardTree.readFromSchematicFile(fileName);
}
// restore the main window's active state
_window->activateWindow();
}
void Application::importVoxels() {
QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
_pasteMode = false;
QStringList fileNameStringList = QFileDialog::getOpenFileNames(_glWidget, tr("Import Voxels"), desktopLocation,
tr(IMPORT_FILE_TYPES));
if (_voxelImporter.exec()) {
qDebug("[DEBUG] Import succedded.\n");
// remember the "selected" voxel point before we do any importing...
float originalX = _mouseVoxel.x;
float originalZ = _mouseVoxel.z;
const int PNG_TYPE_NAME_LENGTH = 4;
const int SVO_TYPE_NAME_LENGTH = 4;
const int SCH_TYPE_NAME_LENGTH = 10;
// assume this is where we'll place it if filename doesn't have tiling
int unspecifiedColumnNum = 1;
int unspecifiedRowNum = 1;
// if they select multiple files, but they don't specify the tiling, we
// will tile them to this size
int unspecifiedSquare = (sqrt(fileNameStringList.size()) + 0.5);
qDebug("unspecifiedSquare: %d\n", unspecifiedSquare);
for (int i = 0; i < fileNameStringList.size(); i++) {
QString fileNameString = fileNameStringList.at(i);
QString extension;
QByteArray fileNameAscii = fileNameString.toLocal8Bit();
const char* fileName = fileNameAscii.data();
int fileTypeNameLength = 0;
VoxelTree importVoxels;
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
extension = QString(".png");
QImage pngImage = QImage(fileName);
fileTypeNameLength = PNG_TYPE_NAME_LENGTH;
if (pngImage.height() != pngImage.width()) {
qDebug("ERROR: Bad PNG size: height != width.\n");
return;
}
const uint32_t* pixels;
if (pngImage.format() == QImage::Format_ARGB32) {
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits());
} else {
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
}
importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height());
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
extension = QString(".svo");
importVoxels.readFromSVOFile(fileName);
fileTypeNameLength = SVO_TYPE_NAME_LENGTH;
} else if (fileNameString.endsWith(".schematic", Qt::CaseInsensitive)) {
extension = QString(".schematic");
importVoxels.readFromSchematicFile(fileName);
fileTypeNameLength = SCH_TYPE_NAME_LENGTH;
}
// Where we plan to place this
int columnNum = 1;
int rowNum = 1;
bool isTileLocationUnspecified = false;
// If we're in multi-file mode, then look for tiling specification in the file name
if (fileNameStringList.size() > 1) {
int indexOfFirstPeriod = fileNameString.indexOf('.');
//qDebug("indexOfFirstPeriod: %d\n", indexOfFirstPeriod);
// If the first period, is the extension, then this is not a grid name;
if (fileNameString.mid(indexOfFirstPeriod, fileNameString.length() - indexOfFirstPeriod) == extension) {
qDebug("not a valid grid name... treat like tile Location Unspecified\n");
isTileLocationUnspecified = true;
} else {
QString fileCoord = fileNameString.mid(indexOfFirstPeriod + 1,
fileNameString.length() - indexOfFirstPeriod - fileTypeNameLength - 1);
//qDebug() << "fileCoord: " << fileCoord << "\n";
indexOfFirstPeriod = fileCoord.indexOf('.');
//qDebug("indexOfFirstPeriod: %d\n", indexOfFirstPeriod);
QString columnNumString = fileCoord.right(fileCoord.length() - indexOfFirstPeriod - 1);
QString rowNumString = fileCoord.left(indexOfFirstPeriod);
//qDebug() << "columnNumString: " << columnNumString << "\n";
//qDebug() << "rowNumString: " << rowNumString << "\n";
columnNum = columnNumString.toFloat();
rowNum = rowNumString.toFloat();
// If there are no "grid sections" in the filename, then we're going to get
if (columnNum < 1 || rowNum < 1) {
qDebug("not a valid grid name... treat like tile Location Unspecified\n");
isTileLocationUnspecified = true;
}
}
}
if (isTileLocationUnspecified) {
qDebug("tile Location is Unspecified... \n");
columnNum = unspecifiedColumnNum;
rowNum = unspecifiedRowNum;
unspecifiedColumnNum++;
if (unspecifiedColumnNum > unspecifiedSquare) {
unspecifiedColumnNum = 1;
unspecifiedRowNum++;
}
}
qDebug("columnNum: %d\t rowNum: %d\n", columnNum, rowNum);
_mouseVoxel.x = originalX + (columnNum - 1) * _mouseVoxel.s;
_mouseVoxel.z = originalZ + (rowNum - 1) * _mouseVoxel.s;
VoxelNode* selectedNode = _voxels.getVoxelAt(_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;
SendVoxelsOperationArgs args;
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
// voxel size/position details.
if (selectedNode) {
args.newBaseOctCode = selectedNode->getOctalCode();
if (_voxelImporter.getimportIntoClipboard()) {
_clipboard.killLocalVoxels();
_voxelImporter.getVoxelSystem()->copySubTreeIntoNewTree(
_voxelImporter.getVoxelSystem()->getVoxelAt(0, 0, 0, 1),
&_clipboard,
true);
} else {
args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
}
qDebug("column:%d, row:%d, voxel:%f,%f,%f,%f\n", columnNum, rowNum, _mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s );
// send the insert/paste of these voxels
importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args);
_voxelEditSender.flushQueue();
if (calculatedOctCode) {
delete[] calculatedOctCode;
_pasteMode = true;
}
} else {
qDebug("[DEBUG] Import failed.\n");
}
// restore the main window's active state
_window->activateWindow();
}
@ -1383,11 +1234,17 @@ void Application::copyVoxels() {
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
if (selectedNode) {
// clear the clipboard first...
_clipboardTree.eraseAllVoxels();
_clipboard.killLocalVoxels();
// then copy onto it
_voxels.copySubTreeIntoNewTree(selectedNode, &_clipboardTree, true);
_voxels.copySubTreeIntoNewTree(selectedNode, &_clipboard, true);
}
_pasteMode = false;
}
void Application::togglePasteMode() {
_pasteMode = !_pasteMode;
}
void Application::pasteVoxels() {
@ -1407,7 +1264,12 @@ void Application::pasteVoxels() {
args.newBaseOctCode = calculatedOctCode = pointToVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
}
_clipboardTree.recurseTreeWithOperation(sendVoxelsOperation, &args);
if (_voxelImporter.getImportWaiting()) {
_voxelImporter.getVoxelSystem()->recurseTreeWithOperation(sendVoxelsOperation, &args);
_voxelImporter.reset();
} else {
_clipboard.recurseTreeWithOperation(sendVoxelsOperation, &args);
}
_voxelEditSender.flushQueue();
if (calculatedOctCode) {
@ -1449,6 +1311,10 @@ void Application::initDisplay() {
void Application::init() {
_voxels.init();
_clipboard.init();
_clipboardViewFrustum.setKeyholeRadius(1000.0f);
_clipboardViewFrustum.calculate();
_clipboard.setViewFrustum(&_clipboardViewFrustum);
_environment.init();
@ -2335,6 +2201,23 @@ void Application::displaySide(Camera& whichCamera) {
glEnable(GL_LIGHTING);
}
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelSelectMode) && _pasteMode) {
glPushMatrix();
glTranslatef(_mouseVoxel.x * TREE_SCALE,
_mouseVoxel.y * TREE_SCALE,
_mouseVoxel.z * TREE_SCALE);
glScalef(_mouseVoxel.s * TREE_SCALE,
_mouseVoxel.s * TREE_SCALE,
_mouseVoxel.s * TREE_SCALE);
if (_voxelImporter.getImportWaiting()) {
_voxelImporter.getVoxelSystem()->render(true);
} else {
_clipboard.render(true);
}
glPopMatrix();
}
_myAvatar.renderScreenTint(SCREEN_TINT_BEFORE_AVATARS, whichCamera);
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
@ -2403,7 +2286,7 @@ void Application::displaySide(Camera& whichCamera) {
}
renderFollowIndicator();
// render the glow effect
_glowEffect.render();
}

View file

@ -42,6 +42,7 @@
#include "VoxelEditPacketSender.h"
#include "VoxelPacketProcessor.h"
#include "VoxelSystem.h"
#include "VoxelImporter.h"
#include "Webcam.h"
#include "avatar/Avatar.h"
#include "avatar/HandControl.h"
@ -137,9 +138,9 @@ public slots:
void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data);
void exportVoxels();
void importVoxels();
void importVoxelsToClipboard();
void cutVoxels();
void copyVoxels();
void togglePasteMode();
void pasteVoxels();
void setRenderVoxels(bool renderVoxels);
@ -237,8 +238,10 @@ private:
Stars _stars;
VoxelSystem _voxels;
VoxelTree _clipboardTree; // if I copy/paste
VoxelSystem _voxels;
VoxelSystem _clipboard; // if I copy/paste
ViewFrustum _clipboardViewFrustum;
VoxelImporter _voxelImporter;
QByteArray _voxelsFilename;
bool _wantToKillLocalVoxels;
@ -340,6 +343,8 @@ private:
ToolsPalette _palette;
Swatch _swatch;
bool _pasteMode;
PieMenu _pieMenu;
VoxelSceneStats _voxelSceneStats;

View file

@ -0,0 +1,260 @@
//
// ImportDialog.cpp
// hifi
//
// Created by Clement Brisset on 8/12/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "ImportDialog.h"
#include "Application.h"
#include <QStandardPaths>
#include <QGridLayout>
#include <QMouseEvent>
const QString WINDOW_NAME = QObject::tr("Import Voxels");
const QString IMPORT_BUTTON_NAME = QObject::tr("Import");
const QString IMPORT_TO_CLIPBOARD_CHECKBOX_STRING = QObject::tr("Import into clipboard");
const QString PREVIEW_CHECKBOX_STRING = QObject::tr("Load preview");
const QString IMPORT_FILE_TYPES = QObject::tr("Sparse Voxel Octree Files, "
"Square PNG, "
"Schematic Files "
"(*.svo *.png *.schematic)");
const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
const glm::vec3 UP_VECT = glm::vec3(0, 1, 0);
const float ANGULAR_RATE = 0.02f;
const float VERTICAL_ANGLE = M_PI_4 / 2.0f;
const float RETURN_RATE = 0.02f;
const float NEAR_CLIP = 0.5f;
const float FAR_CLIP = 10.0f;
const float FIELD_OF_VIEW = 60.0f;
class GLWidget : public QGLWidget {
public:
GLWidget(QWidget* parent = NULL, VoxelSystem* voxelSystem = NULL);
void setDraw(bool draw) {_draw = draw;}
void setTargetCenter(glm::vec3 targetCenter) {_targetCenter = targetCenter;}
protected:
virtual void initializeGL();
virtual void resizeGL(int width, int height);
virtual void paintGL();
void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event);
private:
VoxelSystem* _voxelSystem;
bool _draw;
double _a; // horizontal angle of the camera to the center of the object
double _h; // vertical angle of the camera to the center of the object
glm::vec3 _targetCenter;
bool _pressed;
int _mouseX;
int _mouseY;
};
GLWidget::GLWidget(QWidget *parent, VoxelSystem *voxelSystem)
: QGLWidget(parent, Application::getInstance()->getGLWidget()),
_voxelSystem(voxelSystem),
_draw(false),
_a(0.0f),
_h(VERTICAL_ANGLE),
_targetCenter(0.5f, 0.5f, 0.5f),
_pressed(false),
_mouseX(0),
_mouseY(0) {
}
void GLWidget::initializeGL() {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel (GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
}
void GLWidget::resizeGL(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(FIELD_OF_VIEW,
(float) width / height,
NEAR_CLIP,
FAR_CLIP);
}
void GLWidget::paintGL() {
glEnable(GL_LINE_SMOOTH);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (!_pressed) {
_a += ANGULAR_RATE;
_h = (1.0f - RETURN_RATE) * _h + RETURN_RATE * VERTICAL_ANGLE;
}
gluLookAt(_targetCenter.x + (glm::length(_targetCenter) + NEAR_CLIP) * cos(_a),
_targetCenter.y + (glm::length(_targetCenter) + NEAR_CLIP) * sin(_h),
_targetCenter.z + (glm::length(_targetCenter) + NEAR_CLIP) * sin(_a),
_targetCenter.x, _targetCenter.y, _targetCenter.z,
UP_VECT.x, UP_VECT.y, UP_VECT.z);
if (_draw && _voxelSystem) {
glBegin(GL_LINES);
glColor3d(1, 1 ,1);
glVertex3d(0, 0, 0);
glVertex3d(1, 0, 0);
glVertex3d(0, 0, 0);
glVertex3d(0, 1, 0);
glVertex3d(0, 0, 0);
glVertex3d(0, 0, 1);
glColor3d(0.4f, 0.4f ,0.4f);
glVertex3d(2 * _targetCenter.x, 2 * _targetCenter.y, 2 * _targetCenter.z);
glVertex3d(0 , 2 * _targetCenter.y, 2 * _targetCenter.z);
glVertex3d(2 * _targetCenter.x, 2 * _targetCenter.y, 2 * _targetCenter.z);
glVertex3d(2 * _targetCenter.x, 0 , 2 * _targetCenter.z);
glVertex3d(2 * _targetCenter.x, 2 * _targetCenter.y, 2 * _targetCenter.z);
glVertex3d(2 * _targetCenter.x, 2 * _targetCenter.y, 0 );
glEnd();
_voxelSystem->render(false);
}
}
void GLWidget::mousePressEvent(QMouseEvent* event) {
_pressed = true;
_mouseX = event->globalX();
_mouseY = event->globalY();
}
void GLWidget::mouseMoveEvent(QMouseEvent* event) {
_a += (M_PI * (event->globalX() - _mouseX)) / height();
_h += (M_PI * (event->globalY() - _mouseY)) / height();
_h = glm::clamp(_h, -M_PI_4, M_PI_4);
_mouseX = event->globalX();
_mouseY = event->globalY();
}
void GLWidget::mouseReleaseEvent(QMouseEvent* event) {
_pressed = false;
}
ImportDialog::ImportDialog(QWidget *parent, VoxelSystem* voxelSystem)
: QFileDialog(parent, WINDOW_NAME, DESKTOP_LOCATION, IMPORT_FILE_TYPES),
_importButton (IMPORT_BUTTON_NAME, this),
_clipboardImportBox(IMPORT_TO_CLIPBOARD_CHECKBOX_STRING, this),
_previewBox (PREVIEW_CHECKBOX_STRING, this),
_previewBar (this),
_glPreview (new GLWidget(this, voxelSystem)) {
setOption(QFileDialog::DontUseNativeDialog, true);
setFileMode(QFileDialog::ExistingFile);
setViewMode(QFileDialog::Detail);
QGridLayout* gridLayout = (QGridLayout*) layout();
gridLayout->addWidget(&_importButton , 2, 2);
gridLayout->addWidget(&_clipboardImportBox, 2, 3);
gridLayout->addWidget(&_previewBox , 3, 3);
gridLayout->addWidget(&_previewBar , 0, 3);
gridLayout->addWidget(_glPreview , 1, 3);
gridLayout->setColumnStretch(3, 1);
_previewBar.setVisible(false);
_previewBar.setRange(0, 100);
_previewBar.setValue(0);
connect(&_importButton, SIGNAL(pressed()), SLOT(import()));
connect(&_previewBox, SIGNAL(toggled(bool)), SIGNAL(previewToggled(bool)));
connect(&_previewBox, SIGNAL(toggled(bool)), SLOT(preview(bool)));
connect(this, SIGNAL(currentChanged(QString)), SLOT(saveCurrentFile(QString)));
connect(&_glTimer, SIGNAL(timeout()), SLOT(timer()));
connect(voxelSystem, SIGNAL(importSize(float,float,float)), SLOT(setGLCamera(float, float, float)));
connect(voxelSystem, SIGNAL(importProgress(int)), &_previewBar, SLOT(setValue(int)));
}
ImportDialog::~ImportDialog() {
delete _glPreview;
}
void ImportDialog::import() {
_importButton.setDisabled(true);
_clipboardImportBox.setDisabled(true);
_previewBox.setDisabled(true);
_previewBar.setValue(0);
_previewBar.setVisible(true);
emit accepted();
}
void ImportDialog::accept() {
QFileDialog::accept();
}
void ImportDialog::reject() {
QFileDialog::reject();
}
int ImportDialog::exec() {
return QFileDialog::exec();
}
void ImportDialog::setGLCamera(float x, float y, float z) {
_glPreview->setTargetCenter(glm::vec3(x, y, z) / 2.0f);
}
void ImportDialog::reset() {
_previewBox.setChecked(false);
_previewBar.setVisible(false);
_previewBar.setValue(0);
_importButton.setEnabled(true);
_clipboardImportBox.setEnabled(true);
_previewBox.setEnabled(true);
_glTimer.stop();
_glPreview->setDraw(false);
_glPreview->updateGL();
}
void ImportDialog::preview(bool wantPreview) {
_previewBar.setValue(0);
_previewBar.setVisible(wantPreview);
_glPreview->setDraw(wantPreview);
if (wantPreview) {
_glTimer.start();
} else {
_glTimer.stop();
_glPreview->updateGL();
}
}
void ImportDialog::saveCurrentFile(QString filename) {
_currentFile = filename;
}
void ImportDialog::timer() {
_glPreview->updateGL();
_glTimer.start(16);
}

View file

@ -0,0 +1,61 @@
//
// ImportDialog.h
// hifi
//
// Created by Clement Brisset on 8/12/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__ImportDialog__
#define __hifi__ImportDialog__
#include <VoxelSystem.h>
#include <QFileDialog>
#include <QPushButton>
#include <QCheckBox>
#include <QProgressBar>
#include <QGLWidget>
#include <QTimer>
class GLWidget;
class ImportDialog : public QFileDialog {
Q_OBJECT
public:
ImportDialog(QWidget* parent = NULL, VoxelSystem* voxelSystem = NULL);
~ImportDialog();
bool getWantPreview() const { return _previewBox.isChecked(); }
QString getCurrentFile() const { return _currentFile; }
bool getImportIntoClipboard() const { return _clipboardImportBox.isChecked(); }
void reset();
signals:
void previewToggled(bool);
void accepted();
public slots:
int exec();
void setGLCamera(float x, float y, float z);
void import();
void accept();
void reject();
private slots:
void preview(bool preview);
void saveCurrentFile(QString);
void timer();
private:
QString _currentFile;
QPushButton _importButton;
QCheckBox _clipboardImportBox;
QCheckBox _previewBox;
QProgressBar _previewBar;
GLWidget* _glPreview;
QTimer _glTimer;
};
#endif /* defined(__hifi__ImportDialog__) */

View file

@ -246,14 +246,9 @@ Menu::Menu() :
addActionToQMenuAndActionHash(voxelMenu, MenuOption::ExportVoxels, Qt::CTRL | Qt::Key_E, appInstance, SLOT(exportVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::ImportVoxels, Qt::CTRL | Qt::Key_I, appInstance, SLOT(importVoxels()));
addActionToQMenuAndActionHash(voxelMenu,
MenuOption::ImportVoxelsClipboard,
Qt::SHIFT | Qt::CTRL | Qt::Key_I,
appInstance,
SLOT(importVoxelsToClipboard()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::CutVoxels, Qt::CTRL | Qt::Key_X, appInstance, SLOT(cutVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::CopyVoxels, Qt::CTRL | Qt::Key_C, appInstance, SLOT(copyVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::PasteVoxels, Qt::CTRL | Qt::Key_V, appInstance, SLOT(pasteVoxels()));
addActionToQMenuAndActionHash(voxelMenu, MenuOption::PasteVoxels, Qt::CTRL | Qt::Key_V, appInstance, SLOT(togglePasteMode()));
QMenu* debugMenu = addMenu("Debug");

View file

@ -0,0 +1,180 @@
//
// VoxelImporter.cpp
// hifi
//
// Created by Clement Brisset on 8/9/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include <VoxelImporter.h>
#include <QFileInfo>
#include <QThreadPool>
static const int IMPORT_SYSTEM_SCALE = 1.0f;
static const int MAX_VOXELS_PER_IMPORT = 2000000;
class ImportTask : public QObject, public QRunnable {
public:
ImportTask(VoxelSystem* voxelSystem, const QString &filename);
void run();
private:
VoxelSystem* _voxelSystem;
QString _filename;
};
VoxelImporter::VoxelImporter(QWidget* parent)
: QObject(parent),
_voxelSystem(IMPORT_SYSTEM_SCALE, MAX_VOXELS_PER_IMPORT),
_initialized(false),
_importWaiting(false),
_importDialog(parent, &_voxelSystem),
_currentTask(NULL),
_nextTask(NULL) {
connect(&_importDialog, SIGNAL(previewToggled(bool)), SLOT(preImport()));
connect(&_importDialog, SIGNAL(currentChanged(QString)), SLOT(preImport()));
connect(&_importDialog, SIGNAL(accepted()), SLOT(import()));
}
VoxelImporter::~VoxelImporter() {
if (_nextTask) {
delete _nextTask;
_nextTask = NULL;
}
if (_currentTask) {
disconnect(_currentTask, 0, 0, 0);
_voxelSystem.cancelImport();
_currentTask = NULL;
}
}
void VoxelImporter::reset() {
_voxelSystem.killLocalVoxels();
_importDialog.reset();
_filename = "";
_importWaiting = false;
if (_nextTask) {
delete _nextTask;
_nextTask = NULL;
}
if (_currentTask) {
_voxelSystem.cancelImport();
}
}
int VoxelImporter::exec() {
if (!_initialized) {
_voxelSystem.init();
_importViewFrustum.calculate();
_voxelSystem.setViewFrustum(&_importViewFrustum);
_initialized = true;
}
reset();
int ret = _importDialog.exec();
if (!ret) {
reset();
} else {
_importDialog.reset();
_importWaiting = true;
}
return ret;
}
int VoxelImporter::preImport() {
QString filename = _importDialog.getCurrentFile();
if (!QFileInfo(filename).isFile()) {
return 0;
}
if (_importDialog.getWantPreview()) {
_filename = filename;
if (_nextTask) {
delete _nextTask;
}
_nextTask = new ImportTask(&_voxelSystem, _filename);
connect(_nextTask, SIGNAL(destroyed()), SLOT(launchTask()));
if (_currentTask != NULL) {
_voxelSystem.cancelImport();
} else {
launchTask();
}
}
return 1;
}
int VoxelImporter::import() {
QString filename = _importDialog.getCurrentFile();
if (!QFileInfo(filename).isFile()) {
_importDialog.reject();
return 0;
}
if (_filename == filename) {
if (_currentTask) {
connect(_currentTask, SIGNAL(destroyed()), &_importDialog, SLOT(accept()));
} else {
_importDialog.accept();
}
return 1;
}
_filename = filename;
if (_nextTask) {
delete _nextTask;
}
_nextTask = new ImportTask(&_voxelSystem, _filename);
connect(_nextTask, SIGNAL(destroyed()), SLOT(launchTask()));
connect(_nextTask, SIGNAL(destroyed()), &_importDialog, SLOT(accept()));
if (_currentTask != NULL) {
_voxelSystem.cancelImport();
} else {
launchTask();
}
return 1;
}
void VoxelImporter::launchTask() {
if (_nextTask != NULL) {
_voxelSystem.killLocalVoxels();
_currentTask = _nextTask;
_nextTask = NULL;
QThreadPool::globalInstance()->start(_currentTask);
} else {
_currentTask = NULL;
}
}
ImportTask::ImportTask(VoxelSystem* voxelSystem, const QString &filename)
: _voxelSystem(voxelSystem),
_filename(filename) {
}
void ImportTask::run() {
if (_filename.endsWith(".png", Qt::CaseInsensitive)) {
_voxelSystem->readFromSquareARGB32Pixels(_filename.toLocal8Bit().data());
} else if (_filename.endsWith(".svo", Qt::CaseInsensitive)) {
_voxelSystem->readFromSVOFile(_filename.toLocal8Bit().data());
} else if (_filename.endsWith(".schematic", Qt::CaseInsensitive)) {
_voxelSystem->readFromSchematicFile(_filename.toLocal8Bit().data());
} else {
qDebug("[ERROR] Invalid file extension.\n");
}
}

View file

@ -0,0 +1,53 @@
//
// VoxelImporter.h
// hifi
//
// Created by Clement Brisset on 8/9/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__VoxelImporter__
#define __hifi__VoxelImporter__
#include <VoxelSystem.h>
#include <ImportDialog.h>
#include <QThread>
#include <QRunnable>
class ImportTask;
class VoxelImporter : public QObject {
Q_OBJECT
public:
VoxelImporter(QWidget* parent = NULL);
~VoxelImporter();
void reset();
bool getImportWaiting() const { return _importWaiting; }
VoxelSystem* getVoxelSystem() { return &_voxelSystem; }
bool getimportIntoClipboard() const { return _importDialog.getImportIntoClipboard(); }
public slots:
int exec();
int preImport();
int import();
private slots:
void launchTask();
private:
VoxelSystem _voxelSystem;
ViewFrustum _importViewFrustum;
bool _initialized;
bool _importWaiting;
ImportDialog _importDialog;
QString _filename;
ImportTask* _currentTask;
ImportTask* _nextTask;
};
#endif /* defined(__hifi__VoxelImporter__) */

View file

@ -67,6 +67,9 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) :
_voxelServerCount = 0;
_viewFrustum = Application::getInstance()->getViewFrustum();
connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float)));
connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int)));
}
void VoxelSystem::nodeDeleted(VoxelNode* node) {
@ -142,6 +145,22 @@ bool VoxelSystem::readFromSVOFile(const char* filename) {
return result;
}
bool VoxelSystem::readFromSquareARGB32Pixels(const char *filename) {
bool result = _tree->readFromSquareARGB32Pixels(filename);
if (result) {
setupNewVoxelsForDrawing();
}
return result;
}
bool VoxelSystem::readFromSchematicFile(const char* filename) {
bool result = _tree->readFromSchematicFile(filename);
if (result) {
setupNewVoxelsForDrawing();
}
return result;
}
long int VoxelSystem::getVoxelsCreated() {
return _tree->voxelsCreated;
}
@ -638,7 +657,7 @@ void VoxelSystem::updatePartialVBOs() {
}
// if we got to the end of the array, and we're in an active dirty segment...
if (inSegment) {
if (inSegment) {
updateVBOSegment(segmentStart, _voxelsInReadArrays - 1);
inSegment = false;
}
@ -978,6 +997,10 @@ public:
{ }
};
void VoxelSystem::cancelImport() {
_tree->cancelImport();
}
// "Remove" voxels from the tree that are not in view. We don't actually delete them,
// we remove them from the tree and place them into a holding area for later deletion
bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {
@ -1289,14 +1312,23 @@ void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bo
setupNewVoxelsForDrawing();
};
void VoxelSystem::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot) {
_tree->copySubTreeIntoNewTree(startNode, destinationTree, rebaseToRoot);
void VoxelSystem::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelSystem* destination, bool rebaseToRoot) {
_tree->copySubTreeIntoNewTree(startNode, destination->_tree, rebaseToRoot);
destination->setupNewVoxelsForDrawing();
}
void VoxelSystem::copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destination, bool rebaseToRoot) {
_tree->copySubTreeIntoNewTree(startNode, destination, rebaseToRoot);
}
void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode) {
_tree->copyFromTreeIntoSubTree(sourceTree, destinationNode);
}
void VoxelSystem::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData) {
_tree->recurseTreeWithOperation(operation, extraData);
}
struct FalseColorizeOccludedArgs {
ViewFrustum* viewFrustum;
CoverageMap* map;

View file

@ -51,6 +51,8 @@ public:
void loadVoxelsFile(const char* fileName,bool wantColorRandomizer);
void writeToSVOFile(const char* filename, VoxelNode* node) const;
bool readFromSVOFile(const char* filename);
bool readFromSquareARGB32Pixels(const char* filename);
bool readFromSchematicFile(const char* filename);
long int getVoxelsCreated();
long int getVoxelsColored();
@ -79,9 +81,12 @@ public:
void createSphere(float r,float xc, float yc, float zc, float s, bool solid,
creationMode mode, bool destructive = false, bool debug = false);
void copySubTreeIntoNewTree(VoxelNode* startNode, VoxelSystem* destinationTree, bool rebaseToRoot);
void copySubTreeIntoNewTree(VoxelNode* startNode, VoxelTree* destinationTree, bool rebaseToRoot);
void copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destinationNode);
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
CoverageMapV2 myCoverageMapV2;
CoverageMap myCoverageMap;
@ -89,6 +94,10 @@ public:
virtual void nodeAdded(Node* node);
virtual void nodeKilled(Node* node);
signals:
void importSize(float x, float y, float z);
void importProgress(int progress);
public slots:
void collectStatsForTreesAndVBOs();
@ -102,6 +111,8 @@ public slots:
void falseColorizeOccluded();
void falseColorizeOccludedV2();
void falseColorizeBySource();
void cancelImport();
protected:
float _treeScale;

View file

@ -32,15 +32,6 @@ void AmbientOcclusionEffect::init() {
_occlusionProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/ambient_occlusion.frag");
_occlusionProgram->link();
_blurProgram = new ProgramObject();
_blurProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/ambient_occlusion.vert");
_blurProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/occlusion_blur.frag");
_blurProgram->link();
_blurProgram->bind();
_blurProgram->setUniformValue("originalTexture", 0);
_blurProgram->release();
// create the sample kernel: an array of spherically distributed offset vectors
const int SAMPLE_KERNEL_SIZE = 16;
QVector3D sampleKernel[SAMPLE_KERNEL_SIZE];
@ -83,6 +74,17 @@ void AmbientOcclusionEffect::init() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
_blurProgram = new ProgramObject();
_blurProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/ambient_occlusion.vert");
_blurProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/occlusion_blur.frag");
_blurProgram->link();
_blurProgram->bind();
_blurProgram->setUniformValue("originalTexture", 0);
_blurProgram->release();
_blurScaleLocation = _blurProgram->uniformLocation("blurScale");
}
void AmbientOcclusionEffect::render() {
@ -95,9 +97,9 @@ void AmbientOcclusionEffect::render() {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
// render with the occlusion shader to the secondary buffer
QOpenGLFramebufferObject* secondaryFBO = Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
secondaryFBO->bind();
// render with the occlusion shader to the secondary/tertiary buffer
QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject();
freeFBO->bind();
float left, right, bottom, top, nearVal, farVal;
glm::vec4 nearClipPlane, farClipPlane;
@ -117,7 +119,7 @@ void AmbientOcclusionEffect::render() {
_occlusionProgram->release();
secondaryFBO->release();
freeFBO->release();
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
@ -128,9 +130,10 @@ void AmbientOcclusionEffect::render() {
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture());
glBindTexture(GL_TEXTURE_2D, freeFBO->texture());
_blurProgram->bind();
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / size.width(), 1.0f / size.height());
renderFullscreenQuad();
@ -138,7 +141,6 @@ void AmbientOcclusionEffect::render() {
glBindTexture(GL_TEXTURE_2D, 0);
//glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);

View file

@ -32,6 +32,7 @@ private:
int _noiseScaleLocation;
ProgramObject* _blurProgram;
int _blurScaleLocation;
GLuint _rotationTextureID;
};

View file

@ -15,7 +15,13 @@
#include "ProgramObject.h"
#include "RenderUtil.h"
GlowEffect::GlowEffect() : _renderMode(BLUR_ADD_MODE) {
GlowEffect::GlowEffect() : _renderMode(DIFFUSE_ADD_MODE), _isOddFrame(false) {
}
QOpenGLFramebufferObject* GlowEffect::getFreeFramebufferObject() const {
return (_renderMode == DIFFUSE_ADD_MODE && !_isOddFrame) ?
Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject() :
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
}
static ProgramObject* createProgram(const QString& name) {
@ -51,6 +57,8 @@ void GlowEffect::init() {
_diffuseProgram->bind();
_diffuseProgram->setUniformValue("diffusedTexture", 1);
_diffuseProgram->release();
_diffusionScaleLocation = _diffuseProgram->uniformLocation("diffusionScale");
}
void GlowEffect::prepare() {
@ -58,6 +66,7 @@ void GlowEffect::prepare() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_isEmpty = true;
_isOddFrame = !_isOddFrame;
}
void GlowEffect::begin(float intensity) {
@ -109,7 +118,7 @@ void GlowEffect::render() {
Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject();
QOpenGLFramebufferObject* newDiffusedFBO =
Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject();
if ((_isOddFrame = !_isOddFrame)) {
if (_isOddFrame) {
qSwap(oldDiffusedFBO, newDiffusedFBO);
}
newDiffusedFBO->bind();
@ -118,7 +127,11 @@ void GlowEffect::render() {
glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture());
_diffuseProgram->bind();
QSize size = Application::getInstance()->getGLWidget()->size();
_diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height());
renderFullscreenQuad();
_diffuseProgram->release();
newDiffusedFBO->release();
@ -204,5 +217,22 @@ void GlowEffect::render() {
}
void GlowEffect::cycleRenderMode() {
_renderMode = (RenderMode)((_renderMode + 1) % RENDER_MODE_COUNT);
switch(_renderMode = (RenderMode)((_renderMode + 1) % RENDER_MODE_COUNT)) {
case ADD_MODE:
qDebug() << "Glow mode: Add\n";
break;
case BLUR_ADD_MODE:
qDebug() << "Glow mode: Blur/add\n";
break;
case BLUR_PERSIST_ADD_MODE:
qDebug() << "Glow mode: Blur/persist/add\n";
break;
default:
case DIFFUSE_ADD_MODE:
qDebug() << "Glow mode: Diffuse/add\n";
break;
}
}

View file

@ -11,6 +11,8 @@
#include <QObject>
class QOpenGLFramebufferObject;
class ProgramObject;
/// A generic full screen glow effect.
@ -21,6 +23,10 @@ public:
GlowEffect();
/// Returns a pointer to the framebuffer object that the glow effect is *not* using for persistent state
/// (either the secondary or the tertiary).
QOpenGLFramebufferObject* getFreeFramebufferObject() const;
void init();
/// Prepares the glow effect for rendering the current frame. To be called before rendering the scene.
@ -51,6 +57,7 @@ private:
ProgramObject* _verticalBlurProgram;
ProgramObject* _addSeparateProgram;
ProgramObject* _diffuseProgram;
int _diffusionScaleLocation;
bool _isEmpty; ///< set when nothing in the scene is currently glowing
bool _isOddFrame; ///< controls the alternation between texture targets in diffuse add mode

View file

@ -64,12 +64,11 @@ GLuint TextureCache::getPermutationNormalTextureID() {
QOpenGLFramebufferObject* TextureCache::getPrimaryFramebufferObject() {
if (_primaryFramebufferObject == NULL) {
QSize size = Application::getInstance()->getGLWidget()->size();
_primaryFramebufferObject = new QOpenGLFramebufferObject(size);
Application::getInstance()->getGLWidget()->installEventFilter(this);
_primaryFramebufferObject = createFramebufferObject();
glGenTextures(1, &_primaryDepthTextureID);
glBindTexture(GL_TEXTURE_2D, _primaryDepthTextureID);
QSize size = Application::getInstance()->getGLWidget()->size();
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width(), size.height(),
0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -91,16 +90,14 @@ GLuint TextureCache::getPrimaryDepthTextureID() {
QOpenGLFramebufferObject* TextureCache::getSecondaryFramebufferObject() {
if (_secondaryFramebufferObject == NULL) {
_secondaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
Application::getInstance()->getGLWidget()->installEventFilter(this);
_secondaryFramebufferObject = createFramebufferObject();
}
return _secondaryFramebufferObject;
}
QOpenGLFramebufferObject* TextureCache::getTertiaryFramebufferObject() {
if (_tertiaryFramebufferObject == NULL) {
_tertiaryFramebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
Application::getInstance()->getGLWidget()->installEventFilter(this);
_tertiaryFramebufferObject = createFramebufferObject();
}
return _tertiaryFramebufferObject;
}
@ -124,3 +121,15 @@ bool TextureCache::eventFilter(QObject* watched, QEvent* event) {
}
return false;
}
QOpenGLFramebufferObject* TextureCache::createFramebufferObject() {
QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
Application::getInstance()->getGLWidget()->installEventFilter(this);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
return fbo;
}

View file

@ -46,6 +46,8 @@ public:
private:
QOpenGLFramebufferObject* createFramebufferObject();
GLuint _permutationNormalTextureID;
QOpenGLFramebufferObject* _primaryFramebufferObject;

View file

@ -163,10 +163,13 @@ int retrieveData(std::string filename, std::stringstream &ss) {
ss << file;
return 0;
}
if (type == 0x1F) {
return ungzip(file, ss);
int ret = ungzip(file, ss);
return ret;
}
std::cerr << "[DEBUG] Schematic compression type not recognize : " << type << std::endl;
return 1;
}
@ -242,3 +245,156 @@ int ungzip(std::ifstream &file, std::stringstream &ss) {
}
void computeBlockColor(int id, int data, int& red, int& green, int& blue, int& create) {
switch (id) {
case 1:
case 14:
case 15:
case 16:
case 21:
case 56:
case 73:
case 74:
case 97:
case 129: red = 128; green = 128; blue = 128; break;
case 2: red = 77; green = 117; blue = 66; break;
case 3:
case 60: red = 116; green = 83; blue = 56; break;
case 4: red = 71; green = 71; blue = 71; break;
case 5:
case 125: red = 133; green = 94; blue = 62; break;
case 7: red = 35; green = 35; blue = 35; break;
case 8:
case 9: red = 100; green = 109; blue = 185; break;
case 10:
case 11: red = 192; green = 64; blue = 8; break;
case 12: red = 209; green = 199; blue = 155; break;
case 13: red = 96; green = 94; blue = 93; break;
case 17: red = 71; green = 56; blue = 35; break;
case 18: red = 76; green = 104; blue = 64; break;
case 19: red = 119; green = 119; blue = 37; break;
case 22: red = 22; green = 44; blue = 86; break;
case 23:
case 29:
case 33:
case 61:
case 62:
case 158: red = 61; green = 61; blue = 61; break;
case 24: red = 209; green = 202; blue = 156; break;
case 25:
case 58:
case 84:
case 137: red = 57; green = 38; blue = 25; break;
case 35:
switch (data) {
case 0: red = 234; green = 234; blue = 234; break;
case 1: red = 224; green = 140; blue = 84; break;
case 2: red = 185; green = 90; blue = 194; break;
case 3: red = 124; green = 152; blue = 208; break;
case 4: red = 165; green = 154; blue = 35; break;
case 5: red = 70; green = 187; blue = 61; break;
case 6: red = 206; green = 124; blue = 145; break;
case 7: red = 66; green = 66; blue = 66; break;
case 8: red = 170; green = 176; blue = 176; break;
case 9: red = 45; green = 108; blue = 35; break;
case 10: red = 130; green = 62; blue = 8; break;
case 11: red = 43; green = 51; blue = 29; break;
case 12: red = 73; green = 47; blue = 29; break;
case 13: red = 57; green = 76; blue = 36; break;
case 14: red = 165; green = 58; blue = 53; break;
case 15: red = 24; green = 24; blue = 24; break;
default:
create = 0;
break;
}
break;
case 41: red = 239; green = 238; blue = 105; break;
case 42: red = 146; green = 146; blue = 146; break;
case 43:
case 98: red = 161; green = 161; blue = 161; break;
case 44:
create = 3;
switch (data) {
case 0: red = 161; green = 161; blue = 161; break;
case 1: red = 209; green = 202; blue = 156; break;
case 2: red = 133; green = 94; blue = 62; break;
case 3: red = 71; green = 71; blue = 71; break;
case 4: red = 121; green = 67; blue = 53; break;
case 5: red = 161; green = 161; blue = 161; break;
case 6: red = 45; green = 22; blue = 26; break;
case 7: red = 195; green = 192; blue = 185; break;
default:
create = 0;
break;
}
break;
case 45: red = 121; green = 67; blue = 53; break;
case 46: red = 118; green = 36; blue = 13; break;
case 47: red = 155; green = 127; blue = 76; break;
case 48: red = 61; green = 79; blue = 61; break;
case 49: red = 52; green = 41; blue = 74; break;
case 52: red = 12; green = 66; blue = 71; break;
case 53:
case 67:
case 108:
case 109:
case 114:
case 128:
case 134:
case 135:
case 136:
case 156:
create = 2;
switch (id) {
case 53:
case 134:
case 135:
case 136: red = 133; green = 94; blue = 62; break;
case 67: red = 71; green = 71; blue = 71; break;
case 108: red = 121; green = 67; blue = 53; break;
case 109: red = 161; green = 161; blue = 161; break;
case 114: red = 45; green = 22; blue = 26; break;
case 128: red = 209; green = 202; blue = 156; break;
case 156: red = 195; green = 192; blue = 185; break;
default:
create = 0;
break;
}
break;
case 54:
case 95:
case 146: red = 155; green = 105; blue = 32; break;
case 57: red = 145; green = 219; blue = 215; break;
case 79: red = 142; green = 162; blue = 195; break;
case 80: red = 255; green = 255; blue = 255; break;
case 81: red = 8; green = 64; blue = 15; break;
case 82: red = 150; green = 155; blue = 166; break;
case 86:
case 91: red = 179; green = 108; blue = 17; break;
case 87:
case 153: red = 91; green = 31; blue = 30; break;
case 88: red = 68; green = 49; blue = 38; break;
case 89: red = 180; green = 134; blue = 65; break;
case 103: red = 141; green = 143; blue = 36; break;
case 110: red = 103; green = 92; blue = 95; break;
case 112: red = 45; green = 22; blue = 26; break;
case 121: red = 183; green = 178; blue = 129; break;
case 123: red = 101; green = 59; blue = 31; break;
case 124: red = 213; green = 178; blue = 123; break;
case 130: red = 38; green = 54; blue = 56; break;
case 133: red = 53; green = 84; blue = 85; break;
case 152: red = 131; green = 22; blue = 7; break;
case 155: red = 195; green = 192; blue = 185; break;
case 159: red = 195; green = 165; blue = 150; break;
case 170: red = 168; green = 139; blue = 15; break;
case 172: red = 140; green = 86; blue = 61; break;
case 173: red = 9; green = 9; blue = 9; break;
default:
create = 0;
break;
}
}

View file

@ -29,8 +29,9 @@
#define TAG_Compound 10
#define TAG_Int_Array 11
int retrieveData(std::string filename, std::stringstream &ss);
int ungzip(std::ifstream &file, std::stringstream &ss);
int retrieveData(std::string filename, std::stringstream &ss);
int ungzip(std::ifstream &file, std::stringstream &ss);
void computeBlockColor(int id, int data, int& r, int& g, int& b, int& create);
class Tag {
public:

View file

@ -18,6 +18,7 @@
#include <glm/gtc/noise.hpp>
#include <QtCore/QDebug>
#include <QImage>
#include "CoverageMap.h"
#include "GeometryUtil.h"
@ -48,7 +49,8 @@ VoxelTree::VoxelTree(bool shouldReaverage) :
voxelsColoredStats(100),
voxelsBytesReadStats(100),
_isDirty(true),
_shouldReaverage(shouldReaverage) {
_shouldReaverage(shouldReaverage),
_stopImport(false) {
rootNode = new VoxelNode();
}
@ -359,6 +361,8 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int
// skip bitstream to new startPoint
bitstreamAt += theseBytesRead;
bytesRead += theseBytesRead;
emit importProgress((100 * (bitstreamAt - bitstream)) / bufferSizeBytes);
}
this->voxelsBytesRead += bufferSizeBytes;
@ -1557,6 +1561,10 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
bool VoxelTree::readFromSVOFile(const char* fileName) {
std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate);
if(file.is_open()) {
emit importSize(1.0f, 1.0f, 1.0f);
emit importProgress(0);
qDebug("loading file %s...\n", fileName);
// get file length....
@ -1570,21 +1578,45 @@ bool VoxelTree::readFromSVOFile(const char* fileName) {
readBitstreamToTree(entireFile, fileLength, args);
delete[] entireFile;
emit importProgress(100);
file.close();
return true;
}
return false;
}
bool VoxelTree::readFromSquareARGB32Pixels(const uint32_t* pixels, int dimension) {
SquarePixelMap pixelMap = SquarePixelMap(pixels, dimension);
bool VoxelTree::readFromSquareARGB32Pixels(const char* filename) {
QImage pngImage = QImage(filename);
if (pngImage.height() != pngImage.width()) {
qDebug("ERROR: Bad PNG size: height != width.\n");
return false;
}
emit importSize(1.0f, 1.0f, 1.0f);
emit importProgress(0);
const uint32_t* pixels;
if (pngImage.format() == QImage::Format_ARGB32) {
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits());
} else {
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
}
SquarePixelMap pixelMap = SquarePixelMap(pixels, pngImage.height());
pixelMap.addVoxelsToVoxelTree(this);
emit importProgress(100);
return true;
}
bool VoxelTree::readFromSchematicFile(const char *fileName) {
_stopImport = false;
emit importProgress(0);
std::stringstream ss;
int err = retrieveData(fileName, ss);
int err = retrieveData(std::string(fileName), ss);
if (err && ss.get() != TAG_Compound) {
qDebug("[ERROR] Invalid schematic file.\n");
return false;
@ -1593,7 +1625,7 @@ bool VoxelTree::readFromSchematicFile(const char *fileName) {
ss.get();
TagCompound schematics(ss);
if (!schematics.getBlocksId() || !schematics.getBlocksData()) {
qDebug("[ERROR] Invalid schematic file.\n");
qDebug("[ERROR] Invalid schematic data.\n");
return false;
}
@ -1608,9 +1640,22 @@ bool VoxelTree::readFromSchematicFile(const char *fileName) {
int red = 128, green = 128, blue = 128;
int count = 0;
emit importSize(size * schematics.getWidth(),
size * schematics.getHeight(),
size * schematics.getLength());
emit importProgress(0);
for (int y = 0; y < schematics.getHeight(); ++y) {
for (int z = 0; z < schematics.getLength(); ++z) {
emit importProgress((int) 100 * (y * schematics.getLength() + z) / (schematics.getHeight() * schematics.getLength()));
for (int x = 0; x < schematics.getWidth(); ++x) {
if (_stopImport) {
qDebug("[DEBUG] Canceled import at %d voxels.\n", count);
_stopImport = false;
return true;
}
int pos = ((y * schematics.getLength()) + z) * schematics.getWidth() + x;
int id = schematics.getBlocksId()[pos];
int data = schematics.getBlocksData()[pos];
@ -1656,6 +1701,7 @@ bool VoxelTree::readFromSchematicFile(const char *fileName) {
}
}
emit importProgress(100);
qDebug("Created %d voxels from minecraft import.\n", count);
return true;
@ -1747,155 +1793,6 @@ void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destin
}
}
void VoxelTree::computeBlockColor(int id, int data, int& red, int& green, int& blue, int& create) {
switch (id) {
case 1:
case 14:
case 15:
case 16:
case 21:
case 56:
case 73:
case 74:
case 97:
case 129: red = 128; green = 128; blue = 128; break;
case 2: red = 77; green = 117; blue = 66; break;
case 3:
case 60: red = 116; green = 83; blue = 56; break;
case 4: red = 71; green = 71; blue = 71; break;
case 5:
case 125: red = 133; green = 94; blue = 62; break;
case 7: red = 35; green = 35; blue = 35; break;
case 8:
case 9: red = 100; green = 109; blue = 185; break;
case 10:
case 11: red = 192; green = 64; blue = 8; break;
case 12: red = 209; green = 199; blue = 155; break;
case 13: red = 96; green = 94; blue = 93; break;
case 17: red = 71; green = 56; blue = 35; break;
case 18: red = 76; green = 104; blue = 64; break;
case 19: red = 119; green = 119; blue = 37; break;
case 22: red = 22; green = 44; blue = 86; break;
case 23:
case 29:
case 33:
case 61:
case 62:
case 158: red = 61; green = 61; blue = 61; break;
case 24: red = 209; green = 202; blue = 156; break;
case 25:
case 58:
case 84:
case 137: red = 57; green = 38; blue = 25; break;
case 35:
switch (data) {
case 0: red = 234; green = 234; blue = 234; break;
case 1: red = 224; green = 140; blue = 84; break;
case 2: red = 185; green = 90; blue = 194; break;
case 3: red = 124; green = 152; blue = 208; break;
case 4: red = 165; green = 154; blue = 35; break;
case 5: red = 70; green = 187; blue = 61; break;
case 6: red = 206; green = 124; blue = 145; break;
case 7: red = 66; green = 66; blue = 66; break;
case 8: red = 170; green = 176; blue = 176; break;
case 9: red = 45; green = 108; blue = 35; break;
case 10: red = 130; green = 62; blue = 8; break;
case 11: red = 43; green = 51; blue = 29; break;
case 12: red = 73; green = 47; blue = 29; break;
case 13: red = 57; green = 76; blue = 36; break;
case 14: red = 165; green = 58; blue = 53; break;
case 15: red = 24; green = 24; blue = 24; break;
default:
create = 0;
break;
}
break;
case 41: red = 239; green = 238; blue = 105; break;
case 42: red = 146; green = 146; blue = 146; break;
case 43:
case 98: red = 161; green = 161; blue = 161; break;
case 44:
create = 3;
switch (data) {
case 0: red = 161; green = 161; blue = 161; break;
case 1: red = 209; green = 202; blue = 156; break;
case 2: red = 133; green = 94; blue = 62; break;
case 3: red = 71; green = 71; blue = 71; break;
case 4: red = 121; green = 67; blue = 53; break;
case 5: red = 161; green = 161; blue = 161; break;
case 6: red = 45; green = 22; blue = 26; break;
case 7: red = 195; green = 192; blue = 185; break;
default:
create = 0;
break;
}
break;
case 45: red = 121; green = 67; blue = 53; break;
case 46: red = 118; green = 36; blue = 13; break;
case 47: red = 155; green = 127; blue = 76; break;
case 48: red = 61; green = 79; blue = 61; break;
case 49: red = 52; green = 41; blue = 74; break;
case 52: red = 12; green = 66; blue = 71; break;
case 53:
case 67:
case 108:
case 109:
case 114:
case 128:
case 134:
case 135:
case 136:
case 156:
create = 2;
switch (id) {
case 53:
case 134:
case 135:
case 136: red = 133; green = 94; blue = 62; break;
case 67: red = 71; green = 71; blue = 71; break;
case 108: red = 121; green = 67; blue = 53; break;
case 109: red = 161; green = 161; blue = 161; break;
case 114: red = 45; green = 22; blue = 26; break;
case 128: red = 209; green = 202; blue = 156; break;
case 156: red = 195; green = 192; blue = 185; break;
default:
create = 0;
break;
}
break;
case 54:
case 95:
case 146: red = 155; green = 105; blue = 32; break;
case 57: red = 145; green = 219; blue = 215; break;
case 79: red = 142; green = 162; blue = 195; break;
case 80: red = 255; green = 255; blue = 255; break;
case 81: red = 8; green = 64; blue = 15; break;
case 82: red = 150; green = 155; blue = 166; break;
case 86:
case 91: red = 179; green = 108; blue = 17; break;
case 87:
case 153: red = 91; green = 31; blue = 30; break;
case 88: red = 68; green = 49; blue = 38; break;
case 89: red = 180; green = 134; blue = 65; break;
case 103: red = 141; green = 143; blue = 36; break;
case 110: red = 103; green = 92; blue = 95; break;
case 112: red = 45; green = 22; blue = 26; break;
case 121: red = 183; green = 178; blue = 129; break;
case 123: red = 101; green = 59; blue = 31; break;
case 124: red = 213; green = 178; blue = 123; break;
case 130: red = 38; green = 54; blue = 56; break;
case 133: red = 53; green = 84; blue = 85; break;
case 152: red = 131; green = 22; blue = 7; break;
case 155: red = 195; green = 192; blue = 185; break;
case 159: red = 195; green = 165; blue = 150; break;
case 170: red = 168; green = 139; blue = 15; break;
case 172: red = 140; green = 86; blue = 61; break;
case 173: red = 9; green = 9; blue = 9; break;
default:
create = 0;
break;
}
}
void VoxelTree::cancelImport() {
_stopImport = true;
}

View file

@ -19,6 +19,8 @@
#include "VoxelNodeBag.h"
#include "VoxelSceneStats.h"
#include <QObject>
// Callback function, for recuseTreeWithOperation
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, void* extraData);
typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
@ -112,7 +114,8 @@ public:
{}
};
class VoxelTree {
class VoxelTree : public QObject {
Q_OBJECT
public:
// when a voxel is created in the tree (object new'd)
long voxelsCreated;
@ -172,9 +175,8 @@ public:
void writeToSVOFile(const char* filename, VoxelNode* node = NULL) const;
bool readFromSVOFile(const char* filename);
// reads voxels from square image with alpha as a Y-axis
bool readFromSquareARGB32Pixels(const uint32_t* pixels, int dimension);
bool readFromSquareARGB32Pixels(const char *filename);
bool readFromSchematicFile(const char* filename);
void computeBlockColor(int id, int data, int& r, int& g, int& b, int& create);
unsigned long getVoxelCount();
@ -192,6 +194,13 @@ public:
RecurseVoxelTreeOperation operation,
const glm::vec3& point, void* extraData);
signals:
void importSize(float x, float y, float z);
void importProgress(int progress);
public slots:
void cancelImport();
private:
void deleteVoxelCodeFromTreeRecursion(VoxelNode* node, void* extraData);
@ -209,6 +218,7 @@ private:
bool _isDirty;
unsigned long int _nodesChangedFromBitstream;
bool _shouldReaverage;
bool _stopImport;
};
float boundaryDistanceForRenderLevel(unsigned int renderLevel);