mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 04:23:33 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into kinected
This commit is contained in:
commit
c4deeed121
11 changed files with 364 additions and 19 deletions
|
@ -30,6 +30,7 @@
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
|
#include <QImage>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
@ -450,7 +451,7 @@ void Application::resizeGL(int width, int height) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
camera.setAspectRatio(aspectRatio);
|
camera.setAspectRatio(aspectRatio);
|
||||||
camera.setFieldOfView(fov = 60);
|
camera.setFieldOfView(fov = _horizontalFieldOfView);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell our viewFrustum about this change
|
// Tell our viewFrustum about this change
|
||||||
|
@ -1046,6 +1047,12 @@ void Application::editPreferences() {
|
||||||
avatarURL->setMinimumWidth(400);
|
avatarURL->setMinimumWidth(400);
|
||||||
form->addRow("Avatar URL:", avatarURL);
|
form->addRow("Avatar URL:", avatarURL);
|
||||||
|
|
||||||
|
QSpinBox* horizontalFieldOfView = new QSpinBox();
|
||||||
|
horizontalFieldOfView->setMaximum(180);
|
||||||
|
horizontalFieldOfView->setMinimum(1);
|
||||||
|
horizontalFieldOfView->setValue(_horizontalFieldOfView);
|
||||||
|
form->addRow("Horizontal field of view (degrees):", horizontalFieldOfView);
|
||||||
|
|
||||||
QDoubleSpinBox* headCameraPitchYawScale = new QDoubleSpinBox();
|
QDoubleSpinBox* headCameraPitchYawScale = new QDoubleSpinBox();
|
||||||
headCameraPitchYawScale->setValue(_headCameraPitchYawScale);
|
headCameraPitchYawScale->setValue(_headCameraPitchYawScale);
|
||||||
form->addRow("Head Camera Pitch/Yaw Scale:", headCameraPitchYawScale);
|
form->addRow("Head Camera Pitch/Yaw Scale:", headCameraPitchYawScale);
|
||||||
|
@ -1077,6 +1084,9 @@ void Application::editPreferences() {
|
||||||
if (!shouldDynamicallySetJitterBuffer()) {
|
if (!shouldDynamicallySetJitterBuffer()) {
|
||||||
_audio.setJitterBufferSamples(_audioJitterBufferSamples);
|
_audio.setJitterBufferSamples(_audioJitterBufferSamples);
|
||||||
}
|
}
|
||||||
|
_horizontalFieldOfView = horizontalFieldOfView->value();
|
||||||
|
resizeGL(_glWidget->width(), _glWidget->height());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::pair() {
|
void Application::pair() {
|
||||||
|
@ -1270,6 +1280,12 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||||
codeColorBuffer[bytesInCode + RED_INDEX ] = node->getColor()[RED_INDEX ];
|
codeColorBuffer[bytesInCode + RED_INDEX ] = node->getColor()[RED_INDEX ];
|
||||||
codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX];
|
codeColorBuffer[bytesInCode + GREEN_INDEX] = node->getColor()[GREEN_INDEX];
|
||||||
codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ];
|
codeColorBuffer[bytesInCode + BLUE_INDEX ] = node->getColor()[BLUE_INDEX ];
|
||||||
|
|
||||||
|
// TODO: sendVoxelsOperation() is sending voxels too fast.
|
||||||
|
// This printf function accidently slowed down sending
|
||||||
|
// and hot-fixed the bug when importing
|
||||||
|
// large PNG models (256x256 px and more)
|
||||||
|
static unsigned int sendVoxelsOperationCalled = 0; printf("sending voxel #%u\n", ++sendVoxelsOperationCalled);
|
||||||
|
|
||||||
// if we have room don't have room in the buffer, then send the previously generated message first
|
// 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) {
|
if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
||||||
|
@ -1306,14 +1322,31 @@ void Application::exportVoxels() {
|
||||||
void Application::importVoxels() {
|
void Application::importVoxels() {
|
||||||
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
|
||||||
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation,
|
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation,
|
||||||
tr("Sparse Voxel Octree Files (*.svo)"));
|
tr("Sparse Voxel Octree Files, Square PNG (*.svo *.png)"));
|
||||||
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;
|
VoxelTree importVoxels;
|
||||||
importVoxels.readFromSVOFile(fileName);
|
if (fileNameString.endsWith(".png", Qt::CaseInsensitive)) {
|
||||||
|
QImage pngImage = QImage(fileName);
|
||||||
|
if (pngImage.height() != pngImage.width()) {
|
||||||
|
printLog("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 {
|
||||||
|
importVoxels.readFromSVOFile(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);
|
||||||
|
|
||||||
// Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to
|
// Recurse the Import Voxels tree, where everything is root relative, and send all the colored voxels to
|
||||||
|
@ -1601,7 +1634,7 @@ void Application::init() {
|
||||||
|
|
||||||
_myAvatar.init();
|
_myAvatar.init();
|
||||||
_myAvatar.setPosition(START_LOCATION);
|
_myAvatar.setPosition(START_LOCATION);
|
||||||
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||||
_myCamera.setModeShiftRate(1.0f);
|
_myCamera.setModeShiftRate(1.0f);
|
||||||
_myAvatar.setDisplayingLookatVectors(false);
|
_myAvatar.setDisplayingLookatVectors(false);
|
||||||
|
|
||||||
|
@ -1659,7 +1692,7 @@ void Application::update(float deltaTime) {
|
||||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||||
|
|
||||||
// If we are dragging on a voxel, add thrust according to the amount the mouse is dragging
|
// If we are dragging on a voxel, add thrust according to the amount the mouse is dragging
|
||||||
const float VOXEL_GRAB_THRUST = 5.0f;
|
const float VOXEL_GRAB_THRUST = 0.0f;
|
||||||
if (_mousePressed && (_mouseVoxel.s != 0)) {
|
if (_mousePressed && (_mouseVoxel.s != 0)) {
|
||||||
glm::vec2 mouseDrag(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY);
|
glm::vec2 mouseDrag(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY);
|
||||||
glm::quat orientation = _myAvatar.getOrientation();
|
glm::quat orientation = _myAvatar.getOrientation();
|
||||||
|
@ -1833,7 +1866,7 @@ void Application::update(float deltaTime) {
|
||||||
_myCamera.setModeShiftRate(1.0f);
|
_myCamera.setModeShiftRate(1.0f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const float THIRD_PERSON_SHIFT_VELOCITY = 2.0f;
|
const float THIRD_PERSON_SHIFT_VELOCITY = 1000.0f;
|
||||||
const float TIME_BEFORE_SHIFT_INTO_FIRST_PERSON = 0.75f;
|
const float TIME_BEFORE_SHIFT_INTO_FIRST_PERSON = 0.75f;
|
||||||
const float TIME_BEFORE_SHIFT_INTO_THIRD_PERSON = 0.1f;
|
const float TIME_BEFORE_SHIFT_INTO_THIRD_PERSON = 0.1f;
|
||||||
|
|
||||||
|
@ -2909,6 +2942,8 @@ void Application::loadSettings(QSettings* settings) {
|
||||||
|
|
||||||
_headCameraPitchYawScale = loadSetting(settings, "headCameraPitchYawScale", 0.0f);
|
_headCameraPitchYawScale = loadSetting(settings, "headCameraPitchYawScale", 0.0f);
|
||||||
_audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0);
|
_audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0);
|
||||||
|
_horizontalFieldOfView = loadSetting(settings, "horizontalFieldOfView", HORIZONTAL_FIELD_OF_VIEW_DEGREES);
|
||||||
|
|
||||||
settings->beginGroup("View Frustum Offset Camera");
|
settings->beginGroup("View Frustum Offset Camera");
|
||||||
// in case settings is corrupt or missing loadSetting() will check for NaN
|
// in case settings is corrupt or missing loadSetting() will check for NaN
|
||||||
_viewFrustumOffsetYaw = loadSetting(settings, "viewFrustumOffsetYaw" , 0.0f);
|
_viewFrustumOffsetYaw = loadSetting(settings, "viewFrustumOffsetYaw" , 0.0f);
|
||||||
|
@ -2930,6 +2965,7 @@ void Application::saveSettings(QSettings* settings) {
|
||||||
|
|
||||||
settings->setValue("headCameraPitchYawScale", _headCameraPitchYawScale);
|
settings->setValue("headCameraPitchYawScale", _headCameraPitchYawScale);
|
||||||
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
|
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
|
||||||
|
settings->setValue("horizontalFieldOfView", _horizontalFieldOfView);
|
||||||
settings->beginGroup("View Frustum Offset Camera");
|
settings->beginGroup("View Frustum Offset Camera");
|
||||||
settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffsetYaw);
|
settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffsetYaw);
|
||||||
settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffsetPitch);
|
settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffsetPitch);
|
||||||
|
|
|
@ -297,6 +297,8 @@ private:
|
||||||
|
|
||||||
int _audioJitterBufferSamples; // Number of extra samples to wait before starting audio playback
|
int _audioJitterBufferSamples; // Number of extra samples to wait before starting audio playback
|
||||||
|
|
||||||
|
float _horizontalFieldOfView; // In Degrees, doesn't apply to HMD like Oculus
|
||||||
|
|
||||||
HandControl _handControl;
|
HandControl _handControl;
|
||||||
|
|
||||||
int _mouseX;
|
int _mouseX;
|
||||||
|
|
|
@ -348,12 +348,12 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) :
|
||||||
|
|
||||||
inputParameters.channelCount = 2; // Stereo input
|
inputParameters.channelCount = 2; // Stereo input
|
||||||
inputParameters.sampleFormat = (paInt16 | paNonInterleaved);
|
inputParameters.sampleFormat = (paInt16 | paNonInterleaved);
|
||||||
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
|
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
|
||||||
inputParameters.hostApiSpecificStreamInfo = NULL;
|
inputParameters.hostApiSpecificStreamInfo = NULL;
|
||||||
|
|
||||||
outputParameters.channelCount = 2; // Stereo output
|
outputParameters.channelCount = 2; // Stereo output
|
||||||
outputParameters.sampleFormat = (paInt16 | paNonInterleaved);
|
outputParameters.sampleFormat = (paInt16 | paNonInterleaved);
|
||||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
|
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
|
||||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||||
|
|
||||||
outputPortAudioError(Pa_OpenStream(&_stream,
|
outputPortAudioError(Pa_OpenStream(&_stream,
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#define __interface__Audio__
|
#define __interface__Audio__
|
||||||
|
|
||||||
#include <portaudio.h>
|
#include <portaudio.h>
|
||||||
|
|
||||||
#include <AudioRingBuffer.h>
|
#include <AudioRingBuffer.h>
|
||||||
#include <StdDev.h>
|
#include <StdDev.h>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
|
||||||
const float INITIAL_AREA = 0.2f;
|
const float INITIAL_AREA = 0.2f;
|
||||||
const float BALL_RADIUS = 0.025f;
|
const float BALL_RADIUS = 0.016f;
|
||||||
const glm::vec3 INITIAL_COLOR(0.62f, 0.74f, 0.91f);
|
const glm::vec3 INITIAL_COLOR(0.62f, 0.74f, 0.91f);
|
||||||
|
|
||||||
Balls::Balls(int numberOfBalls) {
|
Balls::Balls(int numberOfBalls) {
|
||||||
|
@ -83,8 +83,9 @@ void Balls::render() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const float CONSTANT_VELOCITY_DAMPING = 1.0f;
|
const float CONSTANT_VELOCITY_DAMPING = 1.0f;
|
||||||
const float NOISE_SCALE = 0.00;
|
const float NOISE_SCALE = 0.06;
|
||||||
const float SPRING_FORCE = 1.0;
|
const float SPRING_FORCE = 30.0;
|
||||||
|
const float ORIGIN_DISTANCE = 0.1;
|
||||||
const float SPRING_DAMPING = 1.0;
|
const float SPRING_DAMPING = 1.0;
|
||||||
|
|
||||||
void Balls::simulate(float deltaTime) {
|
void Balls::simulate(float deltaTime) {
|
||||||
|
@ -100,10 +101,21 @@ void Balls::simulate(float deltaTime) {
|
||||||
// Add noise
|
// Add noise
|
||||||
_balls[i].velocity += randVector() * NOISE_SCALE;
|
_balls[i].velocity += randVector() * NOISE_SCALE;
|
||||||
|
|
||||||
|
// spring force to origin
|
||||||
|
float separation = glm::distance(_balls[i].position,
|
||||||
|
_origin);
|
||||||
|
|
||||||
|
_balls[i].velocity +=
|
||||||
|
glm::normalize(_balls[i].position - _origin)
|
||||||
|
* deltaTime
|
||||||
|
*
|
||||||
|
SPRING_FORCE *
|
||||||
|
(ORIGIN_DISTANCE - separation);
|
||||||
|
|
||||||
// Approach target position
|
// Approach target position
|
||||||
for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
// for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
||||||
_balls[i].position += randFloat() * deltaTime * (_balls[i].targetPosition - _balls[i].position);
|
// _balls[i].position += randFloat() * deltaTime * (_balls[i].targetPosition - _balls[i].position);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Spring Force
|
// Spring Force
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ const float CAMERA_MIRROR_MODE_UP_SHIFT = 0.0f;
|
||||||
const float CAMERA_MIRROR_MODE_DISTANCE = 0.3f;
|
const float CAMERA_MIRROR_MODE_DISTANCE = 0.3f;
|
||||||
const float CAMERA_MIRROR_MODE_TIGHTNESS = 100.0f;
|
const float CAMERA_MIRROR_MODE_TIGHTNESS = 100.0f;
|
||||||
|
|
||||||
|
|
||||||
Camera::Camera() {
|
Camera::Camera() {
|
||||||
|
|
||||||
_needsToInitialize = true;
|
_needsToInitialize = true;
|
||||||
|
@ -35,7 +36,7 @@ Camera::Camera() {
|
||||||
_linearModeShift = 0.0f;
|
_linearModeShift = 0.0f;
|
||||||
_mode = CAMERA_MODE_THIRD_PERSON;
|
_mode = CAMERA_MODE_THIRD_PERSON;
|
||||||
_tightness = 10.0f; // default
|
_tightness = 10.0f; // default
|
||||||
_fieldOfView = 60.0f; // default
|
_fieldOfView = HORIZONTAL_FIELD_OF_VIEW_DEGREES;
|
||||||
_nearClip = 0.08f; // default
|
_nearClip = 0.08f; // default
|
||||||
_farClip = 50.0f * TREE_SCALE; // default
|
_farClip = 50.0f * TREE_SCALE; // default
|
||||||
_upShift = 0.0f;
|
_upShift = 0.0f;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
|
const float HORIZONTAL_FIELD_OF_VIEW_DEGREES = 90.0f;
|
||||||
|
|
||||||
enum CameraMode
|
enum CameraMode
|
||||||
{
|
{
|
||||||
CAMERA_MODE_NULL = -1,
|
CAMERA_MODE_NULL = -1,
|
||||||
|
|
239
libraries/voxels/src/SquarePixelMap.cpp
Normal file
239
libraries/voxels/src/SquarePixelMap.cpp
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
//
|
||||||
|
// SquarePixelMap.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Tomáš Horáček on 6/25/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SquarePixelMap.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define CHILD_COORD_X_IS_1 0x1
|
||||||
|
#define CHILD_COORD_Y_IS_1 0x2
|
||||||
|
#define ALPHA_CHANNEL_RANGE_FLOAT 256.f
|
||||||
|
#define ALPHA_CHANNEL_BIT_OFFSET 24
|
||||||
|
#define RED_CHANNEL_BIT_OFFSET 16
|
||||||
|
#define GREEN_CHANNEL_BIT_OFFSET 8
|
||||||
|
|
||||||
|
unsigned int numberOfBitsForSize(unsigned int size) {
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size--;
|
||||||
|
|
||||||
|
unsigned int ans = 1;
|
||||||
|
while (size >>= 1) {
|
||||||
|
ans++;
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PixelQuadTreeCoordinates {
|
||||||
|
unsigned int x;
|
||||||
|
unsigned int y;
|
||||||
|
unsigned int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PixelQuadTreeNode {
|
||||||
|
public:
|
||||||
|
PixelQuadTreeCoordinates _coord;
|
||||||
|
uint32_t _color; // undefined value for _allChildrenHasSameColor = false
|
||||||
|
bool _allChildrenHasSameColor;
|
||||||
|
uint8_t _minimumNeighbourhoodAplha;
|
||||||
|
|
||||||
|
// 0 x -> 1
|
||||||
|
// +---+---+
|
||||||
|
// y | 0 | 1 | <- child index
|
||||||
|
// | +---+---+
|
||||||
|
// v | 2 | 3 |
|
||||||
|
// +---+---+
|
||||||
|
// 1
|
||||||
|
PixelQuadTreeNode* _children[4];
|
||||||
|
|
||||||
|
PixelQuadTreeNode(PixelQuadTreeCoordinates coord, SquarePixelMap* pixelMap);
|
||||||
|
~PixelQuadTreeNode() {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
delete _children[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateChildCoordinates(int i, PixelQuadTreeCoordinates& childCoord) {
|
||||||
|
childCoord.x = _coord.x;
|
||||||
|
childCoord.y = _coord.y;
|
||||||
|
|
||||||
|
if (i & CHILD_COORD_X_IS_1) {
|
||||||
|
childCoord.x += childCoord.size;
|
||||||
|
}
|
||||||
|
if (i & CHILD_COORD_Y_IS_1) {
|
||||||
|
childCoord.y += childCoord.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAllChildrenSameColor() {
|
||||||
|
return false; //turn off import voxel grouping
|
||||||
|
|
||||||
|
for (int i = 1; i < 4; i++) {
|
||||||
|
if (!_children[i]->_allChildrenHasSameColor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t firstColor = _children[0]->_color;
|
||||||
|
|
||||||
|
for (int i = 1; i < 4; i++) {
|
||||||
|
if (firstColor != _children[i]->_color) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PixelQuadTreeNode::PixelQuadTreeNode(PixelQuadTreeCoordinates coord, SquarePixelMap* pixelMap) : _coord(coord), _minimumNeighbourhoodAplha(-1) {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
_children[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_coord.size == 1) {
|
||||||
|
_color = pixelMap->getPixelAt(_coord.x, _coord.y);
|
||||||
|
|
||||||
|
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x + 1, _coord.y), _minimumNeighbourhoodAplha);
|
||||||
|
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x - 1, _coord.y), _minimumNeighbourhoodAplha);
|
||||||
|
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x, _coord.y + 1), _minimumNeighbourhoodAplha);
|
||||||
|
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x, _coord.y - 1), _minimumNeighbourhoodAplha);
|
||||||
|
|
||||||
|
_allChildrenHasSameColor = true;
|
||||||
|
} else {
|
||||||
|
PixelQuadTreeCoordinates childCoord = PixelQuadTreeCoordinates();
|
||||||
|
childCoord.size = _coord.size / 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
this->updateChildCoordinates(i, childCoord);
|
||||||
|
|
||||||
|
|
||||||
|
if (childCoord.x < pixelMap->dimension() &&
|
||||||
|
childCoord.y < pixelMap->dimension()) {
|
||||||
|
|
||||||
|
_children[i] = new PixelQuadTreeNode(childCoord, pixelMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->hasAllChildrenSameColor()) {
|
||||||
|
_allChildrenHasSameColor = true;
|
||||||
|
_color = _children[0]->_color;
|
||||||
|
|
||||||
|
_minimumNeighbourhoodAplha = _children[0]->_minimumNeighbourhoodAplha;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
_minimumNeighbourhoodAplha = std::min<uint8_t>(_children[i]->_minimumNeighbourhoodAplha, _minimumNeighbourhoodAplha);
|
||||||
|
delete _children[i];
|
||||||
|
_children[i] = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_allChildrenHasSameColor = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SquarePixelMap::SquarePixelMap(const uint32_t* pixels, int dimension) : _rootPixelQuadTreeNode(NULL) {
|
||||||
|
_data = new SquarePixelMapData();
|
||||||
|
_data->dimension = dimension;
|
||||||
|
_data->reference_counter = 1;
|
||||||
|
|
||||||
|
size_t pixels_size = dimension * dimension;
|
||||||
|
_data->pixels = new uint32_t[pixels_size];
|
||||||
|
memcpy((void*)_data->pixels, (void*)pixels, sizeof(uint32_t) * pixels_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
SquarePixelMap::SquarePixelMap(const SquarePixelMap& other) {
|
||||||
|
this->_data = other._data;
|
||||||
|
this->_data->reference_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SquarePixelMap::~SquarePixelMap() {
|
||||||
|
delete _rootPixelQuadTreeNode;
|
||||||
|
|
||||||
|
if (--_data->reference_counter == 0) {
|
||||||
|
delete _data->pixels;
|
||||||
|
delete _data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SquarePixelMap::addVoxelsToVoxelTree(VoxelTree* voxelTree) {
|
||||||
|
this->generateRootPixelQuadTreeNode();
|
||||||
|
this->createVoxelsFromPixelQuadTreeToVoxelTree(_rootPixelQuadTreeNode, voxelTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SquarePixelMap::dimension() {
|
||||||
|
return _data->dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SquarePixelMap::getPixelAt(unsigned int x, unsigned int y) {
|
||||||
|
return _data->pixels[x + y * _data->dimension];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SquarePixelMap::getAlphaAt(int x, int y) {
|
||||||
|
int max_coord = this->dimension() - 1;
|
||||||
|
|
||||||
|
if (x < 0 || y < 0 || x > max_coord || y > max_coord) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->getPixelAt(x, y) >> ALPHA_CHANNEL_BIT_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SquarePixelMap::generateRootPixelQuadTreeNode() {
|
||||||
|
delete _rootPixelQuadTreeNode;
|
||||||
|
|
||||||
|
PixelQuadTreeCoordinates rootNodeCoord = PixelQuadTreeCoordinates();
|
||||||
|
rootNodeCoord.size = 1 << numberOfBitsForSize(_data->dimension);
|
||||||
|
rootNodeCoord.x = rootNodeCoord.y = 0;
|
||||||
|
|
||||||
|
_rootPixelQuadTreeNode = new PixelQuadTreeNode(rootNodeCoord, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SquarePixelMap::createVoxelsFromPixelQuadTreeToVoxelTree(PixelQuadTreeNode* pixelQuadTreeNode, VoxelTree* voxelTree) {
|
||||||
|
if (pixelQuadTreeNode->_allChildrenHasSameColor) {
|
||||||
|
VoxelDetail voxel = this->getVoxelDetail(pixelQuadTreeNode);
|
||||||
|
|
||||||
|
unsigned char minimumNeighbourhoodAplha = std::max<int>(0, pixelQuadTreeNode->_minimumNeighbourhoodAplha - 1);
|
||||||
|
|
||||||
|
float minimumNeighbourhoodY = voxel.s * (floor(minimumNeighbourhoodAplha / (ALPHA_CHANNEL_RANGE_FLOAT * voxel.s)) + 0.5);
|
||||||
|
|
||||||
|
do {
|
||||||
|
voxelTree->createVoxel(voxel.x, voxel.y, voxel.z, voxel.s, voxel.red, voxel.green, voxel.blue, true);
|
||||||
|
} while ((voxel.y -= voxel.s) > minimumNeighbourhoodY);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
PixelQuadTreeNode* child = pixelQuadTreeNode->_children[i];
|
||||||
|
if (child) {
|
||||||
|
this->createVoxelsFromPixelQuadTreeToVoxelTree(child, voxelTree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelDetail SquarePixelMap::getVoxelDetail(PixelQuadTreeNode* pixelQuadTreeNode) {
|
||||||
|
VoxelDetail voxel = VoxelDetail();
|
||||||
|
|
||||||
|
uint32_t color = pixelQuadTreeNode->_color;
|
||||||
|
unsigned char alpha = std::max<int>(0, (color >> ALPHA_CHANNEL_BIT_OFFSET) - 1);
|
||||||
|
|
||||||
|
voxel.red = color >> RED_CHANNEL_BIT_OFFSET;
|
||||||
|
voxel.green = color >> GREEN_CHANNEL_BIT_OFFSET;
|
||||||
|
voxel.blue = color;
|
||||||
|
|
||||||
|
|
||||||
|
float rootSize = _rootPixelQuadTreeNode->_coord.size;
|
||||||
|
|
||||||
|
voxel.s = pixelQuadTreeNode->_coord.size / rootSize;
|
||||||
|
voxel.y = voxel.s * (floor(alpha / (ALPHA_CHANNEL_RANGE_FLOAT * voxel.s)) + 0.5);
|
||||||
|
voxel.x = pixelQuadTreeNode->_coord.x / rootSize + voxel.s / 2;
|
||||||
|
voxel.z = pixelQuadTreeNode->_coord.y / rootSize + voxel.s / 2;
|
||||||
|
|
||||||
|
return voxel;
|
||||||
|
}
|
44
libraries/voxels/src/SquarePixelMap.h
Normal file
44
libraries/voxels/src/SquarePixelMap.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
//
|
||||||
|
// SquarePixelMap.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Tomáš Horáček on 6/25/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__SquarePixelMap__
|
||||||
|
#define __hifi__SquarePixelMap__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "VoxelTree.h"
|
||||||
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
|
class PixelQuadTreeNode;
|
||||||
|
|
||||||
|
struct SquarePixelMapData {
|
||||||
|
const uint32_t* pixels;
|
||||||
|
int dimension;
|
||||||
|
int reference_counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SquarePixelMap {
|
||||||
|
public:
|
||||||
|
SquarePixelMap(const uint32_t* pixels, int dimension);
|
||||||
|
SquarePixelMap(const SquarePixelMap& other);
|
||||||
|
~SquarePixelMap();
|
||||||
|
|
||||||
|
void addVoxelsToVoxelTree(VoxelTree* voxelTree);
|
||||||
|
|
||||||
|
int dimension();
|
||||||
|
uint32_t getPixelAt(unsigned int x, unsigned int y);
|
||||||
|
uint8_t getAlphaAt(int x, int y);
|
||||||
|
private:
|
||||||
|
SquarePixelMapData* _data;
|
||||||
|
PixelQuadTreeNode* _rootPixelQuadTreeNode;
|
||||||
|
|
||||||
|
void generateRootPixelQuadTreeNode();
|
||||||
|
void createVoxelsFromPixelQuadTreeToVoxelTree(PixelQuadTreeNode* pixelQuadTreeNode, VoxelTree* voxelTree);
|
||||||
|
VoxelDetail getVoxelDetail(PixelQuadTreeNode* pixelQuadTreeNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__SquarePixelMap__) */
|
|
@ -23,6 +23,8 @@
|
||||||
#include <fstream> // to load voxels from file
|
#include <fstream> // to load voxels from file
|
||||||
#include "VoxelConstants.h"
|
#include "VoxelConstants.h"
|
||||||
#include "CoverageMap.h"
|
#include "CoverageMap.h"
|
||||||
|
#include "SquarePixelMap.h"
|
||||||
|
|
||||||
|
|
||||||
#include <glm/gtc/noise.hpp>
|
#include <glm/gtc/noise.hpp>
|
||||||
|
|
||||||
|
@ -1447,6 +1449,12 @@ bool VoxelTree::readFromSVOFile(const char* fileName) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VoxelTree::readFromSquareARGB32Pixels(const uint32_t* pixels, int dimension) {
|
||||||
|
SquarePixelMap pixelMap = SquarePixelMap(pixels, dimension);
|
||||||
|
pixelMap.addVoxelsToVoxelTree(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void VoxelTree::writeToSVOFile(const char* fileName, VoxelNode* node) const {
|
void VoxelTree::writeToSVOFile(const char* fileName, VoxelNode* node) const {
|
||||||
|
|
||||||
std::ofstream file(fileName, std::ios::out|std::ios::binary);
|
std::ofstream file(fileName, std::ios::out|std::ios::binary);
|
||||||
|
|
|
@ -133,6 +133,8 @@ public:
|
||||||
// these will read/write files that match the wireformat, excluding the 'V' leading
|
// these will read/write files that match the wireformat, excluding the 'V' leading
|
||||||
void writeToSVOFile(const char* filename, VoxelNode* node = NULL) const;
|
void writeToSVOFile(const char* filename, VoxelNode* node = NULL) const;
|
||||||
bool readFromSVOFile(const char* filename);
|
bool readFromSVOFile(const char* filename);
|
||||||
|
// reads voxels from square image with alpha as a Y-axis
|
||||||
|
bool readFromSquareARGB32Pixels(const uint32_t* pixels, int dimension);
|
||||||
|
|
||||||
unsigned long getVoxelCount();
|
unsigned long getVoxelCount();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue