Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/intern/gpu_buffers.c
| Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
| #include "DNA_userdef_types.h" | #include "DNA_userdef_types.h" | ||||
| #include "GPU_buffers.h" | #include "GPU_buffers.h" | ||||
| #include "GPU_draw.h" | #include "GPU_draw.h" | ||||
| #include "bmesh.h" | #include "bmesh.h" | ||||
| typedef enum { | typedef enum { | ||||
| GPU_BUFFER_VERTEX_STATE = (1 << 0), | GPU_BUFFER_VERTEX_STATE = (1 << 0), | ||||
| GPU_BUFFER_NORMAL_STATE = (1 << 1), | GPU_BUFFER_NORMAL_STATE = (1 << 1), | ||||
| GPU_BUFFER_TEXCOORD_UNIT_0_STATE = (1 << 2), | GPU_BUFFER_TEXCOORD_UNIT_0_STATE = (1 << 2), | ||||
| GPU_BUFFER_TEXCOORD_UNIT_2_STATE = (1 << 3), | GPU_BUFFER_TEXCOORD_UNIT_2_STATE = (1 << 3), | ||||
| GPU_BUFFER_COLOR_STATE = (1 << 4), | GPU_BUFFER_COLOR_STATE = (1 << 4), | ||||
| GPU_BUFFER_ELEMENT_STATE = (1 << 5), | GPU_BUFFER_ELEMENT_STATE = (1 << 5), | ||||
| } GPUBufferState; | } GPUBufferState; | ||||
| ▲ Show 20 Lines • Show All 360 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| #endif /* USE_GPU_POINT_LINK */ | #endif /* USE_GPU_POINT_LINK */ | ||||
| /* update the vert_points and triangle_to_mface fields with a new | /* update the vert_points and triangle_to_mface fields with a new | ||||
| * triangle */ | * triangle */ | ||||
| static void gpu_drawobject_add_triangle(GPUDrawObject *gdo, | static void gpu_drawobject_add_triangle(GPUDrawObject *gdo, | ||||
| int base_point_index, | int base_point_index, | ||||
| int face_index, | int poly_index, | ||||
| int v1, int v2, int v3) | int v1, int v2, int v3) | ||||
| { | { | ||||
| int i, v[3] = {v1, v2, v3}; | int i, v[3] = {v1, v2, v3}; | ||||
| for (i = 0; i < 3; i++) | for (i = 0; i < 3; i++) | ||||
| gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i); | gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i); | ||||
| gdo->triangle_to_mface[base_point_index / 3] = face_index; | gdo->triangle_to_mpoly[base_point_index / 3] = poly_index; | ||||
| } | } | ||||
| /* for each vertex, build a list of points related to it; these lists | /* for each vertex, build a list of points related to it; these lists | ||||
| * are stored in an array sized to the number of vertices */ | * are stored in an array sized to the number of vertices */ | ||||
| static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, const MFace *f, int totface, int totmat) | static void gpu_drawobject_init_vert_points( | ||||
| GPUDrawObject *gdo, | |||||
| const MPoly *mpoly, const MLoop *mloop, | |||||
| const MLoopTri *mlooptri, int mlooptri_num, | |||||
| int totmat) | |||||
| { | { | ||||
| GPUBufferMaterial *mat; | GPUBufferMaterial *mat; | ||||
| int i, *mat_orig_to_new; | int i, *mat_orig_to_new; | ||||
| const MLoopTri *lt; | |||||
| mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat, | mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat, | ||||
| "GPUDrawObject.mat_orig_to_new"); | "GPUDrawObject.mat_orig_to_new"); | ||||
| /* allocate the array and space for links */ | /* allocate the array and space for links */ | ||||
| gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert, | gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert, | ||||
| "GPUDrawObject.vert_points"); | "GPUDrawObject.vert_points"); | ||||
| #ifdef USE_GPU_POINT_LINK | #ifdef USE_GPU_POINT_LINK | ||||
| gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point, | gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point, | ||||
| Show All 9 Lines | #endif | ||||
| /* -1 indicates the link is not yet used */ | /* -1 indicates the link is not yet used */ | ||||
| for (i = 0; i < gdo->totvert; i++) { | for (i = 0; i < gdo->totvert; i++) { | ||||
| #ifdef USE_GPU_POINT_LINK | #ifdef USE_GPU_POINT_LINK | ||||
| gdo->vert_points[i].link = NULL; | gdo->vert_points[i].link = NULL; | ||||
| #endif | #endif | ||||
| gdo->vert_points[i].point_index = -1; | gdo->vert_points[i].point_index = -1; | ||||
| } | } | ||||
| for (i = 0; i < totface; i++, f++) { | for (i = 0, lt = mlooptri; i < mlooptri_num; i++, lt++) { | ||||
| mat = &gdo->materials[mat_orig_to_new[f->mat_nr]]; | const MPoly *p = &mpoly[lt->poly]; | ||||
| mat = &gdo->materials[mat_orig_to_new[p->mat_nr]]; | |||||
| /* add triangle */ | /* add triangle */ | ||||
| gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint, | gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint, lt->poly, | ||||
| i, f->v1, f->v2, f->v3); | mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v); | ||||
| mat->totpoint += 3; | |||||
| /* add second triangle for quads */ | |||||
| if (f->v4) { | |||||
| gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint, | |||||
| i, f->v3, f->v4, f->v1); | |||||
| mat->totpoint += 3; | mat->totpoint += 3; | ||||
| } | } | ||||
| } | |||||
| /* map any unused vertices to loose points */ | /* map any unused vertices to loose points */ | ||||
| for (i = 0; i < gdo->totvert; i++) { | for (i = 0; i < gdo->totvert; i++) { | ||||
| if (gdo->vert_points[i].point_index == -1) { | if (gdo->vert_points[i].point_index == -1) { | ||||
| gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point; | gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point; | ||||
| gdo->tot_loose_point++; | gdo->tot_loose_point++; | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(mat_orig_to_new); | MEM_freeN(mat_orig_to_new); | ||||
| } | } | ||||
| /* see GPUDrawObject's structure definition for a description of the | /* see GPUDrawObject's structure definition for a description of the | ||||
| * data being initialized here */ | * data being initialized here */ | ||||
| GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm) | GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm) | ||||
| { | { | ||||
| GPUDrawObject *gdo; | GPUDrawObject *gdo; | ||||
| const MFace *mface; | const MPoly *mpoly; | ||||
| const MLoop *mloop; | |||||
| const MLoopTri *mlooptri; | |||||
| int totmat = dm->totmat; | int totmat = dm->totmat; | ||||
| int *points_per_mat; | int *points_per_mat; | ||||
| int i, curmat, curpoint, totface; | int i, curmat, curpoint, tottri; | ||||
| /* object contains at least one material (default included) so zero means uninitialized dm */ | /* object contains at least one material (default included) so zero means uninitialized dm */ | ||||
| BLI_assert(totmat != 0); | BLI_assert(totmat != 0); | ||||
| mface = dm->getTessFaceArray(dm); | mpoly = dm->getPolyArray(dm); | ||||
| totface = dm->getNumTessFaces(dm); | mloop = dm->getLoopArray(dm); | ||||
| mlooptri = dm->looptris.array; | |||||
| tottri = dm->looptris.num; | |||||
| /* get the number of points used by each material, treating | /* get the number of points used by each material, treating | ||||
| * each quad as two triangles */ | * each quad as two triangles */ | ||||
| points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new"); | points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new"); | ||||
| for (i = 0; i < totface; i++) | /* NOTE: could loop polys instead (faster) */ | ||||
| points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3; | for (i = 0; i < tottri; i++) | ||||
| points_per_mat[mpoly[mlooptri[i].poly].mat_nr] += 3; | |||||
| /* create the GPUDrawObject */ | /* create the GPUDrawObject */ | ||||
| gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject"); | gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject"); | ||||
| gdo->totvert = dm->getNumVerts(dm); | gdo->totvert = dm->getNumVerts(dm); | ||||
| gdo->totedge = dm->getNumEdges(dm); | gdo->totedge = dm->getNumEdges(dm); | ||||
| /* count the number of materials used by this DerivedMesh */ | /* count the number of materials used by this DerivedMesh */ | ||||
| for (i = 0; i < totmat; i++) { | for (i = 0; i < totmat; i++) { | ||||
| Show All 15 Lines | if (points_per_mat[i] > 0) { | ||||
| curpoint += points_per_mat[i]; | curpoint += points_per_mat[i]; | ||||
| curmat++; | curmat++; | ||||
| } | } | ||||
| } | } | ||||
| /* store total number of points used for triangles */ | /* store total number of points used for triangles */ | ||||
| gdo->tot_triangle_point = curpoint; | gdo->tot_triangle_point = curpoint; | ||||
| gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3), | gdo->triangle_to_mpoly = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3), | ||||
| "GPUDrawObject.triangle_to_mface"); | "GPUDrawObject.triangle_to_mface"); | ||||
| gpu_drawobject_init_vert_points(gdo, mface, totface, totmat); | gpu_drawobject_init_vert_points(gdo, mpoly, mloop, mlooptri, tottri, totmat); | ||||
| MEM_freeN(points_per_mat); | MEM_freeN(points_per_mat); | ||||
| return gdo; | return gdo; | ||||
| } | } | ||||
| void GPU_drawobject_free(DerivedMesh *dm) | void GPU_drawobject_free(DerivedMesh *dm) | ||||
| { | { | ||||
| GPUDrawObject *gdo; | GPUDrawObject *gdo; | ||||
| if (!dm || !(gdo = dm->drawObject)) | if (!dm || !(gdo = dm->drawObject)) | ||||
| return; | return; | ||||
| MEM_freeN(gdo->materials); | MEM_freeN(gdo->materials); | ||||
| MEM_freeN(gdo->triangle_to_mface); | MEM_freeN(gdo->triangle_to_mpoly); | ||||
| MEM_freeN(gdo->vert_points); | MEM_freeN(gdo->vert_points); | ||||
| #ifdef USE_GPU_POINT_LINK | #ifdef USE_GPU_POINT_LINK | ||||
| MEM_freeN(gdo->vert_points_mem); | MEM_freeN(gdo->vert_points_mem); | ||||
| #endif | #endif | ||||
| GPU_buffer_free(gdo->points); | GPU_buffer_free(gdo->points); | ||||
| GPU_buffer_free(gdo->normals); | GPU_buffer_free(gdo->normals); | ||||
| GPU_buffer_free(gdo->uv); | GPU_buffer_free(gdo->uv); | ||||
| GPU_buffer_free(gdo->uv_tex); | GPU_buffer_free(gdo->uv_tex); | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, | ||||
| MEM_freeN(mat_orig_to_new); | MEM_freeN(mat_orig_to_new); | ||||
| BLI_mutex_unlock(&buffer_mutex); | BLI_mutex_unlock(&buffer_mutex); | ||||
| return buffer; | return buffer; | ||||
| } | } | ||||
| static void GPU_buffer_copy_vertex( | static void GPU_buffer_copy_vertex( | ||||
| DerivedMesh *dm, float *varray, | DerivedMesh *dm, float *varray, int *index, | ||||
| int *index, const int *mat_orig_to_new, const void *UNUSED(user)) | const int *mat_orig_to_new, const void *UNUSED(user)) | ||||
| { | { | ||||
| const MVert *mvert; | const MVert *mvert; | ||||
| const MFace *f; | int i, j, tottri; | ||||
| int i, j, start, totface; | |||||
| const MPoly *mpoly; | |||||
| const MLoop *mloop; | |||||
| const MLoopTri *lt; | |||||
| mpoly = dm->getPolyArray(dm); | |||||
| mloop = dm->getLoopArray(dm); | |||||
| mvert = dm->getVertArray(dm); | mvert = dm->getVertArray(dm); | ||||
| f = dm->getTessFaceArray(dm); | lt = dm->looptris.array; | ||||
| tottri = dm->looptris.num; | |||||
| totface = dm->getNumTessFaces(dm); | for (i = 0; i < tottri; i++, lt++) { | ||||
| for (i = 0; i < totface; i++, f++) { | const MPoly *mp = &mpoly[lt->poly]; | ||||
| start = index[mat_orig_to_new[f->mat_nr]]; | const unsigned int vtri[3] = { | ||||
| mloop[lt->tri[0]].v, | |||||
| mloop[lt->tri[1]].v, | |||||
| mloop[lt->tri[2]].v, | |||||
| }; | |||||
| const int start = index[mat_orig_to_new[mp->mat_nr]]; | |||||
| /* v1 v2 v3 */ | /* v1 v2 v3 */ | ||||
| copy_v3_v3(&varray[start], mvert[f->v1].co); | copy_v3_v3(&varray[start + 0], mvert[vtri[0]].co); | ||||
| copy_v3_v3(&varray[start + 3], mvert[f->v2].co); | copy_v3_v3(&varray[start + 3], mvert[vtri[1]].co); | ||||
| copy_v3_v3(&varray[start + 6], mvert[f->v3].co); | copy_v3_v3(&varray[start + 6], mvert[vtri[2]].co); | ||||
| index[mat_orig_to_new[f->mat_nr]] += 9; | index[mat_orig_to_new[mp->mat_nr]] += 9; | ||||
| if (f->v4) { | |||||
| /* v3 v4 v1 */ | |||||
| copy_v3_v3(&varray[start + 9], mvert[f->v3].co); | |||||
| copy_v3_v3(&varray[start + 12], mvert[f->v4].co); | |||||
| copy_v3_v3(&varray[start + 15], mvert[f->v1].co); | |||||
| index[mat_orig_to_new[f->mat_nr]] += 9; | |||||
| } | |||||
| } | } | ||||
| /* copy loose points */ | /* copy loose points */ | ||||
| j = dm->drawObject->tot_triangle_point * 3; | j = dm->drawObject->tot_triangle_point * 3; | ||||
| for (i = 0; i < dm->drawObject->totvert; i++) { | for (i = 0; i < dm->drawObject->totvert; i++) { | ||||
| if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) { | if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) { | ||||
| copy_v3_v3(&varray[j], mvert[i].co); | copy_v3_v3(&varray[j], mvert[i].co); | ||||
| j += 3; | j += 3; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void GPU_buffer_copy_normal( | static void GPU_buffer_copy_normal( | ||||
| DerivedMesh *dm, float *varray, int *index, | DerivedMesh *dm, float *varray, int *index, | ||||
| const int *mat_orig_to_new, const void *UNUSED(user)) | const int *mat_orig_to_new, const void *UNUSED(user)) | ||||
| { | { | ||||
| int i, totface; | int i, tottri; | ||||
| int start; | |||||
| float f_no[3]; | float f_no[3]; | ||||
| const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); | const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL); | ||||
| short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); | const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); | ||||
| const MVert *mvert = dm->getVertArray(dm); | const MVert *mvert = dm->getVertArray(dm); | ||||
| const MFace *f = dm->getTessFaceArray(dm); | |||||
| totface = dm->getNumTessFaces(dm); | const MPoly *mpoly; | ||||
| for (i = 0; i < totface; i++, f++) { | const MLoop *mloop; | ||||
| const int smoothnormal = (f->flag & ME_SMOOTH); | const MLoopTri *lt; | ||||
| start = index[mat_orig_to_new[f->mat_nr]]; | mpoly = dm->getPolyArray(dm); | ||||
| index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9; | mloop = dm->getLoopArray(dm); | ||||
| mvert = dm->getVertArray(dm); | |||||
| lt = dm->looptris.array; | |||||
| tottri = dm->looptris.num; | |||||
| if (tlnors) { | for (i = 0; i < tottri; i++, lt++) { | ||||
| short (*tlnor)[3] = tlnors[i]; | const MPoly *mp = &mpoly[lt->poly]; | ||||
| const unsigned int *ltri = lt->tri; | |||||
| const unsigned int vtri[3] = { | |||||
| mloop[lt->tri[0]].v, | |||||
| mloop[lt->tri[1]].v, | |||||
| mloop[lt->tri[2]].v, | |||||
| }; | |||||
| const bool smoothnormal = (mp->flag & ME_SMOOTH) != 0; | |||||
| const int start = index[mat_orig_to_new[mp->mat_nr]]; | |||||
| index[mat_orig_to_new[mp->mat_nr]] += 9; | |||||
| if (lnors) { | |||||
| /* Copy loop normals */ | /* Copy loop normals */ | ||||
| normal_short_to_float_v3(&varray[start], tlnor[0]); | copy_v3_v3(&varray[start + 0], lnors[ltri[0]]); | ||||
| normal_short_to_float_v3(&varray[start + 3], tlnor[1]); | copy_v3_v3(&varray[start + 3], lnors[ltri[1]]); | ||||
| normal_short_to_float_v3(&varray[start + 6], tlnor[2]); | copy_v3_v3(&varray[start + 6], lnors[ltri[2]]); | ||||
| if (f->v4) { | |||||
| normal_short_to_float_v3(&varray[start + 9], tlnor[2]); | |||||
| normal_short_to_float_v3(&varray[start + 12], tlnor[3]); | |||||
| normal_short_to_float_v3(&varray[start + 15], tlnor[0]); | |||||
| } | |||||
| } | } | ||||
| else if (smoothnormal) { | else if (smoothnormal) { | ||||
| /* copy vertex normal */ | /* copy vertex normal */ | ||||
| normal_short_to_float_v3(&varray[start], mvert[f->v1].no); | normal_short_to_float_v3(&varray[start + 0], mvert[vtri[0]].no); | ||||
| normal_short_to_float_v3(&varray[start + 3], mvert[f->v2].no); | normal_short_to_float_v3(&varray[start + 3], mvert[vtri[1]].no); | ||||
| normal_short_to_float_v3(&varray[start + 6], mvert[f->v3].no); | normal_short_to_float_v3(&varray[start + 6], mvert[vtri[2]].no); | ||||
| if (f->v4) { | |||||
| normal_short_to_float_v3(&varray[start + 9], mvert[f->v3].no); | |||||
| normal_short_to_float_v3(&varray[start + 12], mvert[f->v4].no); | |||||
| normal_short_to_float_v3(&varray[start + 15], mvert[f->v1].no); | |||||
| } | |||||
| } | } | ||||
| else if (nors) { | else if (nors) { | ||||
| /* copy cached face normal */ | /* copy cached face normal */ | ||||
| copy_v3_v3(&varray[start], &nors[i * 3]); | copy_v3_v3(&varray[start + 0], nors[lt->poly]); | ||||
| copy_v3_v3(&varray[start + 3], &nors[i * 3]); | copy_v3_v3(&varray[start + 3], nors[lt->poly]); | ||||
| copy_v3_v3(&varray[start + 6], &nors[i * 3]); | copy_v3_v3(&varray[start + 6], nors[lt->poly]); | ||||
| if (f->v4) { | |||||
| copy_v3_v3(&varray[start + 9], &nors[i * 3]); | |||||
| copy_v3_v3(&varray[start + 12], &nors[i * 3]); | |||||
| copy_v3_v3(&varray[start + 15], &nors[i * 3]); | |||||
| } | |||||
| } | } | ||||
| else { | else { | ||||
| /* calculate face normal */ | /* calculate face normal */ | ||||
| if (f->v4) | normal_tri_v3(f_no, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co); | ||||
| normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co); | |||||
| else | |||||
| normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co); | |||||
| copy_v3_v3(&varray[start], f_no); | copy_v3_v3(&varray[start + 0], f_no); | ||||
| copy_v3_v3(&varray[start + 3], f_no); | copy_v3_v3(&varray[start + 3], f_no); | ||||
| copy_v3_v3(&varray[start + 6], f_no); | copy_v3_v3(&varray[start + 6], f_no); | ||||
| if (f->v4) { | |||||
| copy_v3_v3(&varray[start + 9], f_no); | |||||
| copy_v3_v3(&varray[start + 12], f_no); | |||||
| copy_v3_v3(&varray[start + 15], f_no); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void GPU_buffer_copy_uv( | static void GPU_buffer_copy_uv( | ||||
| DerivedMesh *dm, float *varray, int *index, | DerivedMesh *dm, float *varray, int *index, | ||||
| const int *mat_orig_to_new, const void *UNUSED(user)) | const int *mat_orig_to_new, const void *UNUSED(user)) | ||||
| { | { | ||||
| int start; | int i, tottri; | ||||
| int i, totface; | |||||
| const MTFace *mtface; | const MPoly *mpoly; | ||||
| const MFace *f; | const MLoopTri *lt; | ||||
| const MLoopUV *mloopuv; | |||||
| if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE))) | if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) { | ||||
| return; | return; | ||||
| f = dm->getTessFaceArray(dm); | } | ||||
| mpoly = dm->getPolyArray(dm); | |||||
| lt = dm->looptris.array; | |||||
| tottri = dm->looptris.num; | |||||
| totface = dm->getNumTessFaces(dm); | for (i = 0; i < tottri; i++, lt++) { | ||||
| for (i = 0; i < totface; i++, f++) { | const MPoly *mp = &mpoly[lt->poly]; | ||||
| start = index[mat_orig_to_new[f->mat_nr]]; | const unsigned int *ltri = lt->tri; | ||||
| const int start = index[mat_orig_to_new[mp->mat_nr]]; | |||||
| /* v1 v2 v3 */ | /* v1 v2 v3 */ | ||||
| copy_v2_v2(&varray[start], mtface[i].uv[0]); | copy_v2_v2(&varray[start + 0], mloopuv[ltri[0]].uv); | ||||
| copy_v2_v2(&varray[start + 2], mtface[i].uv[1]); | copy_v2_v2(&varray[start + 2], mloopuv[ltri[1]].uv); | ||||
| copy_v2_v2(&varray[start + 4], mtface[i].uv[2]); | copy_v2_v2(&varray[start + 4], mloopuv[ltri[2]].uv); | ||||
| index[mat_orig_to_new[f->mat_nr]] += 6; | index[mat_orig_to_new[mp->mat_nr]] += 6; | ||||
| if (f->v4) { | |||||
| /* v3 v4 v1 */ | |||||
| copy_v2_v2(&varray[start + 6], mtface[i].uv[2]); | |||||
| copy_v2_v2(&varray[start + 8], mtface[i].uv[3]); | |||||
| copy_v2_v2(&varray[start + 10], mtface[i].uv[0]); | |||||
| index[mat_orig_to_new[f->mat_nr]] += 6; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| static void GPU_buffer_copy_uv_texpaint( | static void GPU_buffer_copy_uv_texpaint( | ||||
| DerivedMesh *dm, float *varray, int *index, | DerivedMesh *dm, float *varray, int *index, | ||||
| const int *mat_orig_to_new, const void *UNUSED(user)) | const int *mat_orig_to_new, const void *UNUSED(user)) | ||||
| { | { | ||||
| int start; | int i, tottri; | ||||
| int i, totface; | const MPoly *mpoly; | ||||
| const MLoopTri *lt; | |||||
| int totmaterial = dm->totmat; | int totmaterial = dm->totmat; | ||||
| const MTFace **mtface_base; | const MLoopUV **uv_base; | ||||
| const MTFace *stencil_base; | const MLoopUV *uv_stencil_base; | ||||
| int stencil; | int stencil; | ||||
| const MFace *mf; | |||||
| /* should have been checked for before, reassert */ | /* should have been checked for before, reassert */ | ||||
| BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE)); | BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV)); | ||||
| mf = dm->getTessFaceArray(dm); | uv_base = MEM_mallocN(totmaterial * sizeof(*uv_base), "texslots"); | ||||
| mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots"); | |||||
| for (i = 0; i < totmaterial; i++) { | for (i = 0; i < totmaterial; i++) { | ||||
| mtface_base[i] = DM_paint_uvlayer_active_get(dm, i); | uv_base[i] = DM_paint_uvlayer_active_get_mloopuv(dm, i); | ||||
| } | } | ||||
| stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE); | stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV); | ||||
| stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil); | uv_stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil); | ||||
| totface = dm->getNumTessFaces(dm); | mpoly = dm->getPolyArray(dm); | ||||
| lt = dm->looptris.array; | |||||
| tottri = dm->looptris.num; | |||||
| for (i = 0; i < totface; i++, mf++) { | for (i = 0; i < tottri; i++, lt++) { | ||||
| int mat_i = mf->mat_nr; | const MPoly *mp = &mpoly[lt->poly]; | ||||
| start = index[mat_orig_to_new[mat_i]]; | const unsigned int *ltri = lt->tri; | ||||
| int mat_i = mp->mat_nr; | |||||
| const int start = index[mat_orig_to_new[mat_i]]; | |||||
| /* v1 v2 v3 */ | /* v1 v2 v3 */ | ||||
| copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]); | copy_v2_v2(&varray[start + 0], uv_base[mat_i][ltri[0]].uv); | ||||
| copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]); | copy_v2_v2(&varray[start + 2], uv_stencil_base[ltri[0]].uv); | ||||
| copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]); | copy_v2_v2(&varray[start + 4], uv_base[mat_i][ltri[1]].uv); | ||||
| copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]); | copy_v2_v2(&varray[start + 6], uv_stencil_base[ltri[1]].uv); | ||||
| copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]); | copy_v2_v2(&varray[start + 8], uv_base[mat_i][ltri[2]].uv); | ||||
| copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]); | copy_v2_v2(&varray[start + 10], uv_stencil_base[ltri[2]].uv); | ||||
| index[mat_orig_to_new[mat_i]] += 12; | |||||
| if (mf->v4) { | |||||
| /* v3 v4 v1 */ | |||||
| copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]); | |||||
| copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]); | |||||
| copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]); | |||||
| copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]); | |||||
| copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]); | |||||
| copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]); | |||||
| index[mat_orig_to_new[mat_i]] += 12; | index[mat_orig_to_new[mat_i]] += 12; | ||||
| } | } | ||||
| } | |||||
| MEM_freeN(mtface_base); | MEM_freeN(uv_base); | ||||
| } | } | ||||
| static void copy_mcol_uc3(unsigned char *v, unsigned char *col) | |||||
| { | |||||
| v[0] = col[3]; | |||||
| v[1] = col[2]; | |||||
| v[2] = col[1]; | |||||
| } | |||||
| /* treat varray_ as an array of MCol, four MCol's per face */ | /* treat varray_ as an array of MCol, four MCol's per face */ | ||||
| static void GPU_buffer_copy_mcol( | static void GPU_buffer_copy_mcol( | ||||
| DerivedMesh *dm, float *varray_, int *index, | DerivedMesh *dm, float *varray_, int *index, | ||||
| const int *mat_orig_to_new, const void *user) | const int *mat_orig_to_new, const void *user) | ||||
| { | { | ||||
| int i, totface; | int i, tottri; | ||||
| const MPoly *mpoly; | |||||
| const MLoopTri *lt; | |||||
| unsigned char *varray = (unsigned char *)varray_; | unsigned char *varray = (unsigned char *)varray_; | ||||
| unsigned char *mcol = (unsigned char *)user; | const MLoopCol *mloopcol = user; | ||||
| const MFace *f = dm->getTessFaceArray(dm); | |||||
| totface = dm->getNumTessFaces(dm); | mpoly = dm->getPolyArray(dm); | ||||
| for (i = 0; i < totface; i++, f++) { | lt = dm->looptris.array; | ||||
| int start = index[mat_orig_to_new[f->mat_nr]]; | tottri = dm->looptris.num; | ||||
| for (i = 0; i < tottri; i++, lt++) { | |||||
| const MPoly *mp = &mpoly[lt->poly]; | |||||
| const int start = index[mat_orig_to_new[mp->mat_nr]]; | |||||
| const unsigned int *ltri = lt->tri; | |||||
| /* v1 v2 v3 */ | /* v1 v2 v3 */ | ||||
| copy_mcol_uc3(&varray[start], &mcol[i * 16]); | copy_v3_v3_char((char *)&varray[start + 0], &mloopcol[ltri[0]].r); | ||||
| copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]); | copy_v3_v3_char((char *)&varray[start + 3], &mloopcol[ltri[1]].r); | ||||
| copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]); | copy_v3_v3_char((char *)&varray[start + 6], &mloopcol[ltri[2]].r); | ||||
| index[mat_orig_to_new[f->mat_nr]] += 9; | index[mat_orig_to_new[mp->mat_nr]] += 9; | ||||
| if (f->v4) { | |||||
| /* v3 v4 v1 */ | |||||
| copy_mcol_uc3(&varray[start + 9], &mcol[i * 16 + 8]); | |||||
| copy_mcol_uc3(&varray[start + 12], &mcol[i * 16 + 12]); | |||||
| copy_mcol_uc3(&varray[start + 15], &mcol[i * 16]); | |||||
| index[mat_orig_to_new[f->mat_nr]] += 9; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| static void GPU_buffer_copy_edge( | static void GPU_buffer_copy_edge( | ||||
| DerivedMesh *dm, float *varray_, int *UNUSED(index), | DerivedMesh *dm, float *varray_, int *UNUSED(index), | ||||
| const int *UNUSED(mat_orig_to_new), const void *UNUSED(user)) | const int *UNUSED(mat_orig_to_new), const void *UNUSED(user)) | ||||
| { | { | ||||
| const MEdge *medge, *medge_base; | const MEdge *medge, *medge_base; | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | static void GPU_buffer_copy_edge( | ||||
| dm->drawObject->loose_edge_offset = tot + tot_hidden; | dm->drawObject->loose_edge_offset = tot + tot_hidden; | ||||
| dm->drawObject->tot_edge_drawn = tot; | dm->drawObject->tot_edge_drawn = tot; | ||||
| } | } | ||||
| static void GPU_buffer_copy_uvedge( | static void GPU_buffer_copy_uvedge( | ||||
| DerivedMesh *dm, float *varray, int *UNUSED(index), | DerivedMesh *dm, float *varray, int *UNUSED(index), | ||||
| const int *UNUSED(mat_orig_to_new), const void *UNUSED(user)) | const int *UNUSED(mat_orig_to_new), const void *UNUSED(user)) | ||||
| { | { | ||||
| const MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); | int i, j = 0, tottri; | ||||
| int i, j = 0; | const MLoopTri *lt; | ||||
| const MLoopUV *mloopuv; | |||||
| if (!tf) | if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) { | ||||
| return; | return; | ||||
| } | |||||
| for (i = 0; i < dm->numTessFaceData; i++, tf++) { | lt = dm->looptris.array; | ||||
| MFace mf; | tottri = dm->looptris.num; | ||||
| dm->getTessFace(dm, i, &mf); | |||||
| copy_v2_v2(&varray[j], tf->uv[0]); | for (i = 0; i < tottri; i++, lt++) { | ||||
| copy_v2_v2(&varray[j + 2], tf->uv[1]); | const unsigned int *ltri = lt->tri; | ||||
| copy_v2_v2(&varray[j + 4], tf->uv[1]); | copy_v2_v2(&varray[j + 0], mloopuv[ltri[0]].uv); | ||||
| copy_v2_v2(&varray[j + 6], tf->uv[2]); | copy_v2_v2(&varray[j + 2], mloopuv[ltri[1]].uv); | ||||
| if (!mf.v4) { | copy_v2_v2(&varray[j + 4], mloopuv[ltri[1]].uv); | ||||
| copy_v2_v2(&varray[j + 8], tf->uv[2]); | copy_v2_v2(&varray[j + 6], mloopuv[ltri[2]].uv); | ||||
| copy_v2_v2(&varray[j + 10], tf->uv[0]); | |||||
| copy_v2_v2(&varray[j + 8], mloopuv[ltri[2]].uv); | |||||
| copy_v2_v2(&varray[j + 10], mloopuv[ltri[0]].uv); | |||||
| j += 12; | j += 12; | ||||
| } | |||||
| else { | |||||
| copy_v2_v2(&varray[j + 8], tf->uv[2]); | |||||
| copy_v2_v2(&varray[j + 10], tf->uv[3]); | |||||
| copy_v2_v2(&varray[j + 12], tf->uv[3]); | |||||
| copy_v2_v2(&varray[j + 14], tf->uv[0]); | |||||
| j += 16; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| typedef enum { | typedef enum { | ||||
| GPU_BUFFER_VERTEX = 0, | GPU_BUFFER_VERTEX = 0, | ||||
| GPU_BUFFER_NORMAL, | GPU_BUFFER_NORMAL, | ||||
| GPU_BUFFER_COLOR, | GPU_BUFFER_COLOR, | ||||
| GPU_BUFFER_UV, | GPU_BUFFER_UV, | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) | ||||
| const GPUBufferTypeSettings *ts; | const GPUBufferTypeSettings *ts; | ||||
| void *user_data = NULL; | void *user_data = NULL; | ||||
| GPUBuffer *buf; | GPUBuffer *buf; | ||||
| ts = &gpu_buffer_type_settings[type]; | ts = &gpu_buffer_type_settings[type]; | ||||
| /* special handling for MCol and UV buffers */ | /* special handling for MCol and UV buffers */ | ||||
| if (type == GPU_BUFFER_COLOR) { | if (type == GPU_BUFFER_COLOR) { | ||||
| if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType))) | if (!(user_data = DM_get_loop_data_layer(dm, dm->drawObject->colType))) | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) { | else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) { | ||||
| if (!DM_get_tessface_data_layer(dm, CD_MTFACE)) | if (!DM_get_loop_data_layer(dm, CD_MLOOPUV)) | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size, | buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size, | ||||
| gpu_buffer_size_from_type(dm, type), | gpu_buffer_size_from_type(dm, type), | ||||
| ts->gl_buffer_type, user_data, ts->copy); | ts->gl_buffer_type, user_data, ts->copy); | ||||
| return buf; | return buf; | ||||
| ▲ Show 20 Lines • Show All 376 Lines • ▼ Show 20 Lines | |||||
| } VertexBufferFormat; | } VertexBufferFormat; | ||||
| struct GPU_PBVH_Buffers { | struct GPU_PBVH_Buffers { | ||||
| /* opengl buffer handles */ | /* opengl buffer handles */ | ||||
| GLuint vert_buf, index_buf; | GLuint vert_buf, index_buf; | ||||
| GLenum index_type; | GLenum index_type; | ||||
| /* mesh pointers in case buffer allocation fails */ | /* mesh pointers in case buffer allocation fails */ | ||||
| const MFace *mface; | const MPoly *mpoly; | ||||
| const MLoop *mloop; | |||||
| const MLoopTri *looptri; | |||||
| const MVert *mvert; | const MVert *mvert; | ||||
| const int *face_indices; | const int *face_indices; | ||||
| int totface; | int totface; | ||||
| const float *vmask; | const float *vmask; | ||||
| /* grid pointers */ | /* grid pointers */ | ||||
| CCGKey gridkey; | CCGKey gridkey; | ||||
| CCGElem **grids; | CCGElem **grids; | ||||
| ▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| void GPU_update_mesh_pbvh_buffers( | void GPU_update_mesh_pbvh_buffers( | ||||
| GPU_PBVH_Buffers *buffers, const MVert *mvert, | GPU_PBVH_Buffers *buffers, const MVert *mvert, | ||||
| const int *vert_indices, int totvert, const float *vmask, | const int *vert_indices, int totvert, const float *vmask, | ||||
| const int (*face_vert_indices)[4], bool show_diffuse_color) | const int (*face_vert_indices)[4], bool show_diffuse_color) | ||||
| { | { | ||||
| VertexBufferFormat *vert_data; | VertexBufferFormat *vert_data; | ||||
| int i, j, k; | int i, j; | ||||
| buffers->vmask = vmask; | buffers->vmask = vmask; | ||||
| buffers->show_diffuse_color = show_diffuse_color; | buffers->show_diffuse_color = show_diffuse_color; | ||||
| buffers->use_matcaps = GPU_material_use_matcaps_get(); | buffers->use_matcaps = GPU_material_use_matcaps_get(); | ||||
| if (buffers->vert_buf) { | if (buffers->vert_buf) { | ||||
| int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); | int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); | ||||
| float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f}; | float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f}; | ||||
| if (buffers->use_matcaps) | if (buffers->use_matcaps) | ||||
| diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; | diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; | ||||
| else if (show_diffuse_color) { | else if (show_diffuse_color) { | ||||
| const MFace *f = buffers->mface + buffers->face_indices[0]; | const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; | ||||
| const MPoly *mp = &buffers->mpoly[lt->poly]; | |||||
| GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); | GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color); | ||||
| } | } | ||||
| copy_v4_v4(buffers->diffuse_color, diffuse_color); | copy_v4_v4(buffers->diffuse_color, diffuse_color); | ||||
| /* Build VBO */ | /* Build VBO */ | ||||
| glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); | glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); | ||||
| glBufferDataARB(GL_ARRAY_BUFFER_ARB, | glBufferDataARB(GL_ARRAY_BUFFER_ARB, | ||||
| sizeof(VertexBufferFormat) * totelem, | sizeof(VertexBufferFormat) * totelem, | ||||
| Show All 19 Lines | #define UPDATE_VERTEX(face, vertex, index, diffuse_color) \ | ||||
| VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \ | VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \ | ||||
| if (vmask) \ | if (vmask) \ | ||||
| gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \ | gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \ | ||||
| else \ | else \ | ||||
| rgb_float_to_uchar(out->color, diffuse_color); \ | rgb_float_to_uchar(out->color, diffuse_color); \ | ||||
| } (void)0 | } (void)0 | ||||
| for (i = 0; i < buffers->totface; i++) { | for (i = 0; i < buffers->totface; i++) { | ||||
| const MFace *f = buffers->mface + buffers->face_indices[i]; | const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; | ||||
| const unsigned int vtri[3] = { | |||||
| buffers->mloop[lt->tri[0]].v, | |||||
| buffers->mloop[lt->tri[1]].v, | |||||
| buffers->mloop[lt->tri[2]].v, | |||||
| }; | |||||
| UPDATE_VERTEX(i, f->v1, 0, diffuse_color); | UPDATE_VERTEX(i, vtri[0], 0, diffuse_color); | ||||
| UPDATE_VERTEX(i, f->v2, 1, diffuse_color); | UPDATE_VERTEX(i, vtri[1], 1, diffuse_color); | ||||
| UPDATE_VERTEX(i, f->v3, 2, diffuse_color); | UPDATE_VERTEX(i, vtri[2], 2, diffuse_color); | ||||
| if (f->v4) | |||||
| UPDATE_VERTEX(i, f->v4, 3, diffuse_color); | |||||
| } | } | ||||
| #undef UPDATE_VERTEX | #undef UPDATE_VERTEX | ||||
| } | } | ||||
| else { | else { | ||||
| for (i = 0; i < buffers->totface; ++i) { | for (i = 0; i < buffers->totface; ++i) { | ||||
| const MFace *f = &buffers->mface[buffers->face_indices[i]]; | const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; | ||||
| const unsigned int *fv = &f->v1; | const unsigned int vtri[3] = { | ||||
| const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}}; | buffers->mloop[lt->tri[0]].v, | ||||
| buffers->mloop[lt->tri[1]].v, | |||||
| buffers->mloop[lt->tri[2]].v, | |||||
| }; | |||||
| float fno[3]; | float fno[3]; | ||||
| short no[3]; | short no[3]; | ||||
| float fmask; | float fmask; | ||||
| if (paint_is_face_hidden(f, mvert)) | if (paint_is_face_hidden(lt, mvert, buffers->mloop)) | ||||
| continue; | continue; | ||||
| /* Face normal and mask */ | /* Face normal and mask */ | ||||
| if (f->v4) { | |||||
| normal_quad_v3(fno, | |||||
| mvert[fv[0]].co, | |||||
| mvert[fv[1]].co, | |||||
| mvert[fv[2]].co, | |||||
| mvert[fv[3]].co); | |||||
| if (vmask) { | |||||
| fmask = (vmask[fv[0]] + | |||||
| vmask[fv[1]] + | |||||
| vmask[fv[2]] + | |||||
| vmask[fv[3]]) * 0.25f; | |||||
| } | |||||
| } | |||||
| else { | |||||
| normal_tri_v3(fno, | normal_tri_v3(fno, | ||||
| mvert[fv[0]].co, | mvert[vtri[0]].co, | ||||
| mvert[fv[1]].co, | mvert[vtri[1]].co, | ||||
| mvert[fv[2]].co); | mvert[vtri[2]].co); | ||||
| if (vmask) { | if (vmask) { | ||||
| fmask = (vmask[fv[0]] + | fmask = (vmask[vtri[0]] + | ||||
| vmask[fv[1]] + | vmask[vtri[1]] + | ||||
| vmask[fv[2]]) / 3.0f; | vmask[vtri[2]]) / 3.0f; | ||||
| } | |||||
| } | } | ||||
| normal_float_to_short_v3(no, fno); | normal_float_to_short_v3(no, fno); | ||||
| for (j = 0; j < (f->v4 ? 2 : 1); j++) { | for (j = 0; j < 3; j++) { | ||||
| for (k = 0; k < 3; k++) { | const MVert *v = &mvert[vtri[j]]; | ||||
| const MVert *v = &mvert[fv[vi[j][k]]]; | |||||
| VertexBufferFormat *out = vert_data; | VertexBufferFormat *out = vert_data; | ||||
| copy_v3_v3(out->co, v->co); | copy_v3_v3(out->co, v->co); | ||||
| memcpy(out->no, no, sizeof(short) * 3); | memcpy(out->no, no, sizeof(short) * 3); | ||||
| if (vmask) | if (vmask) | ||||
| gpu_color_from_mask_copy(fmask, diffuse_color, out->color); | gpu_color_from_mask_copy(fmask, diffuse_color, out->color); | ||||
| else | else | ||||
| rgb_float_to_uchar(out->color, diffuse_color); | rgb_float_to_uchar(out->color, diffuse_color); | ||||
| vert_data++; | vert_data++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); | glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); | ||||
| } | } | ||||
| else { | else { | ||||
| glDeleteBuffersARB(1, &buffers->vert_buf); | glDeleteBuffersARB(1, &buffers->vert_buf); | ||||
| buffers->vert_buf = 0; | buffers->vert_buf = 0; | ||||
| } | } | ||||
| glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); | glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); | ||||
| } | } | ||||
| buffers->mvert = mvert; | buffers->mvert = mvert; | ||||
| } | } | ||||
| GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( | GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( | ||||
| const int (*face_vert_indices)[4], | const int (*face_vert_indices)[4], | ||||
| const MFace *mface, const MVert *mvert, | const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri, | ||||
| const MVert *mvert, | |||||
| const int *face_indices, | const int *face_indices, | ||||
| int totface) | int looptri_num) | ||||
| { | { | ||||
| GPU_PBVH_Buffers *buffers; | GPU_PBVH_Buffers *buffers; | ||||
| unsigned short *tri_data; | unsigned short *tri_data; | ||||
| int i, j, k, tottri; | int i, j, tottri; | ||||
| buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); | buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); | ||||
| buffers->index_type = GL_UNSIGNED_SHORT; | buffers->index_type = GL_UNSIGNED_SHORT; | ||||
| buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH; | buffers->smooth = mpoly[face_indices[0]].flag & ME_SMOOTH; | ||||
| buffers->show_diffuse_color = false; | buffers->show_diffuse_color = false; | ||||
| buffers->use_matcaps = false; | buffers->use_matcaps = false; | ||||
| /* Count the number of visible triangles */ | /* Count the number of visible triangles */ | ||||
| for (i = 0, tottri = 0; i < totface; ++i) { | for (i = 0, tottri = 0; i < looptri_num; ++i) { | ||||
| const MFace *f = &mface[face_indices[i]]; | const MLoopTri *lt = &looptri[face_indices[i]]; | ||||
| if (!paint_is_face_hidden(f, mvert)) | if (!paint_is_face_hidden(lt, mvert, mloop)) | ||||
| tottri += f->v4 ? 2 : 1; | tottri++; | ||||
| } | } | ||||
| if (tottri == 0) { | if (tottri == 0) { | ||||
| buffers->tot_tri = 0; | buffers->tot_tri = 0; | ||||
| buffers->mface = mface; | buffers->mpoly = mpoly; | ||||
| buffers->mloop = mloop; | |||||
| buffers->looptri = looptri; | |||||
| buffers->face_indices = face_indices; | buffers->face_indices = face_indices; | ||||
| buffers->totface = 0; | buffers->totface = 0; | ||||
| return buffers; | return buffers; | ||||
| } | } | ||||
| /* An element index buffer is used for smooth shading, but flat | /* An element index buffer is used for smooth shading, but flat | ||||
| * shading requires separate vertex normals so an index buffer is | * shading requires separate vertex normals so an index buffer is | ||||
| * can't be used there. */ | * can't be used there. */ | ||||
| if (gpu_vbo_enabled() && buffers->smooth) | if (gpu_vbo_enabled() && buffers->smooth) | ||||
| glGenBuffersARB(1, &buffers->index_buf); | glGenBuffersARB(1, &buffers->index_buf); | ||||
| if (buffers->index_buf) { | if (buffers->index_buf) { | ||||
| /* Generate index buffer object */ | /* Generate index buffer object */ | ||||
| glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | ||||
| glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, | glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, | ||||
| sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB); | sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB); | ||||
| /* Fill the triangle buffer */ | /* Fill the triangle buffer */ | ||||
| tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); | tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); | ||||
| if (tri_data) { | if (tri_data) { | ||||
| for (i = 0; i < totface; ++i) { | for (i = 0; i < looptri_num; ++i) { | ||||
| const MFace *f = mface + face_indices[i]; | const MLoopTri *lt = &looptri[face_indices[i]]; | ||||
| int v[3]; | |||||
| /* Skip hidden faces */ | /* Skip hidden faces */ | ||||
| if (paint_is_face_hidden(f, mvert)) | if (paint_is_face_hidden(lt, mvert, mloop)) | ||||
| continue; | continue; | ||||
| v[0] = 0; | for (j = 0; j < 3; ++j) { | ||||
| v[1] = 1; | *tri_data = face_vert_indices[i][j]; | ||||
| v[2] = 2; | |||||
| for (j = 0; j < (f->v4 ? 2 : 1); ++j) { | |||||
| for (k = 0; k < 3; ++k) { | |||||
| *tri_data = face_vert_indices[i][v[k]]; | |||||
| tri_data++; | tri_data++; | ||||
| } | } | ||||
| v[0] = 3; | |||||
| v[1] = 0; | |||||
| v[2] = 2; | |||||
| } | |||||
| } | } | ||||
| glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); | glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); | ||||
| } | } | ||||
| else { | else { | ||||
| glDeleteBuffersARB(1, &buffers->index_buf); | glDeleteBuffersARB(1, &buffers->index_buf); | ||||
| buffers->index_buf = 0; | buffers->index_buf = 0; | ||||
| } | } | ||||
| glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); | ||||
| } | } | ||||
| if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth)) | if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth)) | ||||
| glGenBuffersARB(1, &buffers->vert_buf); | glGenBuffersARB(1, &buffers->vert_buf); | ||||
| buffers->tot_tri = tottri; | buffers->tot_tri = tottri; | ||||
| buffers->mface = mface; | buffers->mpoly = mpoly; | ||||
| buffers->mloop = mloop; | |||||
| buffers->looptri = looptri; | |||||
| buffers->face_indices = face_indices; | buffers->face_indices = face_indices; | ||||
| buffers->totface = totface; | buffers->totface = looptri_num; | ||||
| return buffers; | return buffers; | ||||
| } | } | ||||
| void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, | void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, | ||||
| const DMFlagMat *grid_flag_mats, int *grid_indices, | const DMFlagMat *grid_flag_mats, int *grid_indices, | ||||
| int totgrid, const CCGKey *key, bool show_diffuse_color) | int totgrid, const CCGKey *key, bool show_diffuse_color) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 539 Lines • ▼ Show 20 Lines | GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading) | ||||
| return buffers; | return buffers; | ||||
| } | } | ||||
| static void gpu_draw_buffers_legacy_mesh(GPU_PBVH_Buffers *buffers) | static void gpu_draw_buffers_legacy_mesh(GPU_PBVH_Buffers *buffers) | ||||
| { | { | ||||
| const MVert *mvert = buffers->mvert; | const MVert *mvert = buffers->mvert; | ||||
| int i, j; | int i, j; | ||||
| const int has_mask = (buffers->vmask != NULL); | const int has_mask = (buffers->vmask != NULL); | ||||
| const MFace *face = &buffers->mface[buffers->face_indices[0]]; | const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; | ||||
| const MPoly *mp = &buffers->mpoly[lt->poly]; | |||||
| float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; | float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; | ||||
| if (buffers->use_matcaps) | if (buffers->use_matcaps) | ||||
| diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; | diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; | ||||
| else if (buffers->show_diffuse_color) | else if (buffers->show_diffuse_color) | ||||
| GPU_material_diffuse_get(face->mat_nr + 1, diffuse_color); | GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color); | ||||
| if (has_mask) { | if (has_mask) { | ||||
| gpu_colors_enable(VBO_DISABLED); | gpu_colors_enable(VBO_DISABLED); | ||||
| } | } | ||||
| for (i = 0; i < buffers->totface; ++i) { | for (i = 0; i < buffers->totface; ++i) { | ||||
| const MFace *f = &buffers->mface[buffers->face_indices[i]]; | const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; | ||||
| int S = f->v4 ? 4 : 3; | int sides = 3; | ||||
| const unsigned int *fv = &f->v1; | const unsigned int vtri[3] = { | ||||
| buffers->mloop[lt->tri[0]].v, | |||||
| buffers->mloop[lt->tri[1]].v, | |||||
| buffers->mloop[lt->tri[2]].v, | |||||
| }; | |||||
| if (paint_is_face_hidden(f, buffers->mvert)) | if (paint_is_face_hidden(lt, buffers->mvert, buffers->mloop)) | ||||
| continue; | continue; | ||||
| glBegin((f->v4) ? GL_QUADS : GL_TRIANGLES); | glBegin(GL_TRIANGLES); | ||||
| if (buffers->smooth) { | if (buffers->smooth) { | ||||
| for (j = 0; j < S; j++) { | for (j = 0; j < sides; j++) { | ||||
| if (has_mask) { | if (has_mask) { | ||||
| gpu_color_from_mask_set(buffers->vmask[fv[j]], diffuse_color); | gpu_color_from_mask_set(buffers->vmask[vtri[j]], diffuse_color); | ||||
| } | } | ||||
| glNormal3sv(mvert[fv[j]].no); | glNormal3sv(mvert[vtri[j]].no); | ||||
| glVertex3fv(mvert[fv[j]].co); | glVertex3fv(mvert[vtri[j]].co); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| float fno[3]; | float fno[3]; | ||||
| /* calculate face normal */ | /* calculate face normal */ | ||||
| if (f->v4) { | normal_tri_v3(fno, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co); | ||||
| normal_quad_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co, | |||||
| mvert[fv[2]].co, mvert[fv[3]].co); | |||||
| } | |||||
| else | |||||
| normal_tri_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co, mvert[fv[2]].co); | |||||
| glNormal3fv(fno); | glNormal3fv(fno); | ||||
| if (has_mask) { | if (has_mask) { | ||||
| float fmask; | float fmask; | ||||
| /* calculate face mask color */ | /* calculate face mask color */ | ||||
| fmask = (buffers->vmask[fv[0]] + | fmask = (buffers->vmask[vtri[0]] + | ||||
| buffers->vmask[fv[1]] + | buffers->vmask[vtri[1]] + | ||||
| buffers->vmask[fv[2]]); | buffers->vmask[vtri[2]]) / 3.0f; | ||||
| if (f->v4) | |||||
| fmask = (fmask + buffers->vmask[fv[3]]) * 0.25f; | |||||
| else | |||||
| fmask /= 3.0f; | |||||
| gpu_color_from_mask_set(fmask, diffuse_color); | gpu_color_from_mask_set(fmask, diffuse_color); | ||||
| } | } | ||||
| for (j = 0; j < S; j++) | for (j = 0; j < sides; j++) | ||||
| glVertex3fv(mvert[fv[j]].co); | glVertex3fv(mvert[vtri[j]].co); | ||||
| } | } | ||||
| glEnd(); | glEnd(); | ||||
| } | } | ||||
| if (has_mask) { | if (has_mask) { | ||||
| gpu_colors_disable(VBO_DISABLED); | gpu_colors_disable(VBO_DISABLED); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | |||||
| void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, | void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, | ||||
| bool wireframe) | bool wireframe) | ||||
| { | { | ||||
| /* sets material from the first face, to solve properly face would need to | /* sets material from the first face, to solve properly face would need to | ||||
| * be sorted in buckets by materials */ | * be sorted in buckets by materials */ | ||||
| if (setMaterial) { | if (setMaterial) { | ||||
| if (buffers->totface) { | if (buffers->totface) { | ||||
| const MFace *f = &buffers->mface[buffers->face_indices[0]]; | const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; | ||||
| if (!setMaterial(f->mat_nr + 1, NULL)) | const MPoly *mp = &buffers->mpoly[lt->poly]; | ||||
| if (!setMaterial(mp->mat_nr + 1, NULL)) | |||||
| return; | return; | ||||
| } | } | ||||
| else if (buffers->totgrid) { | else if (buffers->totgrid) { | ||||
| const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]]; | const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]]; | ||||
| if (!setMaterial(f->mat_nr + 1, NULL)) | if (!setMaterial(f->mat_nr + 1, NULL)) | ||||
| return; | return; | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | if (buffers->show_diffuse_color != show_diffuse_color) | ||||
| return true; | return true; | ||||
| if (buffers->use_matcaps != use_matcaps) | if (buffers->use_matcaps != use_matcaps) | ||||
| return true; | return true; | ||||
| if ((buffers->show_diffuse_color == false) || use_matcaps) | if ((buffers->show_diffuse_color == false) || use_matcaps) | ||||
| return false; | return false; | ||||
| if (buffers->mface) { | if (buffers->looptri) { | ||||
| const MFace *f = &buffers->mface[buffers->face_indices[0]]; | const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; | ||||
| const MPoly *mp = &buffers->mpoly[lt->poly]; | |||||
| GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); | GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color); | ||||
| } | } | ||||
| else if (buffers->use_bmesh) { | else if (buffers->use_bmesh) { | ||||
| /* due to dynamic nature of dyntopo, only get first material */ | /* due to dynamic nature of dyntopo, only get first material */ | ||||
| if (BLI_gset_size(bm_faces) > 0) { | if (BLI_gset_size(bm_faces) > 0) { | ||||
| GSetIterator gs_iter; | GSetIterator gs_iter; | ||||
| BMFace *f; | BMFace *f; | ||||
| BLI_gsetIterator_init(&gs_iter, bm_faces); | BLI_gsetIterator_init(&gs_iter, bm_faces); | ||||
| ▲ Show 20 Lines • Show All 126 Lines • Show Last 20 Lines | |||||