Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c')
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c244
1 files changed, 206 insertions, 38 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
index c4317f4d740..f1f82f458aa 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
@@ -62,6 +62,16 @@ typedef struct ConvDMStorage {
*vert_poly_mem,
*edge_poly_mem;
#endif
+
+ MVert *mvert;
+ MEdge *medge;
+ MLoop *mloop;
+ MPoly *mpoly;
+
+ MeshIslandStore island_store;
+ int num_uvs;
+ float *uvs;
+ int *face_uvs;
} ConvDMStorage;
static OpenSubdiv_SchemeType conv_dm_get_type(
@@ -74,6 +84,13 @@ static OpenSubdiv_SchemeType conv_dm_get_type(
return OSD_SCHEME_CATMARK;
}
+static bool conv_dm_get_subdiv_uvs(
+ const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ return (storage->ss->osd_subdiv_uvs);
+}
+
static int conv_dm_get_num_faces(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *storage = converter->user_data;
@@ -99,9 +116,7 @@ static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter,
int face)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MPoly *mp = dm->getPolyArray(dm);
- const MPoly *mpoly = &mp[face];
+ const MPoly *mpoly = &storage->mpoly[face];
return mpoly->totloop;
}
@@ -110,13 +125,10 @@ static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter,
int *face_verts)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
- const MPoly *mpoly = &mp[face];
+ const MPoly *mpoly = &storage->mpoly[face];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- face_verts[loop] = ml[mpoly->loopstart + loop].v;
+ face_verts[loop] = storage->mloop[mpoly->loopstart + loop].v;
}
}
@@ -125,13 +137,10 @@ static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter,
int *face_edges)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
- const MPoly *mpoly = &mp[face];
+ const MPoly *mpoly = &storage->mpoly[face];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- face_edges[loop] = ml[mpoly->loopstart + loop].e;
+ face_edges[loop] = storage->mloop[mpoly->loopstart + loop].e;
}
}
@@ -140,9 +149,7 @@ static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter,
int *edge_verts)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MEdge *me = dm->getEdgeArray(dm);
- const MEdge *medge = &me[edge];
+ const MEdge *medge = &storage->medge[edge];
edge_verts[0] = medge->v1;
edge_verts[1] = medge->v2;
}
@@ -153,14 +160,12 @@ static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->e == edge) {
++num;
break;
@@ -180,14 +185,12 @@ static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->e == edge) {
edge_faces[num++] = poly;
break;
@@ -205,9 +208,8 @@ static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
int edge)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
CCGSubSurf *ss = storage->ss;
- const MEdge *medge = dm->getEdgeArray(dm);
+ const MEdge *medge = storage->medge;
return (float)medge[edge].crease / 255.0f * ss->subdivLevels;
}
@@ -217,10 +219,9 @@ static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MEdge *me = dm->getEdgeArray(dm);
int num = 0, edge;
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
- const MEdge *medge = &me[edge];
+ const MEdge *medge = &user_data->medge[edge];
if (medge->v1 == vert || medge->v2 == vert) {
++num;
}
@@ -238,10 +239,9 @@ static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MEdge *me = dm->getEdgeArray(dm);
int num = 0, edge;
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
- const MEdge *medge = &me[edge];
+ const MEdge *medge = &user_data->medge[edge];
if (medge->v1 == vert || medge->v2 == vert) {
vert_edges[num++] = edge;
}
@@ -259,14 +259,12 @@ static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->v == vert) {
++num;
break;
@@ -286,14 +284,12 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &storage->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->v == vert) {
vert_faces[num++] = poly;
break;
@@ -307,9 +303,114 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
#endif
}
+static int conv_dm_get_num_uv_layers(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ int num_uv_layers = CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
+ return num_uv_layers;
+}
+
+static void conv_dm_precalc_uv_layer(const OpenSubdiv_Converter *converter,
+ int layer)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+
+ const MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer);
+ const int num_loops = dm->getNumLoops(dm);
+
+ /* Initialize memory required for the operations. */
+ if (storage->uvs == NULL) {
+ storage->uvs = MEM_mallocN(sizeof(float) * 2 * num_loops, "osd uvs");
+ }
+ if (storage->face_uvs == NULL) {
+ storage->face_uvs = MEM_mallocN(sizeof(int) * num_loops, "osd face uvs");
+ }
+
+ /* Calculate islands connectivity of the UVs. */
+ BKE_mesh_calc_islands_loop_poly_uvmap(
+ storage->mvert, dm->getNumVerts(dm),
+ storage->medge, dm->getNumEdges(dm),
+ storage->mpoly, dm->getNumPolys(dm),
+ storage->mloop, dm->getNumLoops(dm),
+ mloopuv,
+ &storage->island_store);
+
+ /* Here we "weld" duplicated vertices from island to the same UV value.
+ * The idea here is that we need to pass individual islands to OpenSubdiv.
+ */
+ storage->num_uvs = 0;
+ for (int island = 0; island < storage->island_store.islands_num; ++island) {
+ MeshElemMap *island_poly_map = storage->island_store.islands[island];
+ for (int poly = 0; poly < island_poly_map->count; ++poly) {
+ int poly_index = island_poly_map->indices[poly];
+ /* Within the same UV island we should share UV points across
+ * loops. Otherwise each poly will be subdivided individually
+ * which we don't really want.
+ */
+ const MPoly *mpoly = &storage->mpoly[poly_index];
+ for (int loop = 0; loop < mpoly->totloop; ++loop) {
+ const MLoopUV *luv = &mloopuv[mpoly->loopstart + loop];
+ bool found = false;
+ /* TODO(sergey): Quite bad loop, which gives us O(N^2)
+ * complexity here. But how can we do it smarter, hopefully
+ * without requiring lots of additional memory.
+ */
+ for (int i = 0; i < storage->num_uvs; ++i) {
+ if (equals_v2v2(luv->uv, &storage->uvs[2 * i])) {
+ storage->face_uvs[mpoly->loopstart + loop] = i;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ copy_v2_v2(&storage->uvs[2 * storage->num_uvs], luv->uv);
+ storage->face_uvs[mpoly->loopstart + loop] = storage->num_uvs;
+ ++storage->num_uvs;
+ }
+ }
+ }
+ }
+}
+
+static void conv_dm_finish_uv_layer(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ BKE_mesh_loop_islands_free(&storage->island_store);
+}
+
+static int conv_dm_get_num_uvs(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ return storage->num_uvs;
+}
+
+static void conv_dm_get_uvs(const OpenSubdiv_Converter *converter, float *uvs)
+{
+ ConvDMStorage *storage = converter->user_data;
+ memcpy(uvs, storage->uvs, sizeof(float) * 2 * storage->num_uvs);
+}
+
+static int conv_dm_get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
+ int face,
+ int corner)
+{
+ ConvDMStorage *storage = converter->user_data;
+ const MPoly *mpoly = &storage->mpoly[face];
+ return storage->face_uvs[mpoly->loopstart + corner];
+}
+
static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *user_data = converter->user_data;
+ if (user_data->uvs != NULL) {
+ MEM_freeN(user_data->uvs);
+ }
+ if (user_data->face_uvs != NULL) {
+ MEM_freeN(user_data->face_uvs);
+ }
+
#ifdef USE_MESH_ELEMENT_MAPPING
MEM_freeN(user_data->vert_edge_map);
MEM_freeN(user_data->vert_edge_mem);
@@ -330,6 +431,8 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
converter->get_type = conv_dm_get_type;
+ converter->get_subdiv_uvs = conv_dm_get_subdiv_uvs;
+
converter->get_num_faces = conv_dm_get_num_faces;
converter->get_num_edges = conv_dm_get_num_edges;
converter->get_num_verts = conv_dm_get_num_verts;
@@ -348,9 +451,27 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
converter->get_vert_faces = conv_dm_get_vert_faces;
+ converter->get_num_uv_layers = conv_dm_get_num_uv_layers;
+ converter->precalc_uv_layer = conv_dm_precalc_uv_layer;
+ converter->finish_uv_layer = conv_dm_finish_uv_layer;
+ converter->get_num_uvs = conv_dm_get_num_uvs;
+ converter->get_uvs = conv_dm_get_uvs;
+ converter->get_face_corner_uv_index = conv_dm_get_face_corner_uv_index;
+
user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
user_data->ss = ss;
user_data->dm = dm;
+
+ user_data->mvert = dm->getVertArray(dm);
+ user_data->medge = dm->getEdgeArray(dm);
+ user_data->mloop = dm->getLoopArray(dm);
+ user_data->mpoly = dm->getPolyArray(dm);
+
+ memset(&user_data->island_store, 0, sizeof(user_data->island_store));
+
+ user_data->uvs = NULL;
+ user_data->face_uvs = NULL;
+
converter->free_user_data = conv_dm_free_user_data;
converter->user_data = user_data;
@@ -405,6 +526,13 @@ static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type(
}
}
+static bool conv_ccg_get_subdiv_uvs(
+ const OpenSubdiv_Converter *converter)
+{
+ CCGSubSurf *ss = converter->user_data;
+ return (ss->osd_subdiv_uvs);
+}
+
static int conv_ccg_get_num_faces(const OpenSubdiv_Converter *converter)
{
CCGSubSurf *ss = converter->user_data;
@@ -548,11 +676,44 @@ static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter,
}
}
+static int conv_ccg_get_num_uv_layers(const OpenSubdiv_Converter *UNUSED(converter))
+{
+ return 0;
+}
+
+static void conv_ccg_precalc_uv_layer(const OpenSubdiv_Converter * UNUSED(converter),
+ int UNUSED(layer))
+{
+}
+
+static void conv_ccg_finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
+{
+}
+
+static int conv_ccg_get_num_uvs(const OpenSubdiv_Converter *UNUSED(converter))
+{
+ return 0;
+}
+
+static void conv_ccg_get_uvs(const OpenSubdiv_Converter * UNUSED(converter),
+ float *UNUSED(uvs))
+{
+}
+
+static int conv_ccg_get_face_corner_uv_index(const OpenSubdiv_Converter *UNUSED(converter),
+ int UNUSED(face),
+ int UNUSED(corner_))
+{
+ return 0;
+}
+
void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
OpenSubdiv_Converter *converter)
{
converter->get_type = conv_ccg_get_bilinear_type;
+ converter->get_subdiv_uvs = conv_ccg_get_subdiv_uvs;
+
converter->get_num_faces = conv_ccg_get_num_faces;
converter->get_num_edges = conv_ccg_get_num_edges;
converter->get_num_verts = conv_ccg_get_num_verts;
@@ -571,6 +732,13 @@ void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
converter->get_vert_faces = conv_ccg_get_vert_faces;
+ converter->get_num_uv_layers = conv_ccg_get_num_uv_layers;
+ converter->precalc_uv_layer = conv_ccg_precalc_uv_layer;
+ converter->finish_uv_layer = conv_ccg_finish_uv_layer;
+ converter->get_num_uvs = conv_ccg_get_num_uvs;
+ converter->get_uvs = conv_ccg_get_uvs;
+ converter->get_face_corner_uv_index = conv_ccg_get_face_corner_uv_index;
+
converter->free_user_data = NULL;
converter->user_data = ss;
}