Browse Source

Merge pull request #15114 from capnm/fix-bad-lightmap-crash

Avoid thekla_unwrap crash
Rémi Verschelde 7 years ago
parent
commit
5519481803

+ 7 - 0
modules/thekla_unwrap/register_types.cpp

@@ -28,7 +28,9 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 #include "register_types.h"
+#include "error_macros.h"
 #include "thirdparty/thekla_atlas/thekla/thekla_atlas.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y);
@@ -74,6 +76,11 @@ bool thekla_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
 	delete[] input_mesh.face_array;
 	delete[] input_mesh.vertex_array;
 
+	if (output == NULL) {
+		ERR_PRINT("could not generate atlas output mesh");
+		return false;
+	}
+
 	if (err != Thekla::Atlas_Error_Success) {
 		printf("error with atlas\n");
 	} else {

+ 154 - 0
thirdparty/thekla_atlas/godot-changes.patch

@@ -0,0 +1,154 @@
+diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
+index 5ce452c..11e635d 100644
+--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
++++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp
+@@ -142,9 +142,11 @@ AtlasPacker::AtlasPacker(Atlas * atlas) : m_atlas(atlas), m_bitmap(256, 256)
+ {
+     m_width = 0;
+     m_height = 0;
+-    
+-    m_debug_bitmap.allocate(256, 256);
+-    m_debug_bitmap.fill(Color32(0,0,0,0));
++
++    // -- GODOT start --
++    //m_debug_bitmap.allocate(256, 256);
++    //m_debug_bitmap.fill(Color32(0,0,0,0));
++    // -- GODOT end --
+ }
+ 
+ AtlasPacker::~AtlasPacker()
+@@ -465,7 +467,11 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
+                     nvDebug("origin: %f %f\n", origin.x, origin.y);
+                     nvDebug("majorAxis: %f %f\n", majorAxis.x, majorAxis.y);
+                     nvDebug("minorAxis: %f %f\n", minorAxis.x, minorAxis.y);
+-                    nvDebugBreak();
++                    // -- GODOT start --
++                    //nvDebugBreak();
++                    m_atlas->setFailed();
++                    return;
++                    // -- GODOT end --
+                 }
+                 //nvCheck(tmp.x >= 0 && tmp.y >= 0);
+ 
+@@ -597,8 +603,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
+     m_bitmap.clearAll();
+     if (approximateExtent > m_bitmap.width()) {
+         m_bitmap.resize(approximateExtent, approximateExtent, false);
+-        m_debug_bitmap.resize(approximateExtent, approximateExtent);
+-        m_debug_bitmap.fill(Color32(0,0,0,0));
++        // -- GODOT start --
++        //m_debug_bitmap.resize(approximateExtent, approximateExtent);
++        //m_debug_bitmap.fill(Color32(0,0,0,0));
++        // -- GODOT end --
+     }
+ 
+     
+@@ -680,20 +688,24 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
+         {
+             //nvDebug("Resize bitmap (%d, %d).\n", nextPowerOfTwo(w), nextPowerOfTwo(h));
+             m_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)), false);
+-            m_debug_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)));
++            // -- GODOT start --
++            //m_debug_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)));
++            // -- GODOT end --
+         }
+ 
+         //nvDebug("Add chart at (%d, %d).\n", best_x, best_y);
+ 
+         addChart(&chart_bitmap, w, h, best_x, best_y, best_r, /*debugOutput=*/NULL);
+ 
++        // -- GODOT start --
+         // IC: Output chart again to debug bitmap.
+-        if (chart->isVertexMapped()) {
++        /*if (chart->isVertexMapped()) {
+             addChart(&chart_bitmap, w, h, best_x, best_y, best_r, &m_debug_bitmap);
+         }
+         else {
+             addChart(chart, w, h, best_x, best_y, best_r, &m_debug_bitmap);
+-        }
++        }*/
++        // -- GODOT end --
+ 
+         //float best_angle = 2 * PI * best_r;
+ 
+@@ -842,8 +854,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
+     nvCheck(isAligned(m_width, 4));
+     nvCheck(isAligned(m_height, 4));
+ 
+-    m_debug_bitmap.resize(m_width, m_height);
+-    m_debug_bitmap.setFormat(Image::Format_ARGB);
++    // -- GODOT start --
++    //m_debug_bitmap.resize(m_width, m_height);
++    //m_debug_bitmap.setFormat(Image::Format_ARGB);
++    // -- GODOT end --
+ 
+ #if DEBUG_OUTPUT
+     //outputDebugBitmap("debug_packer_final.tga", m_bitmap, w, h);
+diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
+index 2d305f3..845dbfb 100644
+--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
++++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h
+@@ -48,7 +48,9 @@ namespace nv
+ 
+         Atlas * m_atlas;
+         BitMap m_bitmap;
+-        Image m_debug_bitmap;
++        // -- GODOT start --
++        //Image m_debug_bitmap;
++        // -- GODOT end --
+         RadixSort m_radix;
+ 
+         uint m_width;
+diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
+index d6f0acc..de1953d 100644
+--- a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
++++ b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp
+@@ -2,6 +2,9 @@
+ #include "thekla_atlas.h"
+ 
+ #include <cfloat>
++// -- GODOT start --
++#include <stdio.h>
++// -- GODOT end --
+ 
+ #include "nvmesh/halfedge/Edge.h"
+ #include "nvmesh/halfedge/Mesh.h"
+@@ -112,6 +115,8 @@ static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, con
+     output->index_count = face_count * 3;
+     output->index_array = new int[face_count * 3];
+ 
++    // -- GODOT start --
++    int face_ofs = 0;
+     // Set face indices.
+     for (int f = 0; f < face_count; f++) {
+         uint c = charts->faceChartAt(f);
+@@ -121,14 +126,26 @@ static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, con
+         const Chart * chart = charts->chartAt(c);
+         nvDebugCheck(chart->faceAt(i) == f);
+ 
++        if (i >= chart->chartMesh()->faceCount()) {
++            printf("WARNING: Faces may be missing in the final vertex, which could not be packed\n");
++            continue;
++        }
++
+         const HalfEdge::Face * face = chart->chartMesh()->faceAt(i);
+         const HalfEdge::Edge * edge = face->edge;
+ 
+-        output->index_array[3*f+0] = vertexOffset + edge->vertex->id;
+-        output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id;
+-        output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id;
++        //output->index_array[3*f+0] = vertexOffset + edge->vertex->id;
++        //output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id;
++        //output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id;
++        output->index_array[3 * face_ofs + 0] = vertexOffset + edge->vertex->id;
++        output->index_array[3 * face_ofs + 1] = vertexOffset + edge->next->vertex->id;
++        output->index_array[3 * face_ofs + 2] = vertexOffset + edge->next->next->vertex->id;
++        face_ofs++;
+     }
+ 
++    output->index_count = face_ofs * 3;
++    // -- GODOT end --
++
+     *error = Atlas_Error_Success;
+     output->atlas_width = w;
+     output->atlas_height = h;

+ 5 - 1
thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp

@@ -467,7 +467,11 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned
                     nvDebug("origin: %f %f\n", origin.x, origin.y);
                     nvDebug("majorAxis: %f %f\n", majorAxis.x, majorAxis.y);
                     nvDebug("minorAxis: %f %f\n", minorAxis.x, minorAxis.y);
-                    nvDebugBreak();
+                    // -- GODOT start --
+                    //nvDebugBreak();
+                    m_atlas->setFailed();
+                    return;
+                    // -- GODOT end --
                 }
                 //nvCheck(tmp.x >= 0 && tmp.y >= 0);