]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - radiant/patch.cpp
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / radiant / patch.cpp
index 5b2622bb201c78de903a782c344df5f77e99058e..c48cb44a4fa522929e9a53921d2deaa324c227ea 100644 (file)
@@ -1,27 +1,27 @@
 /*
-Copyright (C) 2001-2006, William Joseph.
-All Rights Reserved.
+   Copyright (C) 2001-2006, William Joseph.
+   All Rights Reserved.
 
-This file is part of GtkRadiant.
+   This file is part of GtkRadiant.
 
-GtkRadiant is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-GtkRadiant is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
 
 #include "patch.h"
 
-#include <glib/gslist.h>
+#include <glib.h>
 #include "preferences.h"
 #include "brush_primit.h"
 #include "signal/signal.h"
@@ -29,20 +29,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 Signal0 g_patchTextureChangedCallbacks;
 
-void Patch_addTextureChangedCallback(const SignalHandlerhandler)
+void Patch_addTextureChangedCallback(const SignalHandler &handler)
 {
-  g_patchTextureChangedCallbacks.connectLast(handler);
+    g_patchTextureChangedCallbacks.connectLast(handler);
 }
 
 void Patch_textureChanged()
 {
-  g_patchTextureChangedCallbacks();
+    g_patchTextureChangedCallbacks();
 }
 
 
-ShaderPatchInstance::m_state_selpoint;
-ShaderPatch::m_state_ctrl;
-ShaderPatch::m_state_lattice;
+Shader *PatchInstance::m_state_selpoint;
+Shader *Patch::m_state_ctrl;
+Shader *Patch::m_state_lattice;
 EPatchType Patch::m_type;
 
 
@@ -53,684 +53,652 @@ int g_PatchSubdivideThreshold = 4;
 
 void BezierCurveTree_Delete(BezierCurveTree *pCurve)
 {
-  if(pCurve)
-  {
-    BezierCurveTree_Delete(pCurve->left);
-    BezierCurveTree_Delete(pCurve->right);
-    delete pCurve;
-  }
+    if (pCurve) {
+        BezierCurveTree_Delete(pCurve->left);
+        BezierCurveTree_Delete(pCurve->right);
+        delete pCurve;
+    }
 }
 
 std::size_t BezierCurveTree_Setup(BezierCurveTree *pCurve, std::size_t index, std::size_t stride)
 {
-  if(pCurve)
-  {
-    if(pCurve->left && pCurve->right)
-    {
-      index = BezierCurveTree_Setup(pCurve->left, index, stride);
-      pCurve->index = index*stride;
-      index++;
-      index = BezierCurveTree_Setup(pCurve->right, index, stride);
-    }
-    else
-    {
-      pCurve->index = BEZIERCURVETREE_MAX_INDEX;
+    if (pCurve) {
+        if (pCurve->left && pCurve->right) {
+            index = BezierCurveTree_Setup(pCurve->left, index, stride);
+            pCurve->index = index * stride;
+            index++;
+            index = BezierCurveTree_Setup(pCurve->right, index, stride);
+        } else {
+            pCurve->index = BEZIERCURVETREE_MAX_INDEX;
+        }
     }
-  }
-  
-  return index;
+
+    return index;
 }
 
 bool BezierCurve_IsCurved(BezierCurve *pCurve)
 {
-  Vector3 vTemp(vector3_subtracted(pCurve->right, pCurve->left));
-  Vector3 v1(vector3_subtracted(pCurve->crd, pCurve->left));
-  Vector3 v2(vector3_subtracted(pCurve->right, pCurve->crd));
+    Vector3 vTemp(vector3_subtracted(pCurve->right, pCurve->left));
+    Vector3 v1(vector3_subtracted(pCurve->crd, pCurve->left));
+    Vector3 v2(vector3_subtracted(pCurve->right, pCurve->crd));
 
-  if(vector3_equal(v1, g_vector3_identity) || vector3_equal(vTemp, v1)) // return 0 if 1->2 == 0 or 1->2 == 1->3
-    return false;
+    if (vector3_equal(v1, g_vector3_identity) || vector3_equal(vTemp, v1)) { // return 0 if 1->2 == 0 or 1->2 == 1->3
+        return false;
+    }
 
-  vector3_normalise(v1);
-  vector3_normalise(v2);
-  if(vector3_equal(v1, v2))
-    return false;
-  
-  Vector3 v3(vTemp);
-  const double width = vector3_length(v3);
-  vector3_scale(v3, 1.0 / width);
+    vector3_normalise(v1);
+    vector3_normalise(v2);
+    if (vector3_equal(v1, v2)) {
+        return false;
+    }
 
-  if(vector3_equal(v1, v3) && vector3_equal(v2, v3))
-    return false;
-  
-  const double angle = acos(vector3_dot(v1, v2)) / c_pi;
+    Vector3 v3(vTemp);
+    const double width = vector3_length(v3);
+    vector3_scale(v3, 1.0 / width);
+
+    if (vector3_equal(v1, v3) && vector3_equal(v2, v3)) {
+        return false;
+    }
 
-  const double index = width * angle;
+    const double angle = acos(vector3_dot(v1, v2)) / c_pi;
 
-  if(index > static_cast<double>(g_PatchSubdivideThreshold))
-    return true;
-  return false;
+    const double index = width * angle;
+
+    if (index > static_cast<double>( g_PatchSubdivideThreshold )) {
+        return true;
+    }
+    return false;
 }
 
 void BezierInterpolate(BezierCurve *pCurve)
 {
-  pCurve->left = vector3_mid(pCurve->left, pCurve->crd);
-  pCurve->right = vector3_mid(pCurve->crd, pCurve->right);
-  pCurve->crd = vector3_mid(pCurve->left, pCurve->right);
+    pCurve->left = vector3_mid(pCurve->left, pCurve->crd);
+    pCurve->right = vector3_mid(pCurve->crd, pCurve->right);
+    pCurve->crd = vector3_mid(pCurve->left, pCurve->right);
 }
 
 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;
-  BezierCurve *pCurve, *pLeftCurve, *pRightCurve;
-  bool bSplit = false;
-
-  for (GSList *l = pCurveList; l; l = l->next)
-  {
-    pCurve = (BezierCurve *)(l->data);
-    if(bSplit || BezierCurve_IsCurved(pCurve))
-    {
-      bSplit = true;
-      pLeftCurve = new BezierCurve;
-      pRightCurve = new BezierCurve;
-      pLeftCurve->left = pCurve->left;
-      pRightCurve->right = pCurve->right;
-      BezierInterpolate(pCurve);
-      pLeftCurve->crd = pCurve->left;
-      pRightCurve->crd = pCurve->right;
-      pLeftCurve->right = pCurve->crd;
-      pRightCurve->left = pCurve->crd;
-
-      pLeftList = g_slist_prepend(pLeftList, pLeftCurve);
-      pRightList = g_slist_prepend(pRightList, pRightCurve);
-    }
-  }
-
-  if(pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH)
-  {
-    pTree->left = new BezierCurveTree;
-    pTree->right = new BezierCurveTree;
-    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))
-    {
-      delete (BezierCurve*)l->data;
+    GSList *pLeftList = 0;
+    GSList *pRightList = 0;
+    BezierCurve *pCurve, *pLeftCurve, *pRightCurve;
+    bool bSplit = false;
+
+    for (GSList *l = pCurveList; l; l = l->next) {
+        pCurve = (BezierCurve *) (l->data);
+        if (bSplit || BezierCurve_IsCurved(pCurve)) {
+            bSplit = true;
+            pLeftCurve = new BezierCurve;
+            pRightCurve = new BezierCurve;
+            pLeftCurve->left = pCurve->left;
+            pRightCurve->right = pCurve->right;
+            BezierInterpolate(pCurve);
+            pLeftCurve->crd = pCurve->left;
+            pRightCurve->crd = pCurve->right;
+            pLeftCurve->right = pCurve->crd;
+            pRightCurve->left = pCurve->crd;
+
+            pLeftList = g_slist_prepend(pLeftList, pLeftCurve);
+            pRightList = g_slist_prepend(pRightList, pRightCurve);
+        }
     }
 
-    for(GSList* l = pRightList; l != 0; l = g_slist_next(l))
-    {
-      delete (BezierCurve*)l->data;
+    if (pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH) {
+        pTree->left = new BezierCurveTree;
+        pTree->right = new BezierCurveTree;
+        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)) {
+            delete (BezierCurve *) l->data;
+        }
+
+        for (GSList *l = pRightList; l != 0; l = g_slist_next(l)) {
+            delete (BezierCurve *) l->data;
+        }
+
+        g_slist_free(pLeftList);
+        g_slist_free(pRightList);
+    } else {
+        pTree->left = 0;
+        pTree->right = 0;
     }
-    
-    g_slist_free(pLeftList);
-    g_slist_free(pRightList);
-  }
-  else
-  {
-    pTree->left = 0;
-    pTree->right = 0;
-  }
 }
 
 
 int Patch::m_CycleCapIndex = 0;
 
 
-void Patch::setDims (std::size_t w, std::size_t h)
+void Patch::setDims(std::size_t w, std::size_t h)
 {
-  if((w%2)==0)
-    w -= 1;
-  ASSERT_MESSAGE(w <= MAX_PATCH_WIDTH, "patch too wide");
-  if(w > MAX_PATCH_WIDTH)
-    w = MAX_PATCH_WIDTH;
-  else if(w < MIN_PATCH_WIDTH)
-    w = MIN_PATCH_WIDTH;
-  
-  if((h%2)==0)
-    m_height -= 1;
-  ASSERT_MESSAGE(h <= MAX_PATCH_HEIGHT, "patch too tall");
-  if(h > MAX_PATCH_HEIGHT)
-    h = MAX_PATCH_HEIGHT;
-  else if(h < MIN_PATCH_HEIGHT)
-    h = MIN_PATCH_HEIGHT;
+    if ((w % 2) == 0) {
+        w -= 1;
+    }
+    ASSERT_MESSAGE(w <= MAX_PATCH_WIDTH, "patch too wide");
+    if (w > MAX_PATCH_WIDTH) {
+        w = MAX_PATCH_WIDTH;
+    } else if (w < MIN_PATCH_WIDTH) {
+        w = MIN_PATCH_WIDTH;
+    }
+
+    if ((h % 2) == 0) {
+        m_height -= 1;
+    }
+    ASSERT_MESSAGE(h <= MAX_PATCH_HEIGHT, "patch too tall");
+    if (h > MAX_PATCH_HEIGHT) {
+        h = MAX_PATCH_HEIGHT;
+    } else if (h < MIN_PATCH_HEIGHT) {
+        h = MIN_PATCH_HEIGHT;
+    }
 
-  m_width = w; m_height = h;
+    m_width = w;
+    m_height = h;
 
-  if(m_width * m_height != m_ctrl.size())
-  {
-    m_ctrl.resize(m_width * m_height);
-    onAllocate(m_ctrl.size());
-  }
+    if (m_width * m_height != m_ctrl.size()) {
+        m_ctrl.resize(m_width * m_height);
+        onAllocate(m_ctrl.size());
+    }
 }
 
-inline const Colour4bcolour_for_index(std::size_t i, std::size_t width)
+inline const Colour4b &colour_for_index(std::size_t i, std::size_t width)
 {
-  return (i%2 || (i/width)%2) ? colour_inside : colour_corner;
+    return (i % 2 || (i / width) % 2) ? colour_inside : colour_corner;
 }
 
 inline bool float_valid(float f)
 {
-  return f == 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;
+    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;
+    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();
-  AccumulateBBox();
-
-  IndexBuffer ctrl_indices;
-
-  m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
-  ctrl_indices.reserve(m_ctrlTransformed.size());
-  {
-    UniqueVertexBuffer<PointVertex> inserter(m_ctrl_vertices);
-    for(iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
-    {
-      ctrl_indices.insert(inserter.insert(pointvertex_quantised(PointVertex(reinterpret_cast<const Vertex3f&>((*i).m_vertex), colour_for_index(i - m_ctrlTransformed.begin(), m_width)))));
+    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();
+    AccumulateBBox();
+
+    IndexBuffer ctrl_indices;
+
+    m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
+    ctrl_indices.reserve(m_ctrlTransformed.size());
+    {
+        UniqueVertexBuffer<PointVertex> inserter(m_ctrl_vertices);
+        for (iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i) {
+            ctrl_indices.insert(inserter.insert(pointvertex_quantised(
+                    PointVertex(reinterpret_cast<const Vertex3f &>((*i).m_vertex ),
+                                colour_for_index(i - m_ctrlTransformed.begin(), m_width)))));
+        }
     }
-  }
-  {
-    for(IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i)
     {
-      if(std::size_t(i - ctrl_indices.begin()) % m_width)
-      {
-        m_lattice_indices.insert(*(i - 1));
-        m_lattice_indices.insert(*i);
-      }
-      if(std::size_t(i - ctrl_indices.begin()) >= m_width)
-      {
-        m_lattice_indices.insert(*(i - m_width));
-        m_lattice_indices.insert(*i);
-      }
-    }
-  }
+        for (IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i) {
+            if (std::size_t(i - ctrl_indices.begin()) % m_width) {
+                m_lattice_indices.insert(*(i - 1));
+                m_lattice_indices.insert(*i);
+            }
+            if (std::size_t(i - ctrl_indices.begin()) >= m_width) {
+                m_lattice_indices.insert(*(i - m_width));
+                m_lattice_indices.insert(*i);
+            }
+        }
+    }
 
 #if 0
-  {
-    Array<RenderIndex>::iterator first = m_tess.m_indices.begin();
-    for(std::size_t s=0; s<m_tess.m_numStrips; s++)
-    {
-      Array<RenderIndex>::iterator last = first + m_tess.m_lenStrips;
+                                                                                                                            {
+               Array<RenderIndex>::iterator first = m_tess.m_indices.begin();
+               for ( std::size_t s = 0; s < m_tess.m_numStrips; s++ )
+               {
+                       Array<RenderIndex>::iterator last = first + m_tess.m_lenStrips;
 
-      for(Array<RenderIndex>::iterator i(first); i+2 != last; i += 2)
-      {
-        ArbitraryMeshTriangle_sumTangents(m_tess.m_vertices[*(i+0)], m_tess.m_vertices[*(i+1)], m_tess.m_vertices[*(i+2)]);
-        ArbitraryMeshTriangle_sumTangents(m_tess.m_vertices[*(i+2)], m_tess.m_vertices[*(i+1)], m_tess.m_vertices[*(i+3)]);
-      }
+                       for ( Array<RenderIndex>::iterator i( first ); i + 2 != last; i += 2 )
+                       {
+                               ArbitraryMeshTriangle_sumTangents( m_tess.m_vertices[*( i + 0 )], m_tess.m_vertices[*( i + 1 )], m_tess.m_vertices[*( i + 2 )] );
+                               ArbitraryMeshTriangle_sumTangents( m_tess.m_vertices[*( i + 2 )], m_tess.m_vertices[*( i + 1 )], m_tess.m_vertices[*( i + 3 )] );
+                       }
 
-      first = last;
-    }
+                       first = last;
+               }
 
-    for(Array<ArbitraryMeshVertex>::iterator i = m_tess.m_vertices.begin(); i != m_tess.m_vertices.end(); ++i)
-    {
-      vector3_normalise(reinterpret_cast<Vector3&>((*i).tangent));
-      vector3_normalise(reinterpret_cast<Vector3&>((*i).bitangent));
-    }
-  }
+               for ( Array<ArbitraryMeshVertex>::iterator i = m_tess.m_vertices.begin(); i != m_tess.m_vertices.end(); ++i )
+               {
+                       vector3_normalise( reinterpret_cast<Vector3&>( ( *i ).tangent ) );
+                       vector3_normalise( reinterpret_cast<Vector3&>( ( *i ).bitangent ) );
+               }
+       }
 #endif
 
-  SceneChangeNotify();
+    SceneChangeNotify();
 }
 
 void Patch::InvertMatrix()
 {
-  undoSave();
+    undoSave();
 
-  PatchControlArray_invert(m_ctrl, m_width, m_height);
+    PatchControlArray_invert(m_ctrl, m_width, m_height);
 
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 void Patch::TransposeMatrix()
 {
-  undoSave();
+    undoSave();
+
+    {
+        Array<PatchControl> tmp(m_width * m_height);
+        copy_ctrl(tmp.data(), m_ctrl.data(), m_ctrl.data() + m_width * m_height);
 
-  {
-    Array<PatchControl> tmp(m_width * m_height);
-    copy_ctrl(tmp.data(), m_ctrl.data(), m_ctrl.data() + m_width * m_height);
+        PatchControlIter from = tmp.data();
+        for (std::size_t h = 0; h != m_height; ++h) {
+            PatchControlIter to = m_ctrl.data() + h;
+            for (std::size_t w = 0; w != m_width; ++w, ++from, to += m_height) {
+                *to = *from;
+            }
+        }
+    }
 
-    PatchControlIter from = tmp.data();
-    for(std::size_t h = 0; h != m_height; ++h)
     {
-      PatchControlIter to = m_ctrl.data() + h;
-      for(std::size_t w = 0; w != m_width; ++w, ++from, to += m_height)
-      {
-        *to = *from;
-      }
+        std::size_t tmp = m_width;
+        m_width = m_height;
+        m_height = tmp;
     }
-  }
 
-  {
-    std::size_t tmp = m_width;
-    m_width = m_height;
-    m_height = tmp;
-  }
-   
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 void Patch::Redisperse(EMatrixMajor mt)
 {
-  std::size_t w, h, width, height, row_stride, col_stride;
-  PatchControl* p1, * p2, * p3;
-
-  undoSave();
-
-  switch(mt)
-  {
-  case COL:
-    width = (m_width-1)>>1;
-    height = m_height;
-    col_stride = 1;
-    row_stride = m_width;
-    break;
-  case ROW:
-    width = (m_height-1)>>1;
-    height = m_width;
-    col_stride = m_width;
-    row_stride = 1;
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return;
-  }
-
-  for(h=0;h<height;h++)
-  {
-    p1 = m_ctrl.data()+(h*row_stride);
-    for(w=0;w<width;w++)
-    {
-      p2 = p1+col_stride;
-      p3 = p2+col_stride;
-      p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
-      p1 = p3;
+    std::size_t w, h, width, height, row_stride, col_stride;
+    PatchControl *p1, *p2, *p3;
+
+    undoSave();
+
+    switch (mt) {
+        case COL:
+            width = (m_width - 1) >> 1;
+            height = m_height;
+            col_stride = 1;
+            row_stride = m_width;
+            break;
+        case ROW:
+            width = (m_height - 1) >> 1;
+            height = m_width;
+            col_stride = m_width;
+            row_stride = 1;
+            break;
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return;
+    }
+
+    for (h = 0; h < height; h++) {
+        p1 = m_ctrl.data() + (h * row_stride);
+        for (w = 0; w < width; w++) {
+            p2 = p1 + col_stride;
+            p3 = p2 + col_stride;
+            p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
+            p1 = p3;
+        }
     }
-  }
-  
-  controlPointsChanged();
+
+    controlPointsChanged();
 }
 
 void Patch::Smooth(EMatrixMajor mt)
 {
-  std::size_t w, h, width, height, row_stride, col_stride;
-  bool wrap;
-  PatchControl* p1, * p2, * p3, * p2b;
-
-  undoSave();
-
-  switch(mt)
-  {
-  case COL:
-    width = (m_width-1)>>1;
-    height = m_height;
-    col_stride = 1;
-    row_stride = m_width;
-    break;
-  case ROW:
-    width = (m_height-1)>>1;
-    height = m_width;
-    col_stride = m_width;
-    row_stride = 1;
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return;
-  }
-
-  wrap = true;
-  for(h=0;h<height;h++)
-  {
-       p1 = m_ctrl.data()+(h*row_stride);
-       p2 = p1+(2*width)*col_stride;
-       //globalErrorStream() << "compare " << p1->m_vertex << " and " << p2->m_vertex << "\n";
-       if(vector3_length_squared(vector3_subtracted(p1->m_vertex, p2->m_vertex)) > 1.0)
-       {
-         //globalErrorStream() << "too far\n";
-         wrap = false;
-         break;
-       }
-  }
+    std::size_t w, h, width, height, row_stride, col_stride;
+    bool wrap;
+    PatchControl *p1, *p2, *p3, *p2b;
 
-  for(h=0;h<height;h++)
-  {
-    p1 = m_ctrl.data()+(h*row_stride)+col_stride;
-    for(w=0;w<width-1;w++)
-    {
-      p2 = p1+col_stride;
-      p3 = p2+col_stride;
-      p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
-      p1 = p3;
-    }
-       if(wrap)
-       {
-         p1 = m_ctrl.data()+(h*row_stride)+(2*width-1)*col_stride;
-         p2 = m_ctrl.data()+(h*row_stride);
-         p2b = m_ctrl.data()+(h*row_stride)+(2*width)*col_stride;
-         p3 = m_ctrl.data()+(h*row_stride)+col_stride;
-         p2->m_vertex = p2b->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
-       }
-  }
-  
-  controlPointsChanged();
+    undoSave();
+
+    switch (mt) {
+        case COL:
+            width = (m_width - 1) >> 1;
+            height = m_height;
+            col_stride = 1;
+            row_stride = m_width;
+            break;
+        case ROW:
+            width = (m_height - 1) >> 1;
+            height = m_width;
+            col_stride = m_width;
+            row_stride = 1;
+            break;
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return;
+    }
+
+    wrap = true;
+    for (h = 0; h < height; h++) {
+        p1 = m_ctrl.data() + (h * row_stride);
+        p2 = p1 + (2 * width) * col_stride;
+        //globalErrorStream() << "compare " << p1->m_vertex << " and " << p2->m_vertex << "\n";
+        if (vector3_length_squared(vector3_subtracted(p1->m_vertex, p2->m_vertex)) > 1.0) {
+            //globalErrorStream() << "too far\n";
+            wrap = false;
+            break;
+        }
+    }
+
+    for (h = 0; h < height; h++) {
+        p1 = m_ctrl.data() + (h * row_stride) + col_stride;
+        for (w = 0; w < width - 1; w++) {
+            p2 = p1 + col_stride;
+            p3 = p2 + col_stride;
+            p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
+            p1 = p3;
+        }
+        if (wrap) {
+            p1 = m_ctrl.data() + (h * row_stride) + (2 * width - 1) * col_stride;
+            p2 = m_ctrl.data() + (h * row_stride);
+            p2b = m_ctrl.data() + (h * row_stride) + (2 * width) * col_stride;
+            p3 = m_ctrl.data() + (h * row_stride) + col_stride;
+            p2->m_vertex = p2b->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
+        }
+    }
+
+    controlPointsChanged();
 }
 
 void Patch::InsertRemove(bool bInsert, bool bColumn, bool bFirst)
 {
-  undoSave();
-
-  if(bInsert)
-  {
-    if(bColumn && (m_width + 2 <= MAX_PATCH_WIDTH))
-      InsertPoints(COL, bFirst);
-    else if(m_height + 2 <= MAX_PATCH_HEIGHT)
-      InsertPoints(ROW, bFirst);
-  }
-  else
-  {
-    if(bColumn && (m_width - 2 >= MIN_PATCH_WIDTH))
-      RemovePoints(COL, bFirst);
-    else if(m_height - 2 >= MIN_PATCH_HEIGHT)
-      RemovePoints(ROW, bFirst);
-  }
-
-  controlPointsChanged();
-}
-
-Patch* Patch::MakeCap(Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst)
-{
-  std::size_t i, width, height;
-
-  switch(mt)
-  {
-  case ROW:
-    width = m_width;
-    height = m_height;
-    break;
-  case COL:
-    width = m_height;
-    height = m_width;
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return 0;
-  }
-
-  Array<Vector3> p(width);
-
-  std::size_t nIndex = (bFirst) ? 0 : height-1;
-  if(mt == ROW)
-  {
-    for (i=0; i<width; i++)
-    {
-      p[(bFirst)?i:(width-1)-i] = ctrlAt(nIndex, i).m_vertex;
+    undoSave();
+
+    if (bInsert) {
+        if (bColumn && (m_width + 2 <= MAX_PATCH_WIDTH)) {
+            InsertPoints(COL, bFirst);
+        } else if (m_height + 2 <= MAX_PATCH_HEIGHT) {
+            InsertPoints(ROW, bFirst);
+        }
+    } else {
+        if (bColumn && (m_width - 2 >= MIN_PATCH_WIDTH)) {
+            RemovePoints(COL, bFirst);
+        } else if (m_height - 2 >= MIN_PATCH_HEIGHT) {
+            RemovePoints(ROW, bFirst);
+        }
     }
-  }
-  else
-  {
-    for (i=0; i<width; i++)
-    {
-      p[(bFirst)?i:(width-1)-i] = ctrlAt(i, nIndex).m_vertex;
+
+    controlPointsChanged();
+}
+
+Patch *Patch::MakeCap(Patch *patch, EPatchCap eType, EMatrixMajor mt, bool bFirst)
+{
+    std::size_t i, width, height;
+
+    switch (mt) {
+        case ROW:
+            width = m_width;
+            height = m_height;
+            break;
+        case COL:
+            width = m_height;
+            height = m_width;
+            break;
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return 0;
     }
-  }
 
-  patch->ConstructSeam(eType, p.data(), width);
-  return patch;
+    Array<Vector3> p(width);
+
+    std::size_t nIndex = (bFirst) ? 0 : height - 1;
+    if (mt == ROW) {
+        for (i = 0; i < width; i++) {
+            p[(bFirst) ? i : (width - 1) - i] = ctrlAt(nIndex, i).m_vertex;
+        }
+    } else {
+        for (i = 0; i < width; i++) {
+            p[(bFirst) ? i : (width - 1) - i] = ctrlAt(i, nIndex).m_vertex;
+        }
+    }
+
+    patch->ConstructSeam(eType, p.data(), width);
+    return patch;
 }
 
 void Patch::FlipTexture(int nAxis)
 {
-  undoSave();
+    undoSave();
+
+    for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
+        (*i).m_texcoord[nAxis] = -(*i).m_texcoord[nAxis];
+    }
 
-  for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
-  {
-    (*i).m_texcoord[nAxis] = -(*i).m_texcoord[nAxis];
-  }
-  
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 void Patch::TranslateTexture(float s, float t)
 {
-  undoSave();
+    undoSave();
 
-  s = -1 * s / m_state->getTexture().width;
-  t = t / m_state->getTexture().height;
+    s = -1 * s / m_state->getTexture().width;
+    t = t / m_state->getTexture().height;
 
-  for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
-  {
-    (*i).m_texcoord[0] += s;
-    (*i).m_texcoord[1] += t;
-  }
+    for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
+        (*i).m_texcoord[0] += s;
+        (*i).m_texcoord[1] += t;
+    }
 
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 void Patch::ScaleTexture(float s, float t)
 {
-  undoSave();
+    undoSave();
 
-  for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
-  {
-    (*i).m_texcoord[0] *= s;
-    (*i).m_texcoord[1] *= t;
-  }
+    for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
+        (*i).m_texcoord[0] *= s;
+        (*i).m_texcoord[1] *= t;
+    }
 
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 void Patch::RotateTexture(float angle)
 {
-  undoSave();
+    undoSave();
+
+    const float s = static_cast<float>( sin(degrees_to_radians(angle)));
+    const float c = static_cast<float>( cos(degrees_to_radians(angle)));
 
-  const float s = static_cast<float>(sin(degrees_to_radians(angle)));
-  const float c = static_cast<float>(cos(degrees_to_radians(angle)));
-    
-  for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
-  {
-    const float x = (*i).m_texcoord[0];
-    const float y = (*i).m_texcoord[1];
-    (*i).m_texcoord[0] = (x * c) - (y * s);
-    (*i).m_texcoord[1] = (y * c) + (x * s);
-  }
+    for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
+        const float x = (*i).m_texcoord[0];
+        const float y = (*i).m_texcoord[1];
+        (*i).m_texcoord[0] = (x * c) - (y * s);
+        (*i).m_texcoord[1] = (y * c) + (x * s);
+    }
 
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 
 void Patch::SetTextureRepeat(float s, float t)
 {
-  std::size_t w, h;
-  float si, ti, sc, tc;
-  PatchControl *pDest;
-  
-  undoSave();
+    std::size_t w, h;
+    float si, ti, sc, tc;
+    PatchControl *pDest;
 
-  si = s / (float)(m_width - 1);
-  ti = t / (float)(m_height - 1);
+    undoSave();
 
-  pDest = m_ctrl.data();
-  for (h=0, tc = 0.0f; h<m_height; h++, tc+=ti)
-  {
-    for (w=0, sc = 0.0f; w<m_width; w++, sc+=si) 
-    {
-      pDest->m_texcoord[0] = sc;
-      pDest->m_texcoord[1] = tc;
-      pDest++;
+    si = s / (float) (m_width - 1);
+    ti = t / (float) (m_height - 1);
+
+    pDest = m_ctrl.data();
+    for (h = 0, tc = 0.0f; h < m_height; h++, tc += ti) {
+        for (w = 0, sc = 0.0f; w < m_width; w++, sc += si) {
+            pDest->m_texcoord[0] = sc;
+            pDest->m_texcoord[1] = tc;
+            pDest++;
+        }
     }
-  }
 
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 /*
-void Patch::SetTextureInfo(texdef_t *pt)
-{
-  if(pt->getShift()[0] || pt->getShift()[1])
+   void Patch::SetTextureInfo(texdef_t *pt)
+   {
+   if(pt->getShift()[0] || pt->getShift()[1])
     TranslateTexture (pt->getShift()[0], pt->getShift()[1]);
-  else if(pt->getScale()[0] || pt->getScale()[1])
-  {
+   else if(pt->getScale()[0] || pt->getScale()[1])
+   {
     if(pt->getScale()[0] == 0.0f) pt->setScale(0, 1.0f);
     if(pt->getScale()[1] == 0.0f) pt->setScale(1, 1.0f);
     ScaleTexture (pt->getScale()[0], pt->getScale()[1]);
-  }
-  else if(pt->rotate)
+   }
+   else if(pt->rotate)
     RotateTexture (pt->rotate);
-}
-*/
+   }
+ */
 
-inline int texture_axis(const Vector3normal)
+inline int texture_axis(const Vector3 &normal)
 {
-  // axis dominance order: Z, X, Y
-  return (normal.x() >= normal.y()) ? (normal.x() > normal.z()) ? 0 : 2 : (normal.y() > normal.z()) ? 1 : 2; 
+    // axis dominance order: Z, X, Y
+    return (normal.x() >= normal.y()) ? (normal.x() > normal.z()) ? 0 : 2 : (normal.y() > normal.z()) ? 1 : 2;
 }
 
 void Patch::CapTexture()
 {
-  const PatchControl& p1 = m_ctrl[m_width];
-  const PatchControl& p2 = m_ctrl[m_width*(m_height-1)];
-  const PatchControl& p3 = m_ctrl[(m_width*m_height)-1];
+    const PatchControl &p1 = m_ctrl[m_width];
+    const PatchControl &p2 = m_ctrl[m_width * (m_height - 1)];
+    const PatchControl &p3 = m_ctrl[(m_width * m_height) - 1];
 
-  
-  Vector3 normal(g_vector3_identity);
 
-  {
-    Vector3 tmp(vector3_cross(
-      vector3_subtracted(p2.m_vertex, m_ctrl[0].m_vertex),
-      vector3_subtracted(p3.m_vertex, m_ctrl[0].m_vertex)
-    ));
-    if(!vector3_equal(tmp, g_vector3_identity))
+    Vector3 normal(g_vector3_identity);
+
     {
-      vector3_add(normal, tmp);
-    }
-  }
-  {
-    Vector3 tmp(vector3_cross(
-      vector3_subtracted(p1.m_vertex, p3.m_vertex),
-      vector3_subtracted(m_ctrl[0].m_vertex, p3.m_vertex)
-    ));
-    if(!vector3_equal(tmp, g_vector3_identity))
+        Vector3 tmp(vector3_cross(
+                vector3_subtracted(p2.m_vertex, m_ctrl[0].m_vertex),
+                vector3_subtracted(p3.m_vertex, m_ctrl[0].m_vertex)
+        ));
+        if (!vector3_equal(tmp, g_vector3_identity)) {
+            vector3_add(normal, tmp);
+        }
+    }
     {
-      vector3_add(normal, tmp);
+        Vector3 tmp(vector3_cross(
+                vector3_subtracted(p1.m_vertex, p3.m_vertex),
+                vector3_subtracted(m_ctrl[0].m_vertex, p3.m_vertex)
+        ));
+        if (!vector3_equal(tmp, g_vector3_identity)) {
+            vector3_add(normal, tmp);
+        }
     }
-  }
 
-  ProjectTexture(texture_axis(normal));
+    ProjectTexture(texture_axis(normal));
 }
 
 // uses longest parallel chord to calculate texture coords for each row/col
 void Patch::NaturalTexture()
 {
-  undoSave();
+    undoSave();
 
-  {
-    float fSize = (float)m_state->getTexture().width * Texdef_getDefaultTextureScale();
-  
-    double texBest = 0;
-    double tex = 0;
-    PatchControl* pWidth = m_ctrl.data();
-    for (std::size_t w=0; w<m_width; w++, pWidth++) 
     {
-      {
-        PatchControl* pHeight = pWidth;
-        for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
-          pHeight->m_texcoord[0] = static_cast<float>(tex);
-      }
-
-      if(w+1 == m_width)
-        break;
-
-      {
-        PatchControl* pHeight = pWidth;
-        for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
-        {
-          Vector3 v(vector3_subtracted(pHeight->m_vertex, (pHeight+1)->m_vertex));
-          double length = tex + (vector3_length(v) / fSize);
-          if(fabs(length) > texBest) texBest = length;
-        }
-      }
+        float fSize = (float) m_state->getTexture().width * Texdef_getDefaultTextureScale();
 
-      tex=texBest;
-    }
-  }
+        double texBest = 0;
+        double tex = 0;
+        PatchControl *pWidth = m_ctrl.data();
+        for (std::size_t w = 0; w < m_width; w++, pWidth++) {
+            {
+                PatchControl *pHeight = pWidth;
+                for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) {
+                    pHeight->m_texcoord[0] = static_cast<float>( tex );
+                }
+            }
 
-  {
-    float fSize = -(float)m_state->getTexture().height * Texdef_getDefaultTextureScale();
+            if (w + 1 == m_width) {
+                break;
+            }
 
-    double texBest = 0;
-    double tex = 0;
-    PatchControl* pHeight = m_ctrl.data();
-    for (std::size_t h=0; h<m_height; h++, pHeight+=m_width) 
-    {
-      {
-        PatchControl* pWidth = pHeight;
-        for (std::size_t w=0; w<m_width; w++, pWidth++)
-          pWidth->m_texcoord[1] = static_cast<float>(tex);
-      }
-
-      if(h+1 == m_height)
-        break;
-
-      {
-        PatchControl* pWidth = pHeight;
-        for (std::size_t w=0; w<m_width; w++, pWidth++)
-        {
-          Vector3 v(vector3_subtracted(pWidth->m_vertex, (pWidth+m_width)->m_vertex));
-          double length = tex + (vector3_length(v) / fSize);
-          if(fabs(length) > texBest) texBest = length;
+            {
+                PatchControl *pHeight = pWidth;
+                for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) {
+                    Vector3 v(vector3_subtracted(pHeight->m_vertex, (pHeight + 1)->m_vertex));
+                    double length = tex + (vector3_length(v) / fSize);
+                    if (fabs(length) > texBest) {
+                        texBest = length;
+                    }
+                }
+            }
+
+            tex = texBest;
         }
-      }
+    }
 
-      tex=texBest;
+    {
+        float fSize = -(float) m_state->getTexture().height * Texdef_getDefaultTextureScale();
+
+        double texBest = 0;
+        double tex = 0;
+        PatchControl *pHeight = m_ctrl.data();
+        for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) {
+            {
+                PatchControl *pWidth = pHeight;
+                for (std::size_t w = 0; w < m_width; w++, pWidth++) {
+                    pWidth->m_texcoord[1] = static_cast<float>( tex );
+                }
+            }
+
+            if (h + 1 == m_height) {
+                break;
+            }
+
+            {
+                PatchControl *pWidth = pHeight;
+                for (std::size_t w = 0; w < m_width; w++, pWidth++) {
+                    Vector3 v(vector3_subtracted(pWidth->m_vertex, (pWidth + m_width)->m_vertex));
+                    double length = tex + (vector3_length(v) / fSize);
+                    if (fabs(length) > texBest) {
+                        texBest = length;
+                    }
+                }
+            }
+
+            tex = texBest;
+        }
     }
-  }
 
-  controlPointsChanged();
+    controlPointsChanged();
 }
 
 
@@ -739,2265 +707,2052 @@ void Patch::NaturalTexture()
 
 void Patch::AccumulateBBox()
 {
-  m_aabb_local = AABB();
+    m_aabb_local = AABB();
 
-  for(PatchControlArray::iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
-  {
-    aabb_extend_by_point_safe(m_aabb_local, (*i).m_vertex);
-  }
+    for (PatchControlArray::iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i) {
+        aabb_extend_by_point_safe(m_aabb_local, (*i).m_vertex);
+    }
 
-  m_boundsChanged();
-  m_lightsChanged();
+    m_boundsChanged();
+    m_lightsChanged();
 }
 
 void Patch::InsertPoints(EMatrixMajor mt, bool bFirst)
 {
-  std::size_t width, height, row_stride, col_stride; 
-
-  switch(mt)
-  {
-  case ROW:
-    col_stride = 1;
-    row_stride = m_width;
-    width = m_width;
-    height = m_height;
-    break;
-  case COL:
-    col_stride = m_width;
-    row_stride = 1;
-    width = m_height;
-    height = m_width;
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return;
-  }
-
-  std::size_t pos = 0;
-  {
-    PatchControl* p1 = m_ctrl.data();
-       /*
-         if(GlobalSelectionSystem().countSelected() != 0) 
-         {  
-                 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-                 PatchInstance* patch = Instance_getPatch(instance);
-                 patch->m_selectable.isSelected();
-         }
-       */
-       for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
-    {
-      {
-        PatchControl* p2 = p1;
-        for(std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride)
-        {
-          if(0)//p2->m_selectable.isSelected())
-          {
-            pos = h;
+    std::size_t width, height, row_stride, col_stride;
+
+    switch (mt) {
+        case ROW:
+            col_stride = 1;
+            row_stride = m_width;
+            width = m_width;
+            height = m_height;
             break;
-          }
-        }
-        if(pos != 0)
-        {
-          break;
-        }
-      }
-  
-      {
-        PatchControl* p2 = p1;
-        for(std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride)
-        {
-          if(0)//p2->m_selectable.isSelected())
-          {
-            pos = h;
+        case COL:
+            col_stride = m_width;
+            row_stride = 1;
+            width = m_height;
+            height = m_width;
             break;
-          }
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return;
+    }
+
+    std::size_t pos = 0;
+    {
+        PatchControl *p1 = m_ctrl.data();
+        /*
+                  if(GlobalSelectionSystem().countSelected() != 0)
+                  {
+                     scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+                     PatchInstance* patch = Instance_getPatch(instance);
+                     patch->m_selectable.isSelected();
+                  }
+                */
+        for (std::size_t w = 0; w != width; ++w, p1 += col_stride) {
+            {
+                PatchControl *p2 = p1;
+                for (std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride) {
+                    if (0) { //p2->m_selectable.isSelected())
+                        pos = h;
+                        break;
+                    }
+                }
+                if (pos != 0) {
+                    break;
+                }
+            }
+
+            {
+                PatchControl *p2 = p1;
+                for (std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride) {
+                    if (0) { //p2->m_selectable.isSelected())
+                        pos = h;
+                        break;
+                    }
+                }
+                if (pos != 0) {
+                    break;
+                }
+            }
         }
-        if(pos != 0)
-        {
-          break;
-        }
-      }
-    }
-  }
-
-  Array<PatchControl> tmp(m_ctrl);
-
-  std::size_t row_stride2, col_stride2;
-  switch(mt)
-  {
-  case ROW:
-    setDims(m_width, m_height+2);
-    col_stride2 = 1;
-    row_stride2 = m_width;
-    break;
-  case COL:
-    setDims(m_width+2, m_height);
-    col_stride2 = m_width;
-    row_stride2 = 1;
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return;
-  }
-    if(bFirst)
-    {
-               pos = height - 1;
     }
-    else
-    {
-               pos = 2;
+
+    Array<PatchControl> tmp(m_ctrl);
+
+    std::size_t row_stride2, col_stride2;
+    switch (mt) {
+        case ROW:
+            setDims(m_width, m_height + 2);
+            col_stride2 = 1;
+            row_stride2 = m_width;
+            break;
+        case COL:
+            setDims(m_width + 2, m_height);
+            col_stride2 = m_width;
+            row_stride2 = 1;
+            break;
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return;
     }
-       
-  if(pos >= height)
-  {
-    if(bFirst)
-    {
-      pos = height - 1;
+    if (bFirst) {
+        pos = height - 1;
+    } else {
+        pos = 2;
     }
-    else
-    {
-      pos = 2;
-    }
-  }
-  else if(pos == 0)
-  {
-    pos = 2;
-  }
-  else if(pos % 2)
-  {
-    ++pos;
-  }
-
-
-  for(std::size_t w = 0; w != width; ++w)
-  {
-    PatchControl* p1 = tmp.data() + (w*col_stride);
-    PatchControl* p2 = m_ctrl.data() + (w*col_stride2);
-    for(std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride)
-    {
-      if(h == pos)
-      {
-        p2 += 2 * row_stride2;
-      }
-      *p2 = *p1;
-    }
-
-    p1 = tmp.data() + (w*col_stride+pos*row_stride);
-    p2 = m_ctrl.data() + (w*col_stride2+pos*row_stride2);
-    
-    PatchControl* r2a = (p2+row_stride2);
-    PatchControl* r2b = (p2-row_stride2);
-    PatchControl* c2a = (p1-2*row_stride);
-    PatchControl* c2b = (p1-row_stride);
-
-    // set two new row points
-    *(p2+2*row_stride2) = *p1;
-    *r2a = *c2b;
-    
-    for(std::size_t i = 0; i != 3; ++i)
-    {
-      r2a->m_vertex[i] = float_mid(c2b->m_vertex[i], p1->m_vertex[i]);
 
-      r2b->m_vertex[i] = float_mid(c2a->m_vertex[i], c2b->m_vertex[i]);
-
-      p2->m_vertex[i] = float_mid(r2a->m_vertex[i], r2b->m_vertex[i]);
+    if (pos >= height) {
+        if (bFirst) {
+            pos = height - 1;
+        } else {
+            pos = 2;
+        }
+    } else if (pos == 0) {
+        pos = 2;
+    } else if (pos % 2) {
+        ++pos;
     }
-    for(std::size_t i = 0; i != 2; ++i)
-    {
-      r2a->m_texcoord[i] = float_mid(c2b->m_texcoord[i], p1->m_texcoord[i]);
 
-      r2b->m_texcoord[i] = float_mid(c2a->m_texcoord[i], c2b->m_texcoord[i]);
 
-      p2->m_texcoord[i] = float_mid(r2a->m_texcoord[i], r2b->m_texcoord[i]);
+    for (std::size_t w = 0; w != width; ++w) {
+        PatchControl *p1 = tmp.data() + (w * col_stride);
+        PatchControl *p2 = m_ctrl.data() + (w * col_stride2);
+        for (std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride) {
+            if (h == pos) {
+                p2 += 2 * row_stride2;
+            }
+            *p2 = *p1;
+        }
+
+        p1 = tmp.data() + (w * col_stride + pos * row_stride);
+        p2 = m_ctrl.data() + (w * col_stride2 + pos * row_stride2);
+
+        PatchControl *r2a = (p2 + row_stride2);
+        PatchControl *r2b = (p2 - row_stride2);
+        PatchControl *c2a = (p1 - 2 * row_stride);
+        PatchControl *c2b = (p1 - row_stride);
+
+        // set two new row points
+        *(p2 + 2 * row_stride2) = *p1;
+        *r2a = *c2b;
+
+        for (std::size_t i = 0; i != 3; ++i) {
+            r2a->m_vertex[i] = float_mid(c2b->m_vertex[i], p1->m_vertex[i]);
+
+            r2b->m_vertex[i] = float_mid(c2a->m_vertex[i], c2b->m_vertex[i]);
+
+            p2->m_vertex[i] = float_mid(r2a->m_vertex[i], r2b->m_vertex[i]);
+        }
+        for (std::size_t i = 0; i != 2; ++i) {
+            r2a->m_texcoord[i] = float_mid(c2b->m_texcoord[i], p1->m_texcoord[i]);
+
+            r2b->m_texcoord[i] = float_mid(c2a->m_texcoord[i], c2b->m_texcoord[i]);
+
+            p2->m_texcoord[i] = float_mid(r2a->m_texcoord[i], r2b->m_texcoord[i]);
+        }
     }
-  }
 }
 
 void Patch::RemovePoints(EMatrixMajor mt, bool bFirst)
 {
-  std::size_t width, height, row_stride, col_stride; 
-
-  switch(mt)
-  {
-  case ROW:
-    col_stride = 1;
-    row_stride = m_width;
-    width = m_width;
-    height = m_height;
-    break;
-  case COL:
-    col_stride = m_width;
-    row_stride = 1;
-    width = m_height;
-    height = m_width;
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return;
-  }
-
-  std::size_t pos = 0;
-  {
-    PatchControl* p1 = m_ctrl.data();
-    for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
-    {
-      {
-        PatchControl* p2 = p1;
-        for(std::size_t h=1; h < height; h += 2, p2 += 2 * row_stride)
-        {
-          if(0)//p2->m_selectable.isSelected())
-          {
-            pos = h;
+    std::size_t width, height, row_stride, col_stride;
+
+    switch (mt) {
+        case ROW:
+            col_stride = 1;
+            row_stride = m_width;
+            width = m_width;
+            height = m_height;
             break;
-          }
-        }
-        if(pos != 0)
-        {
-          break;
-        }
-      }
-  
-      {
-        PatchControl* p2 = p1;
-        for(std::size_t h=0; h < height; h += 2, p2 += 2 * row_stride)
-        {
-          if(0)//p2->m_selectable.isSelected())
-          {
-            pos = h;
+        case COL:
+            col_stride = m_width;
+            row_stride = 1;
+            width = m_height;
+            height = m_width;
             break;
-          }
-        }
-        if(pos != 0)
-        {
-          break;
-        }
-      }
-    }
-  }
-
-  Array<PatchControl> tmp(m_ctrl);
-
-  std::size_t row_stride2, col_stride2;
-  switch(mt)
-  {
-  case ROW:
-    setDims(m_width, m_height-2);
-    col_stride2 = 1;
-    row_stride2 = m_width;
-    break;
-  case COL:
-    setDims(m_width-2, m_height);
-    col_stride2 = m_width;
-    row_stride2 = 1;
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return;
-  }
-    if(bFirst)
-    {
-               pos=height-3;
-    }
-    else
-    {
-               pos=2;
-    }
-  if(pos >= height)
-  {
-    if(bFirst)
-    {
-      pos=height-3;
-    }
-    else
-    {
-      pos=2;
-    }
-  }
-  else if(pos == 0)
-  {
-    pos=2;
-  }
-  else if(pos > height - 3)
-  {
-    pos = height - 3;
-  }
-  else if(pos % 2)
-  {
-    ++pos;
-  }
-
-  for(std::size_t w = 0; w != width; w++)
-  {
-    PatchControl* p1 = tmp.data() + (w*col_stride);
-    PatchControl* p2 = m_ctrl.data() + (w*col_stride2);
-    for(std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride)
-    {
-      if(h == pos)
-      {
-        p1 += 2 * row_stride2; h += 2;
-      }
-      *p2 = *p1;
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return;
     }
 
-    p1 = tmp.data() + (w*col_stride+pos*row_stride);
-    p2 = m_ctrl.data() + (w*col_stride2+pos*row_stride2);
-    
-    for(std::size_t i=0; i<3; i++)
+    std::size_t pos = 0;
     {
-      (p2-row_stride2)->m_vertex[i] = ((p1+2*row_stride)->m_vertex[i]+(p1-2*row_stride)->m_vertex[i]) * 0.5f;
+        PatchControl *p1 = m_ctrl.data();
+        for (std::size_t w = 0; w != width; ++w, p1 += col_stride) {
+            {
+                PatchControl *p2 = p1;
+                for (std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride) {
+                    if (0) { //p2->m_selectable.isSelected())
+                        pos = h;
+                        break;
+                    }
+                }
+                if (pos != 0) {
+                    break;
+                }
+            }
 
-      (p2-row_stride2)->m_vertex[i] = (p2-row_stride2)->m_vertex[i]+(2.0f * ((p1)->m_vertex[i]-(p2-row_stride2)->m_vertex[i]));
+            {
+                PatchControl *p2 = p1;
+                for (std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride) {
+                    if (0) { //p2->m_selectable.isSelected())
+                        pos = h;
+                        break;
+                    }
+                }
+                if (pos != 0) {
+                    break;
+                }
+            }
+        }
     }
-    for(std::size_t i=0; i<2; i++)
-    {
-      (p2-row_stride2)->m_texcoord[i] = ((p1+2*row_stride)->m_texcoord[i]+(p1-2*row_stride)->m_texcoord[i]) * 0.5f;
 
-      (p2-row_stride2)->m_texcoord[i] = (p2-row_stride2)->m_texcoord[i]+(2.0f * ((p1)->m_texcoord[i]-(p2-row_stride2)->m_texcoord[i]));
-    }
-  }
-}
+    Array<PatchControl> tmp(m_ctrl);
 
-void Patch::ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width)
-{
-  switch(eType)
-  {
-  case eCapIBevel:
-    {
-      setDims(3, 3);
-      m_ctrl[0].m_vertex = p[0];
-      m_ctrl[1].m_vertex = p[1];
-      m_ctrl[2].m_vertex = p[1];
-      m_ctrl[3].m_vertex = p[1];
-      m_ctrl[4].m_vertex = p[1];
-      m_ctrl[5].m_vertex = p[1];
-      m_ctrl[6].m_vertex = p[2];
-      m_ctrl[7].m_vertex = p[1];
-      m_ctrl[8].m_vertex = p[1];
-    }
-    break;
-  case eCapBevel:
-    {
-      setDims(3, 3);
-      Vector3 p3(vector3_added(p[2], vector3_subtracted(p[0], p[1])));
-      m_ctrl[0].m_vertex = p3;
-      m_ctrl[1].m_vertex = p3;
-      m_ctrl[2].m_vertex = p[2];
-      m_ctrl[3].m_vertex = p3;
-      m_ctrl[4].m_vertex = p3;
-      m_ctrl[5].m_vertex = p[1];
-      m_ctrl[6].m_vertex = p3;
-      m_ctrl[7].m_vertex = p3;
-      m_ctrl[8].m_vertex = p[0];
-    }
-    break;
-  case eCapEndCap:
-    {
-      Vector3 p5(vector3_mid(p[0], p[4]));
-
-      setDims(3, 3);
-      m_ctrl[0].m_vertex = p[0];
-      m_ctrl[1].m_vertex = p5;
-      m_ctrl[2].m_vertex = p[4];
-      m_ctrl[3].m_vertex = p[1];
-      m_ctrl[4].m_vertex = p[2];
-      m_ctrl[5].m_vertex = p[3];
-      m_ctrl[6].m_vertex = p[2];
-      m_ctrl[7].m_vertex = p[2];
-      m_ctrl[8].m_vertex = p[2];
-    }
-    break;
-  case eCapIEndCap:
-    {
-      setDims(5, 3);
-      m_ctrl[0].m_vertex = p[4];
-      m_ctrl[1].m_vertex = p[3];
-      m_ctrl[2].m_vertex = p[2];
-      m_ctrl[3].m_vertex = p[1];
-      m_ctrl[4].m_vertex = p[0];
-      m_ctrl[5].m_vertex = p[3];
-      m_ctrl[6].m_vertex = p[3];
-      m_ctrl[7].m_vertex = p[2];
-      m_ctrl[8].m_vertex = p[1];
-      m_ctrl[9].m_vertex = p[1];
-      m_ctrl[10].m_vertex = p[3];
-      m_ctrl[11].m_vertex = p[3];
-      m_ctrl[12].m_vertex = p[2];
-      m_ctrl[13].m_vertex = p[1];
-      m_ctrl[14].m_vertex = p[1];
-    }
-    break;
-  case eCapCylinder:
-    {
-      std::size_t mid = (width - 1) >> 1;
+    std::size_t row_stride2, col_stride2;
+    switch (mt) {
+        case ROW:
+            setDims(m_width, m_height - 2);
+            col_stride2 = 1;
+            row_stride2 = m_width;
+            break;
+        case COL:
+            setDims(m_width - 2, m_height);
+            col_stride2 = m_width;
+            row_stride2 = 1;
+            break;
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return;
+    }
+    if (bFirst) {
+        pos = height - 3;
+    } else {
+        pos = 2;
+    }
+    if (pos >= height) {
+        if (bFirst) {
+            pos = height - 3;
+        } else {
+            pos = 2;
+        }
+    } else if (pos == 0) {
+        pos = 2;
+    } else if (pos > height - 3) {
+        pos = height - 3;
+    } else if (pos % 2) {
+        ++pos;
+    }
+
+    for (std::size_t w = 0; w != width; w++) {
+        PatchControl *p1 = tmp.data() + (w * col_stride);
+        PatchControl *p2 = m_ctrl.data() + (w * col_stride2);
+        for (std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride) {
+            if (h == pos) {
+                p1 += 2 * row_stride2;
+                h += 2;
+            }
+            *p2 = *p1;
+        }
 
-      bool degenerate = (mid % 2) != 0;
+        p1 = tmp.data() + (w * col_stride + pos * row_stride);
+        p2 = m_ctrl.data() + (w * col_stride2 + pos * row_stride2);
 
-      std::size_t newHeight = mid + (degenerate ? 2 : 1);
+        for (std::size_t i = 0; i < 3; i++) {
+            (p2 - row_stride2)->m_vertex[i] =
+                    ((p1 + 2 * row_stride)->m_vertex[i] + (p1 - 2 * row_stride)->m_vertex[i]) * 0.5f;
 
-      setDims(3, newHeight);
-      if(degenerate)
-      {
-        ++mid;
-        for(std::size_t i = width; i != width + 2; ++i)
-        {
-          p[i] = p[width - 1];
+            (p2 - row_stride2)->m_vertex[i] =
+                    (p2 - row_stride2)->m_vertex[i] + (2.0f * ((p1)->m_vertex[i] - (p2 - row_stride2)->m_vertex[i]));
         }
-      }
+        for (std::size_t i = 0; i < 2; i++) {
+            (p2 - row_stride2)->m_texcoord[i] =
+                    ((p1 + 2 * row_stride)->m_texcoord[i] + (p1 - 2 * row_stride)->m_texcoord[i]) * 0.5f;
 
-      {
-        PatchControl* pCtrl = m_ctrl.data();
-        for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
-        {
-          pCtrl->m_vertex = p[i];
-        }
-      }
-      {
-        PatchControl* pCtrl = m_ctrl.data() + 2;
-        std::size_t h = m_height - 1;
-        for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
-        {
-          pCtrl->m_vertex = p[h + (h - i)];
+            (p2 - row_stride2)->m_texcoord[i] = (p2 - row_stride2)->m_texcoord[i] +
+                                                (2.0f * ((p1)->m_texcoord[i] - (p2 - row_stride2)->m_texcoord[i]));
         }
-      }
-
-      Redisperse(COL);
     }
-    break;
-  default:
-    ERROR_MESSAGE("invalid patch-cap type");
-    return;
-  }
-  CapTexture();
-  controlPointsChanged();
 }
 
-void Patch::ProjectTexture(int nAxis)
+void Patch::ConstructSeam(EPatchCap eType, Vector3 *p, std::size_t width)
 {
-  undoSave();
-
-  int s, t;
-  
-  switch (nAxis)
-  {
-  case 2:
-    s = 0;
-    t = 1;
-    break;
-  case 0:
-    s = 1;
-    t = 2;
-    break;
-  case 1:
-    s = 0;
-    t = 2;
-    break;
-  default:
-    ERROR_MESSAGE("invalid axis");
-    return;
-  }
-
-  float fWidth = 1 / (m_state->getTexture().width * Texdef_getDefaultTextureScale());
-  float fHeight = 1 / (m_state->getTexture().height * -Texdef_getDefaultTextureScale());
-
-  for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
-  {
-    (*i).m_texcoord[0] = (*i).m_vertex[s] * fWidth;
-    (*i).m_texcoord[1] = (*i).m_vertex[t] * fHeight;
-  }
-
-  controlPointsChanged();
-}
-
-void Patch::constructPlane(const AABB& aabb, int axis, std::size_t width, std::size_t height)
-{
-  setDims(width, height);
-
-  int x, y, z;
-  switch(axis)
-  {
-  case 2: x=0; y=1; z=2; break;
-  case 1: x=0; y=2; z=1; break;
-  case 0: x=1; y=2; z=0; break;
-  default:
-    ERROR_MESSAGE("invalid view-type");
-    return;
-  }
-  
-  if(m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH) m_width = 3;
-  if(m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT) m_height = 3;
-  
-  Vector3 vStart;
-  vStart[x] = aabb.origin[x] - aabb.extents[x];
-  vStart[y] = aabb.origin[y] - aabb.extents[y];
-  vStart[z] = aabb.origin[z];
-  
-  float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float)(m_width - 1));
-  float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float)(m_height - 1));
-
-  Vector3 vTmp;
-  vTmp[z] = vStart[z];
-  PatchControl* pCtrl = m_ctrl.data();
-
-  vTmp[y]=vStart[y];
-  for (std::size_t h=0; h<m_height; h++)
-  {
-    vTmp[x]=vStart[x];
-    for (std::size_t w=0; w<m_width; w++, ++pCtrl)
-    {
-      pCtrl->m_vertex = vTmp;
-      vTmp[x]+=xAdj;
-    }
-    vTmp[y]+=yAdj;
-  }
-
-  NaturalTexture();
-}
-
-void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height)
-{
-  Vector3 vPos[3];
-    
-  if(eType != ePlane)
-  {
-    vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
-    vPos[1] = aabb.origin;
-    vPos[2] = vector3_added(aabb.origin, aabb.extents);
-  }
-  
-  if(eType == ePlane)
-  {
-    constructPlane(aabb, axis, width, height);
-  }
-  else if(eType == eSqCylinder
-    || eType == eCylinder
-    || eType == eDenseCylinder
-    || eType == eVeryDenseCylinder
-    || eType == eCone
-    || eType == eSphere)
-  {
-    unsigned char *pIndex;
-    unsigned char pCylIndex[] =
-    {
-      0, 0,
-      1, 0,
-      2, 0,
-      2, 1,
-      2, 2,
-      1, 2,
-      0, 2,
-      0, 1,
-      0, 0
-    };
-
-    
-    PatchControl *pStart;
-    switch(eType)
-    {
-    case eSqCylinder: setDims(9, 3);
-      pStart = m_ctrl.data();
-      break;
-    case eDenseCylinder: 
-    case eVeryDenseCylinder: 
-    case eCylinder:
-      setDims(9, 3);
-      pStart = m_ctrl.data() + 1;
-      break;
-    case eCone: setDims(9, 3);
-      pStart = m_ctrl.data() + 1;
-      break;
-    case eSphere:
-      setDims(9, 5);
-      pStart = m_ctrl.data() + (9+1);
-      break;
-    default:
-      ERROR_MESSAGE("this should be unreachable");
-      return;
-    }
-
-    for(std::size_t h=0; h<3; h++, pStart+=9)
-    {
-      pIndex = pCylIndex;
-      PatchControl* pCtrl = pStart;
-      for(std::size_t w=0; w<8; w++, pCtrl++)
-      {
-        pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
-        pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
-        pCtrl->m_vertex[2] = vPos[h][2];
-        pIndex+=2;
-      }
-    }
-
-    switch(eType)
-    {
-    case eSqCylinder:
-      {
-        PatchControl* pCtrl=m_ctrl.data();
-        for(std::size_t h=0; h<3; h++, pCtrl+=9)
-        {
-          pCtrl[8].m_vertex = pCtrl[0].m_vertex;
-        }
-      }
-      break;
-    case eDenseCylinder:
-    case eVeryDenseCylinder:
-    case eCylinder:
-      {
-        PatchControl* pCtrl=m_ctrl.data();
-        for (std::size_t h=0; h<3; h++, pCtrl+=9)
-        {
-          pCtrl[0].m_vertex = pCtrl[8].m_vertex;
-        }
-      }
-      break;
-    case eCone:
-      {
-        PatchControl* pCtrl=m_ctrl.data();
-        for (std::size_t h=0; h<2; h++, pCtrl+=9)
-        {
-          pCtrl[0].m_vertex = pCtrl[8].m_vertex;
+    switch (eType) {
+        case eCapIBevel: {
+            setDims(3, 3);
+            m_ctrl[0].m_vertex = p[0];
+            m_ctrl[1].m_vertex = p[1];
+            m_ctrl[2].m_vertex = p[1];
+            m_ctrl[3].m_vertex = p[1];
+            m_ctrl[4].m_vertex = p[1];
+            m_ctrl[5].m_vertex = p[1];
+            m_ctrl[6].m_vertex = p[2];
+            m_ctrl[7].m_vertex = p[1];
+            m_ctrl[8].m_vertex = p[1];
         }
-      }
-      {
-        PatchControl* pCtrl=m_ctrl.data()+9*2;
-        for (std::size_t w=0; w<9; w++, pCtrl++)
-        {
-          pCtrl->m_vertex[0] = vPos[1][0];
-          pCtrl->m_vertex[1] = vPos[1][1];
-          pCtrl->m_vertex[2] = vPos[2][2];
-        }
-      }
-      break;
-    case eSphere:
-      {
-        PatchControl* pCtrl=m_ctrl.data()+9;
-        for (std::size_t h=0; h<3; h++, pCtrl+=9)
-        {
-          pCtrl[0].m_vertex = pCtrl[8].m_vertex;
+            break;
+        case eCapBevel: {
+            setDims(3, 3);
+            Vector3 p3(vector3_added(p[2], vector3_subtracted(p[0], p[1])));
+            m_ctrl[0].m_vertex = p3;
+            m_ctrl[1].m_vertex = p3;
+            m_ctrl[2].m_vertex = p[2];
+            m_ctrl[3].m_vertex = p3;
+            m_ctrl[4].m_vertex = p3;
+            m_ctrl[5].m_vertex = p[1];
+            m_ctrl[6].m_vertex = p3;
+            m_ctrl[7].m_vertex = p3;
+            m_ctrl[8].m_vertex = p[0];
         }
-      }
-      {
-        PatchControl* pCtrl = m_ctrl.data();
-        for (std::size_t w=0; w<9; w++, pCtrl++)
-        {
-          pCtrl->m_vertex[0] = vPos[1][0];
-          pCtrl->m_vertex[1] = vPos[1][1];
-          pCtrl->m_vertex[2] = vPos[0][2];
-        }
-      }
-      {
-        PatchControl* pCtrl = m_ctrl.data()+(9*4);
-        for (std::size_t w=0; w<9; w++, pCtrl++)
-        {
-          pCtrl->m_vertex[0] = vPos[1][0];
-          pCtrl->m_vertex[1] = vPos[1][1];
-          pCtrl->m_vertex[2] = vPos[2][2];
-        }
-      }
-         break;
-    default:
-      ERROR_MESSAGE("this should be unreachable");
-      return;
-    }
-  }
-  else if (eType == eXactCylinder)
-  {
-       int n = (width - 1) / 2; // n = number of segments
-       setDims(width, height);
-
-       // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
-       // vPos[1] = aabb.origin;
-       // vPos[2] = vector3_added(aabb.origin, aabb.extents);
-
-       int i, j;
-       float f = 1 / cos(M_PI / n);
-       for(i = 0; i < width; ++i)
-       {
-               float angle = (M_PI * i) / n; // 0 to 2pi
-               float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * cos(angle) * ((i&1) ? f : 1.0f);
-               float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle) * ((i&1) ? f : 1.0f);
-               for(j = 0; j < height; ++j)
-               {
-                       float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float)(height - 1));
-                       PatchControl *v;
-                       v = &m_ctrl.data()[j*width+i];
-                       v->m_vertex[0] = x;
-                       v->m_vertex[1] = y;
-                       v->m_vertex[2] = z;
-               }
-       }
-  }
-  else if (eType == eXactCone)
-  {
-       int n = (width - 1) / 2; // n = number of segments
-       setDims(width, height);
-
-       // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
-       // vPos[1] = aabb.origin;
-       // vPos[2] = vector3_added(aabb.origin, aabb.extents);
-
-       int i, j;
-       float f = 1 / cos(M_PI / n);
-       for(i = 0; i < width; ++i)
-       {
-               float angle = (M_PI * i) / n;
-               for(j = 0; j < height; ++j)
-               {
-                       float x = vPos[1][0] + (1.0f - (j / (float)(height - 1))) * (vPos[2][0] - vPos[1][0]) * cos(angle) * ((i&1) ? f : 1.0f);
-                       float y = vPos[1][1] + (1.0f - (j / (float)(height - 1))) * (vPos[2][1] - vPos[1][1]) * sin(angle) * ((i&1) ? f : 1.0f);
-                       float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float)(height - 1));
-                       PatchControl *v;
-                       v = &m_ctrl.data()[j*width+i];
-                       v->m_vertex[0] = x;
-                       v->m_vertex[1] = y;
-                       v->m_vertex[2] = z;
-               }
-       }
-  }
-  else if (eType == eXactSphere)
-  {
-       int n = (width - 1) / 2; // n = number of segments (yaw)
-       int m = (height - 1) / 2; // m = number of segments (pitch)
-       setDims(width, height);
-
-       // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
-       // vPos[1] = aabb.origin;
-       // vPos[2] = vector3_added(aabb.origin, aabb.extents);
-
-       int i, j;
-       float f = 1 / cos(M_PI / n);
-       float g = 1 / cos(M_PI / (2*m));
-       for(i = 0; i < width; ++i)
-       {
-               float angle = (M_PI * i) / n;
-               for(j = 0; j < height; ++j)
-               {
-                       float angle2 = (M_PI * j) / (2*m);
-                       float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) *  sin(angle2) * ((j&1) ? g : 1.0f) * cos(angle) * ((i&1) ? f : 1.0f);
-                       float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) *  sin(angle2) * ((j&1) ? g : 1.0f) * sin(angle) * ((i&1) ? f : 1.0f);
-                       float z = vPos[1][2] + (vPos[2][2] - vPos[1][2]) * -cos(angle2) * ((j&1) ? g : 1.0f);
-                       PatchControl *v;
-                       v = &m_ctrl.data()[j*width+i];
-                       v->m_vertex[0] = x;
-                       v->m_vertex[1] = y;
-                       v->m_vertex[2] = z;
-               }
-       }
-  }
-  else if  (eType == eBevel)
-  {
-    unsigned char *pIndex;
-    unsigned char pBevIndex[] =
-    {
-      0, 0,
-      2, 0,
-      2, 2,
-    };
-
-    setDims(3, 3);
-
-    PatchControl* pCtrl = m_ctrl.data();
-    for(std::size_t h=0; h<3; h++)
-    {
-      pIndex=pBevIndex;
-      for(std::size_t w=0; w<3; w++, pIndex+=2, pCtrl++)
-      {
-        pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
-        pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
-        pCtrl->m_vertex[2] = vPos[h][2];
-      }
-    }
-  }
-  else if(eType == eEndCap)
-  {
-    unsigned char *pIndex;
-    unsigned char pEndIndex[] =
-    {
-      2, 0,
-      2, 2,
-      1, 2,
-      0, 2,
-      0, 0,
-    };
+            break;
+        case eCapEndCap: {
+            Vector3 p5(vector3_mid(p[0], p[4]));
+
+            setDims(3, 3);
+            m_ctrl[0].m_vertex = p[0];
+            m_ctrl[1].m_vertex = p5;
+            m_ctrl[2].m_vertex = p[4];
+            m_ctrl[3].m_vertex = p[1];
+            m_ctrl[4].m_vertex = p[2];
+            m_ctrl[5].m_vertex = p[3];
+            m_ctrl[6].m_vertex = p[2];
+            m_ctrl[7].m_vertex = p[2];
+            m_ctrl[8].m_vertex = p[2];
+        }
+            break;
+        case eCapIEndCap: {
+            setDims(5, 3);
+            m_ctrl[0].m_vertex = p[4];
+            m_ctrl[1].m_vertex = p[3];
+            m_ctrl[2].m_vertex = p[2];
+            m_ctrl[3].m_vertex = p[1];
+            m_ctrl[4].m_vertex = p[0];
+            m_ctrl[5].m_vertex = p[3];
+            m_ctrl[6].m_vertex = p[3];
+            m_ctrl[7].m_vertex = p[2];
+            m_ctrl[8].m_vertex = p[1];
+            m_ctrl[9].m_vertex = p[1];
+            m_ctrl[10].m_vertex = p[3];
+            m_ctrl[11].m_vertex = p[3];
+            m_ctrl[12].m_vertex = p[2];
+            m_ctrl[13].m_vertex = p[1];
+            m_ctrl[14].m_vertex = p[1];
+        }
+            break;
+        case eCapCylinder: {
+            std::size_t mid = (width - 1) >> 1;
 
-    setDims(5, 3);
+            bool degenerate = (mid % 2) != 0;
 
-    PatchControl* pCtrl = m_ctrl.data();
-    for(std::size_t h=0; h<3; h++)
-    {
-      pIndex=pEndIndex;
-      for(std::size_t w=0; w<5; w++, pIndex+=2, pCtrl++)
-      {
-        pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
-        pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
-        pCtrl->m_vertex[2] = vPos[h][2];
-      }
-    }
-  }
+            std::size_t newHeight = mid + (degenerate ? 2 : 1);
 
-  if(eType == eDenseCylinder)
-  {
-    InsertRemove(true, false, true);
-  }
+            setDims(3, newHeight);
 
-  if(eType == eVeryDenseCylinder)
-  {
-    InsertRemove(true, false, false);
-    InsertRemove(true, false, true);
-  }
+            if (degenerate) {
+                ++mid;
+                for (std::size_t i = width; i != width + 2; ++i) {
+                    p[i] = p[width - 1];
+                }
+            }
 
-  NaturalTexture();
+            {
+                PatchControl *pCtrl = m_ctrl.data();
+                for (std::size_t i = 0; i != m_height; ++i, pCtrl += m_width) {
+                    pCtrl->m_vertex = p[i];
+                }
+            }
+            {
+                PatchControl *pCtrl = m_ctrl.data() + 2;
+                std::size_t h = m_height - 1;
+                for (std::size_t i = 0; i != m_height; ++i, pCtrl += m_width) {
+                    pCtrl->m_vertex = p[h + (h - i)];
+                }
+            }
+
+            Redisperse(COL);
+        }
+            break;
+        default:
+            ERROR_MESSAGE("invalid patch-cap type");
+            return;
+    }
+    CapTexture();
+    controlPointsChanged();
+}
+
+void Patch::ProjectTexture(int nAxis)
+{
+    undoSave();
+
+    int s, t;
+
+    switch (nAxis) {
+        case 2:
+            s = 0;
+            t = 1;
+            break;
+        case 0:
+            s = 1;
+            t = 2;
+            break;
+        case 1:
+            s = 0;
+            t = 2;
+            break;
+        default:
+            ERROR_MESSAGE("invalid axis");
+            return;
+    }
+
+    float fWidth = 1 / (m_state->getTexture().width * Texdef_getDefaultTextureScale());
+    float fHeight = 1 / (m_state->getTexture().height * -Texdef_getDefaultTextureScale());
+
+    for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
+        (*i).m_texcoord[0] = (*i).m_vertex[s] * fWidth;
+        (*i).m_texcoord[1] = (*i).m_vertex[t] * fHeight;
+    }
+
+    controlPointsChanged();
+}
+
+void Patch::constructPlane(const AABB &aabb, int axis, std::size_t width, std::size_t height)
+{
+    setDims(width, height);
+
+    int x, y, z;
+    switch (axis) {
+        case 2:
+            x = 0;
+            y = 1;
+            z = 2;
+            break;
+        case 1:
+            x = 0;
+            y = 2;
+            z = 1;
+            break;
+        case 0:
+            x = 1;
+            y = 2;
+            z = 0;
+            break;
+        default:
+            ERROR_MESSAGE("invalid view-type");
+            return;
+    }
+
+    if (m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH) {
+        m_width = 3;
+    }
+    if (m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT) {
+        m_height = 3;
+    }
+
+    Vector3 vStart;
+    vStart[x] = aabb.origin[x] - aabb.extents[x];
+    vStart[y] = aabb.origin[y] - aabb.extents[y];
+    vStart[z] = aabb.origin[z];
+
+    float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float) (m_width - 1));
+    float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float) (m_height - 1));
+
+    Vector3 vTmp;
+    vTmp[z] = vStart[z];
+    PatchControl *pCtrl = m_ctrl.data();
+
+    vTmp[y] = vStart[y];
+    for (std::size_t h = 0; h < m_height; h++) {
+        vTmp[x] = vStart[x];
+        for (std::size_t w = 0; w < m_width; w++, ++pCtrl) {
+            pCtrl->m_vertex = vTmp;
+            vTmp[x] += xAdj;
+        }
+        vTmp[y] += yAdj;
+    }
+
+    NaturalTexture();
+}
+
+void Patch::ConstructPrefab(const AABB &aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height)
+{
+    Vector3 vPos[3];
+
+    if (eType != ePlane) {
+        vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
+        vPos[1] = aabb.origin;
+        vPos[2] = vector3_added(aabb.origin, aabb.extents);
+    }
+
+    if (eType == ePlane) {
+        constructPlane(aabb, axis, width, height);
+    } else if (eType == eSqCylinder
+               || eType == eCylinder
+               || eType == eDenseCylinder
+               || eType == eVeryDenseCylinder
+               || eType == eCone
+               || eType == eSphere) {
+        unsigned char *pIndex;
+        unsigned char pCylIndex[] =
+                {
+                        0, 0,
+                        1, 0,
+                        2, 0,
+                        2, 1,
+                        2, 2,
+                        1, 2,
+                        0, 2,
+                        0, 1,
+                        0, 0
+                };
+
+
+        PatchControl *pStart;
+        switch (eType) {
+            case eSqCylinder:
+                setDims(9, 3);
+                pStart = m_ctrl.data();
+                break;
+            case eDenseCylinder:
+            case eVeryDenseCylinder:
+            case eCylinder:
+                setDims(9, 3);
+                pStart = m_ctrl.data() + 1;
+                break;
+            case eCone:
+                setDims(9, 3);
+                pStart = m_ctrl.data() + 1;
+                break;
+            case eSphere:
+                setDims(9, 5);
+                pStart = m_ctrl.data() + (9 + 1);
+                break;
+            default:
+                ERROR_MESSAGE("this should be unreachable");
+                return;
+        }
+
+        for (std::size_t h = 0; h < 3; h++, pStart += 9) {
+            pIndex = pCylIndex;
+            PatchControl *pCtrl = pStart;
+            for (std::size_t w = 0; w < 8; w++, pCtrl++) {
+                pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
+                pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
+                pCtrl->m_vertex[2] = vPos[h][2];
+                pIndex += 2;
+            }
+        }
+
+        switch (eType) {
+            case eSqCylinder: {
+                PatchControl *pCtrl = m_ctrl.data();
+                for (std::size_t h = 0; h < 3; h++, pCtrl += 9) {
+                    pCtrl[8].m_vertex = pCtrl[0].m_vertex;
+                }
+            }
+                break;
+            case eDenseCylinder:
+            case eVeryDenseCylinder:
+            case eCylinder: {
+                PatchControl *pCtrl = m_ctrl.data();
+                for (std::size_t h = 0; h < 3; h++, pCtrl += 9) {
+                    pCtrl[0].m_vertex = pCtrl[8].m_vertex;
+                }
+            }
+                break;
+            case eCone: {
+                PatchControl *pCtrl = m_ctrl.data();
+                for (std::size_t h = 0; h < 2; h++, pCtrl += 9) {
+                    pCtrl[0].m_vertex = pCtrl[8].m_vertex;
+                }
+            }
+                {
+                    PatchControl *pCtrl = m_ctrl.data() + 9 * 2;
+                    for (std::size_t w = 0; w < 9; w++, pCtrl++) {
+                        pCtrl->m_vertex[0] = vPos[1][0];
+                        pCtrl->m_vertex[1] = vPos[1][1];
+                        pCtrl->m_vertex[2] = vPos[2][2];
+                    }
+                }
+                break;
+            case eSphere: {
+                PatchControl *pCtrl = m_ctrl.data() + 9;
+                for (std::size_t h = 0; h < 3; h++, pCtrl += 9) {
+                    pCtrl[0].m_vertex = pCtrl[8].m_vertex;
+                }
+            }
+                {
+                    PatchControl *pCtrl = m_ctrl.data();
+                    for (std::size_t w = 0; w < 9; w++, pCtrl++) {
+                        pCtrl->m_vertex[0] = vPos[1][0];
+                        pCtrl->m_vertex[1] = vPos[1][1];
+                        pCtrl->m_vertex[2] = vPos[0][2];
+                    }
+                }
+                {
+                    PatchControl *pCtrl = m_ctrl.data() + (9 * 4);
+                    for (std::size_t w = 0; w < 9; w++, pCtrl++) {
+                        pCtrl->m_vertex[0] = vPos[1][0];
+                        pCtrl->m_vertex[1] = vPos[1][1];
+                        pCtrl->m_vertex[2] = vPos[2][2];
+                    }
+                }
+                break;
+            default:
+                ERROR_MESSAGE("this should be unreachable");
+                return;
+        }
+    } else if (eType == eXactCylinder) {
+        int n = (width - 1) / 2; // n = number of segments
+        setDims(width, height);
+
+        // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
+        // vPos[1] = aabb.origin;
+        // vPos[2] = vector3_added(aabb.origin, aabb.extents);
+
+        float f = 1 / cos(M_PI / n);
+        for (std::size_t i = 0; i < width; ++i) {
+            float angle = (M_PI * i) / n; // 0 to 2pi
+            float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * cos(angle) * ((i & 1) ? f : 1.0f);
+            float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle) * ((i & 1) ? f : 1.0f);
+            for (std::size_t j = 0; j < height; ++j) {
+                float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float) (height - 1));
+                PatchControl *v;
+                v = &m_ctrl.data()[j * width + i];
+                v->m_vertex[0] = x;
+                v->m_vertex[1] = y;
+                v->m_vertex[2] = z;
+            }
+        }
+    } else if (eType == eXactCone) {
+        int n = (width - 1) / 2; // n = number of segments
+        setDims(width, height);
+
+        // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
+        // vPos[1] = aabb.origin;
+        // vPos[2] = vector3_added(aabb.origin, aabb.extents);
+
+        float f = 1 / cos(M_PI / n);
+        for (std::size_t i = 0; i < width; ++i) {
+            float angle = (M_PI * i) / n;
+            for (std::size_t j = 0; j < height; ++j) {
+                float x = vPos[1][0] + (1.0f - (j / (float) (height - 1))) * (vPos[2][0] - vPos[1][0]) * cos(angle) *
+                                       ((i & 1) ? f : 1.0f);
+                float y = vPos[1][1] + (1.0f - (j / (float) (height - 1))) * (vPos[2][1] - vPos[1][1]) * sin(angle) *
+                                       ((i & 1) ? f : 1.0f);
+                float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float) (height - 1));
+                PatchControl *v;
+                v = &m_ctrl.data()[j * width + i];
+                v->m_vertex[0] = x;
+                v->m_vertex[1] = y;
+                v->m_vertex[2] = z;
+            }
+        }
+    } else if (eType == eXactSphere) {
+        int n = (width - 1) / 2; // n = number of segments (yaw)
+        int m = (height - 1) / 2; // m = number of segments (pitch)
+        setDims(width, height);
+
+        // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
+        // vPos[1] = aabb.origin;
+        // vPos[2] = vector3_added(aabb.origin, aabb.extents);
+
+        float f = 1 / cos(M_PI / n);
+        float g = 1 / cos(M_PI / (2 * m));
+        for (std::size_t i = 0; i < width; ++i) {
+            float angle = (M_PI * i) / n;
+            for (std::size_t j = 0; j < height; ++j) {
+                float angle2 = (M_PI * j) / (2 * m);
+                float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * sin(angle2) * ((j & 1) ? g : 1.0f) * cos(angle) *
+                                       ((i & 1) ? f : 1.0f);
+                float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle2) * ((j & 1) ? g : 1.0f) * sin(angle) *
+                                       ((i & 1) ? f : 1.0f);
+                float z = vPos[1][2] + (vPos[2][2] - vPos[1][2]) * -cos(angle2) * ((j & 1) ? g : 1.0f);
+                PatchControl *v;
+                v = &m_ctrl.data()[j * width + i];
+                v->m_vertex[0] = x;
+                v->m_vertex[1] = y;
+                v->m_vertex[2] = z;
+            }
+        }
+    } else if (eType == eBevel) {
+        unsigned char *pIndex;
+        unsigned char pBevIndex[] =
+                {
+                        0, 0,
+                        2, 0,
+                        2, 2,
+                };
+
+        setDims(3, 3);
+
+        PatchControl *pCtrl = m_ctrl.data();
+        for (std::size_t h = 0; h < 3; h++) {
+            pIndex = pBevIndex;
+            for (std::size_t w = 0; w < 3; w++, pIndex += 2, pCtrl++) {
+                pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
+                pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
+                pCtrl->m_vertex[2] = vPos[h][2];
+            }
+        }
+    } else if (eType == eEndCap) {
+        unsigned char *pIndex;
+        unsigned char pEndIndex[] =
+                {
+                        2, 0,
+                        2, 2,
+                        1, 2,
+                        0, 2,
+                        0, 0,
+                };
+
+        setDims(5, 3);
+
+        PatchControl *pCtrl = m_ctrl.data();
+        for (std::size_t h = 0; h < 3; h++) {
+            pIndex = pEndIndex;
+            for (std::size_t w = 0; w < 5; w++, pIndex += 2, pCtrl++) {
+                pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
+                pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
+                pCtrl->m_vertex[2] = vPos[h][2];
+            }
+        }
+    }
+
+    if (eType == eDenseCylinder) {
+        InsertRemove(true, false, true);
+    }
+
+    if (eType == eVeryDenseCylinder) {
+        InsertRemove(true, false, false);
+        InsertRemove(true, false, true);
+    }
+
+    NaturalTexture();
 }
 
 void Patch::RenderDebug(RenderStateFlags state) const
 {
-  for (std::size_t i = 0; i<m_tess.m_numStrips; i++)
-  {
-    glBegin(GL_QUAD_STRIP);
-    for (std::size_t j = 0; j<m_tess.m_lenStrips; j++)
-    {
-      glNormal3fv(normal3f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->normal));
-      glTexCoord2fv(texcoord2f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->texcoord));
-      glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->vertex));
+    for (std::size_t i = 0; i < m_tess.m_numStrips; i++) {
+        glBegin(GL_QUAD_STRIP);
+        for (std::size_t j = 0; j < m_tess.m_lenStrips; j++) {
+            glNormal3fv(normal3f_to_array(
+                    (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->normal));
+            glTexCoord2fv(texcoord2f_to_array(
+                    (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->texcoord));
+            glVertex3fv(vertex3f_to_array(
+                    (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->vertex));
+        }
+        glEnd();
     }
-    glEnd();
-  }
 }
 
 void RenderablePatchSolid::RenderNormals() const
 {
-  const std::size_t width = m_tess.m_numStrips+1;
-  const std::size_t height = m_tess.m_lenStrips>>1;
-  glBegin(GL_LINES);
-  for(std::size_t i=0;i<width;i++)
-  {
-    for(std::size_t j=0;j<height;j++)
-    {
-      {
-        Vector3 vNormal(
-          vector3_added(
-            vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
-            vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->normal), 8)
-          )
-        );
-        glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
-        glVertex3fv(&vNormal[0]);
-      }
-      {
-        Vector3 vNormal(
-          vector3_added(
-            vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
-            vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->tangent), 8)
-          )
-        );
-        glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
-        glVertex3fv(&vNormal[0]);
-      }
-      {
-        Vector3 vNormal(
-          vector3_added(
-            vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
-            vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->bitangent), 8)
-          )
-        );
-        glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
-        glVertex3fv(&vNormal[0]);
-      }
-    }
-  }
-  glEnd();
-}
-
-#define DEGEN_0a  0x01
-#define DEGEN_1a  0x02
-#define DEGEN_2a  0x04
-#define DEGEN_0b  0x08
-#define DEGEN_1b  0x10
-#define DEGEN_2b  0x20
-#define SPLIT     0x40
-#define AVERAGE   0x80
+    const std::size_t width = m_tess.m_numStrips + 1;
+    const std::size_t height = m_tess.m_lenStrips >> 1;
+    glBegin(GL_LINES);
+    for (std::size_t i = 0; i < width; i++) {
+        for (std::size_t j = 0; j < height; j++) {
+            {
+                Vector3 vNormal(
+                        vector3_added(
+                                vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex),
+                                vector3_scaled(
+                                        normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->normal), 8)
+                        )
+                );
+                glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex));
+                glVertex3fv(&vNormal[0]);
+            }
+            {
+                Vector3 vNormal(
+                        vector3_added(
+                                vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex),
+                                vector3_scaled(
+                                        normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->tangent), 8)
+                        )
+                );
+                glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex));
+                glVertex3fv(&vNormal[0]);
+            }
+            {
+                Vector3 vNormal(
+                        vector3_added(
+                                vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex),
+                                vector3_scaled(
+                                        normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->bitangent), 8)
+                        )
+                );
+                glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex));
+                glVertex3fv(&vNormal[0]);
+            }
+        }
+    }
+    glEnd();
+}
+
+const int DEGEN_0a = 0x01;
+const int DEGEN_1a = 0x02;
+const int DEGEN_2a = 0x04;
+const int DEGEN_0b = 0x08;
+const int DEGEN_1b = 0x10;
+const int DEGEN_2b = 0x20;
+const int SPLIT = 0x40;
+const int AVERAGE = 0x80;
 
 
 unsigned int subarray_get_degen(PatchControlIter subarray, std::size_t strideU, std::size_t strideV)
 {
-  unsigned int nDegen = 0;
-  const PatchControl* p1;
-  const PatchControl* p2;
+    unsigned int nDegen = 0;
+    const PatchControl *p1;
+    const PatchControl *p2;
 
-  p1 = subarray;
-  p2 = p1 + strideU;
-  if(vector3_equal(p1->m_vertex, p2->m_vertex))
-    nDegen |= DEGEN_0a;
-  p1 = p2;
-  p2 = p1 + strideU;
-  if(vector3_equal(p1->m_vertex, p2->m_vertex))
-    nDegen |= DEGEN_0b;
+    p1 = subarray;
+    p2 = p1 + strideU;
+    if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
+        nDegen |= DEGEN_0a;
+    }
+    p1 = p2;
+    p2 = p1 + strideU;
+    if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
+        nDegen |= DEGEN_0b;
+    }
 
-  p1 = subarray + strideV;
-  p2 = p1 + strideU;
-  if(vector3_equal(p1->m_vertex, p2->m_vertex))
-    nDegen |= DEGEN_1a;
-  p1 = p2;
-  p2 = p1 + strideU;
-  if(vector3_equal(p1->m_vertex, p2->m_vertex))
-    nDegen |= DEGEN_1b;
+    p1 = subarray + strideV;
+    p2 = p1 + strideU;
+    if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
+        nDegen |= DEGEN_1a;
+    }
+    p1 = p2;
+    p2 = p1 + strideU;
+    if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
+        nDegen |= DEGEN_1b;
+    }
 
-  p1 = subarray + (strideV << 1);
-  p2 = p1 + strideU;
-  if(vector3_equal(p1->m_vertex, p2->m_vertex))
-    nDegen |= DEGEN_2a;
-  p1 = p2;
-  p2 = p1 + strideU;
-  if(vector3_equal(p1->m_vertex, p2->m_vertex))
-    nDegen |= DEGEN_2b;
+    p1 = subarray + (strideV << 1);
+    p2 = p1 + strideU;
+    if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
+        nDegen |= DEGEN_2a;
+    }
+    p1 = p2;
+    p2 = p1 + strideU;
+    if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
+        nDegen |= DEGEN_2b;
+    }
 
-  return nDegen;
+    return nDegen;
 }
 
 
-inline void deCasteljau3(const Vector3& P0, const Vector3& P1, const Vector3& P2, Vector3& P01, Vector3& P12, Vector3& P012)
+inline void
+deCasteljau3(const Vector3 &P0, const Vector3 &P1, const Vector3 &P2, Vector3 &P01, Vector3 &P12, Vector3 &P012)
 {
-  P01 = vector3_mid(P0, P1);
-  P12 = vector3_mid(P1, P2);
-  P012 = vector3_mid(P01, P12);
+    P01 = vector3_mid(P0, P1);
+    P12 = vector3_mid(P1, P2);
+    P012 = vector3_mid(P01, P12);
 }
 
-inline void BezierInterpolate3( const Vector3& start, Vector3& left, Vector3& mid, Vector3& right, const Vector3& end )
+inline void BezierInterpolate3(const Vector3 &start, Vector3 &left, Vector3 &mid, Vector3 &right, const Vector3 &end)
 {
-  left = vector3_mid(start, mid);
-  right = vector3_mid(mid, end);
-  mid = vector3_mid(left, right);
+    left = vector3_mid(start, mid);
+    right = vector3_mid(mid, end);
+    mid = vector3_mid(left, right);
 }
 
-inline void BezierInterpolate2( const Vector2& start, Vector2& left, Vector2& mid, Vector2& right, const Vector2& end )
+inline void BezierInterpolate2(const Vector2 &start, Vector2 &left, Vector2 &mid, Vector2 &right, const Vector2 &end)
 {
-  left[0]= float_mid(start[0], mid[0]);
-  left[1] = float_mid(start[1], mid[1]);
-  right[0] = float_mid(mid[0], end[0]);
-  right[1] = float_mid(mid[1], end[1]);
-  mid[0] = float_mid(left[0], right[0]);
-  mid[1] = float_mid(left[1], right[1]);
+    left[0] = float_mid(start[0], mid[0]);
+    left[1] = float_mid(start[1], mid[1]);
+    right[0] = float_mid(mid[0], end[0]);
+    right[1] = float_mid(mid[1], end[1]);
+    mid[0] = float_mid(left[0], right[0]);
+    mid[1] = float_mid(left[1], right[1]);
 }
 
 
-inline Vector2& texcoord_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline Vector2 &texcoord_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<Vector2&>(vertices[index].texcoord);
+    return reinterpret_cast<Vector2 &>( vertices[index].texcoord );
 }
 
-inline Vector3& vertex_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline Vector3 &vertex_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<Vector3&>(vertices[index].vertex);
+    return reinterpret_cast<Vector3 &>( vertices[index].vertex );
 }
 
-inline Vector3& normal_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline Vector3 &normal_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<Vector3&>(vertices[index].normal);
+    return reinterpret_cast<Vector3 &>( vertices[index].normal );
 }
 
-inline Vector3& tangent_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline Vector3 &tangent_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<Vector3&>(vertices[index].tangent);
+    return reinterpret_cast<Vector3 &>( vertices[index].tangent );
 }
 
-inline Vector3& bitangent_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline Vector3 &bitangent_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<Vector3&>(vertices[index].bitangent);
+    return reinterpret_cast<Vector3 &>( vertices[index].bitangent );
 }
 
-inline const Vector2& texcoord_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline const Vector2 &texcoord_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<const Vector2&>(vertices[index].texcoord);
+    return reinterpret_cast<const Vector2 &>( vertices[index].texcoord );
 }
 
-inline const Vector3& vertex_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline const Vector3 &vertex_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<const Vector3&>(vertices[index].vertex);
+    return reinterpret_cast<const Vector3 &>( vertices[index].vertex );
 }
 
-inline const Vector3& normal_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline const Vector3 &normal_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<const Vector3&>(vertices[index].normal);
+    return reinterpret_cast<const Vector3 &>( vertices[index].normal );
 }
 
-inline const Vector3& tangent_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline const Vector3 &tangent_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<const Vector3&>(vertices[index].tangent);
+    return reinterpret_cast<const Vector3 &>( vertices[index].tangent );
 }
 
-inline const Vector3& bitangent_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
+inline const Vector3 &bitangent_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
 {
-  return reinterpret_cast<const Vector3&>(vertices[index].bitangent);
+    return reinterpret_cast<const Vector3 &>( vertices[index].bitangent );
 }
 
 #include "math/curve.h"
 
-inline PatchControl QuadraticBezier_evaluate(const PatchControlfirstPoint, double t)
+inline PatchControl QuadraticBezier_evaluate(const PatchControl *firstPoint, double t)
 {
-  PatchControl result = { Vector3(0, 0, 0), Vector2(0, 0) };
-  double denominator = 0;
+    PatchControl result = {Vector3(0, 0, 0), Vector2(0, 0)};
+    double denominator = 0;
+
+    {
+        double weight = BernsteinPolynomial<Zero, Two>::apply(t);
+        vector3_add(result.m_vertex, vector3_scaled(firstPoint[0].m_vertex, weight));
+        vector2_add(result.m_texcoord, vector2_scaled(firstPoint[0].m_texcoord, weight));
+        denominator += weight;
+    }
+    {
+        double weight = BernsteinPolynomial<One, Two>::apply(t);
+        vector3_add(result.m_vertex, vector3_scaled(firstPoint[1].m_vertex, weight));
+        vector2_add(result.m_texcoord, vector2_scaled(firstPoint[1].m_texcoord, weight));
+        denominator += weight;
+    }
+    {
+        double weight = BernsteinPolynomial<Two, Two>::apply(t);
+        vector3_add(result.m_vertex, vector3_scaled(firstPoint[2].m_vertex, weight));
+        vector2_add(result.m_texcoord, vector2_scaled(firstPoint[2].m_texcoord, weight));
+        denominator += weight;
+    }
 
-  {
-    double weight = BernsteinPolynomial<Zero, Two>::apply(t);
-    vector3_add(result.m_vertex, vector3_scaled(firstPoint[0].m_vertex, weight));
-    vector2_add(result.m_texcoord, vector2_scaled(firstPoint[0].m_texcoord, weight));
-    denominator += weight;
-  }
-  {
-    double weight = BernsteinPolynomial<One, Two>::apply(t);
-    vector3_add(result.m_vertex, vector3_scaled(firstPoint[1].m_vertex, weight));
-    vector2_add(result.m_texcoord, vector2_scaled(firstPoint[1].m_texcoord, weight));
-    denominator += weight;
-  }
-  {
-    double weight = BernsteinPolynomial<Two, Two>::apply(t);
-    vector3_add(result.m_vertex, vector3_scaled(firstPoint[2].m_vertex, weight));
-    vector2_add(result.m_texcoord, vector2_scaled(firstPoint[2].m_texcoord, weight));
-    denominator += weight;
-  }
+    vector3_divide(result.m_vertex, denominator);
+    vector2_divide(result.m_texcoord, denominator);
+    return result;
+}
 
-  vector3_divide(result.m_vertex, denominator);
-  vector2_divide(result.m_texcoord, denominator);
-  return result;
+inline Vector3 vector3_linear_interpolated(const Vector3 &a, const Vector3 &b, double t)
+{
+    return vector3_added(vector3_scaled(a, 1.0 - t), vector3_scaled(b, t));
 }
 
-inline Vector3 vector3_linear_interpolated(const Vector3& a, const Vector3& b, double t)
+inline Vector2 vector2_linear_interpolated(const Vector2 &a, const Vector2 &b, double t)
 {
-  return vector3_added(vector3_scaled(a, 1.0 - t), vector3_scaled(b, t));
+    return vector2_added(vector2_scaled(a, 1.0 - t), vector2_scaled(b, t));
 }
 
-inline Vector2 vector2_linear_interpolated(const Vector2& a, const Vector2& b, double t)
+void normalise_safe(Vector3 &normal)
 {
-  return vector2_added(vector2_scaled(a, 1.0 - t), vector2_scaled(b, t));
+    if (!vector3_equal(normal, g_vector3_identity)) {
+        vector3_normalise(normal);
+    }
 }
 
-void normalise_safe(Vector3& normal)
+inline void QuadraticBezier_evaluate(const PatchControl &a, const PatchControl &b, const PatchControl &c, double t,
+                                     PatchControl &point, PatchControl &left, PatchControl &right)
 {
-  if(!vector3_equal(normal, g_vector3_identity))
-  {
-    vector3_normalise(normal);
-  }
+    left.m_vertex = vector3_linear_interpolated(a.m_vertex, b.m_vertex, t);
+    left.m_texcoord = vector2_linear_interpolated(a.m_texcoord, b.m_texcoord, t);
+    right.m_vertex = vector3_linear_interpolated(b.m_vertex, c.m_vertex, t);
+    right.m_texcoord = vector2_linear_interpolated(b.m_texcoord, c.m_texcoord, t);
+    point.m_vertex = vector3_linear_interpolated(left.m_vertex, right.m_vertex, t);
+    point.m_texcoord = vector2_linear_interpolated(left.m_texcoord, right.m_texcoord, t);
 }
 
-inline void QuadraticBezier_evaluate(const PatchControl& a, const PatchControl& b, const PatchControl& c, double t, PatchControl& point, PatchControl& left, PatchControl& right)
+void Patch::TesselateSubMatrixFixed(ArbitraryMeshVertex *vertices, std::size_t strideX, std::size_t strideY,
+                                    unsigned int nFlagsX, unsigned int nFlagsY, PatchControl *subMatrix[3][3])
 {
-  left.m_vertex = vector3_linear_interpolated(a.m_vertex, b.m_vertex, t);
-  left.m_texcoord = vector2_linear_interpolated(a.m_texcoord, b.m_texcoord, t);
-  right.m_vertex = vector3_linear_interpolated(b.m_vertex, c.m_vertex, t);
-  right.m_texcoord = vector2_linear_interpolated(b.m_texcoord, c.m_texcoord, t);
-  point.m_vertex = vector3_linear_interpolated(left.m_vertex, right.m_vertex, t);
-  point.m_texcoord = vector2_linear_interpolated(left.m_texcoord, right.m_texcoord, t);
+    double incrementU = 1.0 / m_subdivisions_x;
+    double incrementV = 1.0 / m_subdivisions_y;
+    const std::size_t width = m_subdivisions_x + 1;
+    const std::size_t height = m_subdivisions_y + 1;
+
+    for (std::size_t i = 0; i != width; ++i) {
+        double tU = (i + 1 == width) ? 1 : i * incrementU;
+        PatchControl pointX[3];
+        PatchControl leftX[3];
+        PatchControl rightX[3];
+        QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0],
+                                 rightX[0]);
+        QuadraticBezier_evaluate(*subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1],
+                                 rightX[1]);
+        QuadraticBezier_evaluate(*subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2],
+                                 rightX[2]);
+
+        ArbitraryMeshVertex *p = vertices + i * strideX;
+        for (std::size_t j = 0; j != height; ++j) {
+            if ((j == 0 || j + 1 == height) && (i == 0 || i + 1 == width)) {
+            } else {
+                double tV = (j + 1 == height) ? 1 : j * incrementV;
+
+                PatchControl pointY[3];
+                PatchControl leftY[3];
+                PatchControl rightY[3];
+                QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0],
+                                         rightY[0]);
+                QuadraticBezier_evaluate(*subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1],
+                                         rightY[1]);
+                QuadraticBezier_evaluate(*subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2],
+                                         rightY[2]);
+
+                PatchControl point;
+                PatchControl left;
+                PatchControl right;
+                QuadraticBezier_evaluate(pointX[0], pointX[1], pointX[2], tV, point, left, right);
+                PatchControl up;
+                PatchControl down;
+                QuadraticBezier_evaluate(pointY[0], pointY[1], pointY[2], tU, point, up, down);
+
+                vertex3f_to_vector3(p->vertex) = point.m_vertex;
+                texcoord2f_to_vector2(p->texcoord) = point.m_texcoord;
+
+                ArbitraryMeshVertex a, b, c;
+
+                a.vertex = vertex3f_for_vector3(left.m_vertex);
+                a.texcoord = texcoord2f_for_vector2(left.m_texcoord);
+                b.vertex = vertex3f_for_vector3(right.m_vertex);
+                b.texcoord = texcoord2f_for_vector2(right.m_texcoord);
+
+                if (i != 0) {
+                    c.vertex = vertex3f_for_vector3(up.m_vertex);
+                    c.texcoord = texcoord2f_for_vector2(up.m_texcoord);
+                } else {
+                    c.vertex = vertex3f_for_vector3(down.m_vertex);
+                    c.texcoord = texcoord2f_for_vector2(down.m_texcoord);
+                }
+
+                Vector3 normal = vector3_normalised(
+                        vector3_cross(right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex));
+
+                Vector3 tangent, bitangent;
+                ArbitraryMeshTriangle_calcTangents(a, b, c, tangent, bitangent);
+                vector3_normalise(tangent);
+                vector3_normalise(bitangent);
+
+                if (((nFlagsX & AVERAGE) != 0 && i == 0) || ((nFlagsY & AVERAGE) != 0 && j == 0)) {
+                    normal3f_to_vector3(p->normal) = vector3_normalised(
+                            vector3_added(normal3f_to_vector3(p->normal), normal));
+                    normal3f_to_vector3(p->tangent) = vector3_normalised(
+                            vector3_added(normal3f_to_vector3(p->tangent), tangent));
+                    normal3f_to_vector3(p->bitangent) = vector3_normalised(
+                            vector3_added(normal3f_to_vector3(p->bitangent), bitangent));
+                } else {
+                    normal3f_to_vector3(p->normal) = normal;
+                    normal3f_to_vector3(p->tangent) = tangent;
+                    normal3f_to_vector3(p->bitangent) = bitangent;
+                }
+            }
+
+            p += strideY;
+        }
+    }
 }
 
-void Patch::TesselateSubMatrixFixed(ArbitraryMeshVertex* vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl* subMatrix[3][3])
+void Patch::TesselateSubMatrix(const BezierCurveTree *BX, const BezierCurveTree *BY,
+                               std::size_t offStartX, std::size_t offStartY,
+                               std::size_t offEndX, std::size_t offEndY,
+                               std::size_t nFlagsX, std::size_t nFlagsY,
+                               Vector3 &left, Vector3 &mid, Vector3 &right,
+                               Vector2 &texLeft, Vector2 &texMid, Vector2 &texRight,
+                               bool bTranspose)
 {
-  double incrementU = 1.0 / m_subdivisions_x;
-  double incrementV = 1.0 / m_subdivisions_y;
-  const std::size_t width = m_subdivisions_x + 1;
-  const std::size_t height = m_subdivisions_y + 1;
+    int newFlagsX, newFlagsY;
 
-  for(std::size_t i = 0; i != width; ++i)
-  {
-    double tU = (i + 1 == width) ? 1 : i * incrementU;
-    PatchControl pointX[3];
-    PatchControl leftX[3];
-    PatchControl rightX[3];
-    QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0], rightX[0]);
-    QuadraticBezier_evaluate(*subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1], rightX[1]);
-    QuadraticBezier_evaluate(*subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2], rightX[2]);
+    Vector3 tmp;
+    Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1;
+    Vector2 texTmp;
+    Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1;
 
-    ArbitraryMeshVertex* p = vertices + i * strideX;
-    for(std::size_t j = 0; j != height; ++j)
     {
-      if((j == 0 || j + 1 == height) && (i == 0 || i + 1 == width))
-      {
-      }
-      else
-      {
-        double tV = (j + 1 == height) ? 1 : j * incrementV;
-
-        PatchControl pointY[3];
-        PatchControl leftY[3];
-        PatchControl rightY[3];
-        QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0], rightY[0]);
-        QuadraticBezier_evaluate(*subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1], rightY[1]);
-        QuadraticBezier_evaluate(*subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2], rightY[2]);
-
-        PatchControl point;
-        PatchControl left;
-        PatchControl right;
-        QuadraticBezier_evaluate(pointX[0], pointX[1], pointX[2], tV, point, left, right);
-        PatchControl up;
-        PatchControl down;
-        QuadraticBezier_evaluate(pointY[0], pointY[1], pointY[2], tU, point, up, down);
-
-        vertex3f_to_vector3(p->vertex) = point.m_vertex;
-        texcoord2f_to_vector2(p->texcoord) = point.m_texcoord;
+        // texcoords
 
-        ArbitraryMeshVertex a, b, c;
+        BezierInterpolate2(texcoord_for_index(m_tess.m_vertices, offStartX + offStartY),
+                           texcoord_0_0,
+                           texcoord_for_index(m_tess.m_vertices, BX->index + offStartY),
+                           texcoord_0_1,
+                           texcoord_for_index(m_tess.m_vertices, offEndX + offStartY));
 
-        a.vertex = vertex3f_for_vector3(left.m_vertex);
-        a.texcoord = texcoord2f_for_vector2(left.m_texcoord);
-        b.vertex = vertex3f_for_vector3(right.m_vertex);
-        b.texcoord = texcoord2f_for_vector2(right.m_texcoord);
 
-        if(i != 0)
-        {
-          c.vertex = vertex3f_for_vector3(up.m_vertex);
-          c.texcoord = texcoord2f_for_vector2(up.m_texcoord);
-        }
-        else
-        {
-          c.vertex = vertex3f_for_vector3(down.m_vertex);
-          c.texcoord = texcoord2f_for_vector2(down.m_texcoord);
+        BezierInterpolate2(texcoord_for_index(m_tess.m_vertices, offStartX + offEndY),
+                           texcoord_2_0,
+                           texcoord_for_index(m_tess.m_vertices, BX->index + offEndY),
+                           texcoord_2_1,
+                           texcoord_for_index(m_tess.m_vertices, offEndX + offEndY));
+
+        texTmp = texMid;
+
+        BezierInterpolate2(texLeft,
+                           texcoord_1_0,
+                           texTmp,
+                           texcoord_1_1,
+                           texRight);
+
+        if (!BezierCurveTree_isLeaf(BY)) {
+            texcoord_for_index(m_tess.m_vertices, BX->index + BY->index) = texTmp;
         }
 
-        Vector3 normal = vector3_normalised(vector3_cross(right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex));
 
-        Vector3 tangent, bitangent;
-        ArbitraryMeshTriangle_calcTangents(a, b, c, tangent, bitangent);
-        vector3_normalise(tangent);
-        vector3_normalise(bitangent);
-       
-        if(((nFlagsX & AVERAGE) != 0 && i == 0) || ((nFlagsY & AVERAGE) != 0  && j == 0))
-        {
-          normal3f_to_vector3(p->normal) = vector3_normalised(vector3_added(normal3f_to_vector3(p->normal), normal));
-          normal3f_to_vector3(p->tangent) = vector3_normalised(vector3_added(normal3f_to_vector3(p->tangent), tangent));
-          normal3f_to_vector3(p->bitangent) = vector3_normalised(vector3_added(normal3f_to_vector3(p->bitangent), bitangent));
+        if (!BezierCurveTree_isLeaf(BX->left)) {
+            texcoord_for_index(m_tess.m_vertices, BX->left->index + offStartY) = texcoord_0_0;
+            texcoord_for_index(m_tess.m_vertices, BX->left->index + offEndY) = texcoord_2_0;
+
+            if (!BezierCurveTree_isLeaf(BY)) {
+                texcoord_for_index(m_tess.m_vertices, BX->left->index + BY->index) = texcoord_1_0;
+            }
         }
-        else
-        {
-          normal3f_to_vector3(p->normal) = normal;
-          normal3f_to_vector3(p->tangent) = tangent;
-          normal3f_to_vector3(p->bitangent) = bitangent;
+        if (!BezierCurveTree_isLeaf(BX->right)) {
+            texcoord_for_index(m_tess.m_vertices, BX->right->index + offStartY) = texcoord_0_1;
+            texcoord_for_index(m_tess.m_vertices, BX->right->index + offEndY) = texcoord_2_1;
+
+            if (!BezierCurveTree_isLeaf(BY)) {
+                texcoord_for_index(m_tess.m_vertices, BX->right->index + BY->index) = texcoord_1_1;
+            }
         }
-      }
 
-      p += strideY;
-    }
-  }
-}
 
-void Patch::TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
-                                        std::size_t offStartX, std::size_t offStartY,
-                                        std::size_t offEndX, std::size_t offEndY,
-                                        std::size_t nFlagsX, std::size_t nFlagsY,
-                                        Vector3& left, Vector3& mid, Vector3& right,
-                                        Vector2& texLeft, Vector2& texMid, Vector2& texRight,
-                                        bool bTranspose )
-{
-  int newFlagsX, newFlagsY;
+        // verts
 
-  Vector3 tmp;
-  Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1;
-  Vector2 texTmp;
-  Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1;
+        BezierInterpolate3(vertex_for_index(m_tess.m_vertices, offStartX + offStartY),
+                           vertex_0_0,
+                           vertex_for_index(m_tess.m_vertices, BX->index + offStartY),
+                           vertex_0_1,
+                           vertex_for_index(m_tess.m_vertices, offEndX + offStartY));
 
-  {
-   // texcoords
 
-    BezierInterpolate2( texcoord_for_index(m_tess.m_vertices, offStartX + offStartY),
-                     texcoord_0_0,
-                     texcoord_for_index(m_tess.m_vertices, BX->index + offStartY),
-                     texcoord_0_1,
-                     texcoord_for_index(m_tess.m_vertices, offEndX + offStartY) );
+        BezierInterpolate3(vertex_for_index(m_tess.m_vertices, offStartX + offEndY),
+                           vertex_2_0,
+                           vertex_for_index(m_tess.m_vertices, BX->index + offEndY),
+                           vertex_2_1,
+                           vertex_for_index(m_tess.m_vertices, offEndX + offEndY));
 
 
-    BezierInterpolate2( texcoord_for_index(m_tess.m_vertices, offStartX + offEndY),
-                     texcoord_2_0,
-                     texcoord_for_index(m_tess.m_vertices, BX->index + offEndY),
-                     texcoord_2_1,
-                     texcoord_for_index(m_tess.m_vertices, offEndX + offEndY) );
+        tmp = mid;
 
-    texTmp = texMid;
+        BezierInterpolate3(left,
+                           vertex_1_0,
+                           tmp,
+                           vertex_1_1,
+                           right);
 
-    BezierInterpolate2(texLeft,
-                      texcoord_1_0,
-                      texTmp,
-                      texcoord_1_1,
-                      texRight);
+        if (!BezierCurveTree_isLeaf(BY)) {
+            vertex_for_index(m_tess.m_vertices, BX->index + BY->index) = tmp;
+        }
 
-    if(!BezierCurveTree_isLeaf(BY))
-    {
-      texcoord_for_index(m_tess.m_vertices, BX->index + BY->index) = texTmp;
-    }
 
-  
-    if(!BezierCurveTree_isLeaf(BX->left))
-    {
-      texcoord_for_index(m_tess.m_vertices, BX->left->index + offStartY) = texcoord_0_0;
-      texcoord_for_index(m_tess.m_vertices, BX->left->index + offEndY) = texcoord_2_0;
+        if (!BezierCurveTree_isLeaf(BX->left)) {
+            vertex_for_index(m_tess.m_vertices, BX->left->index + offStartY) = vertex_0_0;
+            vertex_for_index(m_tess.m_vertices, BX->left->index + offEndY) = vertex_2_0;
 
-      if(!BezierCurveTree_isLeaf(BY))
-      {
-        texcoord_for_index(m_tess.m_vertices, BX->left->index + BY->index) = texcoord_1_0;
-      }
-    }
-    if(!BezierCurveTree_isLeaf(BX->right))
-    {
-      texcoord_for_index(m_tess.m_vertices, BX->right->index + offStartY) = texcoord_0_1;
-      texcoord_for_index(m_tess.m_vertices, BX->right->index + offEndY) = texcoord_2_1;
+            if (!BezierCurveTree_isLeaf(BY)) {
+                vertex_for_index(m_tess.m_vertices, BX->left->index + BY->index) = vertex_1_0;
+            }
+        }
+        if (!BezierCurveTree_isLeaf(BX->right)) {
+            vertex_for_index(m_tess.m_vertices, BX->right->index + offStartY) = vertex_0_1;
+            vertex_for_index(m_tess.m_vertices, BX->right->index + offEndY) = vertex_2_1;
 
-      if(!BezierCurveTree_isLeaf(BY))
-      {
-        texcoord_for_index(m_tess.m_vertices, BX->right->index + BY->index) = texcoord_1_1;
-      }
-    }
+            if (!BezierCurveTree_isLeaf(BY)) {
+                vertex_for_index(m_tess.m_vertices, BX->right->index + BY->index) = vertex_1_1;
+            }
+        }
 
+        // normals
+
+        if (nFlagsX & SPLIT) {
+            ArbitraryMeshVertex a, b, c;
+            Vector3 tangentU;
+
+            if (!(nFlagsX & DEGEN_0a) || !(nFlagsX & DEGEN_0b)) {
+                tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
+                a.vertex = vertex3f_for_vector3(vertex_0_0);
+                a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
+                c.vertex = vertex3f_for_vector3(vertex_0_1);
+                c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
+            } else if (!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b)) {
+                tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
+                a.vertex = vertex3f_for_vector3(vertex_1_0);
+                a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
+                c.vertex = vertex3f_for_vector3(vertex_1_1);
+                c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
+            } else {
+                tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
+                a.vertex = vertex3f_for_vector3(vertex_2_0);
+                a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
+                c.vertex = vertex3f_for_vector3(vertex_2_1);
+                c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
+            }
 
-    // verts
+            Vector3 tangentV;
 
-    BezierInterpolate3( vertex_for_index(m_tess.m_vertices, offStartX + offStartY),
-                     vertex_0_0,
-                     vertex_for_index(m_tess.m_vertices, BX->index + offStartY),
-                     vertex_0_1,
-                     vertex_for_index(m_tess.m_vertices, offEndX + offStartY) );
+            if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a)) {
+                tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
+                b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offEndY].vertex;
+                b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offEndY].texcoord;
+            } else {
+                tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
+                b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offStartY].vertex;
+                b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord;
+            }
 
 
-    BezierInterpolate3( vertex_for_index(m_tess.m_vertices, offStartX + offEndY),
-                     vertex_2_0,
-                     vertex_for_index(m_tess.m_vertices, BX->index + offEndY),
-                     vertex_2_1,
-                     vertex_for_index(m_tess.m_vertices, offEndX + offEndY) );
+            Vector3 normal, s, t;
+            ArbitraryMeshVertex &v = m_tess.m_vertices[offStartY + BX->index];
+            Vector3 &p = normal3f_to_vector3(v.normal);
+            Vector3 &ps = normal3f_to_vector3(v.tangent);
+            Vector3 &pt = normal3f_to_vector3(v.bitangent);
 
+            if (bTranspose) {
+                normal = vector3_cross(tangentV, tangentU);
+            } else {
+                normal = vector3_cross(tangentU, tangentV);
+            }
+            normalise_safe(normal);
+
+            ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
+            normalise_safe(s);
+            normalise_safe(t);
+
+            if (nFlagsX & AVERAGE) {
+                p = vector3_normalised(vector3_added(p, normal));
+                ps = vector3_normalised(vector3_added(ps, s));
+                pt = vector3_normalised(vector3_added(pt, t));
+            } else {
+                p = normal;
+                ps = s;
+                pt = t;
+            }
+        }
 
-    tmp = mid;
+        {
+            ArbitraryMeshVertex a, b, c;
+            Vector3 tangentU;
+
+            if (!(nFlagsX & DEGEN_2a) || !(nFlagsX & DEGEN_2b)) {
+                tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
+                a.vertex = vertex3f_for_vector3(vertex_2_0);
+                a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
+                c.vertex = vertex3f_for_vector3(vertex_2_1);
+                c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
+            } else if (!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b)) {
+                tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
+                a.vertex = vertex3f_for_vector3(vertex_1_0);
+                a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
+                c.vertex = vertex3f_for_vector3(vertex_1_1);
+                c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
+            } else {
+                tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
+                a.vertex = vertex3f_for_vector3(vertex_0_0);
+                a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
+                c.vertex = vertex3f_for_vector3(vertex_0_1);
+                c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
+            }
 
-    BezierInterpolate3( left,
-                     vertex_1_0,
-                     tmp,
-                     vertex_1_1,
-                     right );
+            Vector3 tangentV;
 
-    if(!BezierCurveTree_isLeaf(BY))
-    {
-      vertex_for_index(m_tess.m_vertices, BX->index + BY->index) = tmp;
-    }
+            if ((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b)) {
+                tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
+                b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offStartY].vertex;
+                b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord;
+            } else {
+                tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
+                b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offEndY].vertex;
+                b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offEndY].texcoord;
+            }
 
-  
-    if(!BezierCurveTree_isLeaf(BX->left))
-    {
-      vertex_for_index(m_tess.m_vertices, BX->left->index + offStartY) = vertex_0_0;
-      vertex_for_index(m_tess.m_vertices, BX->left->index + offEndY) = vertex_2_0;
+            ArbitraryMeshVertex &v = m_tess.m_vertices[offEndY + BX->index];
+            Vector3 &p = normal3f_to_vector3(v.normal);
+            Vector3 &ps = normal3f_to_vector3(v.tangent);
+            Vector3 &pt = normal3f_to_vector3(v.bitangent);
 
-      if(!BezierCurveTree_isLeaf(BY))
-      {
-        vertex_for_index(m_tess.m_vertices, BX->left->index + BY->index) = vertex_1_0;
-      }
-    }
-    if(!BezierCurveTree_isLeaf(BX->right))
-    {
-      vertex_for_index(m_tess.m_vertices, BX->right->index + offStartY) = vertex_0_1;
-      vertex_for_index(m_tess.m_vertices, BX->right->index + offEndY) = vertex_2_1;
+            if (bTranspose) {
+                p = vector3_cross(tangentV, tangentU);
+            } else {
+                p = vector3_cross(tangentU, tangentV);
+            }
+            normalise_safe(p);
 
-      if(!BezierCurveTree_isLeaf(BY))
-      {
-        vertex_for_index(m_tess.m_vertices, BX->right->index + BY->index) = vertex_1_1;
-      }
+            ArbitraryMeshTriangle_calcTangents(a, b, c, ps, pt);
+            normalise_safe(ps);
+            normalise_safe(pt);
+        }
     }
 
-    // normals
 
-    if(nFlagsX & SPLIT)
-    {
-      ArbitraryMeshVertex a, b, c;
-      Vector3 tangentU;
-      if(!(nFlagsX & DEGEN_0a) || !(nFlagsX & DEGEN_0b))
-      {
-        tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
-        a.vertex = vertex3f_for_vector3(vertex_0_0);
-        a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
-        c.vertex = vertex3f_for_vector3(vertex_0_1);
-        c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
-      }
-      else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
-      {
-        tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
-        a.vertex = vertex3f_for_vector3(vertex_1_0);
-        a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
-        c.vertex = vertex3f_for_vector3(vertex_1_1);
-        c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
-      }
-      else
-      {
-        tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
-        a.vertex = vertex3f_for_vector3(vertex_2_0);
-        a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
-        c.vertex = vertex3f_for_vector3(vertex_2_1);
-        c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
-      }
-
-      Vector3 tangentV;
-
-      if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
-      {
-        tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
-        b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offEndY].vertex;
-        b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offEndY].texcoord;
-      }
-      else
-      {
-        tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
-        b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offStartY].vertex;
-        b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord;
-      }
-  
-
-      Vector3 normal, s, t;
-      ArbitraryMeshVertex& v = m_tess.m_vertices[offStartY + BX->index];
-      Vector3& p = normal3f_to_vector3(v.normal);
-      Vector3& ps = normal3f_to_vector3(v.tangent);
-      Vector3& pt = normal3f_to_vector3(v.bitangent);
-
-      if(bTranspose)
-      {
-        normal = vector3_cross(tangentV, tangentU);
-      }
-      else
-      {
-        normal = vector3_cross(tangentU, tangentV);
-      }
-      normalise_safe(normal);
-
-      ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
-      normalise_safe(s);
-      normalise_safe(t);
-
-      if(nFlagsX & AVERAGE)
-      {
-        p = vector3_normalised(vector3_added(p, normal));
-        ps = vector3_normalised(vector3_added(ps, s));
-        pt = vector3_normalised(vector3_added(pt, t));
-      }
-      else
-      {
-        p = normal;
-        ps = s;
-        pt = t;
-      }
-    }
-
-    {
-      ArbitraryMeshVertex a, b, c;
-      Vector3 tangentU;
-
-      if(!(nFlagsX & DEGEN_2a) || !(nFlagsX & DEGEN_2b))
-      {
-        tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
-        a.vertex = vertex3f_for_vector3(vertex_2_0);
-        a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
-        c.vertex = vertex3f_for_vector3(vertex_2_1);
-        c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
-      }
-      else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
-      {
-        tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
-        a.vertex = vertex3f_for_vector3(vertex_1_0);
-        a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
-        c.vertex = vertex3f_for_vector3(vertex_1_1);
-        c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
-      }
-      else
-      {
-        tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
-        a.vertex = vertex3f_for_vector3(vertex_0_0);
-        a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
-        c.vertex = vertex3f_for_vector3(vertex_0_1);
-        c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
-      }
-
-      Vector3 tangentV;
-
-      if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
-      {
-        tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
-        b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offStartY].vertex;
-        b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offStartY].texcoord;
-      }
-      else
-      {
-        tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
-        b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offEndY].vertex;
-        b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offEndY].texcoord;
-      }
-
-      ArbitraryMeshVertex& v = m_tess.m_vertices[offEndY+BX->index];
-      Vector3& p = normal3f_to_vector3(v.normal);
-      Vector3& ps = normal3f_to_vector3(v.tangent);
-      Vector3& pt = normal3f_to_vector3(v.bitangent);
-
-      if(bTranspose)
-      {
-        p = vector3_cross(tangentV, tangentU);
-      }
-      else
-      {
-        p = vector3_cross(tangentU, tangentV);
-      }
-      normalise_safe(p);
-
-      ArbitraryMeshTriangle_calcTangents(a, b, c, ps, pt);
-      normalise_safe(ps);
-      normalise_safe(pt);
-    }
-  }
-
-  
-  newFlagsX = newFlagsY = 0;
-
-  if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_0b))
-  {
-    newFlagsX |= DEGEN_0a;
-    newFlagsX |= DEGEN_0b;
-  }
-  if((nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_1b))
-  {
-    newFlagsX |= DEGEN_1a;
-    newFlagsX |= DEGEN_1b;
-  }
-  if((nFlagsX & DEGEN_2a) && (nFlagsX & DEGEN_2b))
-  {
-    newFlagsX |= DEGEN_2a;
-    newFlagsX |= DEGEN_2b;
-  }
-  if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
-  {
-    newFlagsY |= DEGEN_0a;
-    newFlagsY |= DEGEN_1a;
-    newFlagsY |= DEGEN_2a;
-  }
-  if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
-  {
-    newFlagsY |= DEGEN_0b;
-    newFlagsY |= DEGEN_1b;
-    newFlagsY |= DEGEN_2b;
-  }
-
-  
-  //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; }
-  //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; }
-  
-  newFlagsX |= (nFlagsX & SPLIT);
-  newFlagsX |= (nFlagsX & AVERAGE);
-      
-  if(!BezierCurveTree_isLeaf(BY))
-  {
-    {
-      int nTemp = newFlagsY;
+    newFlagsX = newFlagsY = 0;
 
-      if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_0b))
-      {
+    if ((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_0b)) {
+        newFlagsX |= DEGEN_0a;
+        newFlagsX |= DEGEN_0b;
+    }
+    if ((nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_1b)) {
+        newFlagsX |= DEGEN_1a;
+        newFlagsX |= DEGEN_1b;
+    }
+    if ((nFlagsX & DEGEN_2a) && (nFlagsX & DEGEN_2b)) {
+        newFlagsX |= DEGEN_2a;
+        newFlagsX |= DEGEN_2b;
+    }
+    if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a)) {
         newFlagsY |= DEGEN_0a;
+        newFlagsY |= DEGEN_1a;
+        newFlagsY |= DEGEN_2a;
+    }
+    if ((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b)) {
         newFlagsY |= DEGEN_0b;
-      }
-      newFlagsY |= (nFlagsY & SPLIT);
-      newFlagsY |= (nFlagsY & AVERAGE);
-
-      Vector3& p = vertex_for_index(m_tess.m_vertices, BX->index+BY->index);
-      Vector3 vTemp(p);
-
-      Vector2& p2 = texcoord_for_index(m_tess.m_vertices, BX->index+BY->index);
-      Vector2 stTemp(p2);
-
-      TesselateSubMatrix( BY, BX->left,
-                          offStartY, offStartX,
-                          offEndY, BX->index,
-                          newFlagsY, newFlagsX,
-                          vertex_0_0, vertex_1_0, vertex_2_0,
-                          texcoord_0_0, texcoord_1_0, texcoord_2_0,
-                          !bTranspose );
-
-      newFlagsY = nTemp;
-      p = vTemp;
-      p2 = stTemp;
-    }
-
-    if((nFlagsY & DEGEN_2a) && (nFlagsY & DEGEN_2b)) { newFlagsY |= DEGEN_2a; newFlagsY |= DEGEN_2b; }
-    
-    TesselateSubMatrix( BY, BX->right,
-                        offStartY, BX->index,
-                        offEndY, offEndX,
-                        newFlagsY, newFlagsX,
-                        vertex_0_1, vertex_1_1, vertex_2_1,
-                        texcoord_0_1, texcoord_1_1, texcoord_2_1,
-                        !bTranspose );
-  }
-  else
-  {
-    if(!BezierCurveTree_isLeaf(BX->left))
-    {
-      TesselateSubMatrix( BX->left,  BY,
-                          offStartX, offStartY,
-                          BX->index, offEndY,
-                          newFlagsX, newFlagsY,
-                          left, vertex_1_0, tmp,
-                          texLeft, texcoord_1_0, texTmp,
-                          bTranspose );
+        newFlagsY |= DEGEN_1b;
+        newFlagsY |= DEGEN_2b;
     }
 
-    if(!BezierCurveTree_isLeaf(BX->right))
-    {
-      TesselateSubMatrix( BX->right, BY,
-                          BX->index, offStartY,
-                          offEndX, offEndY,
-                          newFlagsX, newFlagsY,
-                          tmp, vertex_1_1, right,
-                          texTmp, texcoord_1_1, texRight,
-                          bTranspose );
+
+    //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; }
+    //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; }
+
+    newFlagsX |= (nFlagsX & SPLIT);
+    newFlagsX |= (nFlagsX & AVERAGE);
+
+    if (!BezierCurveTree_isLeaf(BY)) {
+        {
+            int nTemp = newFlagsY;
+
+            if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_0b)) {
+                newFlagsY |= DEGEN_0a;
+                newFlagsY |= DEGEN_0b;
+            }
+            newFlagsY |= (nFlagsY & SPLIT);
+            newFlagsY |= (nFlagsY & AVERAGE);
+
+            Vector3 &p = vertex_for_index(m_tess.m_vertices, BX->index + BY->index);
+            Vector3 vTemp(p);
+
+            Vector2 &p2 = texcoord_for_index(m_tess.m_vertices, BX->index + BY->index);
+            Vector2 stTemp(p2);
+
+            TesselateSubMatrix(BY, BX->left,
+                               offStartY, offStartX,
+                               offEndY, BX->index,
+                               newFlagsY, newFlagsX,
+                               vertex_0_0, vertex_1_0, vertex_2_0,
+                               texcoord_0_0, texcoord_1_0, texcoord_2_0,
+                               !bTranspose);
+
+            newFlagsY = nTemp;
+            p = vTemp;
+            p2 = stTemp;
+        }
+
+        if ((nFlagsY & DEGEN_2a) && (nFlagsY & DEGEN_2b)) {
+            newFlagsY |= DEGEN_2a;
+            newFlagsY |= DEGEN_2b;
+        }
+
+        TesselateSubMatrix(BY, BX->right,
+                           offStartY, BX->index,
+                           offEndY, offEndX,
+                           newFlagsY, newFlagsX,
+                           vertex_0_1, vertex_1_1, vertex_2_1,
+                           texcoord_0_1, texcoord_1_1, texcoord_2_1,
+                           !bTranspose);
+    } else {
+        if (!BezierCurveTree_isLeaf(BX->left)) {
+            TesselateSubMatrix(BX->left, BY,
+                               offStartX, offStartY,
+                               BX->index, offEndY,
+                               newFlagsX, newFlagsY,
+                               left, vertex_1_0, tmp,
+                               texLeft, texcoord_1_0, texTmp,
+                               bTranspose);
+        }
+
+        if (!BezierCurveTree_isLeaf(BX->right)) {
+            TesselateSubMatrix(BX->right, BY,
+                               BX->index, offStartY,
+                               offEndX, offEndY,
+                               newFlagsX, newFlagsY,
+                               tmp, vertex_1_1, right,
+                               texTmp, texcoord_1_1, texRight,
+                               bTranspose);
+        }
     }
-  }
 
 }
 
 void Patch::BuildTesselationCurves(EMatrixMajor major)
 {
-  std::size_t nArrayStride, length, cross, strideU, strideV;
-  switch(major)
-  {
-  case ROW:
-    nArrayStride = 1;
-    length = (m_width - 1) >> 1;
-    cross = m_height;
-    strideU = 1;
-    strideV = m_width;
-
-    if(!m_patchDef3)
-    {
-      BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU);
-    }
+    std::size_t nArrayStride, length, cross, strideU, strideV;
+    switch (major) {
+        case ROW:
+            nArrayStride = 1;
+            length = (m_width - 1) >> 1;
+            cross = m_height;
+            strideU = 1;
+            strideV = m_width;
+
+            if (!m_patchDef3) {
+                BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU);
+            }
 
-    break;
-  case COL:
-    nArrayStride = m_tess.m_nArrayWidth;
-    length = (m_height - 1) >> 1;
-    cross = m_width;
-    strideU = m_width;
-    strideV = 1;
+            break;
+        case COL:
+            nArrayStride = m_tess.m_nArrayWidth;
+            length = (m_height - 1) >> 1;
+            cross = m_width;
+            strideU = m_width;
+            strideV = 1;
+
+            if (!m_patchDef3) {
+                BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV);
+            }
 
-    if(!m_patchDef3)
-    {
-      BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV);
+            break;
+        default:
+            ERROR_MESSAGE("neither row-major nor column-major");
+            return;
     }
 
-    break;
-  default:
-    ERROR_MESSAGE("neither row-major nor column-major");
-    return;
-  }
+    Array<std::size_t> arrayLength(length);
+    Array<BezierCurveTree *> pCurveTree(length);
 
-  Array<std::size_t> arrayLength(length);
-  Array<BezierCurveTree*> pCurveTree(length);
+    std::size_t nArrayLength = 1;
 
-  std::size_t nArrayLength = 1;
-
-  if(m_patchDef3)
-  {
-    for(Array<std::size_t>::iterator i = arrayLength.begin(); i != arrayLength.end(); ++i)
-    {
-      *i = Array<std::size_t>::value_type((major == ROW) ? m_subdivisions_x : m_subdivisions_y);
-      nArrayLength += *i;
-    }
-  }
-  else
-  {
-    // create a list of the horizontal control curves in each column of sub-patches
-    // adaptively tesselate each horizontal control curve in the list
-    // create a binary tree representing the combined tesselation of the list
-    for(std::size_t i = 0; i != length; ++i)
-    {
-      PatchControl* p1 = m_ctrlTransformed.data() + (i * 2 * strideU);
-      GSList* pCurveList = 0;
-      for(std::size_t j = 0; j < cross; j += 2)
-      {
-        PatchControl* p2 = p1+strideV;
-        PatchControl* p3 = p2+strideV;
-
-        // directly taken from one row of control points
-        {
-          BezierCurve* pCurve = new BezierCurve;
-          pCurve->crd = (p1+strideU)->m_vertex;
-          pCurve->left = p1->m_vertex;
-          pCurve->right = (p1+(strideU<<1))->m_vertex;
-          pCurveList = g_slist_prepend(pCurveList, pCurve);
+    if (m_patchDef3) {
+        for (Array<std::size_t>::iterator i = arrayLength.begin(); i != arrayLength.end(); ++i) {
+            *i = Array<std::size_t>::value_type((major == ROW) ? m_subdivisions_x : m_subdivisions_y);
+            nArrayLength += *i;
         }
+    } else {
+        // create a list of the horizontal control curves in each column of sub-patches
+        // adaptively tesselate each horizontal control curve in the list
+        // create a binary tree representing the combined tesselation of the list
+        for (std::size_t i = 0; i != length; ++i) {
+            PatchControl *p1 = m_ctrlTransformed.data() + (i * 2 * strideU);
+            GSList *pCurveList = 0;
+            for (std::size_t j = 0; j < cross; j += 2) {
+                PatchControl *p2 = p1 + strideV;
+                PatchControl *p3 = p2 + strideV;
+
+                // directly taken from one row of control points
+                {
+                    BezierCurve *pCurve = new BezierCurve;
+                    pCurve->crd = (p1 + strideU)->m_vertex;
+                    pCurve->left = p1->m_vertex;
+                    pCurve->right = (p1 + (strideU << 1))->m_vertex;
+                    pCurveList = g_slist_prepend(pCurveList, pCurve);
+                }
+
+                if (j + 2 >= cross) {
+                    break;
+                }
+
+                // interpolated from three columns of control points
+                {
+                    BezierCurve *pCurve = new BezierCurve;
+                    pCurve->crd = vector3_mid((p1 + strideU)->m_vertex, (p3 + strideU)->m_vertex);
+                    pCurve->left = vector3_mid(p1->m_vertex, p3->m_vertex);
+                    pCurve->right = vector3_mid((p1 + (strideU << 1))->m_vertex, (p3 + (strideU << 1))->m_vertex);
+
+                    pCurve->crd = vector3_mid(pCurve->crd, (p2 + strideU)->m_vertex);
+                    pCurve->left = vector3_mid(pCurve->left, p2->m_vertex);
+                    pCurve->right = vector3_mid(pCurve->right, (p2 + (strideU << 1))->m_vertex);
+                    pCurveList = g_slist_prepend(pCurveList, pCurve);
+                }
+
+                p1 = p3;
+            }
 
-        if(j+2 >= cross)
-        {
-          break;
+            pCurveTree[i] = new BezierCurveTree;
+            BezierCurveTree_FromCurveList(pCurveTree[i], pCurveList);
+            for (GSList *l = pCurveList; l != 0; l = g_slist_next(l)) {
+                delete static_cast<BezierCurve *>((*l).data );
+            }
+            g_slist_free(pCurveList);
+
+            // set up array indices for binary tree
+            // accumulate subarray width
+            arrayLength[i] = Array<std::size_t>::value_type(
+                    BezierCurveTree_Setup(pCurveTree[i], nArrayLength, nArrayStride) - (nArrayLength - 1));
+            // accumulate total array width
+            nArrayLength += arrayLength[i];
         }
-        
-        // interpolated from three columns of control points
-        {
-          BezierCurve* pCurve = new BezierCurve;
-          pCurve->crd = vector3_mid((p1+strideU)->m_vertex, (p3+strideU)->m_vertex);
-          pCurve->left = vector3_mid(p1->m_vertex, p3->m_vertex);
-          pCurve->right = vector3_mid((p1+(strideU<<1))->m_vertex, (p3+(strideU<<1))->m_vertex);
-    
-          pCurve->crd = vector3_mid(pCurve->crd, (p2+strideU)->m_vertex);
-          pCurve->left = vector3_mid(pCurve->left, p2->m_vertex);
-          pCurve->right = vector3_mid(pCurve->right, (p2+(strideU<<1))->m_vertex);
-          pCurveList = g_slist_prepend(pCurveList, pCurve);
-        }
-
-        p1 = p3;
-      }
-
-      pCurveTree[i] = new BezierCurveTree;
-      BezierCurveTree_FromCurveList(pCurveTree[i], pCurveList);
-      for(GSList* l = pCurveList; l != 0; l = g_slist_next(l))
-      {
-        delete static_cast<BezierCurve*>((*l).data);
-      }
-      g_slist_free(pCurveList);
-
-      // set up array indices for binary tree
-      // accumulate subarray width
-      arrayLength[i] = Array<std::size_t>::value_type(BezierCurveTree_Setup(pCurveTree[i], nArrayLength, nArrayStride) - (nArrayLength - 1));
-      // accumulate total array width
-      nArrayLength += arrayLength[i];
-    }
-  }
-
-  switch(major)
-  {
-  case ROW:
-    m_tess.m_nArrayWidth = nArrayLength;
-    std::swap(m_tess.m_arrayWidth, arrayLength);
-
-    if(!m_patchDef3)
-    {
-      std::swap(m_tess.m_curveTreeU, pCurveTree);
     }
-    break;
-  case COL:
-    m_tess.m_nArrayHeight = nArrayLength;
-    std::swap(m_tess.m_arrayHeight, arrayLength);
 
-    if(!m_patchDef3)
-    {
-      std::swap(m_tess.m_curveTreeV, pCurveTree);
+    switch (major) {
+        case ROW:
+            m_tess.m_nArrayWidth = nArrayLength;
+            std::swap(m_tess.m_arrayWidth, arrayLength);
+
+            if (!m_patchDef3) {
+                std::swap(m_tess.m_curveTreeU, pCurveTree);
+            }
+            break;
+        case COL:
+            m_tess.m_nArrayHeight = nArrayLength;
+            std::swap(m_tess.m_arrayHeight, arrayLength);
+
+            if (!m_patchDef3) {
+                std::swap(m_tess.m_curveTreeV, pCurveTree);
+            }
+            break;
     }
-    break;
-  }
 }
 
-inline void vertex_assign_ctrl(ArbitraryMeshVertex& vertex, const PatchControl& ctrl)
+inline void vertex_assign_ctrl(ArbitraryMeshVertex &vertex, const PatchControl &ctrl)
 {
-  vertex.vertex = vertex3f_for_vector3(ctrl.m_vertex);
-  vertex.texcoord = texcoord2f_for_vector2(ctrl.m_texcoord);
+    vertex.vertex = vertex3f_for_vector3(ctrl.m_vertex);
+    vertex.texcoord = texcoord2f_for_vector2(ctrl.m_texcoord);
 }
 
-inline void vertex_clear_normal(ArbitraryMeshVertexvertex)
+inline void vertex_clear_normal(ArbitraryMeshVertex &vertex)
 {
-  vertex.normal = Normal3f(0, 0, 0);
-  vertex.tangent = Normal3f(0, 0, 0);
-  vertex.bitangent = Normal3f(0, 0, 0);
+    vertex.normal = Normal3f(0, 0, 0);
+    vertex.tangent = Normal3f(0, 0, 0);
+    vertex.bitangent = Normal3f(0, 0, 0);
 }
-      
+
 inline void tangents_remove_degenerate(Vector3 tangents[6], Vector2 textureTangents[6], unsigned int flags)
 {
-  if(flags & DEGEN_0a)
-  {
-    const std::size_t i =
-      (flags & DEGEN_0b)
-      ? (flags & DEGEN_1a)
-        ? (flags & DEGEN_1b)
-          ? (flags & DEGEN_2a)
-            ? 5
-            : 4
-          : 3
-        : 2
-      : 1;
-    tangents[0] = tangents[i];
-    textureTangents[0] = textureTangents[i];
-  }
-  if(flags & DEGEN_0b)
-  {
-    const std::size_t i =
-      (flags & DEGEN_0a)
-      ? (flags & DEGEN_1b)
-        ? (flags & DEGEN_1a)
-          ? (flags & DEGEN_2b)
-            ? 4
-            : 5
-          : 2
-        : 3
-      : 0;
-    tangents[1] = tangents[i];
-    textureTangents[1] = textureTangents[i];
-  }
-  if(flags & DEGEN_2a)
-  {
-    const std::size_t i =
-      (flags & DEGEN_2b)
-      ? (flags & DEGEN_1a)
-        ? (flags & DEGEN_1b)
-          ? (flags & DEGEN_0a)
-            ? 1
-            : 0
-          : 3
-        : 2
-      : 5;
-    tangents[4] = tangents[i];
-    textureTangents[4] = textureTangents[i];
-  }
-  if(flags & DEGEN_2b)
-  {
-    const std::size_t i =
-      (flags & DEGEN_2a)
-      ? (flags & DEGEN_1b)
-        ? (flags & DEGEN_1a)
-          ? (flags & DEGEN_0b)
-            ? 0
-            : 1
-          : 2
-        : 3
-      : 4;
-    tangents[5] = tangents[i];
-    textureTangents[5] = textureTangents[i];
-  }
-}
-
-void bestTangents00(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
-{
-  if(fabs(dot + length) < 0.001) // opposing direction = degenerate
-  {
-    if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
-    {
-      index0 = 2;
-      index1 = 0;
-    }
-    else if(!(degenerateFlags & DEGEN_0b))
-    {
-      index0 = 0;
-      index1 = 1;
-    }
-    else
-    {
-      index0 = 1;
-      index1 = 0;
-    }
-  }
-  else if(fabs(dot - length) < 0.001) // same direction = degenerate
-  {
-    if(degenerateFlags & DEGEN_0b)
-    {
-      index0 = 0;
-      index1 = 1;
-    }
-    else
-    {
-      index0 = 1;
-      index1 = 0;
+    if (flags & DEGEN_0a) {
+        const std::size_t i =
+                (flags & DEGEN_0b)
+                ? (flags & DEGEN_1a)
+                  ? (flags & DEGEN_1b)
+                    ? (flags & DEGEN_2a)
+                      ? 5
+                      : 4
+                    : 3
+                  : 2
+                : 1;
+        tangents[0] = tangents[i];
+        textureTangents[0] = textureTangents[i];
+    }
+    if (flags & DEGEN_0b) {
+        const std::size_t i =
+                (flags & DEGEN_0a)
+                ? (flags & DEGEN_1b)
+                  ? (flags & DEGEN_1a)
+                    ? (flags & DEGEN_2b)
+                      ? 4
+                      : 5
+                    : 2
+                  : 3
+                : 0;
+        tangents[1] = tangents[i];
+        textureTangents[1] = textureTangents[i];
+    }
+    if (flags & DEGEN_2a) {
+        const std::size_t i =
+                (flags & DEGEN_2b)
+                ? (flags & DEGEN_1a)
+                  ? (flags & DEGEN_1b)
+                    ? (flags & DEGEN_0a)
+                      ? 1
+                      : 0
+                    : 3
+                  : 2
+                : 5;
+        tangents[4] = tangents[i];
+        textureTangents[4] = textureTangents[i];
+    }
+    if (flags & DEGEN_2b) {
+        const std::size_t i =
+                (flags & DEGEN_2a)
+                ? (flags & DEGEN_1b)
+                  ? (flags & DEGEN_1a)
+                    ? (flags & DEGEN_0b)
+                      ? 0
+                      : 1
+                    : 2
+                  : 3
+                : 4;
+        tangents[5] = tangents[i];
+        textureTangents[5] = textureTangents[i];
+    }
+}
+
+void bestTangents00(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
+{
+    if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
+        if (!(degenerateFlags & DEGEN_1a)) { // if this tangent is degenerate we cannot use it
+            index0 = 2;
+            index1 = 0;
+        } else if (!(degenerateFlags & DEGEN_0b)) {
+            index0 = 0;
+            index1 = 1;
+        } else {
+            index0 = 1;
+            index1 = 0;
+        }
+    } else if (fabs(dot - length) < 0.001) { // same direction = degenerate
+        if (degenerateFlags & DEGEN_0b) {
+            index0 = 0;
+            index1 = 1;
+        } else {
+            index0 = 1;
+            index1 = 0;
+        }
     }
-  }
 }
 
-void bestTangents01(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
+void bestTangents01(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
 {
-  if(fabs(dot - length) < 0.001) // same direction = degenerate
-  {
-    if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
-    {
-      index0 = 2;
-      index1 = 1;
-    }
-    else if(!(degenerateFlags & DEGEN_2b))
-    {
-      index0 = 4;
-      index1 = 0;
-    }
-    else
-    {
-      index0 = 5;
-      index1 = 1;
-    }
-  }
-  else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
-  {
-    if(degenerateFlags & DEGEN_2b)
-    {
-      index0 = 4;
-      index1 = 0;
-    }
-    else
-    {
-      index0 = 5;
-      index1 = 1;
+    if (fabs(dot - length) < 0.001) { // same direction = degenerate
+        if (!(degenerateFlags & DEGEN_1a)) { // if this tangent is degenerate we cannot use it
+            index0 = 2;
+            index1 = 1;
+        } else if (!(degenerateFlags & DEGEN_2b)) {
+            index0 = 4;
+            index1 = 0;
+        } else {
+            index0 = 5;
+            index1 = 1;
+        }
+    } else if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
+        if (degenerateFlags & DEGEN_2b) {
+            index0 = 4;
+            index1 = 0;
+        } else {
+            index0 = 5;
+            index1 = 1;
+        }
     }
-  }
 }
-void bestTangents10(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
+
+void bestTangents10(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
 {
-  if(fabs(dot - length) < 0.001) // same direction = degenerate
-  {
-    if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
-    {
-      index0 = 3;
-      index1 = 4;
-    }
-    else if(!(degenerateFlags & DEGEN_0a))
-    {
-      index0 = 1;
-      index1 = 5;
-    }
-    else
-    {
-      index0 = 0;
-      index1 = 4;
-    }
-  }
-  else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
-  {
-    if(degenerateFlags & DEGEN_0a)
-    {
-      index0 = 1;
-      index1 = 5;
-    }
-    else
-    {
-      index0 = 0;
-      index1 = 4;
+    if (fabs(dot - length) < 0.001) { // same direction = degenerate
+        if (!(degenerateFlags & DEGEN_1b)) { // if this tangent is degenerate we cannot use it
+            index0 = 3;
+            index1 = 4;
+        } else if (!(degenerateFlags & DEGEN_0a)) {
+            index0 = 1;
+            index1 = 5;
+        } else {
+            index0 = 0;
+            index1 = 4;
+        }
+    } else if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
+        if (degenerateFlags & DEGEN_0a) {
+            index0 = 1;
+            index1 = 5;
+        } else {
+            index0 = 0;
+            index1 = 4;
+        }
     }
-  }
 }
 
-void bestTangents11(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
+void bestTangents11(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
 {
-  if(fabs(dot + length) < 0.001) // opposing direction = degenerate
-  {
-    if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
-    {
-      index0 = 3;
-      index1 = 5;
-    }
-    else if(!(degenerateFlags & DEGEN_2a))
-    {
-      index0 = 5;
-      index1 = 4;
-    }
-    else
-    {
-      index0 = 4;
-      index1 = 5;
-    }
-  }
-  else if(fabs(dot - length) < 0.001) // same direction = degenerate
-  {
-    if(degenerateFlags & DEGEN_2a)
-    {
-      index0 = 5;
-      index1 = 4;
-    }
-    else
-    {
-      index0 = 4;
-      index1 = 5;
+    if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
+        if (!(degenerateFlags & DEGEN_1b)) { // if this tangent is degenerate we cannot use it
+            index0 = 3;
+            index1 = 5;
+        } else if (!(degenerateFlags & DEGEN_2a)) {
+            index0 = 5;
+            index1 = 4;
+        } else {
+            index0 = 4;
+            index1 = 5;
+        }
+    } else if (fabs(dot - length) < 0.001) { // same direction = degenerate
+        if (degenerateFlags & DEGEN_2a) {
+            index0 = 5;
+            index1 = 4;
+        } else {
+            index0 = 4;
+            index1 = 5;
+        }
     }
-  }
 }
 
-void Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1)
+void
+Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6],
+                                    Vector2 tangentT[6], std::size_t index0, std::size_t index1)
 {
-  {
-    Vector3 normal(vector3_cross(tangentX[index0], tangentY[index1]));
-    if(!vector3_equal(normal, g_vector3_identity))
     {
-      vector3_add(normal_for_index(m_tess.m_vertices, index), vector3_normalised(normal));
-    }
-  }
-
-  {
-    ArbitraryMeshVertex a, b, c;
-    a.vertex = Vertex3f(0, 0, 0);
-    a.texcoord = TexCoord2f(0, 0);
-    b.vertex = vertex3f_for_vector3(tangentX[index0]);
-    b.texcoord = texcoord2f_for_vector2(tangentS[index0]);
-    c.vertex = vertex3f_for_vector3(tangentY[index1]);
-    c.texcoord = texcoord2f_for_vector2(tangentT[index1]);
-
-    Vector3 s, t;
-    ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
-    if(!vector3_equal(s, g_vector3_identity))
-    {
-      vector3_add(tangent_for_index(m_tess.m_vertices, index), vector3_normalised(s));
+        Vector3 normal(vector3_cross(tangentX[index0], tangentY[index1]));
+        if (!vector3_equal(normal, g_vector3_identity)) {
+            vector3_add(normal_for_index(m_tess.m_vertices, index), vector3_normalised(normal));
+        }
     }
-    if(!vector3_equal(t, g_vector3_identity))
+
     {
-      vector3_add(bitangent_for_index(m_tess.m_vertices, index), vector3_normalised(t));
+        ArbitraryMeshVertex a, b, c;
+        a.vertex = Vertex3f(0, 0, 0);
+        a.texcoord = TexCoord2f(0, 0);
+        b.vertex = vertex3f_for_vector3(tangentX[index0]);
+        b.texcoord = texcoord2f_for_vector2(tangentS[index0]);
+        c.vertex = vertex3f_for_vector3(tangentY[index1]);
+        c.texcoord = texcoord2f_for_vector2(tangentT[index1]);
+
+        Vector3 s, t;
+        ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
+        if (!vector3_equal(s, g_vector3_identity)) {
+            vector3_add(tangent_for_index(m_tess.m_vertices, index), vector3_normalised(s));
+        }
+        if (!vector3_equal(t, g_vector3_identity)) {
+            vector3_add(bitangent_for_index(m_tess.m_vertices, index), vector3_normalised(t));
+        }
     }
-  }
 }
 
 const std::size_t PATCH_MAX_VERTEX_ARRAY = 1048576;
 
 void Patch::BuildVertexArray()
 {
-  const std::size_t strideU = 1;
-  const std::size_t strideV = m_width;
+    const std::size_t strideU = 1;
+    const std::size_t strideV = m_width;
 
-  const std::size_t numElems = m_tess.m_nArrayWidth*m_tess.m_nArrayHeight; // total number of elements in vertex array
+    const std::size_t numElems =
+            m_tess.m_nArrayWidth * m_tess.m_nArrayHeight; // total number of elements in vertex array
 
-  const bool bWidthStrips = (m_tess.m_nArrayWidth >= m_tess.m_nArrayHeight); // decide if horizontal strips are longer than vertical
+    const bool bWidthStrips = (m_tess.m_nArrayWidth >=
+                               m_tess.m_nArrayHeight); // decide if horizontal strips are longer than vertical
 
 
-  // allocate vertex, normal, texcoord and primitive-index arrays
-  m_tess.m_vertices.resize(numElems);
-  m_tess.m_indices.resize(m_tess.m_nArrayWidth *2 * (m_tess.m_nArrayHeight - 1));
+    // allocate vertex, normal, texcoord and primitive-index arrays
+    m_tess.m_vertices.resize(numElems);
+    m_tess.m_indices.resize(m_tess.m_nArrayWidth * 2 * (m_tess.m_nArrayHeight - 1));
 
-  // set up strip indices
-  if(bWidthStrips)
-  {
-    m_tess.m_numStrips = m_tess.m_nArrayHeight-1;
-    m_tess.m_lenStrips = m_tess.m_nArrayWidth*2;
-  
-    for(std::size_t i=0; i<m_tess.m_nArrayWidth; i++)
-    {
-      for(std::size_t j=0; j<m_tess.m_numStrips; j++)
-      {
-        m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(j*m_tess.m_nArrayWidth+i);
-        m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
-        // reverse because radiant uses CULL_FRONT
-        //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(j*m_tess.m_nArrayWidth+i);
-        //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
-      }
-    }
-  }
-  else
-  {
-    m_tess.m_numStrips = m_tess.m_nArrayWidth-1;
-    m_tess.m_lenStrips = m_tess.m_nArrayHeight*2;
-
-    for(std::size_t i=0; i<m_tess.m_nArrayHeight; i++)
-    {
-      for(std::size_t j=0; j<m_tess.m_numStrips; j++)
-      {
-        m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
-        m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1);
-        // reverse because radiant uses CULL_FRONT
-        //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
-        //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1);
-        
-      }
-    }
-  }
-
-  {
-    PatchControlIter pCtrl = m_ctrlTransformed.data();
-    for(std::size_t j = 0, offStartY = 0; j+1 < m_height; j += 2, pCtrl += (strideU + strideV))
-    {
-      // set up array offsets for this sub-patch
-      const bool leafY = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeV[j>>1]);
-      const std::size_t offMidY = (m_patchDef3) ? 0 : m_tess.m_curveTreeV[j>>1]->index;
-      const std::size_t widthY = m_tess.m_arrayHeight[j>>1] * m_tess.m_nArrayWidth;
-      const std::size_t offEndY = offStartY + widthY;
-
-      for(std::size_t i = 0, offStartX = 0; i+1 < m_width; i += 2, pCtrl += (strideU << 1))
-      {
-        const bool leafX = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i>>1]);
-        const std::size_t offMidX = (m_patchDef3) ? 0 : m_tess.m_curveTreeU[i>>1]->index;
-        const std::size_t widthX = m_tess.m_arrayWidth[i>>1];
-        const std::size_t offEndX = offStartX + widthX;
-
-        PatchControl *subMatrix[3][3];
-        subMatrix[0][0] = pCtrl;
-        subMatrix[0][1] = subMatrix[0][0]+strideU;
-        subMatrix[0][2] = subMatrix[0][1]+strideU;
-        subMatrix[1][0] = subMatrix[0][0]+strideV;
-        subMatrix[1][1] = subMatrix[1][0]+strideU;
-        subMatrix[1][2] = subMatrix[1][1]+strideU;
-        subMatrix[2][0] = subMatrix[1][0]+strideV;
-        subMatrix[2][1] = subMatrix[2][0]+strideU;
-        subMatrix[2][2] = subMatrix[2][1]+strideU;
-
-        // assign on-patch control points to vertex array
-        if(i == 0 && j == 0)
-        {
-          vertex_clear_normal(m_tess.m_vertices[offStartX + offStartY]);
-        }
-        vertex_assign_ctrl(m_tess.m_vertices[offStartX + offStartY], *subMatrix[0][0]);
-        if(j == 0)
-        {
-          vertex_clear_normal(m_tess.m_vertices[offEndX + offStartY]);
-        }
-        vertex_assign_ctrl(m_tess.m_vertices[offEndX + offStartY], *subMatrix[0][2]);
-        if(i == 0)
-        {
-          vertex_clear_normal(m_tess.m_vertices[offStartX + offEndY]);
-        }
-        vertex_assign_ctrl(m_tess.m_vertices[offStartX + offEndY], *subMatrix[2][0]);
-      
-        vertex_clear_normal(m_tess.m_vertices[offEndX + offEndY]);
-        vertex_assign_ctrl(m_tess.m_vertices[offEndX + offEndY], *subMatrix[2][2]);
+    // set up strip indices
+    if (bWidthStrips) {
+        m_tess.m_numStrips = m_tess.m_nArrayHeight - 1;
+        m_tess.m_lenStrips = m_tess.m_nArrayWidth * 2;
 
-        if(!m_patchDef3)
-        {
-          // assign remaining control points to vertex array
-          if(!leafX)
-          {
-            vertex_assign_ctrl(m_tess.m_vertices[offMidX + offStartY], *subMatrix[0][1]);
-            vertex_assign_ctrl(m_tess.m_vertices[offMidX + offEndY], *subMatrix[2][1]);
-          }
-          if(!leafY)
-          {
-            vertex_assign_ctrl(m_tess.m_vertices[offStartX + offMidY], *subMatrix[1][0]);
-            vertex_assign_ctrl(m_tess.m_vertices[offEndX + offMidY], *subMatrix[1][2]);
-
-            if(!leafX)
-            {
-              vertex_assign_ctrl(m_tess.m_vertices[offMidX + offMidY], *subMatrix[1][1]);
+        for (std::size_t i = 0; i < m_tess.m_nArrayWidth; i++) {
+            for (std::size_t j = 0; j < m_tess.m_numStrips; j++) {
+                m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2] = RenderIndex(j * m_tess.m_nArrayWidth + i);
+                m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2 + 1] = RenderIndex(
+                        (j + 1) * m_tess.m_nArrayWidth + i);
+                // reverse because radiant uses CULL_FRONT
+                //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(j*m_tess.m_nArrayWidth+i);
+                //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
             }
-          }
-        }
-
-        // test all 12 edges for degeneracy
-        unsigned int nFlagsX = subarray_get_degen(pCtrl, strideU, strideV);
-        unsigned int nFlagsY = subarray_get_degen(pCtrl, strideV, strideU);
-        Vector3 tangentX[6], tangentY[6];
-        Vector2 tangentS[6], tangentT[6];
-
-        // set up tangents for each of the 12 edges if they were not degenerate
-        if(!(nFlagsX & DEGEN_0a))
-        {
-          tangentX[0] = vector3_subtracted(subMatrix[0][1]->m_vertex, subMatrix[0][0]->m_vertex);
-          tangentS[0] = vector2_subtracted(subMatrix[0][1]->m_texcoord, subMatrix[0][0]->m_texcoord);
-        }
-        if(!(nFlagsX & DEGEN_0b))
-        {
-          tangentX[1] = vector3_subtracted(subMatrix[0][2]->m_vertex, subMatrix[0][1]->m_vertex);
-          tangentS[1] = vector2_subtracted(subMatrix[0][2]->m_texcoord, subMatrix[0][1]->m_texcoord);
-        }
-        if(!(nFlagsX & DEGEN_1a))
-        {
-          tangentX[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[1][0]->m_vertex);
-          tangentS[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[1][0]->m_texcoord);
-        }
-        if(!(nFlagsX & DEGEN_1b))
-        {
-          tangentX[3] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[1][1]->m_vertex);
-          tangentS[3] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[1][1]->m_texcoord);
-        }
-        if(!(nFlagsX & DEGEN_2a))
-        {
-          tangentX[4] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[2][0]->m_vertex);
-          tangentS[4] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[2][0]->m_texcoord);
-        }
-        if(!(nFlagsX & DEGEN_2b))
-        {
-          tangentX[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[2][1]->m_vertex);
-          tangentS[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[2][1]->m_texcoord);
-        }
-
-        if(!(nFlagsY & DEGEN_0a))
-        {
-          tangentY[0] = vector3_subtracted(subMatrix[1][0]->m_vertex, subMatrix[0][0]->m_vertex);
-          tangentT[0] = vector2_subtracted(subMatrix[1][0]->m_texcoord, subMatrix[0][0]->m_texcoord);
-        }
-        if(!(nFlagsY & DEGEN_0b))
-        {
-          tangentY[1] = vector3_subtracted(subMatrix[2][0]->m_vertex, subMatrix[1][0]->m_vertex);
-          tangentT[1] = vector2_subtracted(subMatrix[2][0]->m_texcoord, subMatrix[1][0]->m_texcoord);
-        }
-        if(!(nFlagsY & DEGEN_1a))
-        {
-          tangentY[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[0][1]->m_vertex);
-          tangentT[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[0][1]->m_texcoord);
-        }
-        if(!(nFlagsY & DEGEN_1b))
-        {
-          tangentY[3] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[1][1]->m_vertex);
-          tangentT[3] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[1][1]->m_texcoord);
-        }
-        if(!(nFlagsY & DEGEN_2a))
-        {
-          tangentY[4] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[0][2]->m_vertex);
-          tangentT[4] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[0][2]->m_texcoord);
-        }
-        if(!(nFlagsY & DEGEN_2b))
-        {
-          tangentY[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[1][2]->m_vertex);
-          tangentT[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[1][2]->m_texcoord);
-        }
-
-        // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge
-        tangents_remove_degenerate(tangentX, tangentS, nFlagsX);
-        tangents_remove_degenerate(tangentY, tangentT, nFlagsY);
-
-        {
-          // x=0, y=0
-          std::size_t index = offStartX + offStartY;
-          std::size_t index0 = 0;
-          std::size_t index1 = 0;
-
-          double dot = vector3_dot(tangentX[index0], tangentY[index1]);
-          double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
-
-          bestTangents00(nFlagsX, dot, length, index0, index1);
-
-          accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
-        }
-
-        {
-          // x=1, y=0
-          std::size_t index = offEndX + offStartY;
-          std::size_t index0 = 1;
-          std::size_t index1 = 4;
-
-          double dot = vector3_dot(tangentX[index0],tangentY[index1]);
-          double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
-
-          bestTangents10(nFlagsX, dot, length, index0, index1);
-
-          accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
-        }
-
-        {
-          // x=0, y=1
-          std::size_t index = offStartX + offEndY;
-          std::size_t index0 = 4;
-          std::size_t index1 = 1;
-
-          double dot = vector3_dot(tangentX[index0], tangentY[index1]);
-          double length = vector3_length(tangentX[index1]) * vector3_length(tangentY[index1]);
-
-          bestTangents01(nFlagsX, dot, length, index0, index1);
-
-          accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
         }
+    } else {
+        m_tess.m_numStrips = m_tess.m_nArrayWidth - 1;
+        m_tess.m_lenStrips = m_tess.m_nArrayHeight * 2;
+
+        for (std::size_t i = 0; i < m_tess.m_nArrayHeight; i++) {
+            for (std::size_t j = 0; j < m_tess.m_numStrips; j++) {
+                m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2] = RenderIndex(
+                        ((m_tess.m_nArrayHeight - 1) - i) * m_tess.m_nArrayWidth + j);
+                m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2 + 1] = RenderIndex(
+                        ((m_tess.m_nArrayHeight - 1) - i) * m_tess.m_nArrayWidth + j + 1);
+                // reverse because radiant uses CULL_FRONT
+                //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
+                //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1);
 
-        {
-          // x=1, y=1
-          std::size_t index = offEndX + offEndY;
-          std::size_t index0 = 5;
-          std::size_t index1 = 5;
-
-          double dot = vector3_dot(tangentX[index0],tangentY[index1]);
-          double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
-
-          bestTangents11(nFlagsX, dot, length, index0, index1);
-
-          accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
+            }
         }
+    }
 
-        //normalise normals that won't be accumulated again
-        if(i!=0 || j!=0)
-        {
-          normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offStartY));
-          normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offStartY));
-          normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offStartY));
-        }
-        if(i+3 == m_width)
-        {
-          normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offStartY));
-          normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offStartY));
-          normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offStartY));
-        }
-        if(j+3 == m_height)
-        {
-          normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offEndY));
-          normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offEndY));
-          normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offEndY));
-        }
-        if(i+3 == m_width && j+3 == m_height)
-        {
-          normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offEndY));
-          normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offEndY));
-          normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offEndY));
+    {
+        PatchControlIter pCtrl = m_ctrlTransformed.data();
+        for (std::size_t j = 0, offStartY = 0; j + 1 < m_height; j += 2, pCtrl += (strideU + strideV)) {
+            // set up array offsets for this sub-patch
+            const bool leafY = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeV[j >> 1]);
+            const std::size_t offMidY = (m_patchDef3) ? 0 : m_tess.m_curveTreeV[j >> 1]->index;
+            const std::size_t widthY = m_tess.m_arrayHeight[j >> 1] * m_tess.m_nArrayWidth;
+            const std::size_t offEndY = offStartY + widthY;
+
+            for (std::size_t i = 0, offStartX = 0; i + 1 < m_width; i += 2, pCtrl += (strideU << 1)) {
+                const bool leafX = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i >> 1]);
+                const std::size_t offMidX = (m_patchDef3) ? 0 : m_tess.m_curveTreeU[i >> 1]->index;
+                const std::size_t widthX = m_tess.m_arrayWidth[i >> 1];
+                const std::size_t offEndX = offStartX + widthX;
+
+                PatchControl *subMatrix[3][3];
+                subMatrix[0][0] = pCtrl;
+                subMatrix[0][1] = subMatrix[0][0] + strideU;
+                subMatrix[0][2] = subMatrix[0][1] + strideU;
+                subMatrix[1][0] = subMatrix[0][0] + strideV;
+                subMatrix[1][1] = subMatrix[1][0] + strideU;
+                subMatrix[1][2] = subMatrix[1][1] + strideU;
+                subMatrix[2][0] = subMatrix[1][0] + strideV;
+                subMatrix[2][1] = subMatrix[2][0] + strideU;
+                subMatrix[2][2] = subMatrix[2][1] + strideU;
+
+                // assign on-patch control points to vertex array
+                if (i == 0 && j == 0) {
+                    vertex_clear_normal(m_tess.m_vertices[offStartX + offStartY]);
+                }
+                vertex_assign_ctrl(m_tess.m_vertices[offStartX + offStartY], *subMatrix[0][0]);
+                if (j == 0) {
+                    vertex_clear_normal(m_tess.m_vertices[offEndX + offStartY]);
+                }
+                vertex_assign_ctrl(m_tess.m_vertices[offEndX + offStartY], *subMatrix[0][2]);
+                if (i == 0) {
+                    vertex_clear_normal(m_tess.m_vertices[offStartX + offEndY]);
+                }
+                vertex_assign_ctrl(m_tess.m_vertices[offStartX + offEndY], *subMatrix[2][0]);
+
+                vertex_clear_normal(m_tess.m_vertices[offEndX + offEndY]);
+                vertex_assign_ctrl(m_tess.m_vertices[offEndX + offEndY], *subMatrix[2][2]);
+
+                if (!m_patchDef3) {
+                    // assign remaining control points to vertex array
+                    if (!leafX) {
+                        vertex_assign_ctrl(m_tess.m_vertices[offMidX + offStartY], *subMatrix[0][1]);
+                        vertex_assign_ctrl(m_tess.m_vertices[offMidX + offEndY], *subMatrix[2][1]);
+                    }
+                    if (!leafY) {
+                        vertex_assign_ctrl(m_tess.m_vertices[offStartX + offMidY], *subMatrix[1][0]);
+                        vertex_assign_ctrl(m_tess.m_vertices[offEndX + offMidY], *subMatrix[1][2]);
+
+                        if (!leafX) {
+                            vertex_assign_ctrl(m_tess.m_vertices[offMidX + offMidY], *subMatrix[1][1]);
+                        }
+                    }
+                }
+
+                // test all 12 edges for degeneracy
+                unsigned int nFlagsX = subarray_get_degen(pCtrl, strideU, strideV);
+                unsigned int nFlagsY = subarray_get_degen(pCtrl, strideV, strideU);
+                Vector3 tangentX[6], tangentY[6];
+                Vector2 tangentS[6], tangentT[6];
+
+                // set up tangents for each of the 12 edges if they were not degenerate
+                if (!(nFlagsX & DEGEN_0a)) {
+                    tangentX[0] = vector3_subtracted(subMatrix[0][1]->m_vertex, subMatrix[0][0]->m_vertex);
+                    tangentS[0] = vector2_subtracted(subMatrix[0][1]->m_texcoord, subMatrix[0][0]->m_texcoord);
+                }
+                if (!(nFlagsX & DEGEN_0b)) {
+                    tangentX[1] = vector3_subtracted(subMatrix[0][2]->m_vertex, subMatrix[0][1]->m_vertex);
+                    tangentS[1] = vector2_subtracted(subMatrix[0][2]->m_texcoord, subMatrix[0][1]->m_texcoord);
+                }
+                if (!(nFlagsX & DEGEN_1a)) {
+                    tangentX[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[1][0]->m_vertex);
+                    tangentS[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[1][0]->m_texcoord);
+                }
+                if (!(nFlagsX & DEGEN_1b)) {
+                    tangentX[3] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[1][1]->m_vertex);
+                    tangentS[3] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[1][1]->m_texcoord);
+                }
+                if (!(nFlagsX & DEGEN_2a)) {
+                    tangentX[4] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[2][0]->m_vertex);
+                    tangentS[4] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[2][0]->m_texcoord);
+                }
+                if (!(nFlagsX & DEGEN_2b)) {
+                    tangentX[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[2][1]->m_vertex);
+                    tangentS[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[2][1]->m_texcoord);
+                }
+
+                if (!(nFlagsY & DEGEN_0a)) {
+                    tangentY[0] = vector3_subtracted(subMatrix[1][0]->m_vertex, subMatrix[0][0]->m_vertex);
+                    tangentT[0] = vector2_subtracted(subMatrix[1][0]->m_texcoord, subMatrix[0][0]->m_texcoord);
+                }
+                if (!(nFlagsY & DEGEN_0b)) {
+                    tangentY[1] = vector3_subtracted(subMatrix[2][0]->m_vertex, subMatrix[1][0]->m_vertex);
+                    tangentT[1] = vector2_subtracted(subMatrix[2][0]->m_texcoord, subMatrix[1][0]->m_texcoord);
+                }
+                if (!(nFlagsY & DEGEN_1a)) {
+                    tangentY[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[0][1]->m_vertex);
+                    tangentT[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[0][1]->m_texcoord);
+                }
+                if (!(nFlagsY & DEGEN_1b)) {
+                    tangentY[3] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[1][1]->m_vertex);
+                    tangentT[3] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[1][1]->m_texcoord);
+                }
+                if (!(nFlagsY & DEGEN_2a)) {
+                    tangentY[4] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[0][2]->m_vertex);
+                    tangentT[4] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[0][2]->m_texcoord);
+                }
+                if (!(nFlagsY & DEGEN_2b)) {
+                    tangentY[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[1][2]->m_vertex);
+                    tangentT[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[1][2]->m_texcoord);
+                }
+
+                // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge
+                tangents_remove_degenerate(tangentX, tangentS, nFlagsX);
+                tangents_remove_degenerate(tangentY, tangentT, nFlagsY);
+
+                {
+                    // x=0, y=0
+                    std::size_t index = offStartX + offStartY;
+                    std::size_t index0 = 0;
+                    std::size_t index1 = 0;
+
+                    double dot = vector3_dot(tangentX[index0], tangentY[index1]);
+                    double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
+
+                    bestTangents00(nFlagsX, dot, length, index0, index1);
+
+                    accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
+                }
+
+                {
+                    // x=1, y=0
+                    std::size_t index = offEndX + offStartY;
+                    std::size_t index0 = 1;
+                    std::size_t index1 = 4;
+
+                    double dot = vector3_dot(tangentX[index0], tangentY[index1]);
+                    double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
+
+                    bestTangents10(nFlagsX, dot, length, index0, index1);
+
+                    accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
+                }
+
+                {
+                    // x=0, y=1
+                    std::size_t index = offStartX + offEndY;
+                    std::size_t index0 = 4;
+                    std::size_t index1 = 1;
+
+                    double dot = vector3_dot(tangentX[index0], tangentY[index1]);
+                    double length = vector3_length(tangentX[index1]) * vector3_length(tangentY[index1]);
+
+                    bestTangents01(nFlagsX, dot, length, index0, index1);
+
+                    accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
+                }
+
+                {
+                    // x=1, y=1
+                    std::size_t index = offEndX + offEndY;
+                    std::size_t index0 = 5;
+                    std::size_t index1 = 5;
+
+                    double dot = vector3_dot(tangentX[index0], tangentY[index1]);
+                    double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
+
+                    bestTangents11(nFlagsX, dot, length, index0, index1);
+
+                    accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
+                }
+
+                //normalise normals that won't be accumulated again
+                if (i != 0 || j != 0) {
+                    normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offStartY));
+                    normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offStartY));
+                    normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offStartY));
+                }
+                if (i + 3 == m_width) {
+                    normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offStartY));
+                    normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offStartY));
+                    normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offStartY));
+                }
+                if (j + 3 == m_height) {
+                    normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offEndY));
+                    normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offEndY));
+                    normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offEndY));
+                }
+                if (i + 3 == m_width && j + 3 == m_height) {
+                    normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offEndY));
+                    normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offEndY));
+                    normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offEndY));
+                }
+
+                // set flags to average normals between shared edges
+                if (j != 0) {
+                    nFlagsX |= AVERAGE;
+                }
+                if (i != 0) {
+                    nFlagsY |= AVERAGE;
+                }
+                // set flags to save evaluating shared edges twice
+                nFlagsX |= SPLIT;
+                nFlagsY |= SPLIT;
+
+                // if the patch is curved.. tesselate recursively
+                // use the relevant control curves for this sub-patch
+                if (m_patchDef3) {
+                    TesselateSubMatrixFixed(m_tess.m_vertices.data() + offStartX + offStartY, 1, m_tess.m_nArrayWidth,
+                                            nFlagsX, nFlagsY, subMatrix);
+                } else {
+                    if (!leafX) {
+                        TesselateSubMatrix(m_tess.m_curveTreeU[i >> 1], m_tess.m_curveTreeV[j >> 1],
+                                           offStartX, offStartY, offEndX, offEndY, // array offsets
+                                           nFlagsX, nFlagsY,
+                                           subMatrix[1][0]->m_vertex, subMatrix[1][1]->m_vertex,
+                                           subMatrix[1][2]->m_vertex,
+                                           subMatrix[1][0]->m_texcoord, subMatrix[1][1]->m_texcoord,
+                                           subMatrix[1][2]->m_texcoord,
+                                           false);
+                    } else if (!leafY) {
+                        TesselateSubMatrix(m_tess.m_curveTreeV[j >> 1], m_tess.m_curveTreeU[i >> 1],
+                                           offStartY, offStartX, offEndY, offEndX, // array offsets
+                                           nFlagsY, nFlagsX,
+                                           subMatrix[0][1]->m_vertex, subMatrix[1][1]->m_vertex,
+                                           subMatrix[2][1]->m_vertex,
+                                           subMatrix[0][1]->m_texcoord, subMatrix[1][1]->m_texcoord,
+                                           subMatrix[2][1]->m_texcoord,
+                                           true);
+                    }
+                }
+
+                offStartX = offEndX;
+            }
+            offStartY = offEndY;
         }
+    }
+}
 
-        // set flags to average normals between shared edges
-        if(j != 0)
-        {
-          nFlagsX |= AVERAGE;
-        }
-        if(i != 0)
-        {
-          nFlagsY |= AVERAGE;
-        }
-        // set flags to save evaluating shared edges twice
-        nFlagsX |= SPLIT;
-        nFlagsY |= SPLIT;    
-      
-        // if the patch is curved.. tesselate recursively
-        // use the relevant control curves for this sub-patch
-        if(m_patchDef3)
-        {
-          TesselateSubMatrixFixed(m_tess.m_vertices.data() + offStartX + offStartY, 1, m_tess.m_nArrayWidth, nFlagsX, nFlagsY, subMatrix);
-        }
-        else
-        {
-          if(!leafX)
-          {
-            TesselateSubMatrix( m_tess.m_curveTreeU[i>>1], m_tess.m_curveTreeV[j>>1],
-                                offStartX, offStartY, offEndX, offEndY, // array offsets
-                                nFlagsX, nFlagsY,
-                                subMatrix[1][0]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[1][2]->m_vertex,
-                                subMatrix[1][0]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[1][2]->m_texcoord,
-                                false );
-          }
-          else if(!leafY)
-          {
-            TesselateSubMatrix( m_tess.m_curveTreeV[j>>1], m_tess.m_curveTreeU[i>>1],
-                                offStartY, offStartX, offEndY, offEndX, // array offsets
-                                nFlagsY, nFlagsX,
-                                subMatrix[0][1]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[2][1]->m_vertex,
-                                subMatrix[0][1]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[2][1]->m_texcoord,
-                                true );
-          }
-        }
 
-        offStartX = offEndX;
-      }
-      offStartY = offEndY;
+class PatchFilterWrapper : public Filter {
+    bool m_active;
+    bool m_invert;
+    PatchFilter &m_filter;
+public:
+    PatchFilterWrapper(PatchFilter &filter, bool invert) : m_invert(invert), m_filter(filter)
+    {
     }
-  }
-}
 
+    void setActive(bool active)
+    {
+        m_active = active;
+    }
 
+    bool active()
+    {
+        return m_active;
+    }
 
-class PatchFilterWrapper : public Filter
-{
-  bool m_active;
-  bool m_invert;
-  PatchFilter& m_filter;
-public:
-  PatchFilterWrapper(PatchFilter& filter, bool invert) : m_invert(invert), m_filter(filter)
-  {
-  }
-  void setActive(bool active)
-  {
-    m_active = active;
-  }
-  bool active()
-  {
-    return m_active;
-  }
-  bool filter(const Patch& patch)
-  {
-    return m_invert ^ m_filter.filter(patch);
-  }
+    bool filter(const Patch &patch)
+    {
+        return m_invert ^ m_filter.filter(patch);
+    }
 };
 
 
 typedef std::list<PatchFilterWrapper> PatchFilters;
 PatchFilters g_patchFilters;
 
-void add_patch_filter(PatchFilterfilter, int mask, bool invert)
+void add_patch_filter(PatchFilter &filter, int mask, bool invert)
 {
-  g_patchFilters.push_back(PatchFilterWrapper(filter, invert));
-  GlobalFilterSystem().addFilter(g_patchFilters.back(), mask);
+    g_patchFilters.push_back(PatchFilterWrapper(filter, invert));
+    GlobalFilterSystem().addFilter(g_patchFilters.back(), mask);
 }
 
-bool patch_filtered(Patchpatch)
+bool patch_filtered(Patch &patch)
 {
-  for(PatchFilters::iterator i = g_patchFilters.begin(); i != g_patchFilters.end(); ++i)
-  {
-    if((*i).active() && (*i).filter(patch))
-    {
-      return true;
+    for (PatchFilters::iterator i = g_patchFilters.begin(); i != g_patchFilters.end(); ++i) {
+        if ((*i).active() && (*i).filter(patch)) {
+            return true;
+        }
     }
-  }
-  return false;
+    return false;
 }