Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/subsurf_ccg.cc
| Show All 39 Lines | |||||
| #include "BKE_object.h" | #include "BKE_object.h" | ||||
| #include "BKE_paint.h" | #include "BKE_paint.h" | ||||
| #include "BKE_pbvh.h" | #include "BKE_pbvh.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "BKE_subsurf.h" | #include "BKE_subsurf.h" | ||||
| #include "CCGSubSurf.h" | #include "CCGSubSurf.h" | ||||
| /* assumes MLoop's are laid out 4 for each poly, in order */ | /* assumes corners are laid out 4 for each poly, in order */ | ||||
| #define USE_LOOP_LAYOUT_FAST | #define USE_LOOP_LAYOUT_FAST | ||||
| static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, | static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, | ||||
| int drawInteriorEdges, | int drawInteriorEdges, | ||||
| int useSubsurfUv, | int useSubsurfUv, | ||||
| DerivedMesh *dm); | DerivedMesh *dm); | ||||
| /// | /// | ||||
| ▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | |||||
| return faceBase + 1 + (gridSize - 2) * S + (x - 1); | return faceBase + 1 + (gridSize - 2) * S + (x - 1); | ||||
| } | } | ||||
| return faceBase + 1 + (gridSize - 2) * numVerts + S * (gridSize - 2) * (gridSize - 2) + | return faceBase + 1 + (gridSize - 2) * numVerts + S * (gridSize - 2) * (gridSize - 2) + | ||||
| (y - 1) * (gridSize - 2) + (x - 1); | (y - 1) * (gridSize - 2) + (x - 1); | ||||
| } | } | ||||
| static void get_face_uv_map_vert( | static void get_face_uv_map_vert( | ||||
| UvVertMap *vmap, MPoly *mpoly, MLoop *ml, int fi, CCGVertHDL *fverts) | UvVertMap *vmap, MPoly *mpoly, int *poly_verts, int fi, CCGVertHDL *fverts) | ||||
| { | { | ||||
| UvMapVert *v, *nv; | UvMapVert *v, *nv; | ||||
| int j, nverts = mpoly[fi].totloop; | int j, nverts = mpoly[fi].totloop; | ||||
| for (j = 0; j < nverts; j++) { | for (j = 0; j < nverts; j++) { | ||||
| for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, ml[j].v); v; v = v->next) { | for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, poly_verts[j]); v; v = v->next) { | ||||
| if (v->separate) { | if (v->separate) { | ||||
| nv = v; | nv = v; | ||||
| } | } | ||||
| if (v->poly_index == fi) { | if (v->poly_index == fi) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| fverts[j] = POINTER_FROM_UINT(mpoly[nv->poly_index].loopstart + nv->loop_of_poly_index); | fverts[j] = POINTER_FROM_UINT(mpoly[nv->poly_index].loopstart + nv->loop_of_poly_index); | ||||
| } | } | ||||
| } | } | ||||
| static int ss_sync_from_uv(CCGSubSurf *ss, | static int ss_sync_from_uv(CCGSubSurf *ss, | ||||
| CCGSubSurf *origss, | CCGSubSurf *origss, | ||||
| DerivedMesh *dm, | DerivedMesh *dm, | ||||
| const float (*mloopuv)[2]) | const float (*mloopuv)[2]) | ||||
| { | { | ||||
| MPoly *mpoly = dm->getPolyArray(dm); | MPoly *mpoly = dm->getPolyArray(dm); | ||||
| MLoop *mloop = dm->getLoopArray(dm); | int *corner_verts = dm->getCornerVertArray(dm); | ||||
| int totvert = dm->getNumVerts(dm); | int totvert = dm->getNumVerts(dm); | ||||
| int totface = dm->getNumPolys(dm); | int totface = dm->getNumPolys(dm); | ||||
| int i, seam; | int i, seam; | ||||
| UvMapVert *v; | UvMapVert *v; | ||||
| UvVertMap *vmap; | UvVertMap *vmap; | ||||
| blender::Vector<CCGVertHDL, 16> fverts; | blender::Vector<CCGVertHDL, 16> fverts; | ||||
| float limit[2]; | float limit[2]; | ||||
| EdgeSet *eset; | EdgeSet *eset; | ||||
| float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ | float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ | ||||
| limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; | limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; | ||||
| /* previous behavior here is without accounting for winding, however this causes stretching in | /* previous behavior here is without accounting for winding, however this causes stretching in | ||||
| * UV map in really simple cases with mirror + subsurf, see second part of T44530. | * UV map in really simple cases with mirror + subsurf, see second part of T44530. | ||||
| * Also, initially intention is to treat merged vertices from mirror modifier as seams. | * Also, initially intention is to treat merged vertices from mirror modifier as seams. | ||||
| * This fixes a very old regression (2.49 was correct here) */ | * This fixes a very old regression (2.49 was correct here) */ | ||||
| vmap = BKE_mesh_uv_vert_map_create( | vmap = BKE_mesh_uv_vert_map_create( | ||||
| mpoly, nullptr, nullptr, mloop, mloopuv, totface, totvert, limit, false, true); | mpoly, nullptr, nullptr, corner_verts, mloopuv, totface, totvert, limit, false, true); | ||||
| if (!vmap) { | if (!vmap) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| ccgSubSurf_initFullSync(ss); | ccgSubSurf_initFullSync(ss); | ||||
| /* create vertices */ | /* create vertices */ | ||||
| for (i = 0; i < totvert; i++) { | for (i = 0; i < totvert; i++) { | ||||
| Show All 26 Lines | |||||
| eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface)); | eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface)); | ||||
| for (i = 0; i < totface; i++) { | for (i = 0; i < totface; i++) { | ||||
| MPoly *mp = &mpoly[i]; | MPoly *mp = &mpoly[i]; | ||||
| int nverts = mp->totloop; | int nverts = mp->totloop; | ||||
| int j, j_next; | int j, j_next; | ||||
| CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i)); | CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i)); | ||||
| /* uint *fv = &mp->v1; */ | /* uint *fv = &mp->v1; */ | ||||
| MLoop *ml = mloop + mp->loopstart; | |||||
| fverts.reinitialize(nverts); | fverts.reinitialize(nverts); | ||||
| get_face_uv_map_vert(vmap, mpoly, ml, i, fverts.data()); | get_face_uv_map_vert(vmap, mpoly, &corner_verts[mp->loopstart], i, fverts.data()); | ||||
| for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) { | for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) { | ||||
| uint v0 = POINTER_AS_UINT(fverts[j_next]); | uint v0 = POINTER_AS_UINT(fverts[j_next]); | ||||
| uint v1 = POINTER_AS_UINT(fverts[j]); | uint v1 = POINTER_AS_UINT(fverts[j]); | ||||
| if (BLI_edgeset_add(eset, v0, v1)) { | if (BLI_edgeset_add(eset, v0, v1)) { | ||||
| CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next); | CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next); | ||||
| CCGEdgeHDL ehdl = POINTER_FROM_INT(mp->loopstart + j_next); | CCGEdgeHDL ehdl = POINTER_FROM_INT(mp->loopstart + j_next); | ||||
| float crease = ccgSubSurf_getEdgeCrease(orige); | float crease = ccgSubSurf_getEdgeCrease(orige); | ||||
| ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e); | ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_edgeset_free(eset); | BLI_edgeset_free(eset); | ||||
| /* create faces */ | /* create faces */ | ||||
| for (i = 0; i < totface; i++) { | for (i = 0; i < totface; i++) { | ||||
| MPoly *mp = &mpoly[i]; | MPoly *mp = &mpoly[i]; | ||||
| MLoop *ml = &mloop[mp->loopstart]; | |||||
| int nverts = mp->totloop; | int nverts = mp->totloop; | ||||
| CCGFace *f; | CCGFace *f; | ||||
| fverts.reinitialize(nverts); | fverts.reinitialize(nverts); | ||||
| get_face_uv_map_vert(vmap, mpoly, ml, i, fverts.data()); | get_face_uv_map_vert(vmap, mpoly, &corner_verts[mp->loopstart], i, fverts.data()); | ||||
| ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts.data(), &f); | ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts.data(), &f); | ||||
| } | } | ||||
| BKE_mesh_uv_vert_map_free(vmap); | BKE_mesh_uv_vert_map_free(vmap); | ||||
| ccgSubSurf_processSync(ss); | ccgSubSurf_processSync(ss); | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | |||||
| float (*vertexCos)[3], | float (*vertexCos)[3], | ||||
| int useFlatSubdiv) | int useFlatSubdiv) | ||||
| { | { | ||||
| float creaseFactor = float(ccgSubSurf_getSubdivisionLevels(ss)); | float creaseFactor = float(ccgSubSurf_getSubdivisionLevels(ss)); | ||||
| blender::Vector<CCGVertHDL, 16> fverts; | blender::Vector<CCGVertHDL, 16> fverts; | ||||
| float(*positions)[3] = (float(*)[3])dm->getVertArray(dm); | float(*positions)[3] = (float(*)[3])dm->getVertArray(dm); | ||||
| MEdge *medge = dm->getEdgeArray(dm); | MEdge *medge = dm->getEdgeArray(dm); | ||||
| MEdge *me; | MEdge *me; | ||||
| MLoop *mloop = dm->getLoopArray(dm), *ml; | int *corner_verts = dm->getCornerVertArray(dm); | ||||
| MPoly *mpoly = dm->getPolyArray(dm), *mp; | MPoly *mpoly = dm->getPolyArray(dm), *mp; | ||||
| int totvert = dm->getNumVerts(dm); | int totvert = dm->getNumVerts(dm); | ||||
| int totedge = dm->getNumEdges(dm); | int totedge = dm->getNumEdges(dm); | ||||
| int i, j; | int i, j; | ||||
| int *index; | int *index; | ||||
| ccgSubSurf_initFullSync(ss); | ccgSubSurf_initFullSync(ss); | ||||
| Show All 28 Lines | |||||
| mp = mpoly; | mp = mpoly; | ||||
| index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); | index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); | ||||
| for (i = 0; i < dm->numPolyData; i++, mp++) { | for (i = 0; i < dm->numPolyData; i++, mp++) { | ||||
| CCGFace *f; | CCGFace *f; | ||||
| fverts.reinitialize(mp->totloop); | fverts.reinitialize(mp->totloop); | ||||
| ml = mloop + mp->loopstart; | int corner = mp->loopstart; | ||||
| for (j = 0; j < mp->totloop; j++, ml++) { | for (j = 0; j < mp->totloop; j++, corner++) { | ||||
| fverts[j] = POINTER_FROM_UINT(ml->v); | fverts[j] = POINTER_FROM_UINT(corner_verts[corner]); | ||||
| } | } | ||||
| /* This is very bad, means mesh is internally inconsistent. | /* This is very bad, means mesh is internally inconsistent. | ||||
| * it is not really possible to continue without modifying | * it is not really possible to continue without modifying | ||||
| * other parts of code significantly to handle missing faces. | * other parts of code significantly to handle missing faces. | ||||
| * since this really shouldn't even be possible we just bail. */ | * since this really shouldn't even be possible we just bail. */ | ||||
| if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), mp->totloop, fverts.data(), &f) == | if (ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), mp->totloop, fverts.data(), &f) == | ||||
| eCCGError_InvalidValue) { | eCCGError_InvalidValue) { | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| getEdgeIndex(ss, e, x + 1, edgeSize), | getEdgeIndex(ss, e, x + 1, edgeSize), | ||||
| ed_flag); | ed_flag); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| struct CopyFinalLoopArrayData { | struct CopyFinalLoopArrayData { | ||||
| CCGDerivedMesh *ccgdm; | CCGDerivedMesh *ccgdm; | ||||
| MLoop *mloop; | int *corner_verts; | ||||
| int *corner_edges; | |||||
| int grid_size; | int grid_size; | ||||
| int *grid_offset; | int *grid_offset; | ||||
| int edge_size; | int edge_size; | ||||
| size_t mloop_index; | size_t mloop_index; | ||||
| }; | }; | ||||
| static void copyFinalLoopArray_task_cb(void *__restrict userdata, | static void copyFinalLoopArray_task_cb(void *__restrict userdata, | ||||
| const int iter, | const int iter, | ||||
| const TaskParallelTLS *__restrict /*tls*/) | const TaskParallelTLS *__restrict /*tls*/) | ||||
| { | { | ||||
| CopyFinalLoopArrayData *data = static_cast<CopyFinalLoopArrayData *>(userdata); | CopyFinalLoopArrayData *data = static_cast<CopyFinalLoopArrayData *>(userdata); | ||||
| CCGDerivedMesh *ccgdm = data->ccgdm; | CCGDerivedMesh *ccgdm = data->ccgdm; | ||||
| CCGSubSurf *ss = ccgdm->ss; | CCGSubSurf *ss = ccgdm->ss; | ||||
| const int grid_size = data->grid_size; | const int grid_size = data->grid_size; | ||||
| const int edge_size = data->edge_size; | const int edge_size = data->edge_size; | ||||
| CCGFace *f = ccgdm->faceMap[iter].face; | CCGFace *f = ccgdm->faceMap[iter].face; | ||||
| const int num_verts = ccgSubSurf_getFaceNumVerts(f); | const int num_verts = ccgSubSurf_getFaceNumVerts(f); | ||||
| const int grid_index = data->grid_offset[iter]; | const int grid_index = data->grid_offset[iter]; | ||||
| const size_t loop_index = 4 * size_t(grid_index) * (grid_size - 1) * (grid_size - 1); | int *corner_verts = data->corner_verts; | ||||
| MLoop *ml = &data->mloop[loop_index]; | int *corner_edges = data->corner_edges; | ||||
| size_t loop_i = 4 * size_t(grid_index) * (grid_size - 1) * (grid_size - 1); | |||||
| for (int S = 0; S < num_verts; S++) { | for (int S = 0; S < num_verts; S++) { | ||||
| for (int y = 0; y < grid_size - 1; y++) { | for (int y = 0; y < grid_size - 1; y++) { | ||||
| for (int x = 0; x < grid_size - 1; x++) { | for (int x = 0; x < grid_size - 1; x++) { | ||||
| uint v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size); | const int v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size); | ||||
| uint v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size); | const int v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size); | ||||
| uint v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size); | const int v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size); | ||||
| uint v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size); | const int v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size); | ||||
| if (corner_verts) { | |||||
| corner_verts[loop_i + 0] = v1; | |||||
| corner_verts[loop_i + 1] = v2; | |||||
| corner_verts[loop_i + 2] = v3; | |||||
| corner_verts[loop_i + 3] = v4; | |||||
| } | |||||
| if (corner_edges) { | |||||
| corner_edges[loop_i + 0] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2)); | |||||
| corner_edges[loop_i + 1] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3)); | |||||
| corner_edges[loop_i + 2] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4)); | |||||
| corner_edges[loop_i + 3] = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1)); | |||||
| } | |||||
| ml->v = v1; | loop_i += 4; | ||||
| ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2)); | } | ||||
| ml++; | } | ||||
| } | |||||
| } | |||||
| static void ccgDM_copyFinalCornerVertArray(DerivedMesh *dm, int *r_corner_verts) | |||||
| { | |||||
| CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; | |||||
| CCGSubSurf *ss = ccgdm->ss; | |||||
| ml->v = v2; | if (!ccgdm->ehash) { | ||||
| ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3)); | BLI_mutex_lock(&ccgdm->loops_cache_lock); | ||||
| ml++; | if (!ccgdm->ehash) { | ||||
| MEdge *medge; | |||||
| EdgeHash *ehash; | |||||
| ml->v = v3; | ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); | ||||
| ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4)); | medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm); | ||||
| ml++; | |||||
| ml->v = v4; | for (int i = 0; i < ccgdm->dm.numEdgeData; i++) { | ||||
| ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1)); | BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, POINTER_FROM_INT(i)); | ||||
| ml++; | |||||
| } | } | ||||
| atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash); | |||||
| } | } | ||||
| BLI_mutex_unlock(&ccgdm->loops_cache_lock); | |||||
| } | } | ||||
| CopyFinalLoopArrayData data; | |||||
| data.ccgdm = ccgdm; | |||||
| data.corner_verts = r_corner_verts; | |||||
| data.corner_edges = NULL; | |||||
| data.grid_size = ccgSubSurf_getGridSize(ss); | |||||
| data.grid_offset = dm->getGridOffset(dm); | |||||
| data.edge_size = ccgSubSurf_getEdgeSize(ss); | |||||
| /* NOTE: For a dense subdivision we've got enough work for each face and | |||||
| * hence can dedicate whole thread to single face. For less dense | |||||
| * subdivision we handle multiple faces per thread. | |||||
| */ | |||||
| data.mloop_index = data.grid_size >= 5 ? 1 : 8; | |||||
| TaskParallelSettings settings; | |||||
| BLI_parallel_range_settings_defaults(&settings); | |||||
| settings.min_iter_per_thread = 1; | |||||
| BLI_task_parallel_range( | |||||
| 0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings); | |||||
| } | } | ||||
| static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) | static void ccgDM_copyFinalCornerEdgeArray(DerivedMesh *dm, int *r_corner_edges) | ||||
| { | { | ||||
| CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; | CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; | ||||
| CCGSubSurf *ss = ccgdm->ss; | CCGSubSurf *ss = ccgdm->ss; | ||||
| if (!ccgdm->ehash) { | if (!ccgdm->ehash) { | ||||
| BLI_mutex_lock(&ccgdm->loops_cache_lock); | BLI_mutex_lock(&ccgdm->loops_cache_lock); | ||||
| if (!ccgdm->ehash) { | if (!ccgdm->ehash) { | ||||
| MEdge *medge; | MEdge *medge; | ||||
| EdgeHash *ehash; | EdgeHash *ehash; | ||||
| ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); | ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); | ||||
| medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm); | medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm); | ||||
| for (int i = 0; i < ccgdm->dm.numEdgeData; i++) { | for (int i = 0; i < ccgdm->dm.numEdgeData; i++) { | ||||
| BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, POINTER_FROM_INT(i)); | BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, POINTER_FROM_INT(i)); | ||||
| } | } | ||||
| atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash); | atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash); | ||||
| } | } | ||||
| BLI_mutex_unlock(&ccgdm->loops_cache_lock); | BLI_mutex_unlock(&ccgdm->loops_cache_lock); | ||||
| } | } | ||||
| CopyFinalLoopArrayData data; | CopyFinalLoopArrayData data; | ||||
| data.ccgdm = ccgdm; | data.ccgdm = ccgdm; | ||||
| data.mloop = mloop; | data.corner_verts = NULL; | ||||
| data.corner_edges = r_corner_edges; | |||||
| data.grid_size = ccgSubSurf_getGridSize(ss); | data.grid_size = ccgSubSurf_getGridSize(ss); | ||||
| data.grid_offset = dm->getGridOffset(dm); | data.grid_offset = dm->getGridOffset(dm); | ||||
| data.edge_size = ccgSubSurf_getEdgeSize(ss); | data.edge_size = ccgSubSurf_getEdgeSize(ss); | ||||
| /* NOTE: For a dense subdivision we've got enough work for each face and | /* NOTE: For a dense subdivision we've got enough work for each face and | ||||
| * hence can dedicate whole thread to single face. For less dense | * hence can dedicate whole thread to single face. For less dense | ||||
| * subdivision we handle multiple faces per thread. | * subdivision we handle multiple faces per thread. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
| ccgdm->dm.getNumLoops = ccgDM_getNumLoops; | ccgdm->dm.getNumLoops = ccgDM_getNumLoops; | ||||
| ccgdm->dm.getNumPolys = ccgDM_getNumPolys; | ccgdm->dm.getNumPolys = ccgDM_getNumPolys; | ||||
| ccgdm->dm.getVertCo = ccgDM_getFinalVertCo; | ccgdm->dm.getVertCo = ccgDM_getFinalVertCo; | ||||
| ccgdm->dm.getVertNo = ccgDM_getFinalVertNo; | ccgdm->dm.getVertNo = ccgDM_getFinalVertNo; | ||||
| ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; | ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; | ||||
| ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; | ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; | ||||
| ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray; | ccgdm->dm.copyCornerVertArray = ccgDM_copyFinalCornerVertArray; | ||||
| ccgdm->dm.copyCornerEdgeArray = ccgDM_copyFinalCornerEdgeArray; | |||||
| ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray; | ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray; | ||||
| ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer; | ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer; | ||||
| ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer; | ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer; | ||||
| ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer; | ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer; | ||||
| ccgdm->dm.getNumGrids = ccgDM_getNumGrids; | ccgdm->dm.getNumGrids = ccgDM_getNumGrids; | ||||
| ccgdm->dm.getGridSize = ccgDM_getGridSize; | ccgdm->dm.getGridSize = ccgDM_getGridSize; | ||||
| ccgdm->dm.getGridData = ccgDM_getGridData; | ccgdm->dm.getGridData = ccgDM_getGridData; | ||||
| ▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines | |||||