Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/dynamicpaint.c
| Context not available. | |||||
| /* UV Image sequence format point */ | /* UV Image sequence format point */ | ||||
| typedef struct PaintUVPoint { | typedef struct PaintUVPoint { | ||||
| /* Pixel / mesh data */ | /* Pixel / mesh data */ | ||||
| unsigned int face_index, pixel_index; /* face index on domain derived mesh */ | unsigned int tri_index, pixel_index; /* tri index on domain derived mesh */ | ||||
| unsigned int v1, v2, v3; /* vertex indexes */ | unsigned int v1, v2, v3; /* vertex indexes */ | ||||
| unsigned int neighbour_pixel; /* If this pixel isn't uv mapped to any face, | unsigned int neighbour_pixel; /* If this pixel isn't uv mapped to any face, | ||||
| * but it's neighboring pixel is */ | * but it's neighboring pixel is */ | ||||
| short quad; | |||||
| } PaintUVPoint; | } PaintUVPoint; | ||||
| typedef struct ImgSeqFormatData { | typedef struct ImgSeqFormatData { | ||||
| Context not available. | |||||
| /* UV mapped texture */ | /* UV mapped texture */ | ||||
| else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) { | else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) { | ||||
| Tex *tex = surface->init_texture; | Tex *tex = surface->init_texture; | ||||
| MTFace *tface; | |||||
| MFace *mface = dm->getTessFaceArray(dm); | MLoop *mloop = dm->getLoopArray(dm); | ||||
| int numOfFaces = dm->getNumTessFaces(dm); | const MLoopTri *mlooptri = dm->getLoopTriArray(dm); | ||||
| int tottri = dm->getNumLoopTri(dm); | |||||
| MLoopUV *mloopuv = NULL; | |||||
| char uvname[MAX_CUSTOMDATA_LAYER_NAME]; | char uvname[MAX_CUSTOMDATA_LAYER_NAME]; | ||||
| if (!tex) return; | if (!tex) return; | ||||
| /* get uv map */ | /* get uv map */ | ||||
| CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->init_layername, uvname); | CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, surface->init_layername, uvname); | ||||
| tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); | mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, uvname); | ||||
| if (!tface) return; | if (!mloopuv) return; | ||||
| /* for vertex surface loop through tfaces and find uv color | /* for vertex surface loop through tfaces and find uv color | ||||
| * that provides highest alpha */ | * that provides highest alpha */ | ||||
| Context not available. | |||||
| struct ImagePool *pool = BKE_image_pool_new(); | struct ImagePool *pool = BKE_image_pool_new(); | ||||
| #pragma omp parallel for schedule(static) shared(pool) | #pragma omp parallel for schedule(static) shared(pool) | ||||
| for (i = 0; i < numOfFaces; i++) { | for (i = 0; i < tottri; i++) { | ||||
| int numOfVert = (mface[i].v4) ? 4 : 3; | |||||
| float uv[3] = {0.0f}; | float uv[3] = {0.0f}; | ||||
| int j; | int j; | ||||
| for (j = 0; j < numOfVert; j++) { | for (j = 0; j < 3; j++) { | ||||
| TexResult texres = {0}; | TexResult texres = {0}; | ||||
| unsigned int *vert = (&mface[i].v1) + j; | // unsure about syntax?! | ||||
| unsigned int *vert = (&mloop[mlooptri[i].tri[j]].v) + j; | |||||
| /* remap to -1.0 to 1.0 */ | /* remap to -1.0 to 1.0 */ | ||||
| uv[0] = tface[i].uv[j][0] * 2.0f - 1.0f; | uv[0] = mloopuv[mlooptri[i].tri[j]].uv[0] * 2.0f - 1.0f; | ||||
| uv[1] = tface[i].uv[j][1] * 2.0f - 1.0f; | uv[1] = mloopuv[mlooptri[i].tri[j]].uv[1] * 2.0f - 1.0f; | ||||
| multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false); | multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false); | ||||
| Context not available. | |||||
| /* collect all uvs */ | /* collect all uvs */ | ||||
| for (j = 0; j < 3; j++) { | for (j = 0; j < 3; j++) { | ||||
| int v = (f_data->uv_p[i].quad && j > 0) ? j + 1 : j; | copy_v2_v2(&uv[j * 3], mloopuv[mlooptri[f_data->uv_p[i].tri_index].tri[j]].uv); | ||||
| copy_v2_v2(&uv[j * 3], tface[f_data->uv_p[i].face_index].uv[v]); | |||||
| } | } | ||||
| /* interpolate final uv pos */ | /* interpolate final uv pos */ | ||||
| Context not available. | |||||
| /* for vertex surface, just copy colors from mcol */ | /* for vertex surface, just copy colors from mcol */ | ||||
| if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { | ||||
| MLoop *mloop = dm->getLoopArray(dm); | MLoop *mloop = dm->getLoopArray(dm); | ||||
| int numOfLoops = dm->getNumLoops(dm); | int totloop = dm->getNumLoops(dm); | ||||
| MCol *col = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, surface->init_layername); | MCol *col = CustomData_get_layer_named(&dm->loopData, CD_MLOOPCOL, surface->init_layername); | ||||
| if (!col) return; | if (!col) return; | ||||
| #pragma omp parallel for schedule(static) | #pragma omp parallel for schedule(static) | ||||
| for (i = 0; i < numOfLoops; i++) { | for (i = 0; i < totloop; i++) { | ||||
| pPoint[mloop[i].v].color[0] = 1.0f / 255.f * (float)col[i].b; | pPoint[mloop[i].v].color[0] = 1.0f / 255.f * (float)col[i].b; | ||||
| pPoint[mloop[i].v].color[1] = 1.0f / 255.f * (float)col[i].g; | pPoint[mloop[i].v].color[1] = 1.0f / 255.f * (float)col[i].g; | ||||
| pPoint[mloop[i].v].color[2] = 1.0f / 255.f * (float)col[i].r; | pPoint[mloop[i].v].color[2] = 1.0f / 255.f * (float)col[i].r; | ||||
| Context not available. | |||||
| else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { | ||||
| ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; | ||||
| int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; | int samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; | ||||
| // should this be replaced by CD_MLOOPCOL? | |||||
| MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername); | MCol *col = CustomData_get_layer_named(&dm->faceData, CD_MCOL, surface->init_layername); | ||||
| if (!col) return; | if (!col) return; | ||||
| #pragma omp parallel for schedule(static) | #pragma omp parallel for schedule(static) | ||||
| for (i = 0; i < sData->total_points; i++) { | for (i = 0; i < sData->total_points; i++) { | ||||
| int face_ind = f_data->uv_p[i].face_index; | int face_ind = f_data->uv_p[i].tri_index; | ||||
| float colors[3][4] = {{0.0f, 0.0f, 0.0f, 0.0f}}; | float colors[3][4] = {{0.0f, 0.0f, 0.0f, 0.0f}}; | ||||
| float final_color[4]; | float final_color[4]; | ||||
| int j; | int j; | ||||
| /* collect color values */ | /* collect color values */ | ||||
| for (j = 0; j < 3; j++) { | for (j = 0; j < 3; j++) { | ||||
| int v = (f_data->uv_p[i].quad && j > 0) ? j + 1 : j; | colors[j][0] = 1.0f / 255.f * (float)col[face_ind * 4 + j].b; | ||||
| colors[j][0] = 1.0f / 255.f * (float)col[face_ind * 4 + v].b; | colors[j][1] = 1.0f / 255.f * (float)col[face_ind * 4 + j].g; | ||||
| colors[j][1] = 1.0f / 255.f * (float)col[face_ind * 4 + v].g; | colors[j][2] = 1.0f / 255.f * (float)col[face_ind * 4 + j].r; | ||||
| colors[j][2] = 1.0f / 255.f * (float)col[face_ind * 4 + v].r; | colors[j][3] = 1.0f / 255.f * (float)col[face_ind * 4 + j].a; | ||||
| colors[j][3] = 1.0f / 255.f * (float)col[face_ind * 4 + v].a; | |||||
| } | } | ||||
| /* interpolate final color */ | /* interpolate final color */ | ||||
| Context not available. | |||||
| * Check if shifted point is on same face -> it's a correct neighbor | * Check if shifted point is on same face -> it's a correct neighbor | ||||
| * (and if it isn't marked as an "edge pixel") | * (and if it isn't marked as an "edge pixel") | ||||
| */ | */ | ||||
| if ((tPoint->face_index == cPoint->face_index) && (tPoint->neighbour_pixel == -1)) | if ((tPoint->tri_index == cPoint->tri_index) && (tPoint->neighbour_pixel == -1)) | ||||
| return (x + w * y); | return (x + w * y); | ||||
| /* | /* | ||||
| Context not available. | |||||
| * This should work fine as long as uv island | * This should work fine as long as uv island | ||||
| * margin is > 1 pixel. | * margin is > 1 pixel. | ||||
| */ | */ | ||||
| if ((tPoint->face_index != -1) && (tPoint->neighbour_pixel == -1)) { | if ((tPoint->tri_index != -1) && (tPoint->neighbour_pixel == -1)) { | ||||
| return (x + w * y); | return (x + w * y); | ||||
| } | } | ||||
| Context not available. | |||||
| * TODO: Implement something more accurate / optimized? | * TODO: Implement something more accurate / optimized? | ||||
| */ | */ | ||||
| { | { | ||||
| int numOfFaces = dm->getNumTessFaces(dm); | MLoop *mloop = dm->getLoopArray(dm); | ||||
| MFace *mface = dm->getTessFaceArray(dm); | const MLoopTri *mlooptri = dm->getLoopTriArray(dm); | ||||
| MTFace *tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); | int tottri = dm->getNumLoopTri(dm); | ||||
| MLoopUV *mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, uvname); | |||||
| /* Get closest edge to that subpixel on UV map */ | /* Get closest edge to that subpixel on UV map */ | ||||
| { | { | ||||
| Context not available. | |||||
| /* distances only used for comparison */ | /* distances only used for comparison */ | ||||
| float dist_squared, t_dist_squared; | float dist_squared, t_dist_squared; | ||||
| int i, uindex[3], edge1_index, edge2_index, | int i, edge1_index, edge2_index, | ||||
| e1_index, e2_index, target_face; | e1_index, e2_index, target_tri; | ||||
| float closest_point[2], lambda, dir_vec[2]; | float closest_point[2], lambda, dir_vec[2]; | ||||
| int target_uv1, target_uv2, final_pixel[2], final_index; | int target_uv1, target_uv2, final_pixel[2], final_index; | ||||
| Context not available. | |||||
| pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w; | pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w; | ||||
| pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h; | pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h; | ||||
| /* Get uv indexes for current face part */ | |||||
| if (cPoint->quad) { | |||||
| uindex[0] = 0; uindex[1] = 2; uindex[2] = 3; | |||||
| } | |||||
| else { | |||||
| uindex[0] = 0; uindex[1] = 1; uindex[2] = 2; | |||||
| } | |||||
| /* | /* | ||||
| * Find closest edge to that pixel | * Find closest edge to that pixel | ||||
| */ | */ | ||||
| /* Dist to first edge */ | /* Dist to first edge */ | ||||
| e1_index = cPoint->v1; e2_index = cPoint->v2; edge1_index = uindex[0]; edge2_index = uindex[1]; | e1_index = cPoint->v1; | ||||
| dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]); | e2_index = cPoint->v2; | ||||
| edge1_index = 0; | |||||
| edge2_index = 1; | |||||
| dist_squared = dist_squared_to_line_segment_v2(pixel, | |||||
| mloopuv[mlooptri[cPoint->tri_index].tri[0]].uv, | |||||
| mloopuv[mlooptri[cPoint->tri_index].tri[1]].uv); | |||||
| /* Dist to second edge */ | /* Dist to second edge */ | ||||
| t_dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[1]], tface[cPoint->face_index].uv[uindex[2]]); | t_dist_squared = dist_squared_to_line_segment_v2(pixel, | ||||
| if (t_dist_squared < dist_squared) { e1_index = cPoint->v2; e2_index = cPoint->v3; edge1_index = uindex[1]; edge2_index = uindex[2]; dist_squared = t_dist_squared; } | mloopuv[mlooptri[cPoint->tri_index].tri[1]].uv, | ||||
| mloopuv[mlooptri[cPoint->tri_index].tri[2]].uv); | |||||
| if (t_dist_squared < dist_squared) { | |||||
| e1_index = cPoint->v2; | |||||
| e2_index = cPoint->v3; | |||||
| edge1_index = 1; | |||||
| edge2_index = 2; | |||||
| dist_squared = t_dist_squared; | |||||
| } | |||||
| /* Dist to third edge */ | /* Dist to third edge */ | ||||
| t_dist_squared = dist_squared_to_line_segment_v2(pixel, tface[cPoint->face_index].uv[uindex[2]], tface[cPoint->face_index].uv[uindex[0]]); | t_dist_squared = dist_squared_to_line_segment_v2(pixel, | ||||
| if (t_dist_squared < dist_squared) { e1_index = cPoint->v3; e2_index = cPoint->v1; edge1_index = uindex[2]; edge2_index = uindex[0]; dist_squared = t_dist_squared; } | mloopuv[mlooptri[cPoint->tri_index].tri[2]].uv, | ||||
| mloopuv[mlooptri[cPoint->tri_index].tri[0]].uv); | |||||
| if (t_dist_squared < dist_squared) { | |||||
| e1_index = cPoint->v3; | |||||
| e2_index = cPoint->v1; | |||||
| edge1_index = 2; | |||||
| edge2_index = 0; | |||||
| dist_squared = t_dist_squared; | |||||
| } | |||||
| /* | /* | ||||
| * Now find another face that is linked to that edge | * Now find another face that is linked to that edge | ||||
| * phi: could this be simpler? | |||||
| */ | */ | ||||
| target_face = -1; | target_tri = -1; | ||||
| for (i = 0; i < numOfFaces; i++) { | for (i = 0; i < tottri; i++) { | ||||
| /* | /* | ||||
| * Check if both edge vertices share this face | * Check if both edge vertices share this face | ||||
| */ | */ | ||||
| int v4 = (mface[i].v4) ? mface[i].v4 : -1; | if ((e1_index == mloop[mlooptri[i].tri[0]].v || e1_index == mloop[mlooptri[i].tri[1]].v || e1_index == mloop[mlooptri[i].tri[2]].v) && | ||||
| (e2_index == mloop[mlooptri[i].tri[0]].v || e2_index == mloop[mlooptri[i].tri[1]].v || e2_index == mloop[mlooptri[i].tri[2]].v)) | |||||
| if ((e1_index == mface[i].v1 || e1_index == mface[i].v2 || e1_index == mface[i].v3 || e1_index == v4) && | |||||
| (e2_index == mface[i].v1 || e2_index == mface[i].v2 || e2_index == mface[i].v3 || e2_index == v4)) | |||||
| { | { | ||||
| if (i == cPoint->face_index) continue; | if (i == cPoint->tri_index) continue; | ||||
| target_face = i; | target_tri = i; | ||||
| /* | /* | ||||
| * Get edge UV index | * Get edge UV index | ||||
| */ | */ | ||||
| if (e1_index == mface[i].v1) target_uv1 = 0; | if (e1_index == mloop[mlooptri[i].tri[0]].v) target_uv1 = 0; | ||||
| else if (e1_index == mface[i].v2) target_uv1 = 1; | else if (e1_index == mloop[mlooptri[i].tri[1]].v) target_uv1 = 1; | ||||
| else if (e1_index == mface[i].v3) target_uv1 = 2; | else if (e1_index == mloop[mlooptri[i].tri[2]].v) target_uv1 = 2; | ||||
| else target_uv1 = 3; | |||||
| if (e2_index == mface[i].v1) target_uv2 = 0; | if (e2_index == mloop[mlooptri[i].tri[0]].v) target_uv2 = 0; | ||||
| else if (e2_index == mface[i].v2) target_uv2 = 1; | else if (e2_index == mloop[mlooptri[i].tri[1]].v) target_uv2 = 1; | ||||
| else if (e2_index == mface[i].v3) target_uv2 = 2; | else if (e2_index == mloop[mlooptri[i].tri[2]].v) target_uv2 = 2; | ||||
| else target_uv2 = 3; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| /* If none found pixel is on mesh edge */ | /* If none found pixel is on mesh edge */ | ||||
| if (target_face == -1) return ON_MESH_EDGE; | if (target_tri == -1) return ON_MESH_EDGE; | ||||
| /* | /* | ||||
| * If target face is connected in UV space as well, just use original index | * If target face is connected in UV space as well, just use original index | ||||
| */ | */ | ||||
| s_uv1 = (float *)tface[cPoint->face_index].uv[edge1_index]; | s_uv1 = (float *)mloopuv[mlooptri[cPoint->tri_index].tri[edge1_index]].uv; | ||||
| s_uv2 = (float *)tface[cPoint->face_index].uv[edge2_index]; | s_uv2 = (float *)mloopuv[mlooptri[cPoint->tri_index].tri[edge2_index]].uv; | ||||
| t_uv1 = (float *)tface[target_face].uv[target_uv1]; | t_uv1 = (float *)mloopuv[mlooptri[target_tri].tri[target_uv1]].uv; | ||||
| t_uv2 = (float *)tface[target_face].uv[target_uv2]; | t_uv2 = (float *)mloopuv[mlooptri[target_tri].tri[target_uv2]].uv; | ||||
| //printf("connected UV : %f,%f & %f,%f - %f,%f & %f,%f\n", s_uv1[0], s_uv1[1], s_uv2[0], s_uv2[1], t_uv1[0], t_uv1[1], t_uv2[0], t_uv2[1]); | //printf("connected UV : %f,%f & %f,%f - %f,%f & %f,%f\n", s_uv1[0], s_uv1[1], s_uv2[0], s_uv2[1], t_uv1[0], t_uv1[1], t_uv2[0], t_uv2[1]); | ||||
| Context not available. | |||||
| * Find a point that is relatively at same edge position | * Find a point that is relatively at same edge position | ||||
| * on this other face UV | * on this other face UV | ||||
| */ | */ | ||||
| lambda = closest_to_line_v2(closest_point, pixel, tface[cPoint->face_index].uv[edge1_index], tface[cPoint->face_index].uv[edge2_index]); | lambda = closest_to_line_v2(closest_point, pixel, | ||||
| mloopuv[mlooptri[cPoint->tri_index].tri[edge1_index]].uv, | |||||
| mloopuv[mlooptri[cPoint->tri_index].tri[edge2_index]].uv); | |||||
| if (lambda < 0.0f) lambda = 0.0f; | if (lambda < 0.0f) lambda = 0.0f; | ||||
| if (lambda > 1.0f) lambda = 1.0f; | if (lambda > 1.0f) lambda = 1.0f; | ||||
| sub_v2_v2v2(dir_vec, tface[target_face].uv[target_uv2], tface[target_face].uv[target_uv1]); | sub_v2_v2v2(dir_vec, mloopuv[mlooptri[target_tri].tri[target_uv2]].uv, mloopuv[mlooptri[target_tri].tri[target_uv1]].uv); | ||||
| mul_v2_fl(dir_vec, lambda); | mul_v2_fl(dir_vec, lambda); | ||||
| copy_v2_v2(pixel, tface[target_face].uv[target_uv1]); | copy_v2_v2(pixel, mloopuv[mlooptri[target_tri].tri[target_uv1]].uv); | ||||
| add_v2_v2(pixel, dir_vec); | add_v2_v2(pixel, dir_vec); | ||||
| pixel[0] = (pixel[0] * (float)w) - 0.5f; | pixel[0] = (pixel[0] * (float)w) - 0.5f; | ||||
| pixel[1] = (pixel[1] * (float)h) - 0.5f; | pixel[1] = (pixel[1] * (float)h) - 0.5f; | ||||
| Context not available. | |||||
| /* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */ | /* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */ | ||||
| if (final_index == (px + w * py)) return NOT_FOUND; | if (final_index == (px + w * py)) return NOT_FOUND; | ||||
| /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */ | /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */ | ||||
| if (tempPoints[final_index].face_index != target_face) return NOT_FOUND; | if (tempPoints[final_index].tri_index != target_tri) return NOT_FOUND; | ||||
| /* | /* | ||||
| * If final point is an "edge pixel", use it's "real" neighbor instead | * If final point is an "edge pixel", use it's "real" neighbor instead | ||||
| Context not available. | |||||
| }; | }; | ||||
| int ty; | int ty; | ||||
| int w, h; | int w, h; | ||||
| int numOfFaces; | int tottri; | ||||
| char uvname[MAX_CUSTOMDATA_LAYER_NAME]; | char uvname[MAX_CUSTOMDATA_LAYER_NAME]; | ||||
| int active_points = 0; | int active_points = 0; | ||||
| int error = 0; | int error = 0; | ||||
| Context not available. | |||||
| PaintUVPoint *tempPoints = NULL; | PaintUVPoint *tempPoints = NULL; | ||||
| Vec3f *tempWeights = NULL; | Vec3f *tempWeights = NULL; | ||||
| MFace *mface = NULL; | const MLoopTri *mlooptri = NULL; | ||||
| MTFace *tface = NULL; | MLoopUV *mloopuv = NULL; | ||||
| MLoop *mloop = NULL; | |||||
| Bounds2D *faceBB = NULL; | Bounds2D *faceBB = NULL; | ||||
| int *final_index; | int *final_index; | ||||
| int aa_samples; | int aa_samples; | ||||
| Context not available. | |||||
| if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) | if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) | ||||
| return setError(canvas, N_("Cannot bake non-'image sequence' formats")); | return setError(canvas, N_("Cannot bake non-'image sequence' formats")); | ||||
| numOfFaces = dm->getNumTessFaces(dm); | mloop = dm->getLoopArray(dm); | ||||
| mface = dm->getTessFaceArray(dm); | mlooptri = dm->getLoopTriArray(dm); | ||||
| tottri = dm->getNumLoopTri(dm); | |||||
| /* get uv map */ | /* get uv map */ | ||||
| CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, surface->uvlayer_name, uvname); | CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, surface->uvlayer_name, uvname); | ||||
| tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); | mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, uvname); | ||||
| /* Check for validity */ | /* Check for validity */ | ||||
| if (!tface) | if (!mloopuv) | ||||
| return setError(canvas, N_("No UV data on canvas")); | return setError(canvas, N_("No UV data on canvas")); | ||||
| if (surface->image_resolution < 16 || surface->image_resolution > 8192) | if (surface->image_resolution < 16 || surface->image_resolution > 8192) | ||||
| return setError(canvas, N_("Invalid resolution")); | return setError(canvas, N_("Invalid resolution")); | ||||
| Context not available. | |||||
| /* | /* | ||||
| * Start generating the surface | * Start generating the surface | ||||
| */ | */ | ||||
| printf("DynamicPaint: Preparing UV surface of %ix%i pixels and %i faces.\n", w, h, numOfFaces); | printf("DynamicPaint: Preparing UV surface of %ix%i pixels and %i tris.\n", w, h, tottri); | ||||
| /* Init data struct */ | /* Init data struct */ | ||||
| if (surface->data) dynamicPaint_freeSurfaceData(surface); | if (surface->data) dynamicPaint_freeSurfaceData(surface); | ||||
| Context not available. | |||||
| * the pixel-inside-a-face search. | * the pixel-inside-a-face search. | ||||
| */ | */ | ||||
| if (!error) { | if (!error) { | ||||
| faceBB = (struct Bounds2D *) MEM_mallocN(numOfFaces * sizeof(struct Bounds2D), "MPCanvasFaceBB"); | faceBB = (struct Bounds2D *) MEM_mallocN(tottri * sizeof(struct Bounds2D), "MPCanvasFaceBB"); | ||||
| if (!faceBB) error = 1; | if (!faceBB) error = 1; | ||||
| } | } | ||||
| if (!error) | if (!error) | ||||
| for (ty = 0; ty < numOfFaces; ty++) { | for (ty = 0; ty < tottri; ty++) { | ||||
| int numOfVert = (mface[ty].v4) ? 4 : 3; | |||||
| int i; | int i; | ||||
| copy_v2_v2(faceBB[ty].min, tface[ty].uv[0]); | copy_v2_v2(faceBB[ty].min, mloopuv[mlooptri[ty].tri[0]].uv); | ||||
| copy_v2_v2(faceBB[ty].max, tface[ty].uv[0]); | copy_v2_v2(faceBB[ty].max, mloopuv[mlooptri[ty].tri[0]].uv); | ||||
| for (i = 1; i < numOfVert; i++) { | for (i = 1; i < 3; i++) { | ||||
| if (tface[ty].uv[i][0] < faceBB[ty].min[0]) faceBB[ty].min[0] = tface[ty].uv[i][0]; | if (mloopuv[mlooptri[ty].tri[i]].uv[0] < faceBB[ty].min[0]) faceBB[ty].min[0] = mloopuv[mlooptri[ty].tri[i]].uv[0]; | ||||
| if (tface[ty].uv[i][1] < faceBB[ty].min[1]) faceBB[ty].min[1] = tface[ty].uv[i][1]; | if (mloopuv[mlooptri[ty].tri[i]].uv[1] < faceBB[ty].min[1]) faceBB[ty].min[1] = mloopuv[mlooptri[ty].tri[i]].uv[1]; | ||||
| if (tface[ty].uv[i][0] > faceBB[ty].max[0]) faceBB[ty].max[0] = tface[ty].uv[i][0]; | if (mloopuv[mlooptri[ty].tri[i]].uv[0] > faceBB[ty].max[0]) faceBB[ty].max[0] = mloopuv[mlooptri[ty].tri[i]].uv[0]; | ||||
| if (tface[ty].uv[i][1] > faceBB[ty].max[1]) faceBB[ty].max[1] = tface[ty].uv[i][1]; | if (mloopuv[mlooptri[ty].tri[i]].uv[1] > faceBB[ty].max[1]) faceBB[ty].max[1] = mloopuv[mlooptri[ty].tri[i]].uv[1]; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| int index = tx + w * ty; | int index = tx + w * ty; | ||||
| PaintUVPoint *tPoint = (&tempPoints[index]); | PaintUVPoint *tPoint = (&tempPoints[index]); | ||||
| short isInside = 0; /* if point is inside a uv face */ | bool isInside = false; /* if point is inside a uv face */ | ||||
| float d1[2], d2[2], d3[2], point[5][2]; | float d1[2], d2[2], d3[2], point[5][2]; | ||||
| float dot00, dot01, dot02, dot11, dot12, invDenom, u, v; | float dot00, dot01, dot02, dot11, dot12, invDenom, u, v; | ||||
| /* Init per pixel settings */ | /* Init per pixel settings */ | ||||
| tPoint->face_index = -1; | tPoint->tri_index = -1; | ||||
| tPoint->neighbour_pixel = -1; | tPoint->neighbour_pixel = -1; | ||||
| tPoint->pixel_index = index; | tPoint->pixel_index = index; | ||||
| Context not available. | |||||
| for (sample = 0; sample < 5; sample++) { | for (sample = 0; sample < 5; sample++) { | ||||
| /* Loop through every face in the mesh */ | /* Loop through every face in the mesh */ | ||||
| for (i = 0; i < numOfFaces; i++) { | for (i = 0; i < tottri; i++) { | ||||
| /* Check uv bb */ | /* Check uv bb */ | ||||
| if (faceBB[i].min[0] > (point[sample][0])) continue; | if (faceBB[i].min[0] > (point[sample][0])) continue; | ||||
| Context not available. | |||||
| /* Calculate point inside a triangle check | /* Calculate point inside a triangle check | ||||
| * for uv0, 1, 2 */ | * for uv0, 1, 2 */ | ||||
| sub_v2_v2v2(d1, tface[i].uv[2], tface[i].uv[0]); // uv2 - uv0 | |||||
| sub_v2_v2v2(d2, tface[i].uv[1], tface[i].uv[0]); // uv1 - uv0 | // phi: isnt there something in Blender already for this? | ||||
| sub_v2_v2v2(d3, point[sample], tface[i].uv[0]); // point - uv0 | // somthing like isect_point_tri_v3? | ||||
| sub_v2_v2v2(d1, (float *)mloopuv[mlooptri[i].tri[2]].uv, (float *)mloopuv[mlooptri[i].tri[0]].uv); // uv2 - uv0 | |||||
| sub_v2_v2v2(d2, (float *)mloopuv[mlooptri[i].tri[1]].uv, (float *)mloopuv[mlooptri[i].tri[0]].uv); // uv1 - uv0 | |||||
| sub_v2_v2v2(d3, point[sample], (float *)mloopuv[mlooptri[i].tri[0]].uv); // point - uv0 | |||||
| dot00 = d1[0] * d1[0] + d1[1] * d1[1]; | dot00 = d1[0] * d1[0] + d1[1] * d1[1]; | ||||
| dot01 = d1[0] * d2[0] + d1[1] * d2[1]; | dot01 = d1[0] * d2[0] + d1[1] * d2[1]; | ||||
| Context not available. | |||||
| u = (dot11 * dot02 - dot01 * dot12) * invDenom; | u = (dot11 * dot02 - dot01 * dot12) * invDenom; | ||||
| v = (dot00 * dot12 - dot01 * dot02) * invDenom; | v = (dot00 * dot12 - dot01 * dot02) * invDenom; | ||||
| if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = 1; } /* is inside a triangle */ | if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = true; } /* is inside a triangle */ | ||||
| /* If collision wasn't found but the face is a quad | /* If collision wasn't found but the face is a quad | ||||
| * do another check for the second half */ | * do another check for the second half */ | ||||
| if ((!isInside) && mface[i].v4) { | /* phi: code for quad removed here */ | ||||
| /* change d2 to test the other half */ | |||||
| sub_v2_v2v2(d2, tface[i].uv[3], tface[i].uv[0]); // uv3 - uv0 | |||||
| /* test again */ | |||||
| dot00 = d1[0] * d1[0] + d1[1] * d1[1]; | |||||
| dot01 = d1[0] * d2[0] + d1[1] * d2[1]; | |||||
| dot02 = d1[0] * d3[0] + d1[1] * d3[1]; | |||||
| dot11 = d2[0] * d2[0] + d2[1] * d2[1]; | |||||
| dot12 = d2[0] * d3[0] + d2[1] * d3[1]; | |||||
| invDenom = (dot00 * dot11 - dot01 * dot01); | |||||
| invDenom = invDenom ? 1.0f / invDenom : 1.0f; | |||||
| u = (dot11 * dot02 - dot01 * dot12) * invDenom; | |||||
| v = (dot00 * dot12 - dot01 * dot02) * invDenom; | |||||
| if ((u > 0) && (v > 0) && (u + v < 1)) { isInside = 2; } /* is inside the second half of the quad */ | |||||
| } | |||||
| /* | /* | ||||
| * If point was inside the face | * If point was inside the face | ||||
| */ | */ | ||||
| if (isInside != 0) { | if (isInside) { | ||||
| float uv1co[2], uv2co[2], uv3co[2], uv[2]; | float uv1co[2], uv2co[2], uv3co[2], uv[2]; | ||||
| int j; | int j; | ||||
| /* Get triagnle uvs */ | /* Get triagnle uvs */ | ||||
| if (isInside == 1) { | copy_v2_v2(uv1co, (float *)mloopuv[mlooptri[i].tri[0]].uv); | ||||
| copy_v2_v2(uv1co, tface[i].uv[0]); | copy_v2_v2(uv2co, (float *)mloopuv[mlooptri[i].tri[1]].uv); | ||||
| copy_v2_v2(uv2co, tface[i].uv[1]); | copy_v2_v2(uv3co, (float *)mloopuv[mlooptri[i].tri[2]].uv); | ||||
| copy_v2_v2(uv3co, tface[i].uv[2]); | |||||
| } | |||||
| else { | |||||
| copy_v2_v2(uv1co, tface[i].uv[0]); | |||||
| copy_v2_v2(uv2co, tface[i].uv[2]); | |||||
| copy_v2_v2(uv3co, tface[i].uv[3]); | |||||
| } | |||||
| /* Add b-weights per anti-aliasing sample */ | /* Add b-weights per anti-aliasing sample */ | ||||
| for (j = 0; j < aa_samples; j++) { | for (j = 0; j < aa_samples; j++) { | ||||
| Context not available. | |||||
| } | } | ||||
| /* Set surface point face values */ | /* Set surface point face values */ | ||||
| tPoint->face_index = i; /* face index */ | tPoint->tri_index = i; /* tri index */ | ||||
| tPoint->quad = (isInside == 2) ? 1 : 0; /* quad or tri part*/ | |||||
| /* save vertex indexes */ | /* save vertex indexes */ | ||||
| tPoint->v1 = mface[i].v1; | tPoint->v1 = mloop[mlooptri[i].tri[0]].v; | ||||
| tPoint->v2 = (isInside == 2) ? mface[i].v3 : mface[i].v2; | tPoint->v2 = mloop[mlooptri[i].tri[1]].v; | ||||
| tPoint->v3 = (isInside == 2) ? mface[i].v4 : mface[i].v3; | tPoint->v3 = mloop[mlooptri[i].tri[2]].v; | ||||
| sample = 5; /* make sure we exit sample loop as well */ | sample = 5; /* make sure we exit sample loop as well */ | ||||
| break; | break; | ||||
| Context not available. | |||||
| PaintUVPoint *tPoint = (&tempPoints[index]); | PaintUVPoint *tPoint = (&tempPoints[index]); | ||||
| /* If point isn't't on canvas mesh */ | /* If point isn't't on canvas mesh */ | ||||
| if (tPoint->face_index == -1) { | if (tPoint->tri_index == -1) { | ||||
| int u_min, u_max, v_min, v_max; | int u_min, u_max, v_min, v_max; | ||||
| int u, v, ind; | int u, v, ind; | ||||
| float point[2]; | float point[2]; | ||||
| Context not available. | |||||
| ind = (tx + u) + w * (ty + v); | ind = (tx + u) + w * (ty + v); | ||||
| /* if neighbor has index */ | /* if neighbor has index */ | ||||
| if (tempPoints[ind].face_index != -1) { | if (tempPoints[ind].tri_index != -1) { | ||||
| float uv1co[2], uv2co[2], uv3co[2], uv[2]; | float uv1co[2], uv2co[2], uv3co[2], uv[2]; | ||||
| int i = tempPoints[ind].face_index, j; | int i = tempPoints[ind].tri_index, j; | ||||
| /* Now calculate pixel data for this pixel as it was on polygon surface */ | /* Now calculate pixel data for this pixel as it was on polygon surface */ | ||||
| if (!tempPoints[ind].quad) { | copy_v2_v2(uv1co, (float *)mloopuv[mlooptri[i].tri[0]].uv); | ||||
| copy_v2_v2(uv1co, tface[i].uv[0]); | copy_v2_v2(uv2co, (float *)mloopuv[mlooptri[i].tri[1]].uv); | ||||
| copy_v2_v2(uv2co, tface[i].uv[1]); | copy_v2_v2(uv3co, (float *)mloopuv[mlooptri[i].tri[2]].uv); | ||||
| copy_v2_v2(uv3co, tface[i].uv[2]); | |||||
| } | |||||
| else { | |||||
| copy_v2_v2(uv1co, tface[i].uv[0]); | |||||
| copy_v2_v2(uv2co, tface[i].uv[2]); | |||||
| copy_v2_v2(uv3co, tface[i].uv[3]); | |||||
| } | |||||
| /* Add b-weights per anti-aliasing sample */ | /* Add b-weights per anti-aliasing sample */ | ||||
| for (j = 0; j < aa_samples; j++) { | for (j = 0; j < aa_samples; j++) { | ||||
| Context not available. | |||||
| } | } | ||||
| /* Set values */ | /* Set values */ | ||||
| tPoint->neighbour_pixel = ind; // face index | tPoint->neighbour_pixel = ind; // tri index | ||||
| tPoint->quad = tempPoints[ind].quad; // quad or tri | |||||
| /* save vertex indexes */ | /* save vertex indexes */ | ||||
| tPoint->v1 = mface[i].v1; | tPoint->v1 = mloop[mlooptri[i].tri[0]].v; | ||||
| tPoint->v2 = (tPoint->quad) ? mface[i].v3 : mface[i].v2; | tPoint->v2 = mloop[mlooptri[i].tri[1]].v; | ||||
| tPoint->v3 = (tPoint->quad) ? mface[i].v4 : mface[i].v3; | tPoint->v3 = mloop[mlooptri[i].tri[2]].v; | ||||
| u = u_max + 1; /* make sure we exit outer loop as well */ | u = u_max + 1; /* make sure we exit outer loop as well */ | ||||
| break; | break; | ||||
| Context not available. | |||||
| int index = tx + w * ty; | int index = tx + w * ty; | ||||
| PaintUVPoint *tPoint = (&tempPoints[index]); | PaintUVPoint *tPoint = (&tempPoints[index]); | ||||
| if (tPoint->face_index == -1 && tPoint->neighbour_pixel != -1) tPoint->face_index = tempPoints[tPoint->neighbour_pixel].face_index; | if (tPoint->tri_index == -1 && tPoint->neighbour_pixel != -1) tPoint->tri_index = tempPoints[tPoint->neighbour_pixel].tri_index; | ||||
| if (tPoint->face_index != -1) active_points++; | if (tPoint->tri_index != -1) active_points++; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| /* Create a temporary array of final indexes (before unassigned | /* Create a temporary array of final indexes (before unassigned | ||||
| * pixels have been dropped) */ | * pixels have been dropped) */ | ||||
| for (i = 0; i < w * h; i++) { | for (i = 0; i < w * h; i++) { | ||||
| if (tempPoints[i].face_index != -1) { | if (tempPoints[i].tri_index != -1) { | ||||
| final_index[i] = cursor; | final_index[i] = cursor; | ||||
| cursor++; | cursor++; | ||||
| } | } | ||||
| Context not available. | |||||
| for (tx = 0; tx < w; tx++) { | for (tx = 0; tx < w; tx++) { | ||||
| int i, index = tx + w * ty; | int i, index = tx + w * ty; | ||||
| if (tempPoints[index].face_index != -1) { | if (tempPoints[index].tri_index != -1) { | ||||
| ed->n_index[final_index[index]] = n_pos; | ed->n_index[final_index[index]] = n_pos; | ||||
| ed->n_num[final_index[index]] = 0; | ed->n_num[final_index[index]] = 0; | ||||
| Context not available. | |||||
| sData->format_data = f_data; | sData->format_data = f_data; | ||||
| for (index = 0; index < (w * h); index++) { | for (index = 0; index < (w * h); index++) { | ||||
| if (tempPoints[index].face_index != -1) { | if (tempPoints[index].tri_index != -1) { | ||||
| memcpy(&f_data->uv_p[cursor], &tempPoints[index], sizeof(PaintUVPoint)); | memcpy(&f_data->uv_p[cursor], &tempPoints[index], sizeof(PaintUVPoint)); | ||||
| memcpy(&f_data->barycentricWeights[cursor * aa_samples], &tempWeights[index * aa_samples], sizeof(Vec3f) * aa_samples); | memcpy(&f_data->barycentricWeights[cursor * aa_samples], &tempWeights[index * aa_samples], sizeof(Vec3f) * aa_samples); | ||||
| cursor++; | cursor++; | ||||
| Context not available. | |||||
| /* Every pixel that is assigned as "edge pixel" gets blue color */ | /* Every pixel that is assigned as "edge pixel" gets blue color */ | ||||
| if (uvPoint->neighbour_pixel != -1) pPoint->color[2] = 1.0f; | if (uvPoint->neighbour_pixel != -1) pPoint->color[2] = 1.0f; | ||||
| /* and every pixel that finally got an polygon gets red color */ | /* and every pixel that finally got an polygon gets red color */ | ||||
| if (uvPoint->face_index != -1) pPoint->color[0] = 1.0f; | if (uvPoint->tri_index != -1) pPoint->color[0] = 1.0f; | ||||
| /* green color shows pixel face index hash */ | /* green color shows pixel face index hash */ | ||||
| if (uvPoint->face_index != -1) pPoint->color[1] = (float)(uvPoint->face_index % 255) / 256.0f; | if (uvPoint->tri_index != -1) pPoint->color[1] = (float)(uvPoint->tri_index % 255) / 256.0f; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| int faceIndex, short isQuad, DerivedMesh *orcoDm) | int faceIndex, short isQuad, DerivedMesh *orcoDm) | ||||
| { | { | ||||
| Material *mat = bMats->mat; | Material *mat = bMats->mat; | ||||
| // still havent touched this (because of BVH search (which still uses MFace)) | |||||
| MFace *mface = orcoDm->getTessFaceArray(orcoDm); | MFace *mface = orcoDm->getTessFaceArray(orcoDm); | ||||
| /* If no material defined, use the one assigned to the mesh face */ | /* If no material defined, use the one assigned to the mesh face */ | ||||
| if (mat == NULL) { | if (mat == NULL) { | ||||
| if (bMats->ob_mats) { | if (bMats->ob_mats) { | ||||
| // need to use MPoly here, then?... to get to mat_nr... | |||||
| // faceIndex is comming from BVH search (which still uses MFace) | |||||
| int mat_nr = mface[faceIndex].mat_nr; | int mat_nr = mface[faceIndex].mat_nr; | ||||
| if (mat_nr >= (*give_totcolp(brushOb))) return; | if (mat_nr >= (*give_totcolp(brushOb))) return; | ||||
| mat = bMats->ob_mats[mat_nr]; | mat = bMats->ob_mats[mat_nr]; | ||||
| Context not available. | |||||
| DerivedMesh *dm = NULL; | DerivedMesh *dm = NULL; | ||||
| Vec3f *brushVelocity = NULL; | Vec3f *brushVelocity = NULL; | ||||
| MVert *mvert = NULL; | MVert *mvert = NULL; | ||||
| // havent touched this yet (because this will use BVH search later on [which still uses MFace]) | |||||
| MFace *mface = NULL; | MFace *mface = NULL; | ||||
| if (brush->flags & MOD_DPAINT_USES_VELOCITY) | if (brush->flags & MOD_DPAINT_USES_VELOCITY) | ||||
| Context not available. | |||||