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

This commit is contained in:
Andrzej Kapolka 2013-07-10 15:16:38 -07:00
commit 67afc61fd8
6 changed files with 849 additions and 184 deletions

View file

@ -1363,8 +1363,10 @@ void Application::exportVoxels() {
void Application::importVoxels() {
QString desktopLocation = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Import Voxels"), desktopLocation,
tr("Sparse Voxel Octree Files, Square PNG (*.svo *.png)"));
QString fileNameString = QFileDialog::getOpenFileName(
_glWidget, tr("Import Voxels"), desktopLocation,
tr("Sparse Voxel Octree Files, Square PNG, Schematic Files (*.svo *.png *.schematic)"));
QByteArray fileNameAscii = fileNameString.toAscii();
const char* fileName = fileNameAscii.data();
@ -1385,8 +1387,10 @@ void Application::importVoxels() {
}
importVoxels.readFromSquareARGB32Pixels(pixels, pngImage.height());
} else {
} else if (fileNameString.endsWith(".svo", Qt::CaseInsensitive)) {
importVoxels.readFromSVOFile(fileName);
} else {
importVoxels.readFromSchematicFile(fileName);
}
VoxelNode* selectedNode = _voxels.getVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
@ -1582,11 +1586,11 @@ void Application::initMenu() {
_voxelPaintColor->setIcon(createSwatchIcon(paintColor));
(_destructiveAddVoxel = voxelMenu->addAction("Create Voxel is Destructive"))->setCheckable(true);
voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E);
voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I);
voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X);
voxelMenu->addAction("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C);
voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V);
voxelMenu->addAction("Export Voxels", this, SLOT(exportVoxels()), Qt::CTRL | Qt::Key_E);
voxelMenu->addAction("Import Voxels", this, SLOT(importVoxels()), Qt::CTRL | Qt::Key_I);
voxelMenu->addAction("Cut Voxels", this, SLOT(cutVoxels()), Qt::CTRL | Qt::Key_X);
voxelMenu->addAction("Copy Voxels", this, SLOT(copyVoxels()), Qt::CTRL | Qt::Key_C);
voxelMenu->addAction("Paste Voxels", this, SLOT(pasteVoxels()), Qt::CTRL | Qt::Key_V);
QMenu* debugMenu = menuBar->addMenu("Debug");

View file

@ -16,3 +16,8 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
# link ZLIB
find_package(ZLIB)
include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})

View file

@ -0,0 +1,245 @@
//
// Tags.h
// hifi
//
// Created by Clement Brisset on 7/3/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "Tags.h"
#include <Log.h>
#include <zlib.h>
#include <zconf.h>
#include <iostream>
Tag::Tag(int tagId, std::stringstream &ss) : _tagId(tagId) {
int size = ss.get() << 8 | ss.get();
_name.clear();
for (int i = 0; i < size; ++i) { _name += ss.get();
}
}
Tag* Tag::readTag(int tagId, std::stringstream &ss) {
switch (tagId) {
case TAG_Byte:
return new TagByte(ss);
case TAG_Short:
return new TagShort(ss);
case TAG_Int:
return new TagInt(ss);
case TAG_Long:
return new TagLong(ss);
case TAG_Float:
return new TagFloat(ss);
case TAG_Double:
return new TagDouble(ss);
case TAG_Byte_Array:
return new TagByteArray(ss);
case TAG_String:
return new TagString(ss);
case TAG_List:
return new TagList(ss);
case TAG_Compound:
return new TagCompound(ss);
case TAG_Int_Array:
return new TagIntArray(ss);
default:
return NULL;
}
}
TagByte::TagByte(std::stringstream &ss) : Tag(TAG_Byte, ss) {
_data = ss.get();
}
TagShort::TagShort(std::stringstream &ss) : Tag(TAG_Short, ss) {
_data = ss.get() << 8 | ss.get();
}
TagInt::TagInt(std::stringstream &ss) : Tag(TAG_Int, ss) {
_data = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
}
TagLong::TagLong(std::stringstream &ss) : Tag(TAG_Long, ss) {
_data = (((int64_t) ss.get()) << 56 | ((int64_t) ss.get()) << 48
|((int64_t) ss.get()) << 40 | ((int64_t) ss.get()) << 32
| ss.get() << 24 | ss.get() << 16
| ss.get() << 8 | ss.get());
}
// We don't need Float and double, so we just ignore the bytes
TagFloat::TagFloat(std::stringstream &ss) : Tag(TAG_Float, ss) {
ss.seekg(4, ss.cur);
}
TagDouble::TagDouble(std::stringstream &ss) : Tag(TAG_Double, ss) {
ss.seekg(8, ss.cur);
}
TagByteArray::TagByteArray(std::stringstream &ss) : Tag(TAG_Byte_Array, ss) {
_size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
_data = new char[_size];
for (int i = 0; i < _size; ++i) {
_data[i] = ss.get();
}
}
TagString::TagString(std::stringstream &ss) : Tag(TAG_String, ss) {
_size = ss.get() << 8 | ss.get();
for (int i = 0; i < _size; ++i) {
_data += ss.get();
}
}
TagList::TagList(std::stringstream &ss) :
Tag(TAG_List, ss) {
_tagId = ss.get();
_size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
for (int i = 0; i < _size; ++i) {
ss.putback(0);
ss.putback(0);
_data.push_back(readTag(_tagId, ss));
}
}
TagCompound::TagCompound(std::stringstream &ss) :
Tag(TAG_Compound, ss),
_size(0),
_width(0),
_length(0),
_height(0),
_blocksId(NULL),
_blocksData(NULL)
{
int tagId;
while (TAG_End != (tagId = ss.get())) {
_data.push_back(readTag(tagId, ss));
++_size;
if (NULL == _data.back()) {
_blocksId = NULL;
_blocksData = NULL;
return;
} else if (TAG_Short == tagId) {
if ("Width" == _data.back()->getName()) {
_width = ((TagShort*) _data.back())->getData();
} else if ("Height" == _data.back()->getName()) {
_height = ((TagShort*) _data.back())->getData();
} else if ("Length" == _data.back()->getName()) {
_length = ((TagShort*) _data.back())->getData();
}
} else if (TAG_Byte_Array == tagId) {
if ("Blocks" == _data.back()->getName()) {
_blocksId = ((TagByteArray*) _data.back())->getData();
} else if ("Data" == _data.back()->getName()) {
_blocksData = ((TagByteArray*) _data.back())->getData();
}
}
}
}
TagIntArray::TagIntArray(std::stringstream &ss) : Tag(TAG_Int_Array, ss) {
_size = ss.get() << 24 | ss.get() << 16 | ss.get() << 8 | ss.get();
_data = new int[_size];
for (int i = 0; i < _size; ++i) {
_data[i] = ss.get();
}
}
int retrieveData(std::string filename, std::stringstream &ss) {
std::ifstream file(filename.c_str(), std::ios::binary);
int type = file.peek();
if (type == 0x0A) {
ss.flush();
ss << file;
return 0;
}
if (type == 0x1F) {
return ungzip(file, ss);
}
return 1;
}
int ungzip(std::ifstream &file, std::stringstream &ss) {
std::string gzipedBytes;
gzipedBytes.clear();
ss.flush();
while (!file.eof()) {
gzipedBytes += (char) file.get();
}
file.close();
if (gzipedBytes.size() == 0) {
ss << gzipedBytes;
return 0;
}
unsigned int full_length = gzipedBytes.size();
unsigned int half_length = gzipedBytes.size()/2;
unsigned int uncompLength = full_length;
char* uncomp = (char*) calloc(sizeof(char), uncompLength);
z_stream strm;
strm.next_in = (Bytef *) gzipedBytes.c_str();
strm.avail_in = full_length;
strm.total_out = 0;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
bool done = false;
if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) {
free(uncomp);
return 1;
}
while (!done) {
// If our output buffer is too small
if (strm.total_out >= uncompLength) {
// Increase size of output buffer
char* uncomp2 = (char*) calloc(sizeof(char), uncompLength + half_length);
memcpy(uncomp2, uncomp, uncompLength);
uncompLength += half_length;
free(uncomp);
uncomp = uncomp2;
}
strm.next_out = (Bytef *) (uncomp + strm.total_out);
strm.avail_out = uncompLength - strm.total_out;
// Inflate another chunk.
int err = inflate (&strm, Z_SYNC_FLUSH);
if (err == Z_STREAM_END) {
done = true;
} else if (err != Z_OK) {
break;
}
}
if (inflateEnd (&strm) != Z_OK) {
free(uncomp);
return 1;
}
for (size_t i = 0; i < strm.total_out; ++i) {
ss << uncomp[i];
}
free(uncomp);
return 0;
}

175
libraries/voxels/src/Tags.h Normal file
View file

@ -0,0 +1,175 @@
//
// Tags.h
// hifi
//
// Created by Clement Brisset on 7/3/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__Tags__
#define __hifi__Tags__
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <list>
#define TAG_End 0
#define TAG_Byte 1
#define TAG_Short 2
#define TAG_Int 3
#define TAG_Long 4
#define TAG_Float 5
#define TAG_Double 6
#define TAG_Byte_Array 7
#define TAG_String 8
#define TAG_List 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);
class Tag {
public:
Tag(int tagId, std::stringstream &ss);
int getTagId() const {return _tagId;}
std::string getName () const {return _name; }
static Tag* readTag(int tagId, std::stringstream &ss);
protected:
int _tagId;
std::string _name;
};
class TagByte : public Tag {
public:
TagByte(std::stringstream &ss);
int8_t getData() const {return _data;}
private:
int8_t _data;
};
class TagShort : public Tag {
public:
TagShort(std::stringstream &ss);
int16_t getData() const {return _data;}
private:
int16_t _data;
};
class TagInt : public Tag {
public:
TagInt(std::stringstream &ss);
int32_t getData() const {return _data;}
private:
int32_t _data;
};
class TagLong : public Tag {
public:
TagLong(std::stringstream &ss);
int64_t getData() const {return _data;}
private:
int64_t _data;
};
class TagFloat : public Tag {
public:
TagFloat(std::stringstream &ss);
};
class TagDouble : public Tag {
public:
TagDouble(std::stringstream &ss);
};
class TagByteArray : public Tag {
public:
TagByteArray(std::stringstream &ss);
int getSize() const {return _size;}
char* getData() const {return _data;}
private:
int _size;
char* _data;
};
class TagString : public Tag {
public:
TagString(std::stringstream &ss);
int getSize() const {return _size;}
std::string getData() const {return _data;}
private:
int _size;
std::string _data;
};
class TagList : public Tag {
public:
TagList(std::stringstream &ss);
int getTagId() const {return _tagId;}
int getSize () const {return _size; }
std::list<Tag*> getData () const {return _data; }
private:
int _tagId;
int _size;
std::list<Tag*> _data;
};
class TagCompound : public Tag {
public:
TagCompound(std::stringstream &ss);
int getSize () const {return _size; }
std::list<Tag*> getData () const {return _data; }
int getWidth () const {return _width; }
int getLength () const {return _length; }
int getHeight () const {return _height; }
char* getBlocksId () const {return _blocksId; }
char* getBlocksData() const {return _blocksData;}
private:
int _size;
std::list<Tag*> _data;
// Specific to schematics file
int _width;
int _length;
int _height;
char* _blocksData;
char* _blocksId;
};
class TagIntArray : public Tag {
public:
TagIntArray(std::stringstream &ss);
~TagIntArray() {delete _data;}
int getSize() const {return _size;}
int* getData() const {return _data;}
private:
int _size;
int* _data;
};
#endif /* defined(__hifi__Tags__) */

View file

@ -24,10 +24,12 @@
#include "VoxelConstants.h"
#include "CoverageMap.h"
#include "SquarePixelMap.h"
#include "Tags.h"
#include <glm/gtc/noise.hpp>
int boundaryDistanceForRenderLevel(unsigned int renderLevel) {
float voxelSizeScale = 50000.0f;
return voxelSizeScale / powf(2, renderLevel);
@ -124,10 +126,10 @@ VoxelNode* VoxelTree::nodeForOctalCode(VoxelNode* ancestorNode,
if (childNode) {
if (*childNode->getOctalCode() == *needleCode) {
// If the caller asked for the parent, then give them that too...
if (parentOfFoundNode) {
*parentOfFoundNode = ancestorNode;
}
// If the caller asked for the parent, then give them that too...
if (parentOfFoundNode) {
*parentOfFoundNode = ancestorNode;
}
// the fact that the number of sections is equivalent does not always guarantee
// that this is the same node, however due to the recursive traversal
// we know that this is our node
@ -205,8 +207,8 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, unsigned char* nodeData,
if (!nodeWasDirty && nodeIsDirty) {
_nodesChangedFromBitstream++;
}
this->voxelsColored++;
this->voxelsColoredStats.updateAverage(1);
this->voxelsColored++;
this->voxelsColoredStats.updateAverage(1);
}
}
@ -293,7 +295,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, unsigned long int
int theseBytesRead = 0;
theseBytesRead += octalCodeBytes;
theseBytesRead += readNodeData(bitstreamRootNode, bitstreamAt + octalCodeBytes,
bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor, includeExistsBits);
bufferSizeBytes - (bytesRead + octalCodeBytes), includeColor, includeExistsBits);
// skip bitstream to new startPoint
bitstreamAt += theseBytesRead;
@ -534,18 +536,18 @@ void VoxelTree::readCodeColorBufferToTreeRecursion(VoxelNode* node, void* extraD
}
void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes) {
//unsigned short int itemNumber = (*((unsigned short int*)&bitstream[sizeof(PACKET_HEADER)]));
int atByte = sizeof(short int) + sizeof(PACKET_HEADER);
unsigned char* voxelCode = (unsigned char*)&bitstream[atByte];
while (atByte < bufferSizeBytes) {
int codeLength = numberOfThreeBitSectionsInCode(voxelCode);
int voxelDataSize = bytesRequiredForCodeLength(codeLength) + SIZE_OF_COLOR_DATA;
//unsigned short int itemNumber = (*((unsigned short int*)&bitstream[sizeof(PACKET_HEADER)]));
int atByte = sizeof(short int) + sizeof(PACKET_HEADER);
unsigned char* voxelCode = (unsigned char*)&bitstream[atByte];
while (atByte < bufferSizeBytes) {
int codeLength = numberOfThreeBitSectionsInCode(voxelCode);
int voxelDataSize = bytesRequiredForCodeLength(codeLength) + SIZE_OF_COLOR_DATA;
deleteVoxelCodeFromTree(voxelCode, ACTUALLY_DELETE, COLLAPSE_EMPTY_TREE);
deleteVoxelCodeFromTree(voxelCode, ACTUALLY_DELETE, COLLAPSE_EMPTY_TREE);
voxelCode+=voxelDataSize;
atByte+=voxelDataSize;
}
voxelCode+=voxelDataSize;
atByte+=voxelDataSize;
}
}
void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
@ -625,7 +627,7 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
int totalBytesRead = 0;
if(file.is_open()) {
printLog("loading file...\n");
printLog("loading file...\n");
bool bail = false;
while (!file.eof() && !bail) {
file.get(octets);
@ -658,7 +660,7 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
voxelData[lengthInBytes+2] = std::max(0,std::min(255,green + colorRandomizer));
voxelData[lengthInBytes+3] = std::max(0,std::min(255,blue + colorRandomizer));
printLog("voxel color after rand red:%d, green:%d, blue:%d\n",
voxelData[lengthInBytes+1], voxelData[lengthInBytes+2], voxelData[lengthInBytes+3]);
voxelData[lengthInBytes+1], voxelData[lengthInBytes+2], voxelData[lengthInBytes+3]);
//printVoxelCode(voxelData);
this->readCodeColorBufferToTree(voxelData);
@ -699,7 +701,7 @@ void VoxelTree::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, r
}
void VoxelTree::createSphere(float radius, float xc, float yc, float zc, float voxelSize,
bool solid, creationMode mode, bool destructive, bool debug) {
bool solid, creationMode mode, bool destructive, bool debug) {
bool wantColorRandomizer = (mode == RANDOM);
bool wantNaturalSurface = (mode == NATURAL);
@ -775,38 +777,38 @@ void VoxelTree::createSphere(float radius, float xc, float yc, float zc, float v
if (lastLayer) {
if (false && debug) {
printLog("adding candy shell: theta=%f phi=%f thisRadius=%f radius=%f\n",
theta, phi, thisRadius,radius);
theta, phi, thisRadius,radius);
}
switch (mode) {
case RANDOM: {
red = randomColorValue(165);
green = randomColorValue(165);
blue = randomColorValue(165);
} break;
case GRADIENT: {
float gradient = (phi / M_PI);
red = r1 + ((r2 - r1) * gradient);
green = g1 + ((g2 - g1) * gradient);
blue = b1 + ((b2 - b1) * gradient);
} break;
case NATURAL: {
glm::vec3 position = glm::vec3(theta,phi,radius);
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.f)
+ .125f * glm::perlin(position * 16.f);
float gradient = (1.0f + perlin)/ 2.0f;
red = (unsigned char)std::min(255, std::max(0, (int)(r1 + ((r2 - r1) * gradient))));
green = (unsigned char)std::min(255, std::max(0, (int)(g1 + ((g2 - g1) * gradient))));
blue = (unsigned char)std::min(255, std::max(0, (int)(b1 + ((b2 - b1) * gradient))));
if (debug) {
printLog("perlin=%f gradient=%f color=(%d,%d,%d)\n",perlin, gradient, red, green, blue);
}
case RANDOM: {
red = randomColorValue(165);
green = randomColorValue(165);
blue = randomColorValue(165);
} break;
case GRADIENT: {
float gradient = (phi / M_PI);
red = r1 + ((r2 - r1) * gradient);
green = g1 + ((g2 - g1) * gradient);
blue = b1 + ((b2 - b1) * gradient);
} break;
case NATURAL: {
glm::vec3 position = glm::vec3(theta,phi,radius);
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.f)
+ .125f * glm::perlin(position * 16.f);
float gradient = (1.0f + perlin)/ 2.0f;
red = (unsigned char)std::min(255, std::max(0, (int)(r1 + ((r2 - r1) * gradient))));
green = (unsigned char)std::min(255, std::max(0, (int)(g1 + ((g2 - g1) * gradient))));
blue = (unsigned char)std::min(255, std::max(0, (int)(b1 + ((b2 - b1) * gradient))));
if (debug) {
printLog("perlin=%f gradient=%f color=(%d,%d,%d)\n",perlin, gradient, red, green, blue);
}
} break;
}
if (wantNaturalSurface) {
// for natural surfaces, we will render up to 16 voxel's above the surface of the sphere
glm::vec3 position = glm::vec3(theta,phi,radius);
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.f)
+ .125f * glm::perlin(position * 16.f);
+ .125f * glm::perlin(position * 16.f);
float gradient = (1.0f + perlin)/ 2.0f;
int height = (4 * gradient)+1; // make it at least 4 thick, so we get some averaging
@ -963,7 +965,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
// If we've passed our max Search Level, then stop searching. return last level searched
if (currentSearchLevel > maxSearchLevel) {
return currentSearchLevel-1;
}
}
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
if (!node->isInView(viewFrustum)) {
@ -1036,7 +1038,7 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
}
int VoxelTree::encodeTreeBitstream(VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,
EncodeBitstreamParams& params) const {
EncodeBitstreamParams& params) const {
// How many bytes have we written so far at this level;
int bytesWritten = 0;
@ -1244,7 +1246,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
AABox voxelBox = childNode->getAABox();
voxelBox.scale(TREE_SCALE);
VoxelProjectedPolygon* voxelPolygon = new VoxelProjectedPolygon(
params.viewFrustum->getProjectedPolygon(voxelBox));
params.viewFrustum->getProjectedPolygon(voxelBox));
// In order to check occlusion culling, the shadow has to be "all in view" otherwise, we will ignore occlusion
// culling and proceed as normal
@ -1269,6 +1271,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
bool childWasInView = (childNode && params.deltaViewFrustum &&
(params.lastViewFrustum && ViewFrustum::INSIDE == childNode->inFrustum(*params.lastViewFrustum)));
// There are two types of nodes for which we want to send colors:
@ -1461,9 +1464,9 @@ 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()) {
printLog("loading file %s...\n", fileName);
printLog("loading file %s...\n", fileName);
// get file length....
// get file length....
unsigned long fileLength = file.tellg();
file.seekg( 0, std::ios::beg );
@ -1485,12 +1488,91 @@ bool VoxelTree::readFromSquareARGB32Pixels(const uint32_t* pixels, int dimension
return true;
}
bool VoxelTree::readFromSchematicFile(const char *fileName) {
std::stringstream ss;
int err = retrieveData(fileName, ss);
if (err && ss.get() != TAG_Compound) {
printLog("[ERROR] Invalid schematic file.\n");
return false;
}
ss.get();
TagCompound schematics(ss);
if (!schematics.getBlocksId() || !schematics.getBlocksData()) {
printLog("[ERROR] Invalid schematic file.\n");
return false;
}
int max = (schematics.getWidth() > schematics.getLength()) ? schematics.getWidth() : schematics.getLength();
max = (max > schematics.getHeight()) ? max : schematics.getHeight();
int scale = 1;
while (max > scale) {scale *= 2;}
float size = 1.0f / scale;
int create = 1;
int red = 128, green = 128, blue = 128;
int count = 0;
for (int y = 0; y < schematics.getHeight(); ++y) {
for (int z = 0; z < schematics.getLength(); ++z) {
for (int x = 0; x < schematics.getWidth(); ++x) {
int pos = ((y * schematics.getLength()) + z) * schematics.getWidth() + x;
int id = schematics.getBlocksId()[pos];
int data = schematics.getBlocksData()[pos];
create = 1;
computeBlockColor(id, data, red, green, blue, create);
switch (create) {
case 1:
createVoxel(size * x, size * y, size * z, size, red, green, blue, true);
++count;
break;
case 2:
switch (data) {
case 0:
createVoxel(size * x + size / 2, size * y + size / 2, size * z , size / 2, red, green, blue, true);
createVoxel(size * x + size / 2, size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true);
break;
case 1:
createVoxel(size * x , size * y + size / 2, size * z , size / 2, red, green, blue, true);
createVoxel(size * x , size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true);
break;
case 2:
createVoxel(size * x , size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true);
createVoxel(size * x + size / 2, size * y + size / 2, size * z + size / 2, size / 2, red, green, blue, true);
break;
case 3:
createVoxel(size * x , size * y + size / 2, size * z , size / 2, red, green, blue, true);
createVoxel(size * x + size / 2, size * y + size / 2, size * z , size / 2, red, green, blue, true);
break;
}
count += 2;
// There's no break on purpose.
case 3:
createVoxel(size * x , size * y, size * z , size / 2, red, green, blue, true);
createVoxel(size * x + size / 2, size * y, size * z , size / 2, red, green, blue, true);
createVoxel(size * x , size * y, size * z + size / 2, size / 2, red, green, blue, true);
createVoxel(size * x + size / 2, size * y, size * z + size / 2, size / 2, red, green, blue, true);
count += 4;
break;
}
}
}
}
printLog("Created %d voxels from minecraft import.\n", count);
return true;
}
void VoxelTree::writeToSVOFile(const char* fileName, VoxelNode* node) const {
std::ofstream file(fileName, std::ios::out|std::ios::binary);
if(file.is_open()) {
printLog("saving to file %s...\n", fileName);
printLog("saving to file %s...\n", fileName);
VoxelNodeBag nodeBag;
// If we were given a specific node, start from there, otherwise start from root
@ -1569,3 +1651,155 @@ 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;
}
}

View file

@ -135,6 +135,8 @@ public:
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 readFromSchematicFile(const char* filename);
void computeBlockColor(int id, int data, int& r, int& g, int& b, int& create);
unsigned long getVoxelCount();