diff options
Diffstat (limited to 'source/blender/blenkernel/intern/subsurf_ccg.c')
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 319 |
1 files changed, 315 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e8bca50c3d7..16f218d5fb6 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -72,6 +72,7 @@ #include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_glew.h" +#include "GPU_buffers.h" #include "CCGSubSurf.h" @@ -1734,12 +1735,25 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm) } } +static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3]) +{ + float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2]; + float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2]; + + no[0] = b_dY * a_cZ - b_dZ * a_cY; + no[1] = b_dZ * a_cX - b_dX * a_cZ; + no[2] = b_dX * a_cY - b_dY * a_cX; + + normalize_v3(no); +} + + static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) { float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2]; float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2]; float no[3]; - + no[0] = b_dY * a_cZ - b_dZ * a_cY; no[1] = b_dZ * a_cX - b_dX * a_cZ; no[2] = b_dX * a_cY - b_dY * a_cX; @@ -1749,7 +1763,8 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) } /* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial) +static void ccgDM_prepare_normal_data(DerivedMesh *dm, float *varray, int *vindex, + int *mat_orig_to_new, void *UNUSED(user_data)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; @@ -1758,13 +1773,277 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) int gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; DMFlagMat *faceFlags = ccgdm->faceFlags; - int step = (fast) ? gridSize - 1 : 1; int i, totface = ccgSubSurf_getNumFaces(ss); - int drawcurrent = 0, matnr = -1, shademodel = -1; + int matnr, shademodel; + int start; CCG_key_top_level(&key, ss); ccgdm_pbvh_update(ccgdm); + for (i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; + int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); + int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); + short (*ln)[4][3] = NULL; + + if (faceFlags) { + shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT; + matnr = faceFlags[index].mat_nr; + } + else { + shademodel = GL_SMOOTH; + matnr = 0; + } + + if (lnors) { + ln = lnors; + lnors += gridFaces * gridFaces * numVerts; + } + + for (S = 0; S < numVerts; S++) { + CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); + + if (ln) { + /* Can't use quad strips here... */ + for (y = 0; y < gridFaces; y ++) { + for (x = 0; x < gridFaces; x ++) { + start = vindex[mat_orig_to_new[matnr]]; + + normal_short_to_float_v3(&varray[start], ln[0][1]); + normal_short_to_float_v3(&varray[start + 3], ln[0][2]); + normal_short_to_float_v3(&varray[start + 6], ln[0][3]); + + normal_short_to_float_v3(&varray[start + 9], ln[0][3]); + normal_short_to_float_v3(&varray[start + 12], ln[0][1]); + normal_short_to_float_v3(&varray[start + 15], ln[0][0]); + + vindex[mat_orig_to_new[matnr]] += 18; + + ln ++; + } + } + } + else if (shademodel == GL_SMOOTH) { + for (y = 0; y < gridFaces; y ++) { + for (x = 0; x < gridFaces; x ++) { + float *a = CCG_grid_elem_no(&key, faceGridData, x, y ); + float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y); + float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1); + float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1); + + start = vindex[mat_orig_to_new[matnr]]; + + copy_v3_v3(&varray[start], d); + copy_v3_v3(&varray[start + 3], c); + copy_v3_v3(&varray[start + 6], b); + + copy_v3_v3(&varray[start + 9], d); + copy_v3_v3(&varray[start + 12], b); + copy_v3_v3(&varray[start + 15], a); + + vindex[mat_orig_to_new[matnr]] += 18; + } + } + } + else { + for (y = 0; y < gridFaces; y ++) { + for (x = 0; x < gridFaces; x ++) { + float no[3]; + float *a = CCG_grid_elem_co(&key, faceGridData, x, y ); + float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y ); + float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); + float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1); + + ccgDM_NormalFast(a, b, c, d, no); + + start = vindex[mat_orig_to_new[matnr]]; + + copy_v3_v3(&varray[start], no); + copy_v3_v3(&varray[start + 3], no); + copy_v3_v3(&varray[start + 6], no); + + copy_v3_v3(&varray[start + 9], no); + copy_v3_v3(&varray[start + 12], no); + copy_v3_v3(&varray[start + 15], no); + + vindex[mat_orig_to_new[matnr]] += 18; + } + } + } + } + } +} + +/* Only used by non-editmesh types */ +static void ccgDM_prepare_vertex_data(DerivedMesh *dm, float *varray, int *vindex, + int *mat_orig_to_new, void *UNUSED(user_data)) +{ + CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; + CCGSubSurf *ss = ccgdm->ss; + CCGKey key; + int gridSize = ccgSubSurf_getGridSize(ss); + int gridFaces = gridSize - 1; + DMFlagMat *faceFlags = ccgdm->faceFlags; + int i, totface = ccgSubSurf_getNumFaces(ss); + int matnr = -1, start; + + CCG_key_top_level(&key, ss); + ccgdm_pbvh_update(ccgdm); + + for (i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; + int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); + int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); + + if (faceFlags) { + matnr = faceFlags[index].mat_nr; + } + else { + matnr = 0; + } + + for (S = 0; S < numVerts; S++) { + CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); + for (y = 0; y < gridFaces; y++) { + for (x = 0; x < gridFaces; x++) { + float *a = CCG_grid_elem_co(&key, faceGridData, x, y); + float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y); + float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); + float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1); + + start = vindex[mat_orig_to_new[matnr]]; + + copy_v3_v3(&varray[start], d); + copy_v3_v3(&varray[start + 3], c); + copy_v3_v3(&varray[start + 6], b); + + copy_v3_v3(&varray[start + 9], d); + copy_v3_v3(&varray[start + 12], b); + copy_v3_v3(&varray[start + 15], a); + + vindex[mat_orig_to_new[matnr]] += 18; + } + } + } + } +} + +static void ccgDM_copy_gpu_data(DerivedMesh *dm, int type, float *varray, int *index, + int *mat_orig_to_new, void *UNUSED(user_data)) +{ + switch(type) { + case GPU_BUFFER_VERTEX: + ccgDM_prepare_vertex_data(dm, varray, index, mat_orig_to_new, NULL); + break; + case GPU_BUFFER_NORMAL: + ccgDM_prepare_normal_data(dm, varray, index, mat_orig_to_new, NULL); + break; + default: + break; + } +} + +static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) { +// GPUBufferMaterial *mat; + int *mat_orig_to_new; + CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; + CCGSubSurf *ss = ccgdm->ss; + GPUDrawObject *gdo; + DMFlagMat *faceFlags = ccgdm->faceFlags; + int gridSize = ccgSubSurf_getGridSize(ss); + int gridFaces = gridSize - 1; + int totmat = (faceFlags) ? dm->totmat : 1; + int *points_per_mat; + int i, curmat, curpoint, totface; + + /* object contains at least one material (default included) so zero means uninitialized dm */ + BLI_assert(totmat != 0); + + totface = ccgSubSurf_getNumFaces(ss); + + points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new"); + + if (faceFlags) { + for (i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; + int numVerts = ccgSubSurf_getFaceNumVerts(f); + int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); + int new_matnr = faceFlags[index].mat_nr; + points_per_mat[new_matnr] += numVerts * gridFaces * gridFaces * 6; + } + } + else { + for (i = 0; i < totface; i++) { + points_per_mat[0] += gridFaces * gridFaces * 6; + } + } + + /* create the GPUDrawObject */ + gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject"); + gdo->totvert = ccgSubSurf_getNumFinalFaces(ss) * 6; + gdo->totedge = ccgSubSurf_getNumFinalEdges(ss) * 2; + + /* count the number of materials used by this DerivedMesh */ + for (i = 0; i < totmat; i++) { + if (points_per_mat[i] > 0) + gdo->totmaterial++; + } + + /* allocate an array of materials used by this DerivedMesh */ + gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial, + "GPUDrawObject.materials"); + + /* initialize the materials array */ + for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) { + if (points_per_mat[i] > 0) { + gdo->materials[curmat].start = curpoint; + gdo->materials[curmat].totpoint = points_per_mat[i]; + gdo->materials[curmat].mat_nr = i; + + curpoint += points_per_mat[i]; + curmat++; + } + } + + /* store total number of points used for triangles */ + gdo->tot_triangle_point = curpoint; + + mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat, + "GPUDrawObject.mat_orig_to_new"); + + /* build a map from the original material indices to the new + * GPUBufferMaterial indices */ + for (i = 0; i < gdo->totmaterial; i++) { + mat_orig_to_new[gdo->materials[i].mat_nr] = i; + + } + + /* + for (i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; + int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); + int new_matnr = faceFlags[index].mat_nr; + + mat = &gdo->materials[mat_orig_to_new[new_matnr]]; + + } + */ + + + MEM_freeN(mat_orig_to_new); + MEM_freeN(points_per_mat); + + return gdo; +} + +/* Only used by non-editmesh types */ +static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial) +{ + int a; + CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; + + ccgdm_pbvh_update(ccgdm); + if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) { if (BKE_pbvh_has_faces(ccgdm->pbvh)) { BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, @@ -1774,6 +2053,34 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) return; } + + GPU_vertex_setup(dm); + GPU_normal_setup(dm); + glShadeModel(GL_SMOOTH); + for (a = 0; a < dm->drawObject->totmaterial; a++) { + if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) { + glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, + dm->drawObject->materials[a].totpoint); + } + } + GPU_buffer_unbind(); + +#if 0 + + CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; + CCGSubSurf *ss = ccgdm->ss; + CCGKey key; + short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + int gridSize = ccgSubSurf_getGridSize(ss); + int gridFaces = gridSize - 1; + DMFlagMat *faceFlags = ccgdm->faceFlags; + int step = (fast) ? gridSize - 1 : 1; + int i, totface = ccgSubSurf_getNumFaces(ss); + int drawcurrent = 0, matnr = -1, shademodel = -1; + + CCG_key_top_level(&key, ss); + ccgdm_pbvh_update(ccgdm); + for (i = 0; i < totface; i++) { CCGFace *f = ccgdm->faceMap[i].face; @@ -1873,6 +2180,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) } } } + +#endif } /* Only used by non-editmesh types */ @@ -3431,6 +3740,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges; + ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew; + ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data; ccgdm->dm.release = ccgDM_release; |