Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/*
|
|
|
|
|
* ***** 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
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program 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 this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
* 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_mesh.c
|
|
|
|
|
* \ingroup bke
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "BKE_subdiv.h"
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
#include "atomic_ops.h"
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
|
#include "DNA_meshdata_types.h"
|
2018-07-31 15:09:29 +02:00
|
|
|
#include "DNA_key_types.h"
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
|
|
|
|
|
#include "BLI_alloca.h"
|
2018-07-25 16:51:48 +02:00
|
|
|
#include "BLI_bitmap.h"
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
#include "BLI_math_vector.h"
|
|
|
|
|
#include "BLI_task.h"
|
|
|
|
|
|
|
|
|
|
#include "BKE_mesh.h"
|
2018-07-31 15:09:29 +02:00
|
|
|
#include "BKE_key.h"
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* General helpers.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Number of ptex faces for a given polygon. */
|
|
|
|
|
BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly *poly)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
2018-07-23 18:40:04 +02:00
|
|
|
return (poly->totloop == 4) ? 1 : poly->totloop;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
BLI_INLINE int num_edges_per_ptex_face_get(const int resolution)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
return 2 * (resolution - 1) * resolution;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
BLI_INLINE int num_inner_edges_per_ptex_face_get(const int resolution)
|
|
|
|
|
{
|
|
|
|
|
if (resolution < 2) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return (resolution - 2) * resolution +
|
|
|
|
|
(resolution - 1) * (resolution - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* Number of subdivision polygons per ptex face. */
|
|
|
|
|
BLI_INLINE int num_polys_per_ptex_get(const int resolution)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
return (resolution - 1) * (resolution - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* Subdivision resolution per given polygon's ptex faces. */
|
|
|
|
|
BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution)
|
|
|
|
|
{
|
|
|
|
|
return (poly->totloop == 4) ? (resolution)
|
|
|
|
|
: ((resolution >> 1) + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* Mesh subdivision context.
|
|
|
|
|
*/
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
typedef struct SubdivMeshContext {
|
|
|
|
|
const Mesh *coarse_mesh;
|
|
|
|
|
Subdiv *subdiv;
|
|
|
|
|
Mesh *subdiv_mesh;
|
|
|
|
|
const SubdivToMeshSettings *settings;
|
|
|
|
|
/* Cached custom data arrays for fastter access. */
|
|
|
|
|
int *vert_origindex;
|
|
|
|
|
int *edge_origindex;
|
|
|
|
|
int *loop_origindex;
|
|
|
|
|
int *poly_origindex;
|
|
|
|
|
/* UV layers interpolation. */
|
|
|
|
|
int num_uv_layers;
|
|
|
|
|
MLoopUV *uv_layers[MAX_MTFACE];
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Counters of geometry in subdivided mesh, initialized as a part of
|
|
|
|
|
* offsets calculation.
|
|
|
|
|
*/
|
|
|
|
|
int num_subdiv_vertices;
|
|
|
|
|
int num_subdiv_edges;
|
|
|
|
|
int num_subdiv_loops;
|
|
|
|
|
int num_subdiv_polygons;
|
|
|
|
|
/* Offsets of various geometry in the subdivision mesh arrays. */
|
|
|
|
|
int vertices_corner_offset;
|
|
|
|
|
int vertices_edge_offset;
|
|
|
|
|
int vertices_inner_offset;
|
|
|
|
|
int edge_boundary_offset;
|
|
|
|
|
int edge_inner_offset;
|
2018-07-23 18:40:04 +02:00
|
|
|
/* Indexed by coarse polygon index, indicates offset in subdivided mesh
|
|
|
|
|
* vertices, edges and polygons arrays, where first element of the poly
|
|
|
|
|
* begins.
|
|
|
|
|
*/
|
|
|
|
|
int *subdiv_vertex_offset;
|
|
|
|
|
int *subdiv_edge_offset;
|
|
|
|
|
int *subdiv_polygon_offset;
|
|
|
|
|
/* Indexed by base face index, element indicates total number of ptex faces
|
|
|
|
|
* created for preceding base faces.
|
|
|
|
|
*/
|
|
|
|
|
int *face_ptex_offset;
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Bitmap indicating whether vertex was used already or not.
|
|
|
|
|
* - During patch evaluation indicates whether coarse vertex was already
|
|
|
|
|
* evaluated and its position on limit is already known.
|
2018-07-23 18:40:04 +02:00
|
|
|
*/
|
2018-07-25 16:51:48 +02:00
|
|
|
BLI_bitmap *coarse_vertices_used_map;
|
|
|
|
|
/* Bitmap indicating whether edge was used already or not. This includes:
|
|
|
|
|
* - During context initialization it indicates whether subdivided verticies
|
|
|
|
|
* for corresponding edge were already calculated or not.
|
|
|
|
|
* - During patch evaluation it indicates whether vertices along this edge
|
|
|
|
|
* were already evaluated.
|
|
|
|
|
*/
|
|
|
|
|
BLI_bitmap *coarse_edges_used_map;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
} SubdivMeshContext;
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
ctx->num_uv_layers =
|
|
|
|
|
CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV);
|
|
|
|
|
for (int layer_index = 0; layer_index < ctx->num_uv_layers; ++layer_index) {
|
|
|
|
|
ctx->uv_layers[layer_index] = CustomData_get_layer_n(
|
|
|
|
|
&subdiv_mesh->ldata, CD_MLOOPUV, layer_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
/* Pointers to original indices layers. */
|
|
|
|
|
ctx->vert_origindex = CustomData_get_layer(
|
|
|
|
|
&subdiv_mesh->vdata, CD_ORIGINDEX);
|
|
|
|
|
ctx->edge_origindex = CustomData_get_layer(
|
|
|
|
|
&subdiv_mesh->edata, CD_ORIGINDEX);
|
|
|
|
|
ctx->loop_origindex = CustomData_get_layer(
|
|
|
|
|
&subdiv_mesh->ldata, CD_ORIGINDEX);
|
|
|
|
|
ctx->poly_origindex = CustomData_get_layer(
|
|
|
|
|
&subdiv_mesh->pdata, CD_ORIGINDEX);
|
|
|
|
|
/* UV layers interpolation. */
|
|
|
|
|
subdiv_mesh_ctx_cache_uv_layers(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
/* NOTE: Expects edge map to be zeroed. */
|
|
|
|
|
static void subdiv_mesh_ctx_count(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
/* Reset counters. */
|
|
|
|
|
ctx->num_subdiv_vertices = 0;
|
|
|
|
|
ctx->num_subdiv_edges = 0;
|
|
|
|
|
ctx->num_subdiv_loops = 0;
|
|
|
|
|
ctx->num_subdiv_polygons = 0;
|
|
|
|
|
/* Static geometry counters. */
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int no_quad_patch_resolution = ((resolution >> 1) + 1);
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const int num_inner_vertices_per_quad = (resolution - 2) * (resolution - 2);
|
|
|
|
|
const int num_inner_vertices_per_noquad_patch =
|
|
|
|
|
(no_quad_patch_resolution - 2) * (no_quad_patch_resolution - 2);
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
ctx->num_subdiv_vertices = coarse_mesh->totvert;
|
|
|
|
|
ctx->num_subdiv_edges =
|
|
|
|
|
coarse_mesh->totedge * (num_subdiv_vertices_per_coarse_edge + 1);
|
2018-07-31 15:09:29 +02:00
|
|
|
/* Calculate extra vertices and edges createdd by non-loose geometry. */
|
2018-07-25 16:51:48 +02:00
|
|
|
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
const int num_ptex_faces_per_poly =
|
|
|
|
|
num_ptex_faces_per_poly_get(coarse_poly);
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *loop = &coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
const bool is_edge_used =
|
|
|
|
|
BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, loop->e);
|
|
|
|
|
/* Edges which aren't counted yet. */
|
|
|
|
|
if (!is_edge_used) {
|
|
|
|
|
BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e);
|
|
|
|
|
ctx->num_subdiv_vertices += num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Inner verticies of polygon. */
|
|
|
|
|
if (num_ptex_faces_per_poly == 1) {
|
|
|
|
|
ctx->num_subdiv_vertices += num_inner_vertices_per_quad;
|
|
|
|
|
ctx->num_subdiv_edges +=
|
|
|
|
|
num_edges_per_ptex_face_get(resolution - 2) +
|
|
|
|
|
4 * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
ctx->num_subdiv_polygons += num_polys_per_ptex_get(resolution);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ctx->num_subdiv_vertices +=
|
|
|
|
|
1 +
|
|
|
|
|
num_ptex_faces_per_poly * (no_quad_patch_resolution - 2) +
|
|
|
|
|
num_ptex_faces_per_poly * num_inner_vertices_per_noquad_patch;
|
|
|
|
|
ctx->num_subdiv_edges +=
|
|
|
|
|
num_ptex_faces_per_poly *
|
|
|
|
|
(num_inner_edges_per_ptex_face_get(
|
|
|
|
|
no_quad_patch_resolution - 1) +
|
|
|
|
|
(no_quad_patch_resolution - 2) +
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge);
|
|
|
|
|
if (no_quad_patch_resolution >= 3) {
|
|
|
|
|
ctx->num_subdiv_edges += coarse_poly->totloop;
|
|
|
|
|
}
|
|
|
|
|
ctx->num_subdiv_polygons +=
|
|
|
|
|
num_ptex_faces_per_poly *
|
|
|
|
|
num_polys_per_ptex_get(no_quad_patch_resolution);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-13 12:21:29 +02:00
|
|
|
/* Calculate extra vertices createdd by loose edges. */
|
2018-07-31 15:09:29 +02:00
|
|
|
for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
|
|
|
|
|
if (!BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, edge_index)) {
|
|
|
|
|
ctx->num_subdiv_vertices += num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-25 16:51:48 +02:00
|
|
|
ctx->num_subdiv_loops = ctx->num_subdiv_polygons * 4;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
static void subdiv_mesh_ctx_init_offsets(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
2018-07-25 16:51:48 +02:00
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int resolution_2 = resolution - 2;
|
|
|
|
|
const int resolution_2_squared = resolution_2 * resolution_2;
|
|
|
|
|
const int no_quad_patch_resolution = ((resolution >> 1) + 1);
|
|
|
|
|
const int num_irregular_vertices_per_patch =
|
|
|
|
|
(no_quad_patch_resolution - 2) * (no_quad_patch_resolution - 1);
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const int num_subdiv_edges_per_coarse_edge = resolution - 1;
|
|
|
|
|
/* Constant offsets in arrays. */
|
|
|
|
|
ctx->vertices_corner_offset = 0;
|
|
|
|
|
ctx->vertices_edge_offset = coarse_mesh->totvert;
|
|
|
|
|
ctx->vertices_inner_offset =
|
|
|
|
|
ctx->vertices_edge_offset +
|
|
|
|
|
coarse_mesh->totedge * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
ctx->edge_boundary_offset = 0;
|
|
|
|
|
ctx->edge_inner_offset =
|
|
|
|
|
ctx->edge_boundary_offset +
|
|
|
|
|
coarse_mesh->totedge * num_subdiv_edges_per_coarse_edge;
|
|
|
|
|
/* "Indexed" offsets. */
|
2018-07-23 18:40:04 +02:00
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
int vertex_offset = 0;
|
|
|
|
|
int edge_offset = 0;
|
|
|
|
|
int polygon_offset = 0;
|
|
|
|
|
int face_ptex_offset = 0;
|
|
|
|
|
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
const int num_ptex_faces_per_poly =
|
|
|
|
|
num_ptex_faces_per_poly_get(coarse_poly);
|
2018-07-25 16:51:48 +02:00
|
|
|
ctx->face_ptex_offset[poly_index] = face_ptex_offset;
|
2018-07-23 18:40:04 +02:00
|
|
|
ctx->subdiv_vertex_offset[poly_index] = vertex_offset;
|
|
|
|
|
ctx->subdiv_edge_offset[poly_index] = edge_offset;
|
|
|
|
|
ctx->subdiv_polygon_offset[poly_index] = polygon_offset;
|
|
|
|
|
face_ptex_offset += num_ptex_faces_per_poly;
|
2018-07-25 16:51:48 +02:00
|
|
|
if (num_ptex_faces_per_poly == 1) {
|
|
|
|
|
vertex_offset += resolution_2_squared;
|
|
|
|
|
edge_offset += num_edges_per_ptex_face_get(resolution - 2) +
|
|
|
|
|
4 * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
polygon_offset += num_polys_per_ptex_get(resolution);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
vertex_offset +=
|
|
|
|
|
1 +
|
|
|
|
|
num_ptex_faces_per_poly * num_irregular_vertices_per_patch;
|
|
|
|
|
edge_offset +=
|
|
|
|
|
num_ptex_faces_per_poly *
|
|
|
|
|
(num_inner_edges_per_ptex_face_get(
|
|
|
|
|
no_quad_patch_resolution - 1) +
|
2018-07-31 20:11:55 +10:00
|
|
|
(no_quad_patch_resolution - 2) +
|
2018-07-25 16:51:48 +02:00
|
|
|
num_subdiv_vertices_per_coarse_edge);
|
|
|
|
|
if (no_quad_patch_resolution >= 3) {
|
|
|
|
|
edge_offset += coarse_poly->totloop;
|
|
|
|
|
}
|
|
|
|
|
polygon_offset +=
|
|
|
|
|
num_ptex_faces_per_poly *
|
|
|
|
|
num_polys_per_ptex_get(no_quad_patch_resolution);
|
|
|
|
|
}
|
2018-07-23 18:40:04 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_mesh_ctx_init(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
/* Allocate maps and offsets. */
|
|
|
|
|
ctx->coarse_vertices_used_map =
|
|
|
|
|
BLI_BITMAP_NEW(coarse_mesh->totvert, "vertices used map");
|
|
|
|
|
ctx->coarse_edges_used_map =
|
|
|
|
|
BLI_BITMAP_NEW(coarse_mesh->totedge, "edges used map");
|
|
|
|
|
ctx->subdiv_vertex_offset = MEM_malloc_arrayN(
|
|
|
|
|
coarse_mesh->totpoly,
|
|
|
|
|
sizeof(*ctx->subdiv_vertex_offset),
|
|
|
|
|
"vertex_offset");
|
|
|
|
|
ctx->subdiv_edge_offset = MEM_malloc_arrayN(
|
|
|
|
|
coarse_mesh->totpoly,
|
|
|
|
|
sizeof(*ctx->subdiv_edge_offset),
|
|
|
|
|
"subdiv_edge_offset");
|
|
|
|
|
ctx->subdiv_polygon_offset = MEM_malloc_arrayN(
|
|
|
|
|
coarse_mesh->totpoly,
|
|
|
|
|
sizeof(*ctx->subdiv_polygon_offset),
|
|
|
|
|
"subdiv_edge_offset");
|
|
|
|
|
ctx->face_ptex_offset = MEM_malloc_arrayN(coarse_mesh->totpoly,
|
|
|
|
|
sizeof(*ctx->face_ptex_offset),
|
|
|
|
|
"face_ptex_offset");
|
|
|
|
|
/* Initialize all offsets. */
|
2018-07-23 18:40:04 +02:00
|
|
|
subdiv_mesh_ctx_init_offsets(ctx);
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Calculate number of geometry in the result subdivision mesh. */
|
|
|
|
|
subdiv_mesh_ctx_count(ctx);
|
|
|
|
|
/* Re-set maps which were used at this step. */
|
|
|
|
|
BLI_BITMAP_SET_ALL(ctx->coarse_edges_used_map, false, coarse_mesh->totedge);
|
2018-07-23 18:40:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_mesh_ctx_init_result(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
subdiv_mesh_ctx_cache_custom_data_layers(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_mesh_ctx_free(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
MEM_freeN(ctx->coarse_vertices_used_map);
|
|
|
|
|
MEM_freeN(ctx->coarse_edges_used_map);
|
2018-07-23 18:40:04 +02:00
|
|
|
MEM_freeN(ctx->subdiv_vertex_offset);
|
|
|
|
|
MEM_freeN(ctx->subdiv_edge_offset);
|
2018-07-25 16:51:48 +02:00
|
|
|
MEM_freeN(ctx->subdiv_polygon_offset);
|
2018-07-23 18:40:04 +02:00
|
|
|
MEM_freeN(ctx->face_ptex_offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* Loop custom data copy helpers.
|
|
|
|
|
*/
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
typedef struct LoopsOfPtex {
|
|
|
|
|
/* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */
|
|
|
|
|
const MLoop *first_loop;
|
|
|
|
|
/* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */
|
|
|
|
|
const MLoop *last_loop;
|
|
|
|
|
/* For quad coarse faces only. */
|
|
|
|
|
const MLoop *second_loop;
|
|
|
|
|
const MLoop *third_loop;
|
|
|
|
|
} LoopsOfPtex;
|
|
|
|
|
|
|
|
|
|
static void loops_of_ptex_get(
|
|
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
LoopsOfPtex *loops_of_ptex,
|
|
|
|
|
const MPoly *coarse_poly,
|
2018-07-25 16:51:48 +02:00
|
|
|
const int ptex_of_poly_index)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
const MLoop *coarse_mloop = ctx->coarse_mesh->mloop;
|
2018-07-25 16:51:48 +02:00
|
|
|
const int first_ptex_loop_index =
|
|
|
|
|
coarse_poly->loopstart + ptex_of_poly_index;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Loop which look in the (opposite) V direction of the current
|
|
|
|
|
* ptex face.
|
|
|
|
|
*
|
|
|
|
|
* TOOD(sergey): Get rid of using module on every iteration.
|
|
|
|
|
*/
|
|
|
|
|
const int last_ptex_loop_index =
|
|
|
|
|
coarse_poly->loopstart +
|
2018-07-25 16:51:48 +02:00
|
|
|
(ptex_of_poly_index + coarse_poly->totloop - 1) %
|
|
|
|
|
coarse_poly->totloop;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
loops_of_ptex->first_loop = &coarse_mloop[first_ptex_loop_index];
|
|
|
|
|
loops_of_ptex->last_loop = &coarse_mloop[last_ptex_loop_index];
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
|
|
|
|
|
loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
loops_of_ptex->second_loop = NULL;
|
|
|
|
|
loops_of_ptex->third_loop = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Vertex custom data interpolation helpers.
|
|
|
|
|
*/
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* TODO(sergey): Somehow de-duplicate with loops storage, without too much
|
|
|
|
|
* exception cases all over the code.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef struct VerticesForInterpolation {
|
|
|
|
|
/* This field points to a vertex data which is to be used for interpolation.
|
|
|
|
|
* The idea is to avoid unnecessary allocations for regular faces, where
|
2018-07-19 16:06:37 +10:00
|
|
|
* we can simply
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
*/
|
|
|
|
|
const CustomData *vertex_data;
|
|
|
|
|
/* Vertices data calculated for ptex corners. There are always 4 elements
|
|
|
|
|
* in this custom data, aligned the following way:
|
|
|
|
|
*
|
|
|
|
|
* index 0 -> uv (0, 0)
|
|
|
|
|
* index 1 -> uv (0, 1)
|
|
|
|
|
* index 2 -> uv (1, 1)
|
|
|
|
|
* index 3 -> uv (1, 0)
|
|
|
|
|
*
|
|
|
|
|
* Is allocated for non-regular faces (triangles and n-gons).
|
|
|
|
|
*/
|
|
|
|
|
CustomData vertex_data_storage;
|
|
|
|
|
bool vertex_data_storage_allocated;
|
|
|
|
|
/* Infices within vertex_data to interpolate for. The indices are aligned
|
|
|
|
|
* with uv coordinates in a similar way as indices in loop_data_storage.
|
|
|
|
|
*/
|
|
|
|
|
int vertex_indices[4];
|
|
|
|
|
} VerticesForInterpolation;
|
|
|
|
|
|
|
|
|
|
static void vertex_interpolation_init(
|
|
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation,
|
2018-07-19 16:06:37 +10:00
|
|
|
const MPoly *coarse_poly)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
vertex_interpolation->vertex_data = &coarse_mesh->vdata;
|
|
|
|
|
vertex_interpolation->vertex_indices[0] =
|
|
|
|
|
coarse_mloop[coarse_poly->loopstart + 0].v;
|
|
|
|
|
vertex_interpolation->vertex_indices[1] =
|
|
|
|
|
coarse_mloop[coarse_poly->loopstart + 1].v;
|
|
|
|
|
vertex_interpolation->vertex_indices[2] =
|
|
|
|
|
coarse_mloop[coarse_poly->loopstart + 2].v;
|
|
|
|
|
vertex_interpolation->vertex_indices[3] =
|
|
|
|
|
coarse_mloop[coarse_poly->loopstart + 3].v;
|
|
|
|
|
vertex_interpolation->vertex_data_storage_allocated = false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
vertex_interpolation->vertex_data =
|
|
|
|
|
&vertex_interpolation->vertex_data_storage;
|
|
|
|
|
/* Allocate storage for loops corresponding to ptex corners. */
|
|
|
|
|
CustomData_copy(&ctx->coarse_mesh->vdata,
|
|
|
|
|
&vertex_interpolation->vertex_data_storage,
|
|
|
|
|
CD_MASK_EVERYTHING,
|
|
|
|
|
CD_CALLOC,
|
|
|
|
|
4);
|
|
|
|
|
/* Initialize indices. */
|
|
|
|
|
vertex_interpolation->vertex_indices[0] = 0;
|
|
|
|
|
vertex_interpolation->vertex_indices[1] = 1;
|
|
|
|
|
vertex_interpolation->vertex_indices[2] = 2;
|
|
|
|
|
vertex_interpolation->vertex_indices[3] = 3;
|
|
|
|
|
vertex_interpolation->vertex_data_storage_allocated = true;
|
|
|
|
|
/* Interpolate center of poly right away, it stays unchanged for all
|
|
|
|
|
* ptex faces.
|
|
|
|
|
*/
|
|
|
|
|
const float weight = 1.0f / (float)coarse_poly->totloop;
|
|
|
|
|
float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
|
|
|
|
|
int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
|
|
|
|
|
for (int i = 0; i < coarse_poly->totloop; ++i) {
|
|
|
|
|
weights[i] = weight;
|
2018-07-23 19:09:16 +02:00
|
|
|
indices[i] = coarse_mloop[coarse_poly->loopstart + i].v;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
CustomData_interp(&coarse_mesh->vdata,
|
|
|
|
|
&vertex_interpolation->vertex_data_storage,
|
|
|
|
|
indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
coarse_poly->totloop,
|
|
|
|
|
2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vertex_interpolation_from_ptex(
|
|
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation,
|
|
|
|
|
const MPoly *coarse_poly,
|
2018-07-25 16:51:48 +02:00
|
|
|
const int ptex_of_poly_index)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
/* Nothing to do, all indices and data is already assigned. */
|
2018-07-19 16:06:37 +10:00
|
|
|
}
|
|
|
|
|
else {
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
LoopsOfPtex loops_of_ptex;
|
2018-07-25 16:51:48 +02:00
|
|
|
loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, ptex_of_poly_index);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Ptex face corner corresponds to a poly loop with same index. */
|
|
|
|
|
CustomData_copy_data(
|
|
|
|
|
vertex_data,
|
|
|
|
|
&vertex_interpolation->vertex_data_storage,
|
2018-07-25 16:51:48 +02:00
|
|
|
coarse_mloop[coarse_poly->loopstart + ptex_of_poly_index].v,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
0,
|
|
|
|
|
1);
|
|
|
|
|
/* Interpolate remaining ptex face corners, which hits loops
|
|
|
|
|
* middle points.
|
|
|
|
|
*
|
|
|
|
|
* TODO(sergey): Re-use one of interpolation results from previous
|
|
|
|
|
* iteration.
|
|
|
|
|
*/
|
|
|
|
|
const float weights[2] = {0.5f, 0.5f};
|
2018-07-23 19:09:16 +02:00
|
|
|
const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
|
|
|
|
|
const int last_loop_index = loops_of_ptex.last_loop - coarse_mloop;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const int first_indices[2] = {
|
2018-07-23 19:09:16 +02:00
|
|
|
coarse_mloop[first_loop_index].v,
|
|
|
|
|
coarse_mloop[coarse_poly->loopstart +
|
|
|
|
|
(first_loop_index - coarse_poly->loopstart + 1) %
|
|
|
|
|
coarse_poly->totloop].v};
|
|
|
|
|
const int last_indices[2] = {coarse_mloop[first_loop_index].v,
|
|
|
|
|
coarse_mloop[last_loop_index].v};
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
CustomData_interp(vertex_data,
|
|
|
|
|
&vertex_interpolation->vertex_data_storage,
|
|
|
|
|
first_indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
2,
|
|
|
|
|
1);
|
|
|
|
|
CustomData_interp(vertex_data,
|
|
|
|
|
&vertex_interpolation->vertex_data_storage,
|
|
|
|
|
last_indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
2,
|
|
|
|
|
3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vertex_interpolation_end(
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation)
|
|
|
|
|
{
|
|
|
|
|
if (vertex_interpolation->vertex_data_storage_allocated) {
|
|
|
|
|
CustomData_free(&vertex_interpolation->vertex_data_storage, 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Loop custom data interpolation helpers.
|
|
|
|
|
*/
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
typedef struct LoopsForInterpolation {
|
|
|
|
|
/* This field points to a loop data which is to be used for interpolation.
|
|
|
|
|
* The idea is to avoid unnecessary allocations for regular faces, where
|
2018-07-19 16:06:37 +10:00
|
|
|
* we can simply
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
*/
|
|
|
|
|
const CustomData *loop_data;
|
|
|
|
|
/* Loops data calculated for ptex corners. There are always 4 elements
|
|
|
|
|
* in this custom data, aligned the following way:
|
|
|
|
|
*
|
|
|
|
|
* index 0 -> uv (0, 0)
|
|
|
|
|
* index 1 -> uv (0, 1)
|
|
|
|
|
* index 2 -> uv (1, 1)
|
|
|
|
|
* index 3 -> uv (1, 0)
|
|
|
|
|
*
|
|
|
|
|
* Is allocated for non-regular faces (triangles and n-gons).
|
|
|
|
|
*/
|
|
|
|
|
CustomData loop_data_storage;
|
|
|
|
|
bool loop_data_storage_allocated;
|
|
|
|
|
/* Infices within loop_data to interpolate for. The indices are aligned with
|
|
|
|
|
* uv coordinates in a similar way as indices in loop_data_storage.
|
|
|
|
|
*/
|
|
|
|
|
int loop_indices[4];
|
|
|
|
|
} LoopsForInterpolation;
|
|
|
|
|
|
|
|
|
|
static void loop_interpolation_init(
|
|
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
LoopsForInterpolation *loop_interpolation,
|
2018-07-19 16:06:37 +10:00
|
|
|
const MPoly *coarse_poly)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
loop_interpolation->loop_data = &coarse_mesh->ldata;
|
|
|
|
|
loop_interpolation->loop_indices[0] = coarse_poly->loopstart + 0;
|
|
|
|
|
loop_interpolation->loop_indices[1] = coarse_poly->loopstart + 1;
|
|
|
|
|
loop_interpolation->loop_indices[2] = coarse_poly->loopstart + 2;
|
|
|
|
|
loop_interpolation->loop_indices[3] = coarse_poly->loopstart + 3;
|
|
|
|
|
loop_interpolation->loop_data_storage_allocated = false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
|
|
|
|
|
/* Allocate storage for loops corresponding to ptex corners. */
|
|
|
|
|
CustomData_copy(&ctx->coarse_mesh->ldata,
|
|
|
|
|
&loop_interpolation->loop_data_storage,
|
|
|
|
|
CD_MASK_EVERYTHING,
|
|
|
|
|
CD_CALLOC,
|
|
|
|
|
4);
|
|
|
|
|
/* Initialize indices. */
|
|
|
|
|
loop_interpolation->loop_indices[0] = 0;
|
|
|
|
|
loop_interpolation->loop_indices[1] = 1;
|
|
|
|
|
loop_interpolation->loop_indices[2] = 2;
|
|
|
|
|
loop_interpolation->loop_indices[3] = 3;
|
|
|
|
|
loop_interpolation->loop_data_storage_allocated = true;
|
|
|
|
|
/* Interpolate center of poly right away, it stays unchanged for all
|
|
|
|
|
* ptex faces.
|
|
|
|
|
*/
|
|
|
|
|
const float weight = 1.0f / (float)coarse_poly->totloop;
|
|
|
|
|
float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
|
|
|
|
|
int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
|
|
|
|
|
for (int i = 0; i < coarse_poly->totloop; ++i) {
|
|
|
|
|
weights[i] = weight;
|
|
|
|
|
indices[i] = coarse_poly->loopstart + i;
|
|
|
|
|
}
|
|
|
|
|
CustomData_interp(&coarse_mesh->ldata,
|
|
|
|
|
&loop_interpolation->loop_data_storage,
|
|
|
|
|
indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
coarse_poly->totloop,
|
|
|
|
|
2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void loop_interpolation_from_ptex(
|
|
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
LoopsForInterpolation *loop_interpolation,
|
|
|
|
|
const MPoly *coarse_poly,
|
|
|
|
|
const int ptex_face_index)
|
|
|
|
|
{
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
/* Nothing to do, all indices and data is already assigned. */
|
2018-07-19 16:06:37 +10:00
|
|
|
}
|
|
|
|
|
else {
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const CustomData *loop_data = &ctx->coarse_mesh->ldata;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
LoopsOfPtex loops_of_ptex;
|
|
|
|
|
loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, ptex_face_index);
|
|
|
|
|
/* Ptex face corner corresponds to a poly loop with same index. */
|
2018-08-15 11:28:00 +02:00
|
|
|
CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
CustomData_copy_data(loop_data,
|
|
|
|
|
&loop_interpolation->loop_data_storage,
|
|
|
|
|
coarse_poly->loopstart + ptex_face_index,
|
|
|
|
|
0,
|
|
|
|
|
1);
|
|
|
|
|
/* Interpolate remaining ptex face corners, which hits loops
|
|
|
|
|
* middle points.
|
|
|
|
|
*
|
|
|
|
|
* TODO(sergey): Re-use one of interpolation results from previous
|
|
|
|
|
* iteration.
|
|
|
|
|
*/
|
|
|
|
|
const float weights[2] = {0.5f, 0.5f};
|
|
|
|
|
const int first_indices[2] = {
|
|
|
|
|
loops_of_ptex.first_loop - coarse_mloop,
|
|
|
|
|
(loops_of_ptex.first_loop + 1 - coarse_mloop) %
|
|
|
|
|
coarse_poly->totloop};
|
|
|
|
|
const int last_indices[2] = {
|
|
|
|
|
loops_of_ptex.last_loop - coarse_mloop,
|
|
|
|
|
loops_of_ptex.first_loop - coarse_mloop};
|
|
|
|
|
CustomData_interp(loop_data,
|
|
|
|
|
&loop_interpolation->loop_data_storage,
|
|
|
|
|
first_indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
2,
|
|
|
|
|
1);
|
|
|
|
|
CustomData_interp(loop_data,
|
|
|
|
|
&loop_interpolation->loop_data_storage,
|
|
|
|
|
last_indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
2,
|
|
|
|
|
3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
|
|
|
|
|
{
|
|
|
|
|
if (loop_interpolation->loop_data_storage_allocated) {
|
|
|
|
|
CustomData_free(&loop_interpolation->loop_data_storage, 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-14 17:05:54 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Helper evaluation functions.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void eval_final_point_and_vertex_normal(
|
|
|
|
|
Subdiv *subdiv,
|
|
|
|
|
const int ptex_face_index,
|
|
|
|
|
const float u, const float v,
|
|
|
|
|
float r_P[3], short r_N[3])
|
|
|
|
|
{
|
|
|
|
|
if (subdiv->displacement_evaluator == NULL) {
|
|
|
|
|
BKE_subdiv_eval_limit_point_and_short_normal(
|
|
|
|
|
subdiv, ptex_face_index, u, v, r_P, r_N);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BKE_subdiv_eval_final_point(
|
|
|
|
|
subdiv, ptex_face_index, u, v, r_P);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================
|
|
|
|
|
* Displacement helpers
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void subdiv_accumulate_vertex_displacement(
|
|
|
|
|
Subdiv *subdiv,
|
|
|
|
|
const int ptex_face_index,
|
|
|
|
|
const float u, const float v,
|
|
|
|
|
MVert *subdiv_vert)
|
|
|
|
|
{
|
|
|
|
|
float dummy_P[3], dPdu[3], dPdv[3], D[3];
|
|
|
|
|
BKE_subdiv_eval_limit_point_and_derivatives(
|
|
|
|
|
subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
|
|
|
|
|
BKE_subdiv_eval_displacement(subdiv,
|
|
|
|
|
ptex_face_index, u, v,
|
|
|
|
|
dPdu, dPdv,
|
|
|
|
|
D);
|
|
|
|
|
add_v3_v3(subdiv_vert->co, D);
|
|
|
|
|
if (subdiv_vert->flag & ME_VERT_TMP_TAG) {
|
|
|
|
|
mul_v3_fl(subdiv_vert->co, 0.5f);
|
|
|
|
|
}
|
|
|
|
|
subdiv_vert->flag |= ME_VERT_TMP_TAG;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Vertex subdivision process.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Custom data interpolation helpers. */
|
|
|
|
|
|
|
|
|
|
static void subdiv_vertex_data_copy(
|
|
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
const MVert *coarse_vertex,
|
|
|
|
|
MVert *subdiv_vertex)
|
|
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
const int coarse_vertex_index = coarse_vertex - coarse_mesh->mvert;
|
|
|
|
|
const int subdiv_vertex_index = subdiv_vertex - subdiv_mesh->mvert;
|
2018-08-14 17:05:54 +02:00
|
|
|
subdiv_vertex->flag &= ~ME_VERT_TMP_TAG;
|
2018-07-25 16:51:48 +02:00
|
|
|
CustomData_copy_data(&coarse_mesh->vdata,
|
|
|
|
|
&ctx->subdiv_mesh->vdata,
|
|
|
|
|
coarse_vertex_index,
|
|
|
|
|
subdiv_vertex_index,
|
|
|
|
|
1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_vertex_data_interpolate(
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
MVert *subdiv_vertex,
|
|
|
|
|
const VerticesForInterpolation *vertex_interpolation,
|
|
|
|
|
const float u, const float v)
|
|
|
|
|
{
|
|
|
|
|
const int subdiv_vertex_index = subdiv_vertex - ctx->subdiv_mesh->mvert;
|
|
|
|
|
const float weights[4] = {(1.0f - u) * (1.0f - v),
|
|
|
|
|
u * (1.0f - v),
|
|
|
|
|
u * v,
|
|
|
|
|
(1.0f - u) * v};
|
2018-08-14 17:05:54 +02:00
|
|
|
subdiv_vertex->flag &= ~ME_VERT_TMP_TAG;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
CustomData_interp(vertex_interpolation->vertex_data,
|
|
|
|
|
&ctx->subdiv_mesh->vdata,
|
|
|
|
|
vertex_interpolation->vertex_indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
4,
|
|
|
|
|
subdiv_vertex_index);
|
2018-07-18 17:34:44 +02:00
|
|
|
if (ctx->vert_origindex != NULL) {
|
|
|
|
|
ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
|
2018-07-25 16:51:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-14 17:05:54 +02:00
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Evaluation of corner vertices. They are coming from coarse vertices. */
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_corner_vertices_regular(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
const float weights[4][2] = {{0.0f, 0.0f},
|
|
|
|
|
{1.0f, 0.0f},
|
|
|
|
|
{1.0f, 1.0f},
|
|
|
|
|
{0.0f, 1.0f}};
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MVert *coarse_mvert = coarse_mesh->mvert;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map,
|
2018-07-31 19:21:04 +10:00
|
|
|
coarse_loop->v))
|
|
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const MVert *coarse_vert = &coarse_mvert[coarse_loop->v];
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_corner_offset + coarse_loop->v];
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Displacement is accumulated in subdiv vertex position.
|
|
|
|
|
* need to back it up before copying data fro original vertex.
|
|
|
|
|
*/
|
|
|
|
|
float D[3];
|
|
|
|
|
copy_v3_v3(D, subdiv_vert->co);
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
|
|
|
|
|
BKE_subdiv_eval_limit_point_and_short_normal(
|
|
|
|
|
subdiv,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
weights[corner][0], weights[corner][1],
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Apply displacement. */
|
|
|
|
|
add_v3_v3(subdiv_vert->co, D);
|
2018-07-25 16:51:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_corner_vertices_special(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MVert *coarse_mvert = coarse_mesh->mvert;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
for (int corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
corner++, ptex_face_index++)
|
|
|
|
|
{
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map,
|
2018-07-31 19:21:04 +10:00
|
|
|
coarse_loop->v))
|
|
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const MVert *coarse_vert = &coarse_mvert[coarse_loop->v];
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_corner_offset + coarse_loop->v];
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Displacement is accumulated in subdiv vertex position.
|
|
|
|
|
* need to back it up before copying data fro original vertex.
|
|
|
|
|
*/
|
|
|
|
|
float D[3];
|
|
|
|
|
copy_v3_v3(D, subdiv_vert->co);
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
|
|
|
|
|
BKE_subdiv_eval_limit_point_and_short_normal(
|
|
|
|
|
subdiv,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
0.0f, 0.0f,
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Apply displacement. */
|
|
|
|
|
add_v3_v3(subdiv_vert->co, D);
|
2018-07-25 16:51:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_corner_vertices(SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
subdiv_evaluate_corner_vertices_regular(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_evaluate_corner_vertices_special(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-14 17:05:54 +02:00
|
|
|
static void subdiv_displace_corner_vertices_regular(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
const float weights[4][2] = {{0.0f, 0.0f},
|
|
|
|
|
{1.0f, 0.0f},
|
|
|
|
|
{1.0f, 1.0f},
|
|
|
|
|
{0.0f, 1.0f}};
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_corner_offset + coarse_loop->v];
|
|
|
|
|
const float u = weights[corner][0];
|
|
|
|
|
const float v = weights[corner][1];
|
|
|
|
|
subdiv_accumulate_vertex_displacement(
|
|
|
|
|
subdiv, ptex_face_index, u, v, subdiv_vert);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_displace_corner_vertices_special(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
for (int corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
corner++, ptex_face_index++)
|
|
|
|
|
{
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_corner_offset + coarse_loop->v];
|
|
|
|
|
subdiv_accumulate_vertex_displacement(
|
|
|
|
|
subdiv, ptex_face_index, 0.0f, 0.0f, subdiv_vert);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_displace_corner_vertices(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
if (subdiv->displacement_evaluator == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
subdiv_displace_corner_vertices_regular(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_displace_corner_vertices_special(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Evaluation of edge vertices. They are coming from coarse edges. */
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_edge_vertices_regular(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation)
|
|
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int resolution_1 = resolution - 1;
|
|
|
|
|
const float inv_resolution_1 = 1.0f / (float)resolution_1;
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map,
|
2018-07-31 19:21:04 +10:00
|
|
|
coarse_loop->e))
|
|
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
vertex_interpolation_from_ptex(ctx,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
corner);
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
|
|
|
|
|
for (int vertex_index = 0;
|
2018-07-31 19:21:04 +10:00
|
|
|
vertex_index < num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
vertex_index++, subdiv_vert++)
|
2018-07-25 16:51:48 +02:00
|
|
|
{
|
|
|
|
|
float fac = (vertex_index + 1) * inv_resolution_1;
|
|
|
|
|
if (flip) {
|
|
|
|
|
fac = 1.0f - fac;
|
2018-07-25 10:30:11 +02:00
|
|
|
}
|
2018-07-25 16:51:48 +02:00
|
|
|
if (corner >= 2) {
|
|
|
|
|
fac = 1.0f - fac;
|
2018-07-18 17:34:44 +02:00
|
|
|
}
|
2018-07-25 16:51:48 +02:00
|
|
|
float u, v;
|
|
|
|
|
if ((corner & 1) == 0) {
|
|
|
|
|
u = fac;
|
|
|
|
|
v = (corner == 2) ? 1.0f : 0.0f;
|
2018-07-25 10:30:11 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2018-07-25 16:51:48 +02:00
|
|
|
u = (corner == 1) ? 1.0f : 0.0f;
|
|
|
|
|
v = fac;
|
2018-07-18 17:34:44 +02:00
|
|
|
}
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Displacement is accumulated in subdiv vertex position.
|
|
|
|
|
* need to back it up before copying data fro original vertex.
|
|
|
|
|
*/
|
|
|
|
|
float D[3];
|
|
|
|
|
copy_v3_v3(D, subdiv_vert->co);
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_vertex_data_interpolate(ctx,
|
|
|
|
|
subdiv_vert,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
u, v);
|
|
|
|
|
BKE_subdiv_eval_limit_point_and_short_normal(
|
|
|
|
|
subdiv,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
u, v,
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Apply displacement. */
|
|
|
|
|
add_v3_v3(subdiv_vert->co, D);
|
2018-07-18 17:34:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
static void subdiv_evaluate_edge_vertices_special(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
2018-07-25 16:51:48 +02:00
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const int num_vertices_per_ptex_edge = ((resolution >> 1) + 1);
|
|
|
|
|
const float inv_ptex_resolution_1 =
|
|
|
|
|
1.0f / (float)(num_vertices_per_ptex_edge - 1);
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
2018-07-25 16:51:48 +02:00
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
2018-07-25 16:51:48 +02:00
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
const int ptex_face_start_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
int ptex_face_index = ptex_face_start_index;
|
|
|
|
|
for (int corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
corner++, ptex_face_index++)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
if (BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map,
|
2018-07-31 19:21:04 +10:00
|
|
|
coarse_loop->e))
|
|
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
vertex_interpolation_from_ptex(ctx,
|
2018-07-25 16:51:48 +02:00
|
|
|
vertex_interpolation,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
coarse_poly,
|
2018-07-25 16:51:48 +02:00
|
|
|
corner);
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
|
|
|
|
|
int veretx_delta = 1;
|
|
|
|
|
if (flip) {
|
|
|
|
|
subdiv_vert += num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
veretx_delta = -1;
|
|
|
|
|
}
|
|
|
|
|
for (int vertex_index = 1;
|
2018-07-31 19:21:04 +10:00
|
|
|
vertex_index < num_vertices_per_ptex_edge;
|
|
|
|
|
vertex_index++, subdiv_vert += veretx_delta)
|
2018-07-25 16:51:48 +02:00
|
|
|
{
|
|
|
|
|
float u = vertex_index * inv_ptex_resolution_1;
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Displacement is accumulated in subdiv vertex position.
|
|
|
|
|
* need to back it up before copying data fro original vertex.
|
|
|
|
|
*/
|
|
|
|
|
float D[3];
|
|
|
|
|
copy_v3_v3(D, subdiv_vert->co);
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_vertex_data_interpolate(ctx,
|
|
|
|
|
subdiv_vert,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
u, 0.0f);
|
|
|
|
|
BKE_subdiv_eval_limit_point_and_short_normal(
|
|
|
|
|
subdiv,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
u, 0.0f,
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Apply displacement. */
|
|
|
|
|
add_v3_v3(subdiv_vert->co, D);
|
2018-07-25 16:51:48 +02:00
|
|
|
}
|
|
|
|
|
const int next_ptex_face_index =
|
|
|
|
|
ptex_face_start_index + (corner + 1) % coarse_poly->totloop;
|
|
|
|
|
for (int vertex_index = 1;
|
2018-07-31 19:21:04 +10:00
|
|
|
vertex_index < num_vertices_per_ptex_edge - 1;
|
|
|
|
|
vertex_index++, subdiv_vert += veretx_delta)
|
2018-07-25 16:51:48 +02:00
|
|
|
{
|
|
|
|
|
float v = 1.0f - vertex_index * inv_ptex_resolution_1;
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Displacement is accumulated in subdiv vertex position.
|
|
|
|
|
* need to back it up before copying data fro original vertex.
|
|
|
|
|
*/
|
|
|
|
|
float D[3];
|
|
|
|
|
copy_v3_v3(D, subdiv_vert->co);
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_vertex_data_interpolate(ctx,
|
|
|
|
|
subdiv_vert,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
0.0f, v);
|
|
|
|
|
BKE_subdiv_eval_limit_point_and_short_normal(
|
|
|
|
|
subdiv,
|
|
|
|
|
next_ptex_face_index,
|
|
|
|
|
0.0f, v,
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Apply displacement. */
|
|
|
|
|
add_v3_v3(subdiv_vert->co, D);
|
2018-07-25 16:51:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_edge_vertices(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation)
|
|
|
|
|
{
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
subdiv_evaluate_edge_vertices_regular(
|
|
|
|
|
ctx, coarse_poly, vertex_interpolation);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_evaluate_edge_vertices_special(
|
|
|
|
|
ctx, coarse_poly, vertex_interpolation);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-14 17:05:54 +02:00
|
|
|
static void subdiv_displace_edge_vertices_regular(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int resolution_1 = resolution - 1;
|
|
|
|
|
const float inv_resolution_1 = 1.0f / (float)resolution_1;
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
|
|
|
|
|
for (int vertex_index = 0;
|
|
|
|
|
vertex_index < num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
vertex_index++, subdiv_vert++)
|
|
|
|
|
{
|
|
|
|
|
float fac = (vertex_index + 1) * inv_resolution_1;
|
|
|
|
|
if (flip) {
|
|
|
|
|
fac = 1.0f - fac;
|
|
|
|
|
}
|
|
|
|
|
if (corner >= 2) {
|
|
|
|
|
fac = 1.0f - fac;
|
|
|
|
|
}
|
|
|
|
|
float u, v;
|
|
|
|
|
if ((corner & 1) == 0) {
|
|
|
|
|
u = fac;
|
|
|
|
|
v = (corner == 2) ? 1.0f : 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
u = (corner == 1) ? 1.0f : 0.0f;
|
|
|
|
|
v = fac;
|
|
|
|
|
}
|
|
|
|
|
subdiv_accumulate_vertex_displacement(
|
|
|
|
|
subdiv, ptex_face_index, u, v, subdiv_vert);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_displace_edge_vertices_special(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const int num_vertices_per_ptex_edge = ((resolution >> 1) + 1);
|
|
|
|
|
const float inv_ptex_resolution_1 =
|
|
|
|
|
1.0f / (float)(num_vertices_per_ptex_edge - 1);
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
const int ptex_face_start_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
int ptex_face_index = ptex_face_start_index;
|
|
|
|
|
for (int corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
corner++, ptex_face_index++)
|
|
|
|
|
{
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
MVert *subdiv_vert = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge];
|
|
|
|
|
int veretx_delta = 1;
|
|
|
|
|
if (flip) {
|
|
|
|
|
subdiv_vert += num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
veretx_delta = -1;
|
|
|
|
|
}
|
|
|
|
|
for (int vertex_index = 1;
|
|
|
|
|
vertex_index < num_vertices_per_ptex_edge;
|
|
|
|
|
vertex_index++, subdiv_vert += veretx_delta)
|
|
|
|
|
{
|
|
|
|
|
float u = vertex_index * inv_ptex_resolution_1;
|
|
|
|
|
subdiv_accumulate_vertex_displacement(
|
|
|
|
|
subdiv, ptex_face_index, u, 0.0f, subdiv_vert);
|
|
|
|
|
}
|
|
|
|
|
const int next_ptex_face_index =
|
|
|
|
|
ptex_face_start_index + (corner + 1) % coarse_poly->totloop;
|
|
|
|
|
for (int vertex_index = 1;
|
|
|
|
|
vertex_index < num_vertices_per_ptex_edge - 1;
|
|
|
|
|
vertex_index++, subdiv_vert += veretx_delta)
|
|
|
|
|
{
|
|
|
|
|
float v = 1.0f - vertex_index * inv_ptex_resolution_1;
|
|
|
|
|
subdiv_accumulate_vertex_displacement(
|
|
|
|
|
subdiv, next_ptex_face_index, 0.0f, v, subdiv_vert);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static void subdiv_displace_edge_vertices(SubdivMeshContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
if (subdiv->displacement_evaluator == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
subdiv_displace_edge_vertices_regular(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_displace_edge_vertices_special(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Evaluation of inner vertices, they are coming from ptex patches. */
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_inner_vertices_regular(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation)
|
|
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
const int start_vertex_index = ctx->subdiv_vertex_offset[poly_index];
|
|
|
|
|
MVert *subdiv_vert =
|
|
|
|
|
&subdiv_mvert[ctx->vertices_inner_offset + start_vertex_index];
|
|
|
|
|
vertex_interpolation_from_ptex(ctx,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
0);
|
|
|
|
|
for (int y = 1; y < resolution - 1; y++) {
|
|
|
|
|
const float v = y * inv_resolution_1;
|
|
|
|
|
for (int x = 1; x < resolution - 1; x++, subdiv_vert++) {
|
|
|
|
|
const float u = x * inv_resolution_1;
|
|
|
|
|
subdiv_vertex_data_interpolate(ctx,
|
|
|
|
|
subdiv_vert,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
u, v);
|
2018-08-14 17:05:54 +02:00
|
|
|
eval_final_point_and_vertex_normal(
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
u, v,
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_inner_vertices_special(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation)
|
|
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int ptex_face_resolution = ptex_face_resolution_get(
|
|
|
|
|
coarse_poly, resolution);
|
|
|
|
|
const float inv_ptex_face_resolution_1 =
|
|
|
|
|
1.0f / (float)(ptex_face_resolution - 1);
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mesh->mpoly;
|
|
|
|
|
int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
const int start_vertex_index = ctx->subdiv_vertex_offset[poly_index];
|
|
|
|
|
MVert *subdiv_vert =
|
|
|
|
|
&subdiv_mvert[ctx->vertices_inner_offset + start_vertex_index];
|
|
|
|
|
vertex_interpolation_from_ptex(ctx,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
0);
|
|
|
|
|
subdiv_vertex_data_interpolate(ctx,
|
|
|
|
|
subdiv_vert,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
1.0f, 1.0f);
|
2018-08-14 17:05:54 +02:00
|
|
|
eval_final_point_and_vertex_normal(
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
1.0f, 1.0f,
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
|
|
|
|
subdiv_vert++;
|
|
|
|
|
for (int corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
corner++, ptex_face_index++)
|
|
|
|
|
{
|
|
|
|
|
if (corner != 0) {
|
|
|
|
|
vertex_interpolation_from_ptex(ctx,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
corner);
|
|
|
|
|
}
|
|
|
|
|
for (int y = 1; y < ptex_face_resolution - 1; y++) {
|
|
|
|
|
const float v = y * inv_ptex_face_resolution_1;
|
|
|
|
|
for (int x = 1; x < ptex_face_resolution; x++, subdiv_vert++) {
|
|
|
|
|
const float u = x * inv_ptex_face_resolution_1;
|
|
|
|
|
subdiv_vertex_data_interpolate(ctx,
|
|
|
|
|
subdiv_vert,
|
|
|
|
|
vertex_interpolation,
|
|
|
|
|
u, v);
|
2018-08-14 17:05:54 +02:00
|
|
|
eval_final_point_and_vertex_normal(
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
u, v,
|
|
|
|
|
subdiv_vert->co, subdiv_vert->no);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-25 16:51:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_evaluate_inner_vertices(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly,
|
|
|
|
|
VerticesForInterpolation *vertex_interpolation)
|
|
|
|
|
{
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
subdiv_evaluate_inner_vertices_regular(
|
|
|
|
|
ctx, coarse_poly, vertex_interpolation);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_evaluate_inner_vertices_special(
|
|
|
|
|
ctx, coarse_poly, vertex_interpolation);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Evaluate all vertices which are emitted from given coarse polygon. */
|
|
|
|
|
static void subdiv_evaluate_vertices(SubdivMeshContext *ctx,
|
|
|
|
|
const int poly_index)
|
|
|
|
|
{
|
|
|
|
|
/* Base/coarse mesh information. */
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
/* Initialize vertex interpolation, it is reused by corner vertices, coarse
|
|
|
|
|
* edges and patch evaluation.
|
|
|
|
|
*/
|
|
|
|
|
VerticesForInterpolation vertex_interpolation;
|
|
|
|
|
vertex_interpolation_init(ctx, &vertex_interpolation, coarse_poly);
|
|
|
|
|
subdiv_evaluate_corner_vertices(ctx, coarse_poly);
|
|
|
|
|
subdiv_evaluate_edge_vertices(ctx, coarse_poly, &vertex_interpolation);
|
|
|
|
|
subdiv_evaluate_inner_vertices(ctx, coarse_poly, &vertex_interpolation);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
vertex_interpolation_end(&vertex_interpolation);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Edge subdivision process.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-07-19 16:06:37 +10:00
|
|
|
static void subdiv_copy_edge_data(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
MEdge *subdiv_edge,
|
|
|
|
|
const MEdge *coarse_edge)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
2018-07-18 17:49:12 +02:00
|
|
|
const int subdiv_edge_index = subdiv_edge - ctx->subdiv_mesh->medge;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
if (coarse_edge == NULL) {
|
|
|
|
|
subdiv_edge->crease = 0;
|
|
|
|
|
subdiv_edge->bweight = 0;
|
|
|
|
|
subdiv_edge->flag = 0;
|
2018-07-18 17:49:12 +02:00
|
|
|
if (ctx->edge_origindex != NULL) {
|
|
|
|
|
ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
|
|
|
|
|
}
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const int coarse_edge_index = coarse_edge - ctx->coarse_mesh->medge;
|
|
|
|
|
CustomData_copy_data(&ctx->coarse_mesh->edata,
|
|
|
|
|
&ctx->subdiv_mesh->edata,
|
|
|
|
|
coarse_edge_index,
|
|
|
|
|
subdiv_edge_index,
|
|
|
|
|
1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static MEdge *subdiv_create_edges_row(SubdivMeshContext *ctx,
|
|
|
|
|
MEdge *subdiv_edge,
|
|
|
|
|
const MEdge *coarse_edge,
|
|
|
|
|
const int start_vertex_index,
|
2018-07-25 16:51:48 +02:00
|
|
|
const int num_edges_per_row)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
int vertex_index = start_vertex_index;
|
|
|
|
|
for (int edge_index = 0;
|
2018-07-25 16:51:48 +02:00
|
|
|
edge_index < num_edges_per_row - 1;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
edge_index++, subdiv_edge++)
|
|
|
|
|
{
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
|
|
|
|
|
subdiv_edge->v1 = vertex_index;
|
|
|
|
|
subdiv_edge->v2 = vertex_index + 1;
|
|
|
|
|
vertex_index += 1;
|
|
|
|
|
}
|
|
|
|
|
return subdiv_edge;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static MEdge *subdiv_create_edges_column(SubdivMeshContext *ctx,
|
|
|
|
|
MEdge *subdiv_edge,
|
|
|
|
|
const MEdge *coarse_start_edge,
|
|
|
|
|
const MEdge *coarse_end_edge,
|
|
|
|
|
const int start_vertex_index,
|
2018-07-25 16:51:48 +02:00
|
|
|
const int num_edges_per_row)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
int vertex_index = start_vertex_index;
|
|
|
|
|
for (int edge_index = 0;
|
2018-07-25 16:51:48 +02:00
|
|
|
edge_index < num_edges_per_row;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
edge_index++, subdiv_edge++)
|
|
|
|
|
{
|
|
|
|
|
const MEdge *coarse_edge = NULL;
|
|
|
|
|
if (edge_index == 0) {
|
|
|
|
|
coarse_edge = coarse_start_edge;
|
|
|
|
|
}
|
2018-07-25 16:51:48 +02:00
|
|
|
else if (edge_index == num_edges_per_row - 1) {
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
coarse_edge = coarse_end_edge;
|
|
|
|
|
}
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
|
|
|
|
|
subdiv_edge->v1 = vertex_index;
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_edge->v2 = vertex_index + num_edges_per_row;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
vertex_index += 1;
|
|
|
|
|
}
|
|
|
|
|
return subdiv_edge;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Create edges between inner vertices of patch, and also edges to the
|
|
|
|
|
* boundary.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Consider a subdivision of base face at level 1:
|
|
|
|
|
*
|
|
|
|
|
* y
|
|
|
|
|
* ^
|
|
|
|
|
* | (6) ---- (7) ---- (8)
|
|
|
|
|
* | | | |
|
|
|
|
|
* | (3) ---- (4) ---- (5)
|
|
|
|
|
* | | | |
|
|
|
|
|
* | (0) ---- (1) ---- (2)
|
|
|
|
|
* o---------------------------> x
|
|
|
|
|
*
|
|
|
|
|
* This is illustrate which parts of geometry is created by code below.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_edges_all_patches_regular(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
2018-07-25 16:51:48 +02:00
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
2018-07-23 18:40:04 +02:00
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
2018-07-25 16:51:48 +02:00
|
|
|
const int poly_index = coarse_poly - coarse_mpoly;
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int start_vertex_index =
|
|
|
|
|
ctx->vertices_inner_offset +
|
|
|
|
|
ctx->subdiv_vertex_offset[poly_index];
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MEdge *subdiv_medge = subdiv_mesh->medge;
|
2018-07-25 16:51:48 +02:00
|
|
|
MEdge *subdiv_edge = &subdiv_medge[
|
|
|
|
|
ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index]];
|
|
|
|
|
/* Create bottom row of edges (0-1, 1-2). */
|
|
|
|
|
subdiv_edge = subdiv_create_edges_row(
|
|
|
|
|
ctx,
|
|
|
|
|
subdiv_edge,
|
|
|
|
|
NULL,
|
|
|
|
|
start_vertex_index,
|
|
|
|
|
resolution - 2);
|
|
|
|
|
/* Create remaining edges. */
|
|
|
|
|
for (int row = 0; row < resolution - 3; row++) {
|
|
|
|
|
const int start_row_vertex_index =
|
|
|
|
|
start_vertex_index + row * (resolution - 2);
|
|
|
|
|
/* Create vertical columns.
|
|
|
|
|
*
|
|
|
|
|
* At first iteration it will be edges (0-3. 1-4, 2-5), then it
|
|
|
|
|
* will be (3-6, 4-7, 5-8) and so on.
|
|
|
|
|
*/
|
|
|
|
|
subdiv_edge = subdiv_create_edges_column(
|
|
|
|
|
ctx,
|
|
|
|
|
subdiv_edge,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
start_row_vertex_index,
|
|
|
|
|
resolution - 2);
|
|
|
|
|
/* Create horizontal edge row.
|
|
|
|
|
*
|
|
|
|
|
* At first iteration it will be edges (3-4, 4-5), then it will be
|
|
|
|
|
* (6-7, 7-8) and so on.
|
|
|
|
|
*/
|
|
|
|
|
subdiv_edge = subdiv_create_edges_row(
|
|
|
|
|
ctx,
|
|
|
|
|
subdiv_edge,
|
|
|
|
|
NULL,
|
|
|
|
|
start_row_vertex_index + resolution - 2,
|
|
|
|
|
resolution - 2);
|
|
|
|
|
}
|
|
|
|
|
/* Connect inner part of patch to boundary. */
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const int start_edge_vertex = ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
int side_start_index = start_vertex_index;
|
|
|
|
|
int side_stride = 0;
|
|
|
|
|
/* Calculate starting veretx of corresponding inner part of ptex. */
|
|
|
|
|
if (corner == 0) {
|
|
|
|
|
side_stride = 1;
|
|
|
|
|
}
|
|
|
|
|
else if (corner == 1) {
|
|
|
|
|
side_start_index += resolution - 3;
|
|
|
|
|
side_stride = resolution - 2;
|
|
|
|
|
}
|
|
|
|
|
else if (corner == 2) {
|
|
|
|
|
side_start_index += num_subdiv_vertices_per_coarse_edge *
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
side_stride = -1;
|
|
|
|
|
}
|
|
|
|
|
else if (corner == 3) {
|
|
|
|
|
side_start_index += num_subdiv_vertices_per_coarse_edge *
|
|
|
|
|
(num_subdiv_vertices_per_coarse_edge - 1);
|
|
|
|
|
side_stride = -(resolution - 2);
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < resolution - 2; i++, subdiv_edge++) {
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
|
|
|
|
|
if (flip) {
|
|
|
|
|
subdiv_edge->v1 = start_edge_vertex + (resolution - i - 3);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_edge->v1 = start_edge_vertex + i;
|
|
|
|
|
}
|
|
|
|
|
subdiv_edge->v2 = side_start_index + side_stride * i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_edges_all_patches_special(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mpoly;
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int ptex_face_resolution =
|
|
|
|
|
ptex_face_resolution_get(coarse_poly, resolution);
|
|
|
|
|
const int ptex_face_inner_resolution = ptex_face_resolution - 2;
|
|
|
|
|
const int num_inner_vertices_per_ptex =
|
|
|
|
|
(ptex_face_resolution - 1) * (ptex_face_resolution - 2);
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const int center_vertex_index =
|
|
|
|
|
ctx->vertices_inner_offset +
|
|
|
|
|
ctx->subdiv_vertex_offset[poly_index];
|
|
|
|
|
const int start_vertex_index = center_vertex_index + 1;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MEdge *subdiv_medge = subdiv_mesh->medge;
|
|
|
|
|
MEdge *subdiv_edge = &subdiv_medge[
|
|
|
|
|
ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index]];
|
|
|
|
|
/* Create inner ptex edges. */
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const int start_ptex_face_vertex_index =
|
2018-07-25 16:51:48 +02:00
|
|
|
start_vertex_index + corner * num_inner_vertices_per_ptex;
|
|
|
|
|
/* Similar steps to regular patch case. */
|
2018-07-19 16:06:37 +10:00
|
|
|
subdiv_edge = subdiv_create_edges_row(
|
|
|
|
|
ctx,
|
|
|
|
|
subdiv_edge,
|
2018-07-25 16:51:48 +02:00
|
|
|
NULL,
|
2018-07-19 16:06:37 +10:00
|
|
|
start_ptex_face_vertex_index,
|
2018-07-25 16:51:48 +02:00
|
|
|
ptex_face_inner_resolution + 1);
|
|
|
|
|
for (int row = 0; row < ptex_face_inner_resolution - 1; row++) {
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const int start_row_vertex_index =
|
2018-07-25 16:51:48 +02:00
|
|
|
start_ptex_face_vertex_index +
|
|
|
|
|
row * (ptex_face_inner_resolution + 1);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
subdiv_edge = subdiv_create_edges_column(
|
|
|
|
|
ctx,
|
|
|
|
|
subdiv_edge,
|
2018-07-25 16:51:48 +02:00
|
|
|
NULL,
|
|
|
|
|
NULL,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
start_row_vertex_index,
|
2018-07-25 16:51:48 +02:00
|
|
|
ptex_face_inner_resolution + 1);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
subdiv_edge = subdiv_create_edges_row(
|
|
|
|
|
ctx,
|
|
|
|
|
subdiv_edge,
|
2018-07-25 16:51:48 +02:00
|
|
|
NULL,
|
|
|
|
|
start_row_vertex_index + ptex_face_inner_resolution + 1,
|
|
|
|
|
ptex_face_inner_resolution + 1);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Create connections between ptex faces. */
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const int next_corner = (corner + 1) % coarse_poly->totloop;
|
|
|
|
|
int current_patch_vertex_index =
|
|
|
|
|
start_vertex_index + corner * num_inner_vertices_per_ptex +
|
|
|
|
|
ptex_face_inner_resolution;
|
|
|
|
|
int next_path_vertex_index =
|
|
|
|
|
start_vertex_index + next_corner * num_inner_vertices_per_ptex +
|
|
|
|
|
num_inner_vertices_per_ptex - ptex_face_resolution + 1;
|
|
|
|
|
for (int row = 0;
|
|
|
|
|
row < ptex_face_inner_resolution;
|
|
|
|
|
row++, subdiv_edge++)
|
|
|
|
|
{
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
|
|
|
|
|
subdiv_edge->v1 = current_patch_vertex_index;
|
|
|
|
|
subdiv_edge->v2 = next_path_vertex_index;
|
|
|
|
|
current_patch_vertex_index += ptex_face_inner_resolution + 1;
|
|
|
|
|
next_path_vertex_index += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Create edges from center. */
|
|
|
|
|
if (ptex_face_resolution >= 3) {
|
|
|
|
|
for (int corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
corner++, subdiv_edge++)
|
|
|
|
|
{
|
|
|
|
|
const int current_patch_end_vertex_index =
|
|
|
|
|
start_vertex_index + corner * num_inner_vertices_per_ptex +
|
|
|
|
|
num_inner_vertices_per_ptex - 1;
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
|
|
|
|
|
subdiv_edge->v1 = center_vertex_index;
|
|
|
|
|
subdiv_edge->v2 = current_patch_end_vertex_index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Connect inner path of patch to boundary. */
|
|
|
|
|
const MLoop *prev_coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
{
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const int start_edge_vertex = ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
int side_start_index;
|
|
|
|
|
if (ptex_face_resolution >= 3) {
|
|
|
|
|
side_start_index =
|
|
|
|
|
start_vertex_index + num_inner_vertices_per_ptex * corner;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
side_start_index = center_vertex_index;
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < ptex_face_resolution - 1; i++, subdiv_edge++) {
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
|
|
|
|
|
if (flip) {
|
|
|
|
|
subdiv_edge->v1 = start_edge_vertex + (resolution - i - 3);
|
2018-07-31 19:21:04 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_edge->v1 = start_edge_vertex + i;
|
|
|
|
|
}
|
|
|
|
|
subdiv_edge->v2 = side_start_index + i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ptex_face_resolution >= 3) {
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[prev_coarse_loop->e];
|
|
|
|
|
const int start_edge_vertex = ctx->vertices_edge_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
int side_start_index =
|
|
|
|
|
start_vertex_index + num_inner_vertices_per_ptex * corner;
|
|
|
|
|
for (int i = 0; i < ptex_face_resolution - 2; i++, subdiv_edge++) {
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, NULL);
|
|
|
|
|
if (flip) {
|
|
|
|
|
subdiv_edge->v1 = start_edge_vertex + (resolution - i - 3);
|
2018-07-31 19:21:04 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_edge->v1 = start_edge_vertex + i;
|
|
|
|
|
}
|
|
|
|
|
subdiv_edge->v2 = side_start_index +
|
|
|
|
|
(ptex_face_inner_resolution + 1) * i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
prev_coarse_loop = coarse_loop;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_edges_all_patches(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
subdiv_create_edges_all_patches_regular(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_create_edges_all_patches_special(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_edges(SubdivMeshContext *ctx, int poly_index)
|
|
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
subdiv_create_edges_all_patches(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_boundary_edges(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
int edge_index)
|
|
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[edge_index];
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const int num_subdiv_edges_per_coarse_edge = resolution - 1;
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MEdge *subdiv_medge = subdiv_mesh->medge;
|
|
|
|
|
MEdge *subdiv_edge = &subdiv_medge[
|
|
|
|
|
ctx->edge_boundary_offset +
|
|
|
|
|
edge_index * num_subdiv_edges_per_coarse_edge];
|
|
|
|
|
int last_vertex_index = ctx->vertices_corner_offset + coarse_edge->v1;
|
|
|
|
|
for (int i = 0;
|
|
|
|
|
i < num_subdiv_edges_per_coarse_edge - 1;
|
|
|
|
|
i++, subdiv_edge++)
|
|
|
|
|
{
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
|
|
|
|
|
subdiv_edge->v1 = last_vertex_index;
|
|
|
|
|
subdiv_edge->v2 =
|
|
|
|
|
ctx->vertices_edge_offset +
|
|
|
|
|
edge_index * num_subdiv_vertices_per_coarse_edge +
|
|
|
|
|
i;
|
|
|
|
|
last_vertex_index = subdiv_edge->v2;
|
|
|
|
|
}
|
|
|
|
|
subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
|
|
|
|
|
subdiv_edge->v1 = last_vertex_index;
|
|
|
|
|
subdiv_edge->v2 = ctx->vertices_corner_offset + coarse_edge->v2;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Loops creation/interpolation.
|
|
|
|
|
*/
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
static void subdiv_copy_loop_data(
|
|
|
|
|
const SubdivMeshContext *ctx,
|
|
|
|
|
MLoop *subdiv_loop,
|
|
|
|
|
const LoopsForInterpolation *loop_interpolation,
|
|
|
|
|
const float u, const float v)
|
|
|
|
|
{
|
|
|
|
|
const int subdiv_loop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
|
|
|
|
|
const float weights[4] = {(1.0f - u) * (1.0f - v),
|
|
|
|
|
u * (1.0f - v),
|
|
|
|
|
u * v,
|
|
|
|
|
(1.0f - u) * v};
|
|
|
|
|
CustomData_interp(loop_interpolation->loop_data,
|
|
|
|
|
&ctx->subdiv_mesh->ldata,
|
|
|
|
|
loop_interpolation->loop_indices,
|
|
|
|
|
weights, NULL,
|
|
|
|
|
4,
|
|
|
|
|
subdiv_loop_index);
|
|
|
|
|
/* TODO(sergey): Set ORIGINDEX. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
|
|
|
|
|
MLoop *subdiv_loop,
|
|
|
|
|
const int ptex_face_index,
|
|
|
|
|
const float u, const float v,
|
2018-07-25 16:51:48 +02:00
|
|
|
const float du, const float dv)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
if (ctx->num_uv_layers == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Subdiv *subdiv = ctx->subdiv;
|
|
|
|
|
const int mloop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
|
|
|
|
|
for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
|
|
|
|
|
MLoopUV *subdiv_loopuv = &ctx->uv_layers[layer_index][mloop_index];
|
|
|
|
|
BKE_subdiv_eval_face_varying(subdiv,
|
2018-08-01 18:31:05 +02:00
|
|
|
layer_index,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
ptex_face_index,
|
|
|
|
|
u, v,
|
|
|
|
|
subdiv_loopuv[0].uv);
|
|
|
|
|
BKE_subdiv_eval_face_varying(subdiv,
|
2018-08-01 18:31:05 +02:00
|
|
|
layer_index,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
ptex_face_index,
|
|
|
|
|
u + du, v,
|
|
|
|
|
subdiv_loopuv[1].uv);
|
|
|
|
|
BKE_subdiv_eval_face_varying(subdiv,
|
2018-08-01 18:31:05 +02:00
|
|
|
layer_index,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
ptex_face_index,
|
|
|
|
|
u + du, v + dv,
|
|
|
|
|
subdiv_loopuv[2].uv);
|
|
|
|
|
BKE_subdiv_eval_face_varying(subdiv,
|
2018-08-01 18:31:05 +02:00
|
|
|
layer_index,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
ptex_face_index,
|
|
|
|
|
u, v + dv,
|
|
|
|
|
subdiv_loopuv[3].uv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
static void rotate_indices(const int rot, int *a, int *b, int *c, int *d)
|
|
|
|
|
{
|
|
|
|
|
int values[4] = {*a, *b, *c, *d};
|
|
|
|
|
*a = values[(0 - rot + 4) % 4];
|
|
|
|
|
*b = values[(1 - rot + 4) % 4];
|
|
|
|
|
*c = values[(2 - rot + 4) % 4];
|
|
|
|
|
*d = values[(3 - rot + 4) % 4];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_loops_of_poly(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
LoopsForInterpolation *loop_interpolation,
|
|
|
|
|
MLoop *subdiv_loop_start,
|
|
|
|
|
const int ptex_face_index,
|
|
|
|
|
const int rotation,
|
|
|
|
|
/*const*/ int v0, /*const*/ int e0,
|
|
|
|
|
/*const*/ int v1, /*const*/ int e1,
|
|
|
|
|
/*const*/ int v2, /*const*/ int e2,
|
|
|
|
|
/*const*/ int v3, /*const*/ int e3,
|
|
|
|
|
const float u, const float v,
|
|
|
|
|
const float du, const float dv)
|
|
|
|
|
{
|
|
|
|
|
rotate_indices(rotation, &v0, &v1, &v2, &v3);
|
|
|
|
|
rotate_indices(rotation, &e0, &e1, &e2, &e3);
|
|
|
|
|
subdiv_copy_loop_data(ctx,
|
|
|
|
|
&subdiv_loop_start[0],
|
|
|
|
|
loop_interpolation,
|
|
|
|
|
u, v);
|
|
|
|
|
subdiv_loop_start[0].v = v0;
|
|
|
|
|
subdiv_loop_start[0].e = e0;
|
|
|
|
|
subdiv_copy_loop_data(ctx,
|
|
|
|
|
&subdiv_loop_start[1],
|
|
|
|
|
loop_interpolation,
|
|
|
|
|
u + du, v);
|
|
|
|
|
subdiv_loop_start[1].v = v1;
|
|
|
|
|
subdiv_loop_start[1].e = e1;
|
|
|
|
|
subdiv_copy_loop_data(ctx,
|
|
|
|
|
&subdiv_loop_start[2],
|
|
|
|
|
loop_interpolation,
|
|
|
|
|
u + du, v + dv);
|
|
|
|
|
subdiv_loop_start[2].v = v2;
|
|
|
|
|
subdiv_loop_start[2].e = e2;
|
|
|
|
|
subdiv_copy_loop_data(ctx,
|
|
|
|
|
&subdiv_loop_start[3],
|
|
|
|
|
loop_interpolation,
|
|
|
|
|
u, v + dv);
|
|
|
|
|
subdiv_loop_start[3].v = v3;
|
|
|
|
|
subdiv_loop_start[3].e = e3;
|
|
|
|
|
/* Interpolate UV layers using OpenSubdiv. */
|
|
|
|
|
subdiv_eval_uv_layer(ctx,
|
|
|
|
|
subdiv_loop_start,
|
|
|
|
|
ptex_face_index,
|
|
|
|
|
u, v, du, dv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_loops_regular(SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
/* Base/coarse mesh information. */
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
2018-07-25 16:51:48 +02:00
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
2018-07-23 18:40:04 +02:00
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
2018-07-25 16:51:48 +02:00
|
|
|
const int poly_index = coarse_poly - coarse_mpoly;
|
2018-07-23 18:40:04 +02:00
|
|
|
const int ptex_resolution =
|
|
|
|
|
ptex_face_resolution_get(coarse_poly, resolution);
|
2018-07-25 16:51:48 +02:00
|
|
|
const int ptex_inner_resolution = ptex_resolution - 2;
|
|
|
|
|
const int num_subdiv_edges_per_coarse_edge = resolution - 1;
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
2018-07-23 18:40:04 +02:00
|
|
|
const float inv_ptex_resolution_1 = 1.0f / (float)(ptex_resolution - 1);
|
2018-07-25 16:51:48 +02:00
|
|
|
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
const int start_vertex_index =
|
|
|
|
|
ctx->vertices_inner_offset +
|
|
|
|
|
ctx->subdiv_vertex_offset[poly_index];
|
|
|
|
|
const int start_edge_index =
|
|
|
|
|
ctx->edge_inner_offset +
|
|
|
|
|
ctx->subdiv_edge_offset[poly_index];
|
|
|
|
|
const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
|
2018-07-23 18:40:04 +02:00
|
|
|
const int start_loop_index = 4 * start_poly_index;
|
|
|
|
|
const float du = inv_ptex_resolution_1;
|
|
|
|
|
const float dv = inv_ptex_resolution_1;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Hi-poly subdivided mesh. */
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MLoop *subdiv_loopoop = subdiv_mesh->mloop;
|
|
|
|
|
MLoop *subdiv_loop = &subdiv_loopoop[start_loop_index];
|
|
|
|
|
LoopsForInterpolation loop_interpolation;
|
|
|
|
|
loop_interpolation_init(ctx, &loop_interpolation, coarse_poly);
|
2018-07-25 16:51:48 +02:00
|
|
|
loop_interpolation_from_ptex(ctx,
|
|
|
|
|
&loop_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
0);
|
|
|
|
|
/* Loops for inner part of ptex. */
|
|
|
|
|
for (int y = 1; y < ptex_resolution - 2; y++) {
|
|
|
|
|
const float v = y * inv_ptex_resolution_1;
|
|
|
|
|
const int inner_y = y - 1;
|
|
|
|
|
for (int x = 1; x < ptex_resolution - 2; x++, subdiv_loop += 4) {
|
|
|
|
|
const int inner_x = x - 1;
|
|
|
|
|
const float u = x * inv_ptex_resolution_1;
|
|
|
|
|
/* Vertex indicies ordered counter-clockwise. */
|
|
|
|
|
const int v0 = start_vertex_index +
|
|
|
|
|
(inner_y * ptex_inner_resolution + inner_x);
|
|
|
|
|
const int v1 = v0 + 1;
|
|
|
|
|
const int v2 = v0 + ptex_inner_resolution + 1;
|
|
|
|
|
const int v3 = v0 + ptex_inner_resolution;
|
|
|
|
|
/* Edge indicies ordered counter-clockwise. */
|
|
|
|
|
const int e0 = start_edge_index +
|
|
|
|
|
(inner_y * (2 * ptex_inner_resolution - 1) + inner_x);
|
|
|
|
|
const int e1 = e0 + ptex_inner_resolution;
|
|
|
|
|
const int e2 = e0 + (2 * ptex_inner_resolution - 1);
|
|
|
|
|
const int e3 = e0 + ptex_inner_resolution - 1;
|
|
|
|
|
subdiv_create_loops_of_poly(
|
|
|
|
|
ctx, &loop_interpolation, subdiv_loop, ptex_face_index, 0,
|
|
|
|
|
v0, e0, v1, e1, v2, e2, v3, e3,
|
|
|
|
|
u, v, du, dv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Loops for faces connecting inner ptex part with boundary. */
|
|
|
|
|
const MLoop *prev_coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
|
|
|
|
|
const int start_edge_vertex = ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
int side_start_index = start_vertex_index;
|
|
|
|
|
int side_stride = 0;
|
|
|
|
|
int v0 = ctx->vertices_corner_offset + coarse_loop->v;
|
|
|
|
|
int v3, e3;
|
|
|
|
|
int e2_offset, e2_stride;
|
|
|
|
|
float u, v, delta_u, delta_v;
|
|
|
|
|
if (prev_coarse_loop->v == prev_coarse_edge->v1) {
|
|
|
|
|
v3 = ctx->vertices_edge_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
e3 = ctx->edge_boundary_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
|
|
|
|
|
num_subdiv_edges_per_coarse_edge - 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v3 = ctx->vertices_edge_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
e3 = ctx->edge_boundary_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
|
|
|
|
|
}
|
|
|
|
|
/* Calculate starting veretx of corresponding inner part of ptex. */
|
|
|
|
|
if (corner == 0) {
|
|
|
|
|
side_stride = 1;
|
|
|
|
|
e2_offset = 0;
|
|
|
|
|
e2_stride = 1;
|
|
|
|
|
u = 0.0f;
|
|
|
|
|
v = 0.0f;
|
|
|
|
|
delta_u = du;
|
|
|
|
|
delta_v = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else if (corner == 1) {
|
|
|
|
|
side_start_index += resolution - 3;
|
|
|
|
|
side_stride = resolution - 2;
|
|
|
|
|
e2_offset = 2 * num_subdiv_edges_per_coarse_edge - 4;
|
|
|
|
|
e2_stride = 2 * num_subdiv_edges_per_coarse_edge - 3;
|
|
|
|
|
u = 1.0f - du;
|
|
|
|
|
v = 0;
|
|
|
|
|
delta_u = 0.0f;
|
|
|
|
|
delta_v = dv;
|
|
|
|
|
}
|
|
|
|
|
else if (corner == 2) {
|
|
|
|
|
side_start_index += num_subdiv_vertices_per_coarse_edge *
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
side_stride = -1;
|
|
|
|
|
e2_offset = num_edges_per_ptex_face_get(resolution - 2) - 1;
|
|
|
|
|
e2_stride = -1;
|
|
|
|
|
u = 1.0f - du;
|
|
|
|
|
v = 1.0f - dv;
|
|
|
|
|
delta_u = -du;
|
|
|
|
|
delta_v = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else if (corner == 3) {
|
|
|
|
|
side_start_index += num_subdiv_vertices_per_coarse_edge *
|
|
|
|
|
(num_subdiv_vertices_per_coarse_edge - 1);
|
|
|
|
|
side_stride = -(resolution - 2);
|
|
|
|
|
e2_offset = num_edges_per_ptex_face_get(resolution - 2) -
|
|
|
|
|
(2 * num_subdiv_edges_per_coarse_edge - 3);
|
|
|
|
|
e2_stride = -(2 * num_subdiv_edges_per_coarse_edge - 3);
|
|
|
|
|
u = 0.0f;
|
|
|
|
|
v = 1.0f - dv;
|
|
|
|
|
delta_u = 0.0f;
|
|
|
|
|
delta_v = -dv;
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < resolution - 2; i++, subdiv_loop += 4) {
|
|
|
|
|
int v1;
|
|
|
|
|
if (flip) {
|
|
|
|
|
v1 = start_edge_vertex + (resolution - i - 3);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v1 = start_edge_vertex + i;
|
|
|
|
|
}
|
|
|
|
|
const int v2 = side_start_index + side_stride * i;
|
|
|
|
|
int e0;
|
|
|
|
|
if (flip) {
|
|
|
|
|
e0 = ctx->edge_boundary_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_edges_per_coarse_edge +
|
|
|
|
|
num_subdiv_edges_per_coarse_edge - i - 1;
|
2018-07-31 19:21:04 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2018-07-25 16:51:48 +02:00
|
|
|
e0 = ctx->edge_boundary_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_edges_per_coarse_edge +
|
|
|
|
|
i;
|
|
|
|
|
}
|
|
|
|
|
int e1 = start_edge_index +
|
|
|
|
|
num_edges_per_ptex_face_get(resolution - 2) +
|
|
|
|
|
corner * num_subdiv_vertices_per_coarse_edge +
|
|
|
|
|
i;
|
|
|
|
|
int e2;
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
e2 = start_edge_index +
|
|
|
|
|
num_edges_per_ptex_face_get(resolution - 2) +
|
|
|
|
|
((corner - 1 + coarse_poly->totloop) %
|
|
|
|
|
coarse_poly->totloop) *
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge +
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
e2 = start_edge_index + e2_offset + e2_stride * (i - 1);
|
|
|
|
|
}
|
|
|
|
|
subdiv_create_loops_of_poly(
|
|
|
|
|
ctx, &loop_interpolation, subdiv_loop,
|
|
|
|
|
ptex_face_index, corner,
|
|
|
|
|
v0, e0, v1, e1, v2, e2, v3, e3,
|
|
|
|
|
u + delta_u * i, v + delta_v * i, du, dv);
|
|
|
|
|
v0 = v1;
|
|
|
|
|
v3 = v2;
|
|
|
|
|
e3 = e1;
|
|
|
|
|
}
|
|
|
|
|
prev_coarse_loop = coarse_loop;
|
|
|
|
|
}
|
|
|
|
|
loop_interpolation_end(&loop_interpolation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_loops_special(SubdivMeshContext *ctx,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
/* Base/coarse mesh information. */
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
const MLoop *coarse_mloop = coarse_mesh->mloop;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
const int poly_index = coarse_poly - coarse_mpoly;
|
|
|
|
|
const int ptex_face_resolution =
|
|
|
|
|
ptex_face_resolution_get(coarse_poly, resolution);
|
|
|
|
|
const int ptex_face_inner_resolution = ptex_face_resolution - 2;
|
|
|
|
|
const float inv_ptex_resolution_1 =
|
|
|
|
|
1.0f / (float)(ptex_face_resolution - 1);
|
|
|
|
|
const int num_inner_vertices_per_ptex =
|
|
|
|
|
(ptex_face_resolution - 1) * (ptex_face_resolution - 2);
|
|
|
|
|
const int num_inner_edges_per_ptex_face =
|
|
|
|
|
num_inner_edges_per_ptex_face_get(
|
|
|
|
|
ptex_face_inner_resolution + 1);
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const int num_subdiv_edges_per_coarse_edge = resolution - 1;
|
|
|
|
|
const int ptex_face_index = ctx->face_ptex_offset[poly_index];
|
|
|
|
|
const int center_vertex_index =
|
|
|
|
|
ctx->vertices_inner_offset +
|
|
|
|
|
ctx->subdiv_vertex_offset[poly_index];
|
|
|
|
|
const int start_vertex_index = center_vertex_index + 1;
|
|
|
|
|
const int start_inner_vertex_index = center_vertex_index + 1;
|
|
|
|
|
const int start_edge_index = ctx->edge_inner_offset +
|
|
|
|
|
ctx->subdiv_edge_offset[poly_index];
|
|
|
|
|
const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
|
|
|
|
|
const int start_loop_index = 4 * start_poly_index;
|
|
|
|
|
const float du = inv_ptex_resolution_1;
|
|
|
|
|
const float dv = inv_ptex_resolution_1;
|
|
|
|
|
/* Hi-poly subdivided mesh. */
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MLoop *subdiv_loopoop = subdiv_mesh->mloop;
|
|
|
|
|
MLoop *subdiv_loop = &subdiv_loopoop[start_loop_index];
|
|
|
|
|
LoopsForInterpolation loop_interpolation;
|
|
|
|
|
loop_interpolation_init(ctx, &loop_interpolation, coarse_poly);
|
|
|
|
|
for (int corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
corner++)
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
const int corner_vertex_index =
|
|
|
|
|
start_vertex_index + corner * num_inner_vertices_per_ptex;
|
|
|
|
|
const int corner_edge_index =
|
|
|
|
|
start_edge_index + corner * num_inner_edges_per_ptex_face;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
loop_interpolation_from_ptex(ctx,
|
|
|
|
|
&loop_interpolation,
|
|
|
|
|
coarse_poly,
|
2018-07-25 16:51:48 +02:00
|
|
|
corner);
|
|
|
|
|
for (int y = 1; y < ptex_face_inner_resolution; y++) {
|
2018-07-23 18:40:04 +02:00
|
|
|
const float v = y * inv_ptex_resolution_1;
|
2018-07-25 16:51:48 +02:00
|
|
|
const int inner_y = y - 1;
|
|
|
|
|
for (int x = 1;
|
|
|
|
|
x < ptex_face_inner_resolution + 1;
|
|
|
|
|
x++, subdiv_loop += 4)
|
|
|
|
|
{
|
|
|
|
|
const int inner_x = x - 1;
|
2018-07-23 18:40:04 +02:00
|
|
|
const float u = x * inv_ptex_resolution_1;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Vertex indicies ordered counter-clockwise. */
|
2018-07-25 16:51:48 +02:00
|
|
|
const int v0 =
|
|
|
|
|
corner_vertex_index +
|
|
|
|
|
(inner_y * (ptex_face_inner_resolution + 1) + inner_x);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
const int v1 = v0 + 1;
|
2018-07-25 16:51:48 +02:00
|
|
|
const int v2 = v0 + ptex_face_inner_resolution + 2;
|
|
|
|
|
const int v3 = v0 + ptex_face_inner_resolution + 1;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Edge indicies ordered counter-clockwise. */
|
2018-07-25 16:51:48 +02:00
|
|
|
const int e0 = corner_edge_index +
|
|
|
|
|
(inner_y * (2 * ptex_face_inner_resolution + 1) + inner_x);
|
|
|
|
|
const int e1 = e0 + ptex_face_inner_resolution + 1;
|
|
|
|
|
const int e2 = e0 + (2 * ptex_face_inner_resolution + 1);
|
|
|
|
|
const int e3 = e0 + ptex_face_inner_resolution;
|
|
|
|
|
subdiv_create_loops_of_poly(
|
|
|
|
|
ctx, &loop_interpolation, subdiv_loop,
|
|
|
|
|
ptex_face_index + corner, 0,
|
|
|
|
|
v0, e0, v1, e1, v2, e2, v3, e3,
|
|
|
|
|
u, v, du, dv);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-25 16:51:48 +02:00
|
|
|
/* Create connections between ptex faces. */
|
|
|
|
|
for (int corner = 0; corner < coarse_poly->totloop; corner++) {
|
|
|
|
|
const int next_corner = (corner + 1) % coarse_poly->totloop;
|
|
|
|
|
const int corner_edge_index =
|
|
|
|
|
start_edge_index + corner * num_inner_edges_per_ptex_face;
|
|
|
|
|
const int next_corner_edge_index =
|
|
|
|
|
start_edge_index + next_corner * num_inner_edges_per_ptex_face;
|
|
|
|
|
int current_patch_vertex_index =
|
|
|
|
|
start_inner_vertex_index +
|
|
|
|
|
corner * num_inner_vertices_per_ptex +
|
|
|
|
|
ptex_face_inner_resolution;
|
|
|
|
|
int next_path_vertex_index =
|
|
|
|
|
start_inner_vertex_index +
|
|
|
|
|
next_corner * num_inner_vertices_per_ptex +
|
|
|
|
|
num_inner_vertices_per_ptex - ptex_face_resolution + 1;
|
|
|
|
|
int v0 = current_patch_vertex_index;
|
|
|
|
|
int v1 = next_path_vertex_index;
|
|
|
|
|
current_patch_vertex_index += ptex_face_inner_resolution + 1;
|
|
|
|
|
next_path_vertex_index += 1;
|
|
|
|
|
int e0 = start_edge_index +
|
|
|
|
|
coarse_poly->totloop * num_inner_edges_per_ptex_face +
|
|
|
|
|
corner * (ptex_face_resolution - 2);
|
|
|
|
|
int e1 = next_corner_edge_index + num_inner_edges_per_ptex_face -
|
|
|
|
|
ptex_face_resolution + 2;
|
|
|
|
|
int e3 = corner_edge_index + 2 * ptex_face_resolution - 4;
|
|
|
|
|
loop_interpolation_from_ptex(ctx,
|
|
|
|
|
&loop_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
next_corner);
|
|
|
|
|
for (int row = 1;
|
|
|
|
|
row < ptex_face_inner_resolution;
|
|
|
|
|
row++, subdiv_loop += 4)
|
|
|
|
|
{
|
|
|
|
|
const int v2 = next_path_vertex_index;
|
|
|
|
|
const int v3 = current_patch_vertex_index;
|
|
|
|
|
const int e2 = e0 + 1;
|
|
|
|
|
const float u = row * du;
|
|
|
|
|
const float v = 1.0f - dv;
|
|
|
|
|
subdiv_create_loops_of_poly(
|
|
|
|
|
ctx, &loop_interpolation, subdiv_loop,
|
|
|
|
|
ptex_face_index + next_corner, 3,
|
|
|
|
|
v0, e0, v1, e1, v2, e2, v3, e3,
|
|
|
|
|
u, v, du, dv);
|
|
|
|
|
current_patch_vertex_index += ptex_face_inner_resolution + 1;
|
|
|
|
|
next_path_vertex_index += 1;
|
|
|
|
|
v0 = v3;
|
|
|
|
|
v1 = v2;
|
|
|
|
|
e0 = e2;
|
|
|
|
|
e1 += 1;
|
|
|
|
|
e3 += 2 * ptex_face_resolution - 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Create loops from center. */
|
|
|
|
|
if (ptex_face_resolution >= 3) {
|
|
|
|
|
const int start_center_edge_index =
|
|
|
|
|
start_edge_index +
|
|
|
|
|
(num_inner_edges_per_ptex_face +
|
|
|
|
|
ptex_face_inner_resolution) * coarse_poly->totloop;
|
|
|
|
|
const int start_boundary_edge =
|
|
|
|
|
start_edge_index +
|
|
|
|
|
coarse_poly->totloop * num_inner_edges_per_ptex_face +
|
|
|
|
|
ptex_face_inner_resolution - 1;
|
|
|
|
|
for (int corner = 0, prev_corner = coarse_poly->totloop - 1;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
prev_corner = corner, corner++, subdiv_loop += 4)
|
|
|
|
|
{
|
|
|
|
|
loop_interpolation_from_ptex(ctx,
|
|
|
|
|
&loop_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
corner);
|
|
|
|
|
const int corner_edge_index =
|
|
|
|
|
start_edge_index +
|
|
|
|
|
corner * num_inner_edges_per_ptex_face;
|
|
|
|
|
const int current_patch_end_vertex_index =
|
|
|
|
|
start_vertex_index + corner * num_inner_vertices_per_ptex +
|
|
|
|
|
num_inner_vertices_per_ptex - 1;
|
|
|
|
|
const int prev_current_patch_end_vertex_index =
|
|
|
|
|
start_vertex_index + prev_corner *
|
|
|
|
|
num_inner_vertices_per_ptex +
|
|
|
|
|
num_inner_vertices_per_ptex - 1;
|
|
|
|
|
const int v0 = center_vertex_index;
|
|
|
|
|
const int v1 = prev_current_patch_end_vertex_index;
|
|
|
|
|
const int v2 = current_patch_end_vertex_index - 1;
|
|
|
|
|
const int v3 = current_patch_end_vertex_index;
|
|
|
|
|
const int e0 = start_center_edge_index + prev_corner;
|
|
|
|
|
const int e1 = start_boundary_edge +
|
|
|
|
|
prev_corner * (ptex_face_inner_resolution);
|
|
|
|
|
const int e2 = corner_edge_index +
|
|
|
|
|
num_inner_edges_per_ptex_face - 1;
|
|
|
|
|
const int e3 = start_center_edge_index + corner;
|
|
|
|
|
const float u = 1.0f - du;
|
|
|
|
|
const float v = 1.0f - dv;
|
|
|
|
|
subdiv_create_loops_of_poly(
|
|
|
|
|
ctx, &loop_interpolation, subdiv_loop,
|
|
|
|
|
ptex_face_index + corner, 2,
|
|
|
|
|
v0, e0, v1, e1, v2, e2, v3, e3,
|
|
|
|
|
u, v, du, dv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Loops for faces connecting inner ptex part with boundary. */
|
|
|
|
|
const MLoop *prev_coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
|
|
|
|
|
for (int prev_corner = coarse_poly->totloop - 1, corner = 0;
|
|
|
|
|
corner < coarse_poly->totloop;
|
|
|
|
|
prev_corner = corner, corner++)
|
|
|
|
|
{
|
|
|
|
|
loop_interpolation_from_ptex(ctx,
|
|
|
|
|
&loop_interpolation,
|
|
|
|
|
coarse_poly,
|
|
|
|
|
corner);
|
|
|
|
|
const MLoop *coarse_loop =
|
|
|
|
|
&coarse_mloop[coarse_poly->loopstart + corner];
|
|
|
|
|
const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
|
|
|
|
|
const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
|
|
|
|
|
const bool flip = (coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
const int start_edge_vertex = ctx->vertices_edge_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
const int corner_vertex_index =
|
|
|
|
|
start_vertex_index + corner * num_inner_vertices_per_ptex;
|
|
|
|
|
const int corner_edge_index =
|
|
|
|
|
start_edge_index + corner * num_inner_edges_per_ptex_face;
|
|
|
|
|
/* Create loops for polygons along U axis. */
|
|
|
|
|
int v0 = ctx->vertices_corner_offset + coarse_loop->v;
|
|
|
|
|
int v3, e3;
|
|
|
|
|
if (prev_coarse_loop->v == prev_coarse_edge->v1) {
|
|
|
|
|
v3 = ctx->vertices_edge_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
e3 = ctx->edge_boundary_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
|
|
|
|
|
num_subdiv_edges_per_coarse_edge - 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v3 = ctx->vertices_edge_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
e3 = ctx->edge_boundary_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0;
|
|
|
|
|
i <= ptex_face_inner_resolution;
|
|
|
|
|
i++, subdiv_loop += 4)
|
|
|
|
|
{
|
|
|
|
|
int v1;
|
|
|
|
|
if (flip) {
|
|
|
|
|
v1 = start_edge_vertex + (resolution - i - 3);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v1 = start_edge_vertex + i;
|
|
|
|
|
}
|
|
|
|
|
int v2;
|
|
|
|
|
if (ptex_face_inner_resolution >= 1) {
|
|
|
|
|
v2 = corner_vertex_index + i;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v2 = center_vertex_index;
|
|
|
|
|
}
|
|
|
|
|
int e0;
|
|
|
|
|
if (flip) {
|
|
|
|
|
e0 = ctx->edge_boundary_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_edges_per_coarse_edge +
|
|
|
|
|
num_subdiv_edges_per_coarse_edge - i - 1;
|
2018-07-31 19:21:04 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2018-07-25 16:51:48 +02:00
|
|
|
e0 = ctx->edge_boundary_offset +
|
|
|
|
|
coarse_loop->e * num_subdiv_edges_per_coarse_edge +
|
|
|
|
|
i;
|
|
|
|
|
}
|
|
|
|
|
int e1 = start_edge_index +
|
|
|
|
|
corner * (2 * ptex_face_inner_resolution + 1);
|
|
|
|
|
if (ptex_face_resolution >= 3) {
|
|
|
|
|
e1 += coarse_poly->totloop * (num_inner_edges_per_ptex_face +
|
|
|
|
|
ptex_face_inner_resolution + 1) +
|
|
|
|
|
i;
|
|
|
|
|
}
|
|
|
|
|
int e2 = 0;
|
|
|
|
|
if (i == 0 && ptex_face_resolution >= 3) {
|
|
|
|
|
e2 = start_edge_index +
|
|
|
|
|
coarse_poly->totloop *
|
|
|
|
|
(num_inner_edges_per_ptex_face +
|
|
|
|
|
ptex_face_inner_resolution + 1) +
|
|
|
|
|
corner * (2 * ptex_face_inner_resolution + 1) +
|
|
|
|
|
ptex_face_inner_resolution + 1;
|
|
|
|
|
}
|
|
|
|
|
else if (i == 0 && ptex_face_resolution < 3) {
|
|
|
|
|
e2 = start_edge_index +
|
|
|
|
|
prev_corner * (2 * ptex_face_inner_resolution + 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
e2 = corner_edge_index + i - 1;
|
|
|
|
|
}
|
|
|
|
|
const float u = du * i;
|
|
|
|
|
const float v = 0.0f;
|
|
|
|
|
subdiv_create_loops_of_poly(
|
|
|
|
|
ctx, &loop_interpolation, subdiv_loop,
|
|
|
|
|
ptex_face_index + corner, 0,
|
|
|
|
|
v0, e0, v1, e1, v2, e2, v3, e3,
|
|
|
|
|
u, v, du, dv);
|
|
|
|
|
v0 = v1;
|
|
|
|
|
v3 = v2;
|
|
|
|
|
e3 = e1;
|
|
|
|
|
}
|
|
|
|
|
/* Create loops for polygons along V axis. */
|
|
|
|
|
const bool flip_prev = (prev_coarse_edge->v2 == coarse_loop->v);
|
|
|
|
|
v0 = corner_vertex_index;
|
|
|
|
|
if (prev_coarse_loop->v == prev_coarse_edge->v1) {
|
|
|
|
|
v3 = ctx->vertices_edge_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
|
|
|
|
|
num_subdiv_vertices_per_coarse_edge - 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v3 = ctx->vertices_edge_offset +
|
|
|
|
|
prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
|
|
|
|
|
}
|
|
|
|
|
e3 = start_edge_index +
|
|
|
|
|
coarse_poly->totloop *
|
|
|
|
|
(num_inner_edges_per_ptex_face +
|
|
|
|
|
ptex_face_inner_resolution + 1) +
|
|
|
|
|
corner * (2 * ptex_face_inner_resolution + 1) +
|
|
|
|
|
ptex_face_inner_resolution + 1;
|
|
|
|
|
for (int i = 0;
|
|
|
|
|
i <= ptex_face_inner_resolution - 1;
|
|
|
|
|
i++, subdiv_loop += 4)
|
|
|
|
|
{
|
|
|
|
|
int v1;
|
|
|
|
|
int e0, e1;
|
|
|
|
|
if (i == ptex_face_inner_resolution - 1) {
|
|
|
|
|
v1 = start_vertex_index +
|
|
|
|
|
prev_corner * num_inner_vertices_per_ptex +
|
|
|
|
|
ptex_face_inner_resolution;
|
|
|
|
|
e1 = start_edge_index +
|
|
|
|
|
coarse_poly->totloop *
|
|
|
|
|
(num_inner_edges_per_ptex_face +
|
|
|
|
|
ptex_face_inner_resolution + 1) +
|
|
|
|
|
prev_corner * (2 * ptex_face_inner_resolution + 1) +
|
|
|
|
|
ptex_face_inner_resolution;
|
|
|
|
|
e0 = start_edge_index +
|
|
|
|
|
coarse_poly->totloop * num_inner_edges_per_ptex_face +
|
|
|
|
|
prev_corner * ptex_face_inner_resolution;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v1 = v0 + ptex_face_inner_resolution + 1;
|
|
|
|
|
e0 = corner_edge_index + ptex_face_inner_resolution +
|
|
|
|
|
i * (2 * ptex_face_inner_resolution + 1);
|
|
|
|
|
e1 = e3 + 1;
|
|
|
|
|
}
|
|
|
|
|
int v2 = flip_prev ? v3 - 1 : v3 + 1;
|
|
|
|
|
int e2;
|
|
|
|
|
if (flip_prev) {
|
|
|
|
|
e2 = ctx->edge_boundary_offset +
|
|
|
|
|
prev_coarse_loop->e *
|
|
|
|
|
num_subdiv_edges_per_coarse_edge +
|
|
|
|
|
num_subdiv_edges_per_coarse_edge - 2 - i;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
e2 = ctx->edge_boundary_offset +
|
|
|
|
|
prev_coarse_loop->e *
|
|
|
|
|
num_subdiv_edges_per_coarse_edge + 1 + i;
|
|
|
|
|
}
|
|
|
|
|
const float u = 0.0f;
|
|
|
|
|
const float v = du * (i + 1);
|
|
|
|
|
subdiv_create_loops_of_poly(
|
|
|
|
|
ctx, &loop_interpolation, subdiv_loop,
|
|
|
|
|
ptex_face_index + corner, 1,
|
|
|
|
|
v0, e0, v1, e1, v2, e2, v3, e3,
|
|
|
|
|
u, v, du, dv);
|
|
|
|
|
v0 = v1;
|
|
|
|
|
v3 = v2;
|
|
|
|
|
e3 = e1;
|
|
|
|
|
}
|
|
|
|
|
prev_coarse_loop = coarse_loop;
|
|
|
|
|
}
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
loop_interpolation_end(&loop_interpolation);
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-25 16:51:48 +02:00
|
|
|
static void subdiv_create_loops(SubdivMeshContext *ctx, int poly_index)
|
|
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
if (coarse_poly->totloop == 4) {
|
|
|
|
|
subdiv_create_loops_regular(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_create_loops_special(ctx, coarse_poly);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Polygons subdivision process.
|
|
|
|
|
*/
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
static void subdiv_copy_poly_data(const SubdivMeshContext *ctx,
|
|
|
|
|
MPoly *subdiv_poly,
|
|
|
|
|
const MPoly *coarse_poly)
|
|
|
|
|
{
|
|
|
|
|
const int coarse_poly_index = coarse_poly - ctx->coarse_mesh->mpoly;
|
|
|
|
|
const int subdiv_poly_index = subdiv_poly - ctx->subdiv_mesh->mpoly;
|
|
|
|
|
CustomData_copy_data(&ctx->coarse_mesh->pdata,
|
|
|
|
|
&ctx->subdiv_mesh->pdata,
|
|
|
|
|
coarse_poly_index,
|
|
|
|
|
subdiv_poly_index,
|
|
|
|
|
1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_polys(SubdivMeshContext *ctx, int poly_index)
|
|
|
|
|
{
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
2018-07-31 20:11:55 +10:00
|
|
|
const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Base/coarse mesh information. */
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
2018-07-23 18:40:04 +02:00
|
|
|
const MPoly *coarse_mpoly = coarse_mesh->mpoly;
|
|
|
|
|
const MPoly *coarse_poly = &coarse_mpoly[poly_index];
|
|
|
|
|
const int num_ptex_faces_per_poly =
|
|
|
|
|
num_ptex_faces_per_poly_get(coarse_poly);
|
|
|
|
|
const int ptex_resolution =
|
|
|
|
|
ptex_face_resolution_get(coarse_poly, resolution);
|
|
|
|
|
const int num_polys_per_ptex = num_polys_per_ptex_get(ptex_resolution);
|
|
|
|
|
const int num_loops_per_ptex = 4 * num_polys_per_ptex;
|
|
|
|
|
const int start_loop_index = 4 * start_poly_index;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Hi-poly subdivided mesh. */
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MPoly *subdiv_mpoly = subdiv_mesh->mpoly;
|
|
|
|
|
MPoly *subdiv_mp = &subdiv_mpoly[start_poly_index];
|
|
|
|
|
for (int ptex_of_poly_index = 0;
|
2018-07-23 18:40:04 +02:00
|
|
|
ptex_of_poly_index < num_ptex_faces_per_poly;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
ptex_of_poly_index++)
|
|
|
|
|
{
|
|
|
|
|
for (int subdiv_poly_index = 0;
|
|
|
|
|
subdiv_poly_index < num_polys_per_ptex;
|
|
|
|
|
subdiv_poly_index++, subdiv_mp++)
|
|
|
|
|
{
|
|
|
|
|
subdiv_copy_poly_data(ctx, subdiv_mp, coarse_poly);
|
|
|
|
|
subdiv_mp->loopstart = start_loop_index +
|
|
|
|
|
(ptex_of_poly_index * num_loops_per_ptex) +
|
|
|
|
|
(subdiv_poly_index * 4);
|
|
|
|
|
subdiv_mp->totloop = 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-31 15:09:29 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Loose elements subdivision process.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_loose_vertices_task(
|
|
|
|
|
void *__restrict userdata,
|
|
|
|
|
const int vertex_index,
|
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
|
|
|
|
{
|
|
|
|
|
SubdivMeshContext *ctx = userdata;
|
|
|
|
|
if (BLI_BITMAP_TEST_BOOL(ctx->coarse_vertices_used_map, vertex_index)) {
|
|
|
|
|
/* Vertex is not loose, was handled when handling polygons. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MVert *coarse_mvert = coarse_mesh->mvert;
|
|
|
|
|
const MVert *coarse_vertex = &coarse_mvert[vertex_index];
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
MVert *subdiv_vertex = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_corner_offset + vertex_index];
|
|
|
|
|
subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get neighbor edges of the given one.
|
|
|
|
|
* - neighbors[0] is an edge adjacent to edge->v1.
|
|
|
|
|
* - neighbors[1] is an edge adjacent to edge->v1.
|
|
|
|
|
*/
|
|
|
|
|
static void find_edge_neighbors(const SubdivMeshContext *ctx,
|
|
|
|
|
const MEdge *edge,
|
|
|
|
|
const MEdge *neighbors[2])
|
|
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_medge = coarse_mesh->medge;
|
|
|
|
|
neighbors[0] = NULL;
|
|
|
|
|
neighbors[1] = NULL;
|
|
|
|
|
for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
|
|
|
|
|
if (BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, edge_index)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const MEdge *current_edge = &coarse_medge[edge_index];
|
|
|
|
|
if (current_edge == edge) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (ELEM(edge->v1, current_edge->v1, current_edge->v2)) {
|
|
|
|
|
neighbors[0] = current_edge;
|
|
|
|
|
}
|
|
|
|
|
if (ELEM(edge->v2, current_edge->v1, current_edge->v2)) {
|
|
|
|
|
neighbors[1] = current_edge;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void points_for_loose_edges_interpolation_get(
|
|
|
|
|
SubdivMeshContext *ctx,
|
|
|
|
|
const MEdge *coarse_edge,
|
|
|
|
|
const MEdge *neighbors[2],
|
2018-08-08 10:59:50 +10:00
|
|
|
float points_r[4][3])
|
2018-07-31 15:09:29 +02:00
|
|
|
{
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MVert *coarse_mvert = coarse_mesh->mvert;
|
|
|
|
|
/* Middle points corresponds to the edge. */
|
|
|
|
|
copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co);
|
|
|
|
|
copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co);
|
|
|
|
|
/* Start point, duplicate from edge start if no neighbor. */
|
|
|
|
|
if (neighbors[0] != NULL) {
|
|
|
|
|
if (neighbors[0]->v1 == coarse_edge->v1) {
|
|
|
|
|
copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v1].co);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sub_v3_v3v3(points_r[0], points_r[1], points_r[2]);
|
|
|
|
|
add_v3_v3(points_r[0], points_r[1]);
|
|
|
|
|
}
|
|
|
|
|
/* End point, duplicate from edge end if no neighbor. */
|
|
|
|
|
if (neighbors[1] != NULL) {
|
|
|
|
|
if (neighbors[1]->v1 == coarse_edge->v2) {
|
|
|
|
|
copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v2].co);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v1].co);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sub_v3_v3v3(points_r[3], points_r[2], points_r[1]);
|
|
|
|
|
add_v3_v3(points_r[3], points_r[2]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_vertices_of_loose_edges_task(
|
|
|
|
|
void *__restrict userdata,
|
|
|
|
|
const int edge_index,
|
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
|
|
|
|
{
|
|
|
|
|
SubdivMeshContext *ctx = userdata;
|
|
|
|
|
if (BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, edge_index)) {
|
|
|
|
|
/* Vertex is not loose, was handled when handling polygons. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const int resolution = ctx->settings->resolution;
|
|
|
|
|
const int resolution_1 = resolution - 1;
|
|
|
|
|
const float inv_resolution_1 = 1.0f / (float)resolution_1;
|
|
|
|
|
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
|
|
|
|
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
|
|
|
|
const MEdge *coarse_edge = &coarse_mesh->medge[edge_index];
|
|
|
|
|
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
|
|
|
|
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
|
|
|
|
/* Find neighbors of the current loose edge. */
|
|
|
|
|
const MEdge *neighbors[2];
|
|
|
|
|
find_edge_neighbors(ctx, coarse_edge, neighbors);
|
|
|
|
|
/* Get points for b-spline interpolation. */
|
|
|
|
|
float points[4][3];
|
|
|
|
|
points_for_loose_edges_interpolation_get(
|
|
|
|
|
ctx, coarse_edge, neighbors, points);
|
|
|
|
|
/* Subdivion verticies which corresponds to edge's v1 and v2. */
|
|
|
|
|
MVert *subdiv_v1 = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_corner_offset + coarse_edge->v1];
|
|
|
|
|
MVert *subdiv_v2 = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_corner_offset + coarse_edge->v2];
|
|
|
|
|
/* First subdivided inner vertex of the edge. */
|
|
|
|
|
MVert *subdiv_start_vertex = &subdiv_mvert[
|
|
|
|
|
ctx->vertices_edge_offset +
|
|
|
|
|
edge_index * num_subdiv_vertices_per_coarse_edge];
|
|
|
|
|
/* Perform interpolation. */
|
|
|
|
|
for (int i = 0; i < resolution; i++) {
|
|
|
|
|
const float u = i * inv_resolution_1;
|
|
|
|
|
float weights[4];
|
|
|
|
|
key_curve_position_weights(u, weights, KEY_BSPLINE);
|
|
|
|
|
|
|
|
|
|
MVert *subdiv_vertex;
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
subdiv_vertex = subdiv_v1;
|
|
|
|
|
}
|
|
|
|
|
else if (i == resolution - 1) {
|
|
|
|
|
subdiv_vertex = subdiv_v2;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
subdiv_vertex = &subdiv_start_vertex[i - 1];
|
|
|
|
|
}
|
|
|
|
|
interp_v3_v3v3v3v3(subdiv_vertex->co,
|
|
|
|
|
points[0],
|
|
|
|
|
points[1],
|
|
|
|
|
points[2],
|
|
|
|
|
points[3],
|
|
|
|
|
weights);
|
|
|
|
|
/* Reset flags and such. */
|
|
|
|
|
subdiv_vertex->flag = 0;
|
|
|
|
|
subdiv_vertex->bweight = 0.0f;
|
|
|
|
|
/* Reset normal. */
|
|
|
|
|
subdiv_vertex->no[0] = 0.0f;
|
|
|
|
|
subdiv_vertex->no[1] = 0.0f;
|
|
|
|
|
subdiv_vertex->no[2] = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:40:04 +02:00
|
|
|
/* =============================================================================
|
|
|
|
|
* Subdivision process entry points.
|
|
|
|
|
*/
|
|
|
|
|
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
static void subdiv_eval_task(
|
|
|
|
|
void *__restrict userdata,
|
|
|
|
|
const int poly_index,
|
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
|
|
|
|
{
|
2018-07-25 16:51:48 +02:00
|
|
|
SubdivMeshContext *ctx = userdata;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Evaluate hi-poly vertex coordinates and normals. */
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_evaluate_vertices(ctx, poly_index);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Create mesh geometry for the given base poly index. */
|
2018-07-25 16:51:48 +02:00
|
|
|
subdiv_create_edges(ctx, poly_index);
|
|
|
|
|
subdiv_create_loops(ctx, poly_index);
|
|
|
|
|
subdiv_create_polys(ctx, poly_index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void subdiv_create_boundary_edges_task(
|
|
|
|
|
void *__restrict userdata,
|
|
|
|
|
const int edge_index,
|
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
|
|
|
|
{
|
|
|
|
|
SubdivMeshContext *ctx = userdata;
|
|
|
|
|
subdiv_create_boundary_edges(ctx, edge_index);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mesh *BKE_subdiv_to_mesh(
|
|
|
|
|
Subdiv *subdiv,
|
|
|
|
|
const SubdivToMeshSettings *settings,
|
|
|
|
|
const Mesh *coarse_mesh)
|
|
|
|
|
{
|
2018-07-19 16:27:18 +02:00
|
|
|
BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Make sure evaluator is up to date with possible new topology, and that
|
|
|
|
|
* is is refined for the new positions of coarse vertices.
|
|
|
|
|
*/
|
2018-08-13 12:21:29 +02:00
|
|
|
if (!BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh)) {
|
|
|
|
|
/* This could happen in two situations:
|
|
|
|
|
* - OpenSubdiv is disabled.
|
|
|
|
|
* - Something totally bad happened, and OpenSubdiv rejected our
|
|
|
|
|
* topology.
|
|
|
|
|
* In either way, we can't safely continue.
|
|
|
|
|
*/
|
|
|
|
|
if (coarse_mesh->totpoly) {
|
|
|
|
|
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-23 18:40:04 +02:00
|
|
|
SubdivMeshContext ctx = {0};
|
|
|
|
|
ctx.coarse_mesh = coarse_mesh;
|
|
|
|
|
ctx.subdiv = subdiv;
|
|
|
|
|
ctx.settings = settings;
|
|
|
|
|
subdiv_mesh_ctx_init(&ctx);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
Mesh *result = BKE_mesh_new_nomain_from_template(
|
|
|
|
|
coarse_mesh,
|
2018-07-23 18:40:04 +02:00
|
|
|
ctx.num_subdiv_vertices,
|
|
|
|
|
ctx.num_subdiv_edges,
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
0,
|
2018-07-23 18:40:04 +02:00
|
|
|
ctx.num_subdiv_loops,
|
|
|
|
|
ctx.num_subdiv_polygons);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
ctx.subdiv_mesh = result;
|
2018-07-23 18:40:04 +02:00
|
|
|
subdiv_mesh_ctx_init_result(&ctx);
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
/* Multi-threaded evaluation. */
|
2018-07-25 16:51:48 +02:00
|
|
|
BKE_subdiv_stats_begin(&subdiv->stats,
|
|
|
|
|
SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
|
2018-08-14 17:05:54 +02:00
|
|
|
/* Single threaded passes to average displacement on the corner vertices
|
|
|
|
|
* and boundary edges.
|
|
|
|
|
*/
|
|
|
|
|
subdiv_displace_corner_vertices(&ctx);
|
|
|
|
|
subdiv_displace_edge_vertices(&ctx);
|
|
|
|
|
ParallelRangeSettings parallel_range_settings;
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
BLI_parallel_range_settings_defaults(¶llel_range_settings);
|
|
|
|
|
BLI_task_parallel_range(0, coarse_mesh->totpoly,
|
|
|
|
|
&ctx,
|
|
|
|
|
subdiv_eval_task,
|
|
|
|
|
¶llel_range_settings);
|
2018-07-31 15:09:29 +02:00
|
|
|
BLI_task_parallel_range(0, coarse_mesh->totvert,
|
|
|
|
|
&ctx,
|
|
|
|
|
subdiv_create_loose_vertices_task,
|
|
|
|
|
¶llel_range_settings);
|
|
|
|
|
BLI_task_parallel_range(0, coarse_mesh->totedge,
|
|
|
|
|
&ctx,
|
|
|
|
|
subdiv_create_vertices_of_loose_edges_task,
|
|
|
|
|
¶llel_range_settings);
|
2018-07-25 16:51:48 +02:00
|
|
|
BLI_task_parallel_range(0, coarse_mesh->totedge,
|
|
|
|
|
&ctx,
|
|
|
|
|
subdiv_create_boundary_edges_task,
|
|
|
|
|
¶llel_range_settings);
|
2018-07-23 18:40:04 +02:00
|
|
|
subdiv_mesh_ctx_free(&ctx);
|
2018-07-25 16:51:48 +02:00
|
|
|
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
|
2018-07-23 18:40:04 +02:00
|
|
|
// BKE_mesh_validate(result, true, true);
|
2018-07-19 16:27:18 +02:00
|
|
|
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
|
2018-08-14 17:05:54 +02:00
|
|
|
if (subdiv->displacement_evaluator != NULL) {
|
|
|
|
|
result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
|
|
|
|
|
}
|
Subsurf: Begin new subdivision surface module
The idea is to use this as a replacement of old CCG, now it is
based on OpenSubdiv. The goal is to reduce any possible overhead
which was happening with OpenSubdiv used by CCG.
Currently implemented/supported:
- Creation from mesh, including topology on OpenSubdiv side,
its refinement.
- Evaluation of limit point, first order derivatives, normal,
and face-varying data for individual coarse position.
- Evaluation of whole patches.
Currently not optimized, uses evaluation of individual coarse
positions.
- Creation of Mesh from subdiv, with all geometry being real:
all mvert, medge, mloop, and mpoly.
This includes custom data interpolation, but all faces currently
are getting separated (they are converted to ptex patches, which
we need to weld back together).
Still need to support lighter weights grids and such, but this
is already a required part to have subsurf working in the middle
of modifier stack.
Annoying part is ifdef all over the place, to keep it compilable
when OpenSubdiv is disabled. More cleaner approach would be to
have stub API for OpenSubdiv, so everything gets ifdef-ed in a
much fewer places.
2018-07-17 18:07:26 +02:00
|
|
|
return result;
|
|
|
|
|
}
|