projection paint cleanup (nothing to see here)

* BarycentricWeightsPersp2f was calling BarycentricWeights2f, and re-weighting. Changed so the re-weighting isnt needed.
* replaced tri_depth_2d with VecZDepthOrtho and VecZDepthPersp
* project_paint_occlude_ptv_clip now calls project_paint_occlude_ptv to remove duplicate code.
This commit is contained in:
Campbell Barton 2008-12-13 16:11:52 +00:00
parent aa40953210
commit f8aa295596

@ -539,47 +539,45 @@ static float AreaSignedF2Dfl(float *v1, float *v2, float *v3)
(v1[1]-v2[1])*(v3[0]-v2[0])));
}
static void BarycentricWeights2f(float v1[2], float v2[2], float v3[2], float pt[2], float w[3])
static void BarycentricWeights2f(float pt[2], float v1[2], float v2[2], float v3[2], float w[3])
{
float wtot_inv, wtot, wsign[3];
float wtot_inv, wtot;
wsign[0] = AreaSignedF2Dfl(v2, v3, pt);
wsign[1] = AreaSignedF2Dfl(v3, v1, pt);
wsign[2] = AreaSignedF2Dfl(v1, v2, pt);
wtot = wsign[0]+wsign[1]+wsign[2];
w[0] = AreaSignedF2Dfl(v2, v3, pt);
w[1] = AreaSignedF2Dfl(v3, v1, pt);
w[2] = AreaSignedF2Dfl(v1, v2, pt);
wtot = w[0]+w[1]+w[2];
if (fabs(wtot) > 0.0f) {
if (wtot != 0.0f) {
wtot_inv = 1.0f/wtot;
w[0] = wsign[0]*wtot_inv;
w[1] = wsign[1]*wtot_inv;
w[2] = wsign[2]*wtot_inv;
w[0] = w[0]*wtot_inv;
w[1] = w[1]*wtot_inv;
w[2] = w[2]*wtot_inv;
}
else /* dummy values for zero area face */
w[0] = w[1] = w[2] = 1.0f/3.0f;
}
/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */
static void BarycentricWeightsPersp2f(float v1[4], float v2[4], float v3[4], float pt[2], float w[3])
static void BarycentricWeightsPersp2f(float pt[2], float v1[4], float v2[4], float v3[4], float w[3])
{
float persp_tot, persp_tot_inv;
BarycentricWeights2f(v1, v2, v3, pt, w);
float wtot_inv, wtot;
w[0] /= v1[3];
w[1] /= v2[3];
w[2] /= v3[3];
w[0] = AreaSignedF2Dfl(v2, v3, pt) / v1[3];
w[1] = AreaSignedF2Dfl(v3, v1, pt) / v2[3];
w[2] = AreaSignedF2Dfl(v1, v2, pt) / v3[3];
wtot = w[0]+w[1]+w[2];
persp_tot = w[0]+w[1]+w[2];
if (persp_tot > 0.0f) {
persp_tot_inv = 1.0f / persp_tot;
w[0] *= persp_tot_inv;
w[1] *= persp_tot_inv;
w[2] *= persp_tot_inv;
}
else {
w[0] = w[1] = w[2] = 1.0f/3.0f; /* dummy values for zero area face */
if (wtot != 0.0f) {
wtot_inv = 1.0f/wtot;
w[0] = w[0]*wtot_inv;
w[1] = w[1]*wtot_inv;
w[2] = w[2]*wtot_inv;
}
else /* dummy values for zero area face */
w[0] = w[1] = w[2] = 1.0f/3.0f;
}
static void VecWeightf(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
@ -595,9 +593,15 @@ static void Vec2Weightf(float p[2], const float v1[2], const float v2[2], const
p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2];
}
static float tri_depth_2d(float v1[3], float v2[3], float v3[3], float pt[2], float w[3])
static float VecZDepthOrtho(float pt[2], float v1[3], float v2[3], float v3[3], float w[3])
{
BarycentricWeights2f(v1, v2, v3, pt, w);
BarycentricWeights2f(pt, v1, v2, v3, w);
return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]);
}
static float VecZDepthPersp(float pt[2], float v1[3], float v2[3], float v3[3], float w[3])
{
BarycentricWeightsPersp2f(pt, v1, v2, v3, w);
return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]);
}
@ -633,7 +637,9 @@ static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w
v3= ps->screenCoords[mf->v3];
if (IsectPT2Df(pt, v1, v2, v3)) {
z_depth= tri_depth_2d(v1, v2, v3, pt, w_tmp);
if (ps->is_ortho) z_depth= VecZDepthOrtho(pt, v1, v2, v3, w_tmp);
else z_depth= VecZDepthPersp(pt, v1, v2, v3, w_tmp);
if (z_depth < z_depth_best) {
best_face_index = face_index;
best_side = 0;
@ -645,7 +651,9 @@ static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w
v4= ps->screenCoords[mf->v4];
if (IsectPT2Df(pt, v1, v3, v4)) {
z_depth= tri_depth_2d(v1, v3, v4, pt, w_tmp);
if (ps->is_ortho) z_depth= VecZDepthOrtho(pt, v1, v3, v4, w_tmp);
else z_depth= VecZDepthPersp(pt, v1, v3, v4, w_tmp);
if (z_depth < z_depth_best) {
best_face_index = face_index;
best_side= 1;
@ -768,9 +776,10 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float
* return...
* 0 : no occlusion
* -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad)
* 1 : occluded */
* 1 : occluded
2 : occluded with w[3] weights set (need to know in some cases) */
static int project_paint_occlude_ptv(float pt[3], float v1[3], float v2[3], float v3[3])
static int project_paint_occlude_ptv(float pt[3], float v1[3], float v2[3], float v3[3], float w[3], int is_ortho)
{
/* if all are behind us, return false */
if(v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
@ -787,10 +796,13 @@ static int project_paint_occlude_ptv(float pt[3], float v1[3], float v2[3], floa
return 1;
}
else {
float w[3];
/* we intersect? - find the exact depth at the point of intersection */
if (tri_depth_2d(v1, v2, v3, pt, w) < pt[2]) {
return 1; /* This point is occluded by another face */
/* Is this point is occluded by another face? */
if (is_ortho) {
if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2;
}
else {
if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2;
}
}
return -1;
@ -803,19 +815,17 @@ static int project_paint_occlude_ptv_clip(
const int side )
{
float w[3], wco[3];
int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho);
/* if all are behind us, return false */
if(v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
return 0;
if (ret <= 0)
return ret;
/* do a 2D point in try intersection */
if (!IsectPT2Df(pt, v1, v2, v3))
return 0; /* we know there is */
/* we intersect? - find the exact depth at the point of intersection */
if (tri_depth_2d(v1, v2, v3, pt, w) > pt[2])
return -1;
if (ret==1) { /* weights not calculated */
if (ps->is_ortho) BarycentricWeights2f(pt, v1, v2, v3, w);
else BarycentricWeightsPersp2f(pt, v1, v2, v3, w);
}
/* Test if we're in the clipped area, */
if (side) VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
else VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
@ -836,21 +846,27 @@ static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *buc
MFace *mf;
int face_index;
int isect_ret;
float w[3]; /* not needed when clipping */
/* we could return 0 for 1 face buckets, as long as this function assumes
* that the point its testing is only every originated from an existing face */
if(G.vd->flag & V3D_CLIPPING) {
for (; bucketFace; bucketFace = bucketFace->next) {
face_index = (int)bucketFace->link;
if (orig_face != face_index) {
mf = ps->dm_mface + face_index;
if(G.vd->flag & V3D_CLIPPING)
isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0);
else
isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho);
/* Note, if isect_ret==-1 then we dont want to test the other side of the quad */
if (isect_ret==0 && mf->v4) {
if(G.vd->flag & V3D_CLIPPING)
isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1);
else
isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho);
}
if (isect_ret==1) {
/* TODO - we may want to cache the first hit,
@ -859,27 +875,6 @@ static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *buc
}
}
}
}
else {
for (; bucketFace; bucketFace = bucketFace->next) {
face_index = (int)bucketFace->link;
if (orig_face != face_index) {
mf = ps->dm_mface + face_index;
isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3]);
/* Note, if isect_ret==-1 then we dont want to test the other side of the quad */
if (isect_ret==0 && mf->v4) {
isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4]);
}
if (isect_ret==1) {
/* TODO - we may want to cache the first hit,
* it is not possible to swap the face order in the list anymore */
return 1;
}
}
}
}
return 0;
}
@ -1285,7 +1280,7 @@ static void screen_px_from_ortho(
float pixelScreenCo[4],
float w[3])
{
BarycentricWeights2f(uv1co, uv2co, uv3co, uv, w);
BarycentricWeights2f(uv, uv1co, uv2co, uv3co, w);
VecWeightf(pixelScreenCo, v1co, v2co, v3co, w);
}
@ -1300,7 +1295,7 @@ static void screen_px_from_persp(
{
float wtot_inv, wtot;
BarycentricWeights2f(uv1co, uv2co, uv3co, uv, w);
BarycentricWeights2f(uv, uv1co, uv2co, uv3co, w);
/* re-weight from the 4th coord of each screen vert */
w[0] *= v1co[3];
@ -1360,7 +1355,7 @@ float project_paint_uvpixel_mask(
const int side,
const float w[3])
{
float mask, mask_angle;
float mask;
/* Image Mask */
if (ps->do_layer_mask) {
@ -1872,22 +1867,22 @@ static void rect_to_uvspace_ortho(
/* get the UV space bounding box */
uv[0] = bucket_bounds->xmax;
uv[1] = bucket_bounds->ymin;
BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w);
//uv[0] = bucket_bounds->xmax; // set above
uv[1] = bucket_bounds->ymax;
BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w);
uv[0] = bucket_bounds->xmin;
//uv[1] = bucket_bounds->ymax; // set above
BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w);
//uv[0] = bucket_bounds->xmin; // set above
uv[1] = bucket_bounds->ymin;
BarycentricWeights2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w);
}
@ -1906,22 +1901,22 @@ static void rect_to_uvspace_persp(
/* get the UV space bounding box */
uv[0] = bucket_bounds->xmax;
uv[1] = bucket_bounds->ymin;
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w);
//uv[0] = bucket_bounds->xmax; // set above
uv[1] = bucket_bounds->ymax;
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w);
uv[0] = bucket_bounds->xmin;
//uv[1] = bucket_bounds->ymax; // set above
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w);
//uv[0] = bucket_bounds->xmin; // set above
uv[1] = bucket_bounds->ymin;
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, uv, w);
BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w);
}
@ -2163,13 +2158,13 @@ static void project_bucket_clip_face(
if (is_ortho) {
for(i=0; i<(*tot); i++) {
BarycentricWeights2f(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
BarycentricWeights2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
}
}
else {
for(i=0; i<(*tot); i++) {
BarycentricWeightsPersp2f(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
BarycentricWeightsPersp2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w);
Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
}
}
@ -2597,10 +2592,10 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (ps->do_mask_normal || ps->dm_mtface_clone) {
/* TODO, this is not QUITE correct since UV is not inside the UV's but good enough for seams */
if (side) {
BarycentricWeights2f(tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], uv, w);
BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], w);
}
else {
BarycentricWeights2f(tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], uv, w);
BarycentricWeights2f(uv, tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], w);
}
}