diff options
Diffstat (limited to 'source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c')
-rw-r--r-- | source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c | 244 |
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; } |