Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / blenkernel / intern / subdiv.c
index 370448d..44990f6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
  * This program 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
  *
  * The Original Code is Copyright (C) 2018 by Blender Foundation.
  * All rights reserved.
- *
- * Contributor(s): Sergey Sharybin.
- *
- * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/blenkernel/intern/subdiv.c
- *  \ingroup bke
+/** \file \ingroup bke
  */
 
 #include "BKE_subdiv.h"
 
 #include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 
 #include "BLI_utildefines.h"
@@ -66,8 +60,47 @@ BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth)
        return SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL;
 }
 
+/* ================================ SETTINGS ================================ */
+
+static bool check_mesh_has_non_quad(const Mesh *mesh)
+{
+       for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
+               const MPoly *poly = &mesh->mpoly[poly_index];
+               if (poly->totloop != 4) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+void BKE_subdiv_settings_validate_for_mesh(SubdivSettings *settings,
+                                           const Mesh *mesh)
+{
+       if (settings->level != 1) {
+               return;
+       }
+       if (check_mesh_has_non_quad(mesh)) {
+               settings->level = 2;
+       }
+}
+
+bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a,
+                               const SubdivSettings *settings_b)
+{
+       return
+               (settings_a->is_simple == settings_b->is_simple &&
+                settings_a->is_adaptive == settings_b->is_adaptive &&
+                settings_a->level == settings_b->level &&
+                settings_a->vtx_boundary_interpolation ==
+                        settings_b->vtx_boundary_interpolation &&
+                settings_a->fvar_linear_interpolation ==
+                        settings_b->fvar_linear_interpolation);
+}
+
 /* ============================== CONSTRUCTION ============================== */
 
+/* Creation from scratch. */
+
 Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
                                       struct OpenSubdiv_Converter *converter)
 {
@@ -82,7 +115,6 @@ Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
                osd_topology_refiner =
                        openSubdiv_createTopologyRefinerFromConverter(
                                converter, &topology_refiner_settings);
-
        }
        else {
                /* TODO(sergey): Check whether original geometry had any vertices.
@@ -112,6 +144,53 @@ Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings,
        return subdiv;
 }
 
+/* Creation with cached-aware semantic. */
+
+Subdiv *BKE_subdiv_update_from_converter(Subdiv *subdiv,
+                                         const SubdivSettings *settings,
+                                         OpenSubdiv_Converter *converter)
+{
+       /* Check if the existing descriptor can be re-used. */
+       bool can_reuse_subdiv = true;
+       if (subdiv != NULL && subdiv->topology_refiner != NULL) {
+               if (!BKE_subdiv_settings_equal(&subdiv->settings, settings)) {
+                       can_reuse_subdiv = false;
+               }
+               else {
+                       BKE_subdiv_stats_begin(
+                               &subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE);
+                       can_reuse_subdiv = openSubdiv_topologyRefinerCompareWithConverter(
+                               subdiv->topology_refiner, converter);
+                       BKE_subdiv_stats_end(
+                               &subdiv->stats, SUBDIV_STATS_TOPOLOGY_COMPARE);
+               }
+       }
+       else {
+               can_reuse_subdiv = false;
+       }
+       if (can_reuse_subdiv) {
+               return subdiv;
+       }
+       /* Create new subdiv. */
+       if (subdiv != NULL) {
+               BKE_subdiv_free(subdiv);
+       }
+       return BKE_subdiv_new_from_converter(settings, converter);
+}
+
+Subdiv *BKE_subdiv_update_from_mesh(Subdiv *subdiv,
+                                    const SubdivSettings *settings,
+                                    const Mesh *mesh)
+{
+       OpenSubdiv_Converter converter;
+       BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
+       subdiv = BKE_subdiv_update_from_converter(subdiv, settings, &converter);
+       BKE_subdiv_converter_free(&converter);
+       return subdiv;
+}
+
+/* Memory release. */
+
 void BKE_subdiv_free(Subdiv *subdiv)
 {
        if (subdiv->evaluator != NULL) {