ported bobtoolz
[xonotic/netradiant.git] / radiant / patch.cpp
index 80ffe35142058f2a07717ecec9fc926e72d8f1b0..c7b6344f4a469adf22b2f0362acc69b3cbc5c9ac 100644 (file)
@@ -118,7 +118,9 @@ void BezierInterpolate(BezierCurve *pCurve)
   pCurve->crd = vector3_mid(pCurve->left, pCurve->right);
 }
 
-void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList)
+const std::size_t PATCH_MAX_SUBDIVISION_DEPTH = 16;
+
+void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList, std::size_t depth = 0)
 {
   GSList *pLeftList = 0;
   GSList *pRightList = 0;
@@ -146,19 +148,20 @@ void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList)
     }
   }
 
-  if(pLeftList != 0 && pRightList != 0)
+  if(pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH)
   {
     pTree->left = new BezierCurveTree;
     pTree->right = new BezierCurveTree;
-    BezierCurveTree_FromCurveList(pTree->left, pLeftList);
-    BezierCurveTree_FromCurveList(pTree->right, pRightList);
+    BezierCurveTree_FromCurveList(pTree->left, pLeftList, depth + 1);
+    BezierCurveTree_FromCurveList(pTree->right, pRightList, depth + 1);
 
+    for(GSList* l = pLeftList; l != 0; l = g_slist_next(l))
     {
-    GSList *l;
-    for (l = pLeftList; l != 0; l = g_slist_next(l))
       delete (BezierCurve*)l->data;
+    }
 
-    for (l = pRightList; l != 0; l = g_slist_next(l))
+    for(GSList* l = pRightList; l != 0; l = g_slist_next(l))
+    {
       delete (BezierCurve*)l->data;
     }
     
@@ -208,10 +211,54 @@ inline const Colour4b& colour_for_index(std::size_t i, std::size_t width)
   return (i%2 || (i/width)%2) ? colour_inside : colour_corner;
 }
 
-void Patch::UpdateCachedData()
+inline bool float_valid(float f)
+{
+  return f == f;
+}
+
+bool Patch::isValid() const
 {
   if(!m_width || !m_height)
+  {
+    return false;
+  }
+
+  for(const_iterator i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
+  {
+    if(!float_valid((*i).m_vertex.x())
+      || !float_valid((*i).m_vertex.y())
+      || !float_valid((*i).m_vertex.z())
+      || !float_valid((*i).m_texcoord.x())
+      || !float_valid((*i).m_texcoord.y()))
+    {
+      globalErrorStream() << "patch has invalid control points\n";
+      return false;
+    }
+  }
+  return true;
+}
+
+void Patch::UpdateCachedData()
+{
+  m_ctrl_vertices.clear();
+  m_lattice_indices.clear();
+
+  if(!isValid())
+  {
+    m_tess.m_numStrips = 0;
+    m_tess.m_lenStrips = 0;
+    m_tess.m_nArrayHeight = 0;
+    m_tess.m_nArrayWidth = 0;
+    m_tess.m_curveTreeU.resize(0);
+    m_tess.m_curveTreeV.resize(0);
+    m_tess.m_indices.resize(0);
+    m_tess.m_vertices.resize(0);
+    m_tess.m_arrayHeight.resize(0);
+    m_tess.m_arrayWidth.resize(0);
+    m_aabb_local = AABB();
     return;
+  }
+
   BuildTesselationCurves(ROW);
   BuildTesselationCurves(COL);
   BuildVertexArray();
@@ -219,9 +266,6 @@ void Patch::UpdateCachedData()
 
   IndexBuffer ctrl_indices;
 
-  m_ctrl_vertices.clear();
-  m_lattice_indices.clear();
-
   m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
   ctrl_indices.reserve(m_ctrlTransformed.size());
   {
@@ -2424,6 +2468,8 @@ void Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6],
   }
 }
 
+const std::size_t PATCH_MAX_VERTEX_ARRAY = 1048576;
+
 void Patch::BuildVertexArray()
 {
   const std::size_t strideU = 1;