lightmap leak fixes; updated xatlas; ortho shader fixes; (#993)
This commit is contained in:
+18
-6
@@ -249,12 +249,14 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
flipCullingButton.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
flipCullingButton.OnClick([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
wi::unordered_set<MeshComponent*> visited_meshes; // fix double visit (straight mesh + object->mesh)
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
MeshComponent* mesh = get_mesh(scene, x);
|
||||
if (mesh == nullptr)
|
||||
if (mesh == nullptr || visited_meshes.count(mesh) > 0)
|
||||
continue;
|
||||
mesh->FlipCulling();
|
||||
visited_meshes.insert(mesh);
|
||||
}
|
||||
SetEntity(entity, subset);
|
||||
});
|
||||
@@ -266,12 +268,14 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
flipNormalsButton.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
flipNormalsButton.OnClick([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
wi::unordered_set<MeshComponent*> visited_meshes; // fix double visit (straight mesh + object->mesh)
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
MeshComponent* mesh = get_mesh(scene, x);
|
||||
if (mesh == nullptr)
|
||||
if (mesh == nullptr || visited_meshes.count(mesh) > 0)
|
||||
continue;
|
||||
mesh->FlipNormals();
|
||||
visited_meshes.insert(mesh);
|
||||
}
|
||||
SetEntity(entity, subset);
|
||||
});
|
||||
@@ -283,12 +287,14 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
computeNormalsSmoothButton.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
computeNormalsSmoothButton.OnClick([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
wi::unordered_set<MeshComponent*> visited_meshes; // fix double visit (straight mesh + object->mesh)
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
MeshComponent* mesh = get_mesh(scene, x);
|
||||
if (mesh == nullptr)
|
||||
if (mesh == nullptr || visited_meshes.count(mesh) > 0)
|
||||
continue;
|
||||
mesh->ComputeNormals(MeshComponent::COMPUTE_NORMALS_SMOOTH);
|
||||
visited_meshes.insert(mesh);
|
||||
}
|
||||
SetEntity(entity, subset);
|
||||
});
|
||||
@@ -300,12 +306,14 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
computeNormalsHardButton.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
computeNormalsHardButton.OnClick([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
wi::unordered_set<MeshComponent*> visited_meshes; // fix double visit (straight mesh + object->mesh)
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
MeshComponent* mesh = get_mesh(scene, x);
|
||||
if (mesh == nullptr)
|
||||
if (mesh == nullptr || visited_meshes.count(mesh) > 0)
|
||||
continue;
|
||||
mesh->ComputeNormals(MeshComponent::COMPUTE_NORMALS_HARD);
|
||||
visited_meshes.insert(mesh);
|
||||
}
|
||||
SetEntity(entity, subset);
|
||||
});
|
||||
@@ -317,12 +325,14 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
recenterButton.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
recenterButton.OnClick([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
wi::unordered_set<MeshComponent*> visited_meshes; // fix double visit (straight mesh + object->mesh)
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
MeshComponent* mesh = get_mesh(scene, x);
|
||||
if (mesh == nullptr)
|
||||
if (mesh == nullptr || visited_meshes.count(mesh) > 0)
|
||||
continue;
|
||||
mesh->Recenter();
|
||||
visited_meshes.insert(mesh);
|
||||
}
|
||||
});
|
||||
AddWidget(&recenterButton);
|
||||
@@ -333,12 +343,14 @@ void MeshWindow::Create(EditorComponent* _editor)
|
||||
recenterToBottomButton.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
recenterToBottomButton.OnClick([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
wi::unordered_set<MeshComponent*> visited_meshes; // fix double visit (straight mesh + object->mesh)
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
MeshComponent* mesh = get_mesh(scene, x);
|
||||
if (mesh == nullptr)
|
||||
if (mesh == nullptr || visited_meshes.count(mesh) > 0)
|
||||
continue;
|
||||
mesh->RecenterToBottom();
|
||||
visited_meshes.insert(mesh);
|
||||
}
|
||||
});
|
||||
AddWidget(&recenterToBottomButton);
|
||||
|
||||
@@ -84,7 +84,7 @@ static Atlas_Dim GenerateMeshAtlas(MeshComponent& meshcomponent, uint32_t resolu
|
||||
mesh.indexCount = (int)meshcomponent.indices.size();
|
||||
mesh.indexData = meshcomponent.indices.data();
|
||||
mesh.indexFormat = xatlas::IndexFormat::UInt32;
|
||||
xatlas::AddMeshError::Enum error = xatlas::AddMesh(atlas, mesh);
|
||||
xatlas::AddMeshError error = xatlas::AddMesh(atlas, mesh);
|
||||
if (error != xatlas::AddMeshError::Success) {
|
||||
wi::helper::messageBox(xatlas::StringForEnum(error), "Adding mesh to xatlas failed!");
|
||||
return dim;
|
||||
@@ -94,13 +94,15 @@ static Atlas_Dim GenerateMeshAtlas(MeshComponent& meshcomponent, uint32_t resolu
|
||||
// Generate atlas:
|
||||
{
|
||||
xatlas::ChartOptions chartoptions;
|
||||
xatlas::ParameterizeOptions parametrizeoptions;
|
||||
xatlas::PackOptions packoptions;
|
||||
chartoptions.useInputMeshUvs = true;
|
||||
chartoptions.fixWinding = true;
|
||||
|
||||
xatlas::PackOptions packoptions;
|
||||
packoptions.resolution = resolution;
|
||||
packoptions.blockAlign = true;
|
||||
packoptions.padding = 2;
|
||||
|
||||
xatlas::Generate(atlas, chartoptions, parametrizeoptions, packoptions);
|
||||
xatlas::Generate(atlas, chartoptions, packoptions);
|
||||
dim.width = atlas->width;
|
||||
dim.height = atlas->height;
|
||||
|
||||
@@ -543,13 +545,11 @@ void ObjectWindow::Create(EditorComponent* _editor)
|
||||
y += step;
|
||||
|
||||
|
||||
lightmapResolutionSlider.Create(32, 1024, 128, 1024 - 32, "Lightmap resolution: ");
|
||||
lightmapResolutionSlider.Create(32, 8192, 512, 8192 - 32, "Lightmap resolution: ");
|
||||
lightmapResolutionSlider.SetTooltip("Set the approximate resolution for this object's lightmap. This will be packed into the larger global lightmap later.");
|
||||
lightmapResolutionSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
lightmapResolutionSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
lightmapResolutionSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
// unfortunately, we must be pow2 with full float lightmap format, otherwise it could be unlimited (but accumulation blending would suffer then)
|
||||
// or at least for me, downloading the lightmap was glitching out when non-pow 2 and RGBA32_FLOAT format
|
||||
lightmapResolutionSlider.SetValue(float(wi::math::GetNextPowerOfTwo(uint32_t(args.fValue))));
|
||||
});
|
||||
AddWidget(&lightmapResolutionSlider);
|
||||
|
||||
+1976
-2106
File diff suppressed because it is too large
Load Diff
+71
-73
@@ -31,20 +31,18 @@ Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
|
||||
#pragma once
|
||||
#ifndef XATLAS_H
|
||||
#define XATLAS_H
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace xatlas {
|
||||
|
||||
struct ChartType
|
||||
enum class ChartType
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
Planar,
|
||||
Ortho,
|
||||
LSCM,
|
||||
Piecewise,
|
||||
Invalid
|
||||
};
|
||||
Planar,
|
||||
Ortho,
|
||||
LSCM,
|
||||
Piecewise,
|
||||
Invalid
|
||||
};
|
||||
|
||||
// A group of connected faces, belonging to a single atlas.
|
||||
@@ -53,7 +51,7 @@ struct Chart
|
||||
uint32_t *faceArray;
|
||||
uint32_t atlasIndex; // Sub-atlas index.
|
||||
uint32_t faceCount;
|
||||
ChartType::Enum type;
|
||||
ChartType type;
|
||||
uint32_t material;
|
||||
};
|
||||
|
||||
@@ -87,12 +85,12 @@ struct Atlas
|
||||
{
|
||||
uint32_t *image;
|
||||
Mesh *meshes; // The output meshes, corresponding to each AddMesh call.
|
||||
float *utilization; // Normalized atlas texel utilization array. E.g. a value of 0.8 means 20% empty space. atlasCount in length.
|
||||
uint32_t width; // Atlas width in texels.
|
||||
uint32_t height; // Atlas height in texels.
|
||||
uint32_t atlasCount; // Number of sub-atlases. Equal to 0 unless PackOptions resolution is changed from default (0).
|
||||
uint32_t chartCount; // Total number of charts in all meshes.
|
||||
uint32_t meshCount; // Number of output meshes. Equal to the number of times AddMesh was called.
|
||||
float *utilization; // Normalized atlas texel utilization array. E.g. a value of 0.8 means 20% empty space. atlasCount in length.
|
||||
float texelsPerUnit; // Equal to PackOptions texelsPerUnit if texelsPerUnit > 0, otherwise an estimated value to match PackOptions resolution.
|
||||
};
|
||||
|
||||
@@ -101,13 +99,10 @@ Atlas *Create();
|
||||
|
||||
void Destroy(Atlas *atlas);
|
||||
|
||||
struct IndexFormat
|
||||
enum class IndexFormat
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
UInt16,
|
||||
UInt32
|
||||
};
|
||||
UInt16,
|
||||
UInt32
|
||||
};
|
||||
|
||||
// Input mesh declaration.
|
||||
@@ -117,36 +112,43 @@ struct MeshDecl
|
||||
const void *vertexNormalData = nullptr; // optional
|
||||
const void *vertexUvData = nullptr; // optional. The input UVs are provided as a hint to the chart generator.
|
||||
const void *indexData = nullptr; // optional
|
||||
|
||||
// Optional. indexCount / 3 (triangle count) in length.
|
||||
|
||||
// Optional. Must be faceCount in length.
|
||||
// Don't atlas faces set to true. Ignored faces still exist in the output meshes, Vertex uv is set to (0, 0) and Vertex atlasIndex to -1.
|
||||
const bool *faceIgnoreData = nullptr;
|
||||
|
||||
// Optional. Must be faceCount in length.
|
||||
// Only faces with the same material will be assigned to the same chart.
|
||||
const uint32_t *faceMaterialData = nullptr;
|
||||
|
||||
// Optional. Must be faceCount in length.
|
||||
// Polygon / n-gon support. Faces are assumed to be triangles if this is null.
|
||||
const uint8_t *faceVertexCount = nullptr;
|
||||
|
||||
uint32_t vertexCount = 0;
|
||||
uint32_t vertexPositionStride = 0;
|
||||
uint32_t vertexNormalStride = 0; // optional
|
||||
uint32_t vertexUvStride = 0; // optional
|
||||
uint32_t indexCount = 0;
|
||||
int32_t indexOffset = 0; // optional. Add this offset to all indices.
|
||||
IndexFormat::Enum indexFormat = IndexFormat::UInt16;
|
||||
uint32_t faceCount = 0; // Optional if faceVertexCount is null. Otherwise assumed to be indexCount / 3.
|
||||
IndexFormat indexFormat = IndexFormat::UInt16;
|
||||
|
||||
// Vertex positions within epsilon distance of each other are considered colocal.
|
||||
float epsilon = 1.192092896e-07F;
|
||||
};
|
||||
|
||||
struct AddMeshError
|
||||
enum class AddMeshError
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
Success, // No error.
|
||||
Error, // Unspecified error.
|
||||
IndexOutOfRange, // An index is >= MeshDecl vertexCount.
|
||||
InvalidIndexCount // Not evenly divisible by 3 - expecting triangles.
|
||||
};
|
||||
Success, // No error.
|
||||
Error, // Unspecified error.
|
||||
IndexOutOfRange, // An index is >= MeshDecl vertexCount.
|
||||
InvalidFaceVertexCount, // Must be >= 3.
|
||||
InvalidIndexCount // Not evenly divisible by 3 - expecting triangles.
|
||||
};
|
||||
|
||||
// Add a mesh to the atlas. MeshDecl data is copied, so it can be freed after AddMesh returns.
|
||||
AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0);
|
||||
AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0);
|
||||
|
||||
// Wait for AddMesh async processing to finish. ComputeCharts / Generate call this internally.
|
||||
void AddMeshJoin(Atlas *atlas);
|
||||
@@ -155,19 +157,23 @@ struct UvMeshDecl
|
||||
{
|
||||
const void *vertexUvData = nullptr;
|
||||
const void *indexData = nullptr; // optional
|
||||
const uint32_t *faceMaterialData = nullptr; // Optional. Faces with different materials won't be assigned to the same chart. Must be indexCount / 3 in length.
|
||||
const uint32_t *faceMaterialData = nullptr; // Optional. Overlapping UVs should be assigned a different material. Must be indexCount / 3 in length.
|
||||
uint32_t vertexCount = 0;
|
||||
uint32_t vertexStride = 0;
|
||||
uint32_t indexCount = 0;
|
||||
int32_t indexOffset = 0; // optional. Add this offset to all indices.
|
||||
IndexFormat::Enum indexFormat = IndexFormat::UInt16;
|
||||
bool rotateCharts = true;
|
||||
IndexFormat indexFormat = IndexFormat::UInt16;
|
||||
};
|
||||
|
||||
AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl);
|
||||
AddMeshError AddUvMesh(Atlas *atlas, const UvMeshDecl &decl);
|
||||
|
||||
// Custom parameterization function. texcoords initial values are an orthogonal parameterization.
|
||||
typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount);
|
||||
|
||||
struct ChartOptions
|
||||
{
|
||||
ParameterizeFunc paramFunc = nullptr;
|
||||
|
||||
float maxChartArea = 0.0f; // Don't grow charts to be larger than this. 0 means no limit.
|
||||
float maxBoundaryLength = 0.0f; // Don't grow charts to have a longer boundary than this. 0 means no limit.
|
||||
|
||||
@@ -180,38 +186,16 @@ struct ChartOptions
|
||||
|
||||
float maxCost = 2.0f; // If total of all metrics * weights > maxCost, don't grow chart. Lower values result in more charts.
|
||||
uint32_t maxIterations = 1; // Number of iterations of the chart growing and seeding phases. Higher values result in better charts.
|
||||
|
||||
bool useInputMeshUvs = false; // Use MeshDecl::vertexUvData for charts.
|
||||
bool fixWinding = false; // Enforce consistent texture coordinate winding.
|
||||
};
|
||||
|
||||
// Call after all AddMesh calls. Can be called multiple times to recompute charts with different options.
|
||||
void ComputeCharts(Atlas *atlas, ChartOptions options = ChartOptions());
|
||||
|
||||
// Custom parameterization function. texcoords initial values are an orthogonal parameterization.
|
||||
typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount);
|
||||
|
||||
struct ParameterizeOptions
|
||||
{
|
||||
ParameterizeFunc func = nullptr;
|
||||
bool closeHoles = true; // If the custom parameterization function works with multiple boundaries, this can be set to false to improve performance.
|
||||
bool fixTJunctions = true; // If meshes don't have T-junctions, this can be set to false to improve performance.
|
||||
};
|
||||
|
||||
// Call after ComputeCharts. Can be called multiple times to re-parameterize charts with a different ParameterizeFunc.
|
||||
void ParameterizeCharts(Atlas *atlas, ParameterizeOptions options = ParameterizeOptions());
|
||||
|
||||
struct PackOptions
|
||||
{
|
||||
// Leave space around charts for texels that would be sampled by bilinear filtering.
|
||||
bool bilinear = true;
|
||||
|
||||
// Align charts to 4x4 blocks. Also improves packing speed, since there are fewer possible chart locations to consider.
|
||||
bool blockAlign = false;
|
||||
|
||||
// Slower, but gives the best result. If false, use random chart placement.
|
||||
bool bruteForce = false;
|
||||
|
||||
// Create Atlas::image
|
||||
bool createImage = false;
|
||||
|
||||
// Charts larger than this will be scaled down. 0 means no limit.
|
||||
uint32_t maxChartSize = 0;
|
||||
|
||||
@@ -227,29 +211,43 @@ struct PackOptions
|
||||
// If not 0, and texelsPerUnit is not 0, generate one or more atlases with that exact resolution.
|
||||
// If not 0, and texelsPerUnit is 0, texelsPerUnit is estimated to approximately match the resolution.
|
||||
uint32_t resolution = 0;
|
||||
|
||||
// Leave space around charts for texels that would be sampled by bilinear filtering.
|
||||
bool bilinear = true;
|
||||
|
||||
// Align charts to 4x4 blocks. Also improves packing speed, since there are fewer possible chart locations to consider.
|
||||
bool blockAlign = false;
|
||||
|
||||
// Slower, but gives the best result. If false, use random chart placement.
|
||||
bool bruteForce = false;
|
||||
|
||||
// Create Atlas::image
|
||||
bool createImage = false;
|
||||
|
||||
// Rotate charts to the axis of their convex hull.
|
||||
bool rotateChartsToAxis = true;
|
||||
|
||||
// Rotate charts to improve packing.
|
||||
bool rotateCharts = true;
|
||||
};
|
||||
|
||||
// Call after ParameterizeCharts. Can be called multiple times to re-pack charts with different options.
|
||||
// Call after ComputeCharts. Can be called multiple times to re-pack charts with different options.
|
||||
void PackCharts(Atlas *atlas, PackOptions packOptions = PackOptions());
|
||||
|
||||
// Equivalent to calling ComputeCharts, ParameterizeCharts and PackCharts in sequence. Can be called multiple times to regenerate with different options.
|
||||
void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), ParameterizeOptions parameterizeOptions = ParameterizeOptions(), PackOptions packOptions = PackOptions());
|
||||
// Equivalent to calling ComputeCharts and PackCharts in sequence. Can be called multiple times to regenerate with different options.
|
||||
void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), PackOptions packOptions = PackOptions());
|
||||
|
||||
// Progress tracking.
|
||||
struct ProgressCategory
|
||||
enum class ProgressCategory
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
AddMesh,
|
||||
ComputeCharts,
|
||||
ParameterizeCharts,
|
||||
PackCharts,
|
||||
BuildOutputMeshes
|
||||
};
|
||||
AddMesh,
|
||||
ComputeCharts,
|
||||
PackCharts,
|
||||
BuildOutputMeshes
|
||||
};
|
||||
|
||||
// May be called from any thread. Return false to cancel.
|
||||
typedef bool (*ProgressFunc)(ProgressCategory::Enum category, int progress, void *userData);
|
||||
typedef bool (*ProgressFunc)(ProgressCategory category, int progress, void *userData);
|
||||
|
||||
void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc = nullptr, void *progressUserData = nullptr);
|
||||
|
||||
@@ -263,8 +261,8 @@ typedef int (*PrintFunc)(const char *, ...);
|
||||
void SetPrint(PrintFunc print, bool verbose);
|
||||
|
||||
// Helper functions for error messages.
|
||||
const char *StringForEnum(AddMeshError::Enum error);
|
||||
const char *StringForEnum(ProgressCategory::Enum category);
|
||||
const char *StringForEnum(AddMeshError error);
|
||||
const char *StringForEnum(ProgressCategory category);
|
||||
|
||||
} // namespace xatlas
|
||||
|
||||
|
||||
Reference in New Issue
Block a user