VOXELFORMAT: add qef format support #54

master
Martin Gerhardy 2020-07-26 08:25:10 +02:00
parent 21bd6719a1
commit 8b74a7aa00
5 changed files with 617 additions and 0 deletions

442
data/tests/qubicle.qef Normal file
View File

@ -0,0 +1,442 @@
Qubicle Exchange Format
Version 0.2
www.minddesk.com
8 8 8
10
0.078431 0.070588 0.117647
0.152941 0.262745 0.541176
0.184314 0.435294 0.537255
0.235294 0.341176 0.294118
0.258824 0.682353 0.223529
0.368627 0.529412 0.482353
0.419608 0.666667 0.592157
0.498039 0.243137 0.713726
0.521569 0.576471 1.000000
0.670588 0.109804 0.035294
0 0 0 0 126
0 0 1 3 126
0 0 2 6 22
0 0 3 6 22
0 0 4 6 22
0 0 5 6 22
0 0 6 3 126
0 0 7 1 126
0 1 0 3 126
0 1 1 5 126
0 1 2 5 126
0 1 3 5 126
0 1 4 5 126
0 1 5 5 126
0 1 6 5 126
0 1 7 3 126
0 2 0 6 68
0 2 1 6 4
0 2 2 6 4
0 2 3 6 4
0 2 4 6 4
0 2 5 6 4
0 2 6 6 4
0 2 7 6 36
0 3 0 5 126
0 3 1 5 126
0 3 2 5 126
0 3 3 9 126
0 3 4 9 126
0 3 5 5 126
0 3 6 5 126
0 3 7 5 126
0 4 0 6 68
0 4 1 6 4
0 4 2 6 4
0 4 3 9 126
0 4 4 6 4
0 4 5 6 4
0 4 6 6 4
0 4 7 6 36
0 5 0 5 126
0 5 1 5 126
0 5 2 5 126
0 5 3 9 126
0 5 4 9 126
0 5 5 5 126
0 5 6 5 126
0 5 7 5 126
0 6 0 3 126
0 6 1 6 4
0 6 2 6 4
0 6 3 9 126
0 6 4 9 126
0 6 5 6 4
0 6 6 6 4
0 6 7 3 126
0 7 0 8 126
0 7 1 3 126
0 7 2 5 126
0 7 3 5 126
0 7 4 5 126
0 7 5 5 126
0 7 6 3 126
0 7 7 2 126
1 0 0 3 126
1 0 7 3 126
1 1 0 5 126
1 2 0 6 64
1 2 1 5 126
1 2 2 5 126
1 2 3 5 126
1 2 4 5 126
1 2 5 5 126
1 2 6 5 126
1 2 7 6 48
1 3 0 5 126
1 3 1 6 0
1 3 2 6 0
1 3 3 6 0
1 3 4 6 0
1 3 5 6 0
1 3 6 6 0
1 3 7 5 126
1 4 0 6 64
1 4 1 6 0
1 4 2 6 0
1 4 3 6 0
1 4 4 6 0
1 4 5 6 0
1 4 6 6 0
1 4 7 6 32
1 5 0 5 126
1 5 1 6 0
1 5 2 6 0
1 5 3 6 0
1 5 4 6 0
1 5 5 6 0
1 5 6 6 0
1 5 7 5 126
1 6 0 6 64
1 6 1 6 0
1 6 2 6 0
1 6 3 6 0
1 6 4 6 0
1 6 5 6 0
1 6 6 6 0
1 6 7 6 32
1 7 0 3 126
1 7 1 6 8
1 7 2 6 8
1 7 3 6 8
1 7 4 6 8
1 7 5 6 8
1 7 6 6 8
1 7 7 3 126
2 0 0 6 112
2 0 7 6 120
2 1 0 5 126
2 2 0 6 64
2 2 1 5 126
2 2 2 6 126
2 2 3 6 126
2 2 4 6 126
2 2 5 6 126
2 2 6 5 126
2 2 7 6 48
2 3 0 5 126
2 3 1 6 0
2 3 2 6 0
2 3 3 6 0
2 3 4 6 0
2 3 5 6 0
2 3 6 6 0
2 3 7 5 126
2 4 0 6 64
2 4 1 6 0
2 4 2 6 0
2 4 3 6 0
2 4 4 6 0
2 4 5 6 0
2 4 6 6 0
2 4 7 6 32
2 5 0 5 126
2 5 1 6 0
2 5 2 6 0
2 5 3 6 0
2 5 4 6 0
2 5 5 6 0
2 5 6 6 0
2 5 7 5 126
2 6 0 6 64
2 6 1 6 0
2 6 2 6 0
2 6 3 6 0
2 6 4 6 0
2 6 5 6 0
2 6 6 6 0
2 6 7 6 32
2 7 0 5 126
2 7 1 6 8
2 7 2 9 126
2 7 3 5 126
2 7 4 5 126
2 7 5 5 126
2 7 6 6 8
2 7 7 5 126
3 0 0 6 112
3 0 7 6 120
3 1 0 5 126
3 2 0 6 64
3 2 1 5 126
3 2 2 6 126
3 2 3 5 126
3 2 4 5 126
3 2 5 6 126
3 2 6 5 126
3 2 7 6 48
3 3 0 9 126
3 3 1 6 0
3 3 2 6 0
3 3 3 6 0
3 3 4 6 0
3 3 5 6 0
3 3 6 6 0
3 3 7 9 126
3 4 0 9 126
3 4 1 6 0
3 4 2 6 0
3 4 3 6 0
3 4 4 6 0
3 4 5 6 0
3 4 6 6 0
3 4 7 9 126
3 5 0 9 126
3 5 1 6 0
3 5 2 6 0
3 5 3 6 0
3 5 4 6 0
3 5 5 6 0
3 5 6 6 0
3 5 7 9 126
3 6 0 6 64
3 6 1 6 0
3 6 2 6 0
3 6 3 6 0
3 6 4 6 0
3 6 5 6 0
3 6 6 6 0
3 6 7 9 126
3 7 0 5 126
3 7 1 6 8
3 7 2 9 126
3 7 3 9 126
3 7 4 9 126
3 7 5 9 126
3 7 6 6 8
3 7 7 5 126
4 0 0 6 112
4 0 7 6 120
4 1 0 5 126
4 2 0 6 64
4 2 1 5 126
4 2 2 6 126
4 2 3 5 126
4 2 4 5 126
4 2 5 6 126
4 2 6 5 126
4 2 7 6 48
4 3 0 9 126
4 3 1 6 0
4 3 2 6 0
4 3 3 6 0
4 3 4 6 0
4 3 5 6 0
4 3 6 6 0
4 3 7 5 126
4 4 0 9 126
4 4 1 6 0
4 4 2 6 0
4 4 3 6 0
4 4 4 6 0
4 4 5 6 0
4 4 6 6 0
4 4 7 9 126
4 5 0 9 126
4 5 1 6 0
4 5 2 6 0
4 5 3 6 0
4 5 4 6 0
4 5 5 6 0
4 5 6 6 0
4 5 7 5 126
4 6 0 9 126
4 6 1 6 0
4 6 2 6 0
4 6 3 6 0
4 6 4 6 0
4 6 5 6 0
4 6 6 6 0
4 6 7 9 126
4 7 0 5 126
4 7 1 6 8
4 7 2 9 126
4 7 3 6 8
4 7 4 6 8
4 7 5 5 126
4 7 6 6 8
4 7 7 5 126
5 0 0 6 112
5 0 7 6 120
5 1 0 5 126
5 2 0 6 64
5 2 1 5 126
5 2 2 6 126
5 2 3 6 126
5 2 4 6 126
5 2 5 6 126
5 2 6 5 126
5 2 7 6 48
5 3 0 5 126
5 3 1 6 0
5 3 2 6 0
5 3 3 6 0
5 3 4 6 0
5 3 5 6 0
5 3 6 6 0
5 3 7 5 126
5 4 0 6 64
5 4 1 6 0
5 4 2 6 0
5 4 3 6 0
5 4 4 6 0
5 4 5 6 0
5 4 6 6 0
5 4 7 6 32
5 5 0 5 126
5 5 1 6 0
5 5 2 6 0
5 5 3 6 0
5 5 4 6 0
5 5 5 6 0
5 5 6 6 0
5 5 7 5 126
5 6 0 6 64
5 6 1 6 0
5 6 2 6 0
5 6 3 6 0
5 6 4 6 0
5 6 5 6 0
5 6 6 6 0
5 6 7 6 32
5 7 0 5 126
5 7 1 6 8
5 7 2 5 126
5 7 3 5 126
5 7 4 5 126
5 7 5 5 126
5 7 6 6 8
5 7 7 5 126
6 0 0 3 126
6 0 7 6 120
6 1 0 5 126
6 2 0 6 64
6 2 1 5 126
6 2 2 5 126
6 2 3 5 126
6 2 4 5 126
6 2 5 5 126
6 2 6 5 126
6 2 7 6 48
6 3 0 5 126
6 3 1 6 0
6 3 2 6 0
6 3 3 6 0
6 3 4 6 0
6 3 5 6 0
6 3 6 6 0
6 3 7 5 126
6 4 0 6 64
6 4 1 6 0
6 4 2 6 0
6 4 3 6 0
6 4 4 6 0
6 4 5 6 0
6 4 6 6 0
6 4 7 6 32
6 5 0 5 126
6 5 1 6 0
6 5 2 6 0
6 5 3 6 0
6 5 4 6 0
6 5 5 6 0
6 5 6 6 0
6 5 7 5 126
6 6 0 6 64
6 6 1 6 0
6 6 2 6 0
6 6 3 6 0
6 6 4 6 0
6 6 5 6 0
6 6 6 6 0
6 6 7 6 32
6 7 0 3 126
6 7 1 6 8
6 7 2 6 8
6 7 3 6 8
6 7 4 6 8
6 7 5 6 8
6 7 6 6 8
6 7 7 3 126
7 0 0 1 126
7 0 1 3 126
7 0 2 6 30
7 0 3 6 30
7 0 4 6 30
7 0 5 6 30
7 0 6 6 30
7 0 7 7 126
7 1 0 3 126
7 2 0 6 66
7 2 1 6 18
7 2 2 6 18
7 2 3 6 18
7 2 4 6 18
7 2 5 6 18
7 2 6 6 18
7 2 7 6 50
7 3 0 5 126
7 3 1 5 126
7 3 2 5 126
7 3 3 9 126
7 3 4 9 126
7 3 5 5 126
7 3 6 5 126
7 3 7 5 126
7 4 0 6 66
7 4 1 6 2
7 4 2 6 2
7 4 3 6 2
7 4 4 9 126
7 4 5 6 2
7 4 6 6 2
7 4 7 6 34
7 5 0 5 126
7 5 1 5 126
7 5 2 5 126
7 5 3 5 126
7 5 4 9 126
7 5 5 5 126
7 5 6 5 126
7 5 7 5 126
7 6 0 3 126
7 6 1 6 2
7 6 2 6 2
7 6 3 6 2
7 6 4 9 126
7 6 5 6 2
7 6 6 6 2
7 6 7 3 126
7 7 0 2 126
7 7 1 3 126
7 7 2 5 126
7 7 3 5 126
7 7 4 5 126
7 7 5 5 126
7 7 6 3 126
7 7 7 4 126

View File

@ -8,6 +8,7 @@ set(SRCS
VoxFormat.h VoxFormat.cpp
QBTFormat.h QBTFormat.cpp
QBFormat.h QBFormat.cpp
QEFFormat.h QEFFormat.cpp
VXMFormat.h VXMFormat.cpp
VXLFormat.h VXLFormat.cpp
MeshCache.h MeshCache.cpp
@ -25,6 +26,7 @@ set(TEST_SRCS
tests/VoxFormatTest.cpp
tests/QBTFormatTest.cpp
tests/QBFormatTest.cpp
tests/QEFFormatTest.cpp
tests/CubFormatTest.cpp
tests/KVXFormatTest.cpp
tests/KV6FormatTest.cpp
@ -34,6 +36,7 @@ set(TEST_SRCS
set(TEST_FILES
tests/qubicle.qb
tests/qubicle.qbt
tests/qubicle.qef
tests/aceofspades.vxl
tests/cc.vxl
tests/test.binvox

View File

@ -0,0 +1,123 @@
/**
* @file
*/
#include "QEFFormat.h"
#include "SDL_stdinc.h"
#include "core/Log.h"
#include "core/GLM.h"
#include "voxel/Voxel.h"
#include <glm/common.hpp>
namespace voxel {
#define wrap(read) \
if (read != 0) { \
Log::error("Could not load qef file: Not enough data in stream " CORE_STRINGIFY(read) " - still %i bytes left (line %i)", (int)stream.remaining(), (int)__LINE__); \
return false; \
}
#define wrapBool(read) \
if (read == false) { \
Log::error("Could not load qef file: Not enough data in stream " CORE_STRINGIFY(read) " - still %i bytes left (line %i)", (int)stream.remaining(), (int)__LINE__); \
return false; \
}
bool QEFFormat::loadGroups(const io::FilePtr &file, VoxelVolumes &volumes) {
if (!(bool)file || !file->exists()) {
Log::error("Could not load qef file: File doesn't exist");
return false;
}
io::FileStream stream(file.get());
char buf[64];
wrapBool(stream.readLine(64, buf))
if (SDL_strcmp(buf, "Qubicle Exchange Format")) {
Log::error("Unexpected magic line: '%s'", buf);
return false;
}
wrapBool(stream.readLine(64, buf))
if (SDL_strcmp(buf, "Version 0.2")) {
Log::error("Unexpected version line: '%s'", buf);
return false;
}
wrapBool(stream.readLine(64, buf))
if (SDL_strcmp(buf, "www.minddesk.com")) {
Log::error("Unexpected url line: '%s'", buf);
return false;
}
int width, height, depth;
wrapBool(stream.readLine(64, buf))
if (SDL_sscanf(buf, "%i %i %i", &width, &depth, &height) != 3) {
Log::error("Failed to parse dimensions");
return false;
}
const glm::ivec3 size(width, height, depth);
if (glm::any(glm::greaterThan(size, glm::ivec3(MaxRegionSize)))) {
Log::warn("Size of matrix exceeds the max allowed value");
return false;
}
if (glm::any(glm::lessThan(size, glm::ivec3(1)))) {
Log::warn("Size of matrix results in empty space");
return false;
}
const voxel::Region region(glm::ivec3(0), glm::ivec3(size) - 1);
if (!region.isValid()) {
Log::error("Invalid region");
return false;
}
int paletteSize;
wrapBool(stream.readLine(64, buf))
if (SDL_sscanf(buf, "%i", &paletteSize) != 1) {
Log::error("Failed to parse palette size");
return false;
}
if (paletteSize > 256) {
Log::error("Max palette size exceeded");
return false;
}
_paletteSize = paletteSize;
for (int i = 0; i < paletteSize; ++i) {
float r, g, b;
wrapBool(stream.readLine(64, buf))
if (SDL_sscanf(buf, "%f %f %f", &r, &g, &b) != 3) {
Log::error("Failed to parse palette color");
return false;
}
_palette.push_back(findClosestIndex(glm::vec4(r, g, b, 1.0f)));
}
voxel::RawVolume* volume = new voxel::RawVolume(region);
volumes.push_back(VoxelVolume(volume, file->name(), true, glm::ivec3(0)));
while (stream.remaining() > 0) {
wrapBool(stream.readLine(64, buf))
int x, y, z, color, vismask;
if (SDL_sscanf(buf, "%i %i %i %i %i", &x, &z, &y, &color, &vismask) != 5) {
Log::error("Failed to parse voxel data line");
return false;
}
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, convertPaletteIndex(color));
volume->setVoxel(x, y, z, voxel);
}
return true;
}
bool QEFFormat::saveGroups(const VoxelVolumes &volumes, const io::FilePtr &file) {
return false;
}
#undef wrap
#undef wrapBool
}

View File

@ -0,0 +1,29 @@
/**
* @file
*/
#pragma once
#include "VoxFileFormat.h"
#include "core/io/FileStream.h"
namespace voxel {
/**
* @brief Qubicle Exchange (QEF)
*
* QEF is a rather old ASCII exchange format originally developed for the unreleased Qubicle Plugin for Maya. It is
* recommended to use the newer and more flexible Qubicle Binary exchange format instead.
*
* @see QBTFormat
* @see QBFormat
*
* http://minddesk.com/learn/article.php?id=23
*/
class QEFFormat : public VoxFileFormat {
public:
bool loadGroups(const io::FilePtr& file, VoxelVolumes& volumes) override;
bool saveGroups(const VoxelVolumes& volumes, const io::FilePtr& file) override;
};
}

View File

@ -0,0 +1,20 @@
/**
* @file
*/
#include "AbstractVoxFormatTest.h"
#include "voxelformat/QEFFormat.h"
#include "voxelformat/Loader.h"
namespace voxel {
class QEFFormatTest: public AbstractVoxFormatTest {
};
TEST_F(QEFFormatTest, testLoad) {
QEFFormat f;
std::unique_ptr<RawVolume> volume(load("qubicle.qef", f));
ASSERT_NE(nullptr, volume) << "Could not load qef file";
}
}