Commit d7c31bb2 authored by Johannes Braun's avatar Johannes Braun
Browse files

Finished LS generation

parent 62cdd5c6
......@@ -71,8 +71,9 @@ void main()
vec4 position = hit__getFromBarycentric(line.nearest.barycentric, triangle, position);
gl_Position = u_view_projection * position;
color = vec4(0, 1, 0, 1);
last_position = position;
color = vec4(0, 1, 0, 1);
color.b = (line.begin.face) / 6.f;
EmitVertex();
}
......
......@@ -3,9 +3,6 @@
#include <advanced/IntersectionTests.h>
#include <advanced/linespace/LineSpaceMaskGenerator.h>
#include <advanced/linespace/LineSpaceMath.h>
#include <advanced/tracer/RayGenerator.h>
#include <advanced/tracer/Raytracer.h>
......
......@@ -2,7 +2,7 @@
#include <engine/graphics/ImageTexture2DMultisample.h>
#include <components/Rotator.h>
#include <advanced/linespace/LineSpaceMath.h>
#include <linespace/LineSpace.h>
namespace glare
{
......@@ -47,7 +47,7 @@ namespace glare
//Create a skybox from cube map.
m_skybox = std::make_shared<core::Skybox>(core::Skybox::collectFilesFrom(core::asset("/textures/ryfjallet/")));
initializeScene(core::asset("/meshes/scenery/simple_flat_box.dae"), 1.f);
initializeScene(core::asset("/meshes/scenery/floored_bunny.dae"), 1.f);
initializeRenderRequirements();
initializeAdvanced();
initializeGUI();
......@@ -70,20 +70,15 @@ namespace glare
unsigned line_mesh_id = 0;
const auto &mesh_collector = m_collector->meshCollectors().at(line_mesh_id);
Log_Info << "Size of line: " << sizeof(advanced::lsmath::Line);
std::vector<advanced::lsmath::Line> lines = advanced::lsmath::generateLines(*mesh_collector, 32);
int ls_resolution = 5;
ls::LineSpace linespace(*mesh_collector, ls_resolution);
std::vector<std::shared_ptr<core::Shader>> shaders = {
std::make_shared<core::Shader>(gl::ShaderType::eVertex, "/linespace/visualize/lines.vert"),
std::make_shared<core::Shader>(gl::ShaderType::eGeometry, "/linespace/visualize/lines.geom"),
std::make_shared<core::Shader>(gl::ShaderType::eFragment, "/linespace/visualize/lines.frag")
};
std::unique_ptr<core::ShaderProgram> lines_program = std::make_unique<core::ShaderProgram>(shaders);
core::Buffer<gl::BufferType::eShaderStorage> line_buffer;
line_buffer.setData(lines, gl::BufferUsage::eDynamicRead);
std::unique_ptr<core::ShaderProgram> lines_program = std::make_unique<core::ShaderProgram>(shaders);
core::VertexArray lines_vao;
#endif
......@@ -124,22 +119,27 @@ namespace glare
{
m_collector->collect();
lines_program->use();
lines_program->updateStorageBuffer("mesh_buffer", m_collector->meshBuffer());
lines_program->updateStorageBuffer("line_buffer", line_buffer);
static bool u_full_ls = true;
ImGui::Begin("LineSpace");
ImGui::Checkbox("Show full LS", &u_full_ls);
ImGui::DragInt("Max. Subdivision", &ls_resolution);
if (ImGui::Button("Rebuild with Settings")) {
linespace.generate(*mesh_collector, ls_resolution);
}
ImGui::End();
lines_program->use();
lines_program->updateStorageBuffer("mesh_buffer", m_collector->meshBuffer());
lines_program->updateStorageBuffer("line_buffer", linespace.lineBuffer());
lines_program->updateUniformInt("u_full_ls", int(u_full_ls));
lines_program->updateUniformUInt("u_mesh", line_mesh_id);
lines_program->updateUniformUInt("u_triangle_count", unsigned(mesh_collector->triangles().size()));
lines_program->updateUniformMatrix("u_view_projection", core::EngineState::main_camera->getViewProjection());
lines_vao.draw(gl::PrimitiveType::ePoints, lines.size());
lines_vao.draw(gl::PrimitiveType::ePoints, linespace.lines().size());
}
break;
case AppRenderState::eRaytrace:
......@@ -205,7 +205,7 @@ namespace glare
{
Log_Info << node->name();
std::string name = "#Cylinder-mesh";
std::string name = "#bun_zipper_res2-mesh";
if (auto&& mesh = node->getComponent<core::MeshRenderer>())
{
if (mesh->getOwner()->name() == name) {
......
#include <glare_core>
#include <glare_advanced>
#include <glare_io>
using namespace glare;
int main(int argc, char* argv[])
{
io::Arguments arguments(argc, argv);
std::string mask_asset_path = arguments.get("o", 0, std::string(""));
advanced::LineSpaceMaskMode mask_mode = arguments.has("ns") ? advanced::LineSpaceMaskMode::eNonSymmetrical : advanced::LineSpaceMaskMode::eSymmetrical;
unsigned mask_resolution_min = arguments.get("r", 0, 1);
unsigned mask_resolution_max = arguments.get("r", 1, 16);
bool check_after = arguments.get("check", 0, false);
advanced::LineSpaceMaskGenerator::generate(mask_mode, math::Range<unsigned>(mask_resolution_min, mask_resolution_max), mask_asset_path, check_after);
quitPromptDefault(0);
return 0;
}
\ No newline at end of file
#include "LineSpaceMaskGenerator.h"
#include <engine/Log.h>
#include <engine/Time.h>
#include <set>
#include <fstream>
#include <io/AlignedCompress.h>
namespace glare
{
namespace advanced
{
LineSpaceHelper::LineSpaceHelper(size_t resolution)
{
m_resolution = resolution;
m_resolution2 = m_resolution * m_resolution;
m_resolution2_6 = 6 * m_resolution2;
m_face_mirrored = { 3, 4, 5, 0, 1, 2 };
m_face_dim_axis_mirrored = {
{-1, 0, 1},
{0, -1, 1},
{0, 1, -1},
{-1, 0, 1},
{0, -1, 1},
{0, 1, -1}
};
}
void LineSpaceHelper::getDimensionFromShaftNum(int num, int &face, int &dimA, int &dimB) const
{
face = int(num / m_resolution2);
dimB = int((num % m_resolution2) / m_resolution);
dimA = int(num % m_resolution);
}
void LineSpaceHelper::getDimensionsFromShaftNum(int num, int &sface, int &sdimA, int &sdimB, int &eface, int &edimA, int &edimB) const
{
getDimensionFromShaftNum(int(num / m_resolution2_6), sface, sdimA, sdimB);
getDimensionFromShaftNum(int(num % m_resolution2_6), eface, edimA, edimB);
}
int LineSpaceHelper::getShaftNumFromDimension(int face, int dimA, int dimB) const
{
return int(face * m_resolution2 + dimB * m_resolution + dimA);
}
int LineSpaceHelper::getShaftNumFromDimensions(int sface, int sdimA, int sdimB, int eface, int edimA, int edimB) const
{
return int(getShaftNumFromDimension(sface, sdimA, sdimB) * m_resolution2_6 + getShaftNumFromDimension(eface, edimA, edimB));
}
void LineSpaceHelper::mirrorDimension(int &face, int &dimA, int &dimB, int axis)
{
if ((axis == face) || (axis == m_face_mirrored[face]))
face = m_face_mirrored[face];
else
{
const int mirrorAxis = m_face_dim_axis_mirrored[face][axis];
if (mirrorAxis == 0) dimA = int(m_resolution - dimA - 1);
if (mirrorAxis == 1) dimB = int(m_resolution - dimB - 1);
}
}
std::ofstream LineSpaceMaskIO::createFile(fs::path path, uint32_t num_sets)
{
std::ofstream file(path, std::ios::out | std::ios::binary);
file.write(reinterpret_cast<char*>(&num_sets), sizeof(uint32_t));
return file;
}
void LineSpaceMaskIO::writeNonSymmetrical(fs::path path, const mask_t& mask, uint32_t resolution)
{
Log_Info << "Starting to write binary mask file...";
glare::core::ClockS clock;
auto file = createFile(path, uint32_t(mask.size()));
for (const auto &line : mask)
io::AlignedCompress::writeCompress(file, line);
file.close();
Log_Info << "Finished writing binary mask file to \"" << path
<< "\" in " << clock.time() << " seconds.";
}
void LineSpaceMaskIO::writeSymmetrical(fs::path path, const mask_t& mask, uint32_t resolution)
{
Log_Info << "Starting to write binary mask file...";
glare::core::ClockS clock;
auto file = createFile(path, uint32_t(mask.size()));
file.write(reinterpret_cast<char*>(&resolution), sizeof(uint32_t));
unsigned int n2 = (resolution + 1) / 2;
for (unsigned int z = 0; z < n2; z++)
for (unsigned int y = 0; y < n2; y++)
for (unsigned int x = 0; x < n2; x++)
io::AlignedCompress::writeCompress(file, mask[z*resolution*resolution + y*resolution + x]);
file.close();
Log_Info << "Finished writing binary mask file to \"" << path
<< "\" in " << clock.time() << " seconds.";
}
void LineSpaceMaskIO::save(fs::path path, const mask_t& mask, uint32_t resolution)
{
fs::create_directories(path.parent_path());
if (path.extension() == LineSpaceMaskExtension.at(LineSpaceMaskMode::eNonSymmetrical))
{
writeNonSymmetrical(path, mask, resolution);
}
else if (path.extension() == LineSpaceMaskExtension.at(LineSpaceMaskMode::eSymmetrical))
{
writeSymmetrical(path, mask, resolution);
}
else
{
Log_Error << "Unsupported file format: " + path.extension().string();
}
}
mask_t LineSpaceMaskIO::readSymmetrical(fs::path path)
{
Log_Info << "Starting to read binary symmetric mask file...";
core::ClockS clock;
//do read
int numSets, n;
std::ifstream file(path, std::ios::in | std::ios::binary);
file.read(reinterpret_cast<char*>(&numSets), sizeof(uint32_t));
file.read(reinterpret_cast<char*>(&n), sizeof(uint32_t));
mask_t result;
result.resize(numSets);
LineSpaceHelper helper(n);
unsigned half_n = (n + 1) / 2;
int start_face, start_dimension_a, start_dimension_b;
int end_face, end_dimension_a, end_dimension_b;
unsigned n_minus_one = n - 1;
for (unsigned z = 0; z < half_n; z++)
for (unsigned y = 0; y < half_n; y++)
for (unsigned x = 0; x < half_n; x++)
{
std::vector<uint32_t> wide_line = io::AlignedCompress::readUncompress(file);
for (uint32_t t : wide_line)
{
result[z*n*n + y*n + x].push_back(t);
for (unsigned int i = 1; i < 8; i++)
{
unsigned x2 = (i & 0x1) ? n_minus_one - x : x;
unsigned y2 = (i & 0x2) ? n_minus_one - y : y;
unsigned z2 = (i & 0x4) ? n_minus_one - z : z;
if ((x == x2) && (y == y2) && (z == z2)) continue;
if (((n_minus_one - x) == x) && (i & 0x1)) continue;
if (((n_minus_one - y) == y) && (i & 0x2)) continue;
if (((n_minus_one - z) == z) && (i & 0x4)) continue;
size_t index = z2*n*n + y2*n + x2;
helper.getDimensionsFromShaftNum(t, start_face, start_dimension_a, start_dimension_b, end_face, end_dimension_a, end_dimension_b);
if (i & 0x1)
{
helper.mirrorDimension(start_face, start_dimension_a, start_dimension_b, 0);
helper.mirrorDimension(end_face, end_dimension_a, end_dimension_b, 0);
}
if (i & 0x2)
{
helper.mirrorDimension(start_face, start_dimension_a, start_dimension_b, 1);
helper.mirrorDimension(end_face, end_dimension_a, end_dimension_b, 1);
}
if (i & 0x4)
{
helper.mirrorDimension(start_face, start_dimension_a, start_dimension_b, 2);
helper.mirrorDimension(end_face, end_dimension_a, end_dimension_b, 2);
}
int shaft = helper.getShaftNumFromDimensions(start_face, start_dimension_a, start_dimension_b, end_face, end_dimension_a, end_dimension_b);
result[index].push_back(shaft);
}
}
}
file.close();
Log_Info << "Finished reading binary mask file of \"" << path
<< "\" in " << clock.time() << " seconds.";
return result;
}
mask_t LineSpaceMaskIO::readNonSymmetrical(fs::path path)
{
Log_Info << "Starting to read binary mask file...";
core::ClockS clock;
//do read
int numSets;
std::ifstream file(path, std::ios::in | std::ios::binary);
file.read(reinterpret_cast<char*>(&numSets), sizeof(uint32_t));
std::vector<std::vector<uint32_t>> result;
result.reserve(numSets);
for (int i = 0; i < numSets; i++)
{
result.push_back(io::AlignedCompress::readUncompress(file));
}
file.close();
Log_Info << "Finished reading binary mask file of \"" << path
<< "\" in " << clock.time() << " seconds.";
return result;
}
mask_t LineSpaceMaskIO::load(fs::path path)
{
if (path.extension() == LineSpaceMaskExtension.at(LineSpaceMaskMode::eNonSymmetrical))
{
return readNonSymmetrical(path);
}
if (path.extension() == LineSpaceMaskExtension.at(LineSpaceMaskMode::eSymmetrical))
{
return readSymmetrical(path);
}
Log_Error << "Unsupported file format: " + path.extension().string();
return mask_t(0);
}
void LineSpaceMaskGenerator::generate(LineSpaceMaskMode mode, math::Range<unsigned> resolution_range, fs::path target_directory, bool check_mask)
{
glm::vec3 face_tangents[6][2];
fillTangents(face_tangents);
if(target_directory.empty())
{
target_directory = LineSpaceMaskPath.at(mode);
}
for (unsigned resolution = resolution_range.first; resolution <= resolution_range.last; resolution++)
{
Log_Info << "Generating mask for N=" << resolution;
const int resolution_pow2 = resolution * resolution;
const int resolution_pow3 = resolution_pow2 * resolution;
const int maxIndex = resolution - 1;
mask_t mask(resolution_pow3);
glm::vec3 face_origins[6];
fillOrigins(face_origins, float(resolution));
//To save everyone from 10 quadrillion indented for-loops, the start and end faces are packed into one counter type, as well as the Face a and b Dimensions for each face.
//See LineSpaceMaskGenerator.h and look for Faces and FaceDimensions structs.
//
//As for Faces: Checks for zero-equality and start-end-equality included.
for (Faces faces; faces.inRange(); ++faces) {
for (FaceDimensions start_face_dimensions(0, 0, resolution); start_face_dimensions.inRange(); ++start_face_dimensions) {
int start_index = arrayFaceIndex(faces.start) * resolution_pow2 + start_face_dimensions.b * resolution + start_face_dimensions.a;
glm::vec3 start_corners[4];
getCorners(faces.start, start_face_dimensions, face_origins, face_tangents, start_corners);
for (FaceDimensions end_face_dimensions(0, 0, resolution); end_face_dimensions.inRange(); ++end_face_dimensions) {
int end_index = arrayFaceIndex(faces.end) * resolution_pow2 + end_face_dimensions.b * resolution + end_face_dimensions.a;
glm::vec3 end_corners[4];
getCorners(faces.end, end_face_dimensions, face_origins, face_tangents, end_corners);
//Now, we can trace the shaft
// from faces.start at dimension [start_face_dimension.a, start_face_dimension.b]
// to faces.end at dimension [end_face_dimensions.a, end_face_dimensions.b]
//Check voxels for each ray from any start corner to any end corner.
for (int startSample = 0; startSample < 4; startSample++) {
for (int endSample = 0; endSample < 4; endSample++) {
glm::vec3 direction = end_corners[endSample] - start_corners[startSample];
int stepX = ((1.f / direction.x) >= 0) ? 1 : -1;
int stepY = ((1.f / direction.y) >= 0) ? 1 : -1;
int stepZ = ((1.f / direction.z) >= 0) ? 1 : -1;
float distance = float(direction.length());
float deltaX = distance / (direction.x) * stepX;
float deltaY = distance / (direction.y) * stepY;
float deltaZ = distance / (direction.z) * stepZ;
int posX = 0, posY = 0, posZ = 0;
switch (faces.start) {
case 1:
posX = 0;
posY = start_face_dimensions.a;
posZ = start_face_dimensions.b;
break;
case -1:
posX = maxIndex;
posY = start_face_dimensions.a;
posZ = start_face_dimensions.b;
break;
case 2:
posX = start_face_dimensions.a;
posY = 0;
posZ = start_face_dimensions.b;
break;
case -2:
posX = start_face_dimensions.a;
posY = maxIndex;
posZ = start_face_dimensions.b;
break;
case 3:
posX = start_face_dimensions.a;
posY = start_face_dimensions.b;
posZ = 0;
break;
case -3:
posX = start_face_dimensions.a;
posY = start_face_dimensions.b;
posZ = maxIndex;
break;
default: break;
}
float nextX, nextY, nextZ;
if (glm::abs(faces.start) == 1) {
nextX = deltaX;
}
else {
if (stepX < 0) {
nextX = (start_corners[startSample].x - int(start_corners[startSample].x)) * deltaX;
}
else {
nextX = (1 - (start_corners[startSample].x - int(start_corners[startSample].x))) * deltaX;
}
}
if (glm::abs(faces.start) == 2) {
nextY = deltaY;
}
else {
if (stepY < 0) {
nextY = (start_corners[startSample].y - int(start_corners[startSample].y)) * deltaY;
}
else {
nextY = (1 - (start_corners[startSample].y - int(start_corners[startSample].y))) * deltaY;
}
}
if (glm::abs(faces.start) == 3) {
nextZ = deltaZ;
}
else {
if (stepZ < 0) {
nextZ = (start_corners[startSample].z - int(start_corners[startSample].z)) * deltaZ;
}
else {
nextZ = (1 - (start_corners[startSample].z - int(start_corners[startSample].z))) * deltaZ;
}
}
while (true) {
int vI = posZ * resolution_pow2 + posY * resolution + posX;
int val = start_index * 6 * resolution_pow2 + end_index;
if ((mask[vI].empty()) || (mask[vI].back() != val))
mask[vI].push_back(val);
if (nextX < nextY) {
if (nextX < nextZ) {
nextX += deltaX;
posX += stepX;
if ((posX < 0) || (posX > maxIndex)) {
break;
}
}
else {
nextZ += deltaZ;
posZ += stepZ;
if ((posZ < 0) || (posZ > maxIndex)) {
break;
}
}
}
else {
if (nextY < nextZ) {
nextY += deltaY;
posY += stepY;
if ((posY < 0) || (posY > maxIndex)) {
break;
}
}
else {
nextZ += deltaZ;
posZ += stepZ;
if ((posZ < 0) || (posZ > maxIndex)) {
break;
}
}
}
}
}
}
}
}
}
fs::path path = target_directory / fs::path("mask_" + std::to_string(resolution) + extension(mode));
LineSpaceMaskIO::save(path, mask, resolution);
if (check_mask) {
checkMask(mask, path);
}
}
}
void LineSpaceMaskGenerator::checkMask(const mask_t &mask, fs::path path)
{
bool success = true;
mask_t compare = LineSpaceMaskIO::load(path);
if (mask.size() != compare.size())
{
success = false;
Log_Error << "Mask check failed. Sizes not equal.";
}
for (unsigned int i = 0; i < mask.size(); i++)
if (mask[i].size() != compare[i].size())
{
success = false;
Log_Error << "Mask check failed in special sizes " << i << " - mask: " << mask[i].size() <<
", compare: " << compare[i].size();
}
for (unsigned int i = 0; i < mask.size(); i++)
{
std::set<uint32_t> tempMaskSet(std::begin(mask[i]), std::end(mask[i]));
std::set<uint32_t> tempCompSet(std::begin(compare[i]), std::end(compare[i]));
if ((tempMaskSet.size() != mask[i].size()) || (tempCompSet.size() != compare[i].size()))
{
success = false;
Log_Error << "Mask check failed in set sizes " << i << " - tempMaskSet: " << tempMaskSet.size() <<
", tempCompSet: " << tempCompSet.size() << ", mask: " << compare[i].size();
}
if (tempCompSet != tempMaskSet)
{
success = false;
Log_Error << "Mask check failed in equality: Sets " << i << " not