speedup occlusion by removing octree raytracing method and use the bucket's face list.
This commit is contained in:
parent
80971310a3
commit
81dd05fd55
@ -88,8 +88,6 @@
|
||||
#include "BDR_imagepaint.h"
|
||||
#include "BDR_vpaint.h"
|
||||
|
||||
#include "RE_raytrace.h" /* For projection painting occlusion */
|
||||
|
||||
#include "GPU_draw.h"
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
@ -136,7 +134,6 @@ typedef struct ImagePaintState {
|
||||
/* testing options */
|
||||
#define PROJ_BUCKET_DIV 128 /* TODO - test other values, this is a guess, seems ok */
|
||||
|
||||
#define PROJ_LAZY_INIT 1
|
||||
// #define PROJ_PAINT_DEBUG 1
|
||||
|
||||
/* projectFaceFlags options */
|
||||
@ -167,11 +164,10 @@ typedef struct ProjectPaintState {
|
||||
/* projection painting only */
|
||||
MemArena *projectArena; /* use for alocating many pixel structs and link-lists */
|
||||
LinkNode **projectBuckets; /* screen sized 2D array, each pixel has a linked list of ImagePaintProjectPixel's */
|
||||
#ifdef PROJ_LAZY_INIT
|
||||
LinkNode **projectFaces; /* projectBuckets alligned array linkList of faces overlapping each bucket */
|
||||
char *projectBucketFlags; /* store if the bucks have been initialized */
|
||||
char *projectFaceFlags; /* store info about faces, if they are initialized etc*/
|
||||
#endif
|
||||
|
||||
int bucketsX; /* The size of the bucket grid, the grid span's viewMin2D/viewMax2D so you can paint outsize the screen or with 2 brushes at once */
|
||||
int bucketsY;
|
||||
|
||||
@ -179,10 +175,7 @@ typedef struct ProjectPaintState {
|
||||
int projectImageTotal; /* size of projectImages array */
|
||||
int image_index; /* current image, use for context switching */
|
||||
|
||||
float (*projectVertCos2D)[2]; /* verts projected into floating point screen space */
|
||||
|
||||
RayTree *projectRayTree; /* ray tracing acceleration structure */
|
||||
Isect isec; /* re-use ray intersection var */
|
||||
float (*projectVertScreenCos)[3]; /* verts projected into floating point screen space */
|
||||
|
||||
/* options for projection painting */
|
||||
short projectOcclude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
|
||||
@ -190,16 +183,12 @@ typedef struct ProjectPaintState {
|
||||
|
||||
float projectMat[4][4]; /* Projection matrix, use for getting screen coords */
|
||||
float viewMat[4][4];
|
||||
float viewPoint[3]; /* Use only when in perspective mode with projectOcclude, the point we are viewing from, cast rays to this */
|
||||
float viewDir[3]; /* View vector, use for projectBackfaceCull and for ray casting with an ortho viewport */
|
||||
|
||||
float viewMin2D[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */
|
||||
float viewMax2D[2];
|
||||
float viewWidth; /* Calculated from viewMin2D & viewMax2D */
|
||||
float viewHeight;
|
||||
|
||||
|
||||
|
||||
} ProjectPaintState;
|
||||
|
||||
typedef struct ImagePaintProjectPixel {
|
||||
@ -367,21 +356,6 @@ static void undo_imagepaint_push_end()
|
||||
}
|
||||
|
||||
|
||||
static MVert * mvert_static = NULL;
|
||||
static void project_paint_begin_coords_func(RayFace *face, float **v1, float **v2, float **v3, float **v4)
|
||||
{
|
||||
MFace *mface= (MFace*)face;
|
||||
|
||||
*v1= mvert_static[mface->v1].co;
|
||||
*v2= mvert_static[mface->v2].co;
|
||||
*v3= mvert_static[mface->v3].co;
|
||||
*v4= (mface->v4)? mvert_static[mface->v4].co: NULL;
|
||||
}
|
||||
|
||||
static int project_paint_begin_check_func(Isect *is, int ob, RayFace *face)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
static int project_paint_BucketOffset(ProjectPaintState *ps, float *projCo2D)
|
||||
{
|
||||
|
||||
@ -399,10 +373,107 @@ static int project_paint_BucketOffset(ProjectPaintState *ps, float *projCo2D)
|
||||
( ( (int)(( (projCo2D[1] - ps->viewMin2D[1]) / ps->viewHeight) * ps->bucketsY)) * ps->bucketsX );
|
||||
}
|
||||
|
||||
static void project_paint_face_init(ProjectPaintState *ps, MFace *mf, MTFace *tf, ImBuf *ibuf)
|
||||
/* return...
|
||||
* 0 : no occlusion
|
||||
* -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad)
|
||||
* 1 : occluded */
|
||||
|
||||
static int screenco_tri_pt_occlude(float *pt, float *v1, float *v2, float *v3)
|
||||
{
|
||||
float w1, w2, w3, wtot; /* weights for converting the pixel into 3d worldspace coords */
|
||||
|
||||
/* if all are behind us, return false */
|
||||
if(v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
|
||||
return 0;
|
||||
|
||||
/* do a 2D point in try intersection */
|
||||
if ( !IsectPT2Df(pt, v1, v2, v3) )
|
||||
return 0; /* we know there is */
|
||||
|
||||
/* From here on we know there IS an intersection */
|
||||
|
||||
/* if ALL of the verts are infront of us then we know it intersects ? */
|
||||
if( v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
|
||||
return 1;
|
||||
} else {
|
||||
/* we intersect? - find the exact depth at the point of intersection */
|
||||
w1 = AreaF2Dfl(v2, v3, pt);
|
||||
w2 = AreaF2Dfl(v3, v1, pt);
|
||||
w3 = AreaF2Dfl(v1, v2, pt);
|
||||
wtot = w1 + w2 + w3;
|
||||
|
||||
if ((v1[2]*w1/wtot) + (v2[2]*w2/wtot) + (v3[2]*w3/wtot) < pt[2]) {
|
||||
return 1; /* This point is occluded by another face */
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison */
|
||||
static int project_bucket_point_occluded(ProjectPaintState *ps, int bucket_index, int orig_face, float pixelScreenCo[3])
|
||||
{
|
||||
LinkNode *node = ps->projectFaces[bucket_index];
|
||||
LinkNode *prev_node = NULL;
|
||||
MFace *mf;
|
||||
int face_index;
|
||||
int isect_ret;
|
||||
|
||||
while (node) {
|
||||
face_index = (int)node->link;
|
||||
|
||||
if (orig_face != face_index) {
|
||||
|
||||
mf = ps->dm_mface + face_index;
|
||||
|
||||
isect_ret = screenco_tri_pt_occlude(
|
||||
pixelScreenCo,
|
||||
ps->projectVertScreenCos[mf->v1],
|
||||
ps->projectVertScreenCos[mf->v2],
|
||||
ps->projectVertScreenCos[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 = screenco_tri_pt_occlude(
|
||||
pixelScreenCo,
|
||||
ps->projectVertScreenCos[mf->v1],
|
||||
ps->projectVertScreenCos[mf->v3],
|
||||
ps->projectVertScreenCos[mf->v4]);
|
||||
}
|
||||
|
||||
if (isect_ret==1) {
|
||||
/* Cheap Optimization!
|
||||
* This function runs for every UV Screen pixel,
|
||||
* therefor swapping the swapping the faces for this buckets list helps because
|
||||
* the next ~5 to ~200 runs will can hit the first face each time. */
|
||||
if (ps->projectFaces[bucket_index] != node) {
|
||||
/* SWAP(void *, ps->projectFaces[bucket_index]->link, node->link); */
|
||||
|
||||
/* dont need to use swap since we alredy have face_index */
|
||||
node->link = ps->projectFaces[bucket_index]->link; /* move the value item to the current value */
|
||||
ps->projectFaces[bucket_index]->link = (void *) face_index;
|
||||
|
||||
/*printf("swapping %d %d\n", (int)node->link, face_index);*/
|
||||
} /*else {
|
||||
printf("first hit %d\n", face_index);
|
||||
}*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
prev_node = node;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void project_paint_face_init(ProjectPaintState *ps, int face_index, ImBuf *ibuf)
|
||||
{
|
||||
/* Projection vars, to get the 3D locations into screen space */
|
||||
ImagePaintProjectPixel *projPixel;
|
||||
MFace *mf = ps->dm_mface + face_index;
|
||||
MTFace *tf = ps->dm_mtface + face_index;
|
||||
|
||||
float pxWorldCo[3];
|
||||
float pxProjCo[4];
|
||||
@ -412,31 +483,25 @@ static void project_paint_face_init(ProjectPaintState *ps, MFace *mf, MTFace *tf
|
||||
int y;/* Image Y-Pixel */
|
||||
float uv[2]; /* Image floating point UV - same as x,y but from 0.0-1.0 */
|
||||
int pixel_size = 4; /* each pixel is 4 x 8-bits packed in unsigned int */
|
||||
float xmin, ymin, xmax, ymax; /* UV bounds */
|
||||
float min_uv[2], max_uv[2]; /* UV bounds */
|
||||
int xmini, ymini, xmaxi, ymaxi; /* UV Bounds converted to int's for pixel */
|
||||
float w1, w2, w3, wtot; /* weights for converting the pixel into 3d worldspace coords */
|
||||
float *v1co, *v2co, *v3co, *v4co; /* for convenience only */
|
||||
|
||||
int i;
|
||||
|
||||
/* clamp to 0-1 for now */
|
||||
xmin = ymin = 1.0f;
|
||||
xmax = ymax = 0.0f;
|
||||
INIT_MINMAX2(min_uv, max_uv);
|
||||
|
||||
i = mf->v4 ? 3:2;
|
||||
do {
|
||||
xmin = MIN2(xmin, tf->uv[i][0]);
|
||||
ymin = MIN2(ymin, tf->uv[i][1]);
|
||||
|
||||
xmax = MAX2(xmax, tf->uv[i][0]);
|
||||
ymax = MAX2(ymax, tf->uv[i][1]);
|
||||
DO_MINMAX2(tf->uv[i], min_uv, max_uv);
|
||||
} while (i--);
|
||||
|
||||
xmini = (int)(ibuf->x * xmin);
|
||||
ymini = (int)(ibuf->y * ymin);
|
||||
xmini = (int)(ibuf->x * min_uv[0]);
|
||||
ymini = (int)(ibuf->y * min_uv[1]);
|
||||
|
||||
xmaxi = (int)(ibuf->x * xmax) +1;
|
||||
ymaxi = (int)(ibuf->y * ymax) +1;
|
||||
xmaxi = (int)(ibuf->x * max_uv[0]) +1;
|
||||
ymaxi = (int)(ibuf->y * max_uv[1]) +1;
|
||||
|
||||
/*printf("%d %d %d %d \n", xmini, ymini, xmaxi, ymaxi);*/
|
||||
|
||||
@ -458,6 +523,10 @@ static void project_paint_face_init(ProjectPaintState *ps, MFace *mf, MTFace *tf
|
||||
|
||||
for (y = ymini; y < ymaxi; y++) {
|
||||
uv[1] = (((float)y)+0.5) / (float)ibuf->y;
|
||||
|
||||
/* IsectPT2Df works fine but is too slow
|
||||
* rather then IsectPT2Df's all the time we can do somthing more like scanlines */
|
||||
|
||||
for (x = xmini; x < xmaxi; x++) {
|
||||
uv[0] = (((float)x)+0.5) / (float)ibuf->x;
|
||||
|
||||
@ -496,38 +565,34 @@ static void project_paint_face_init(ProjectPaintState *ps, MFace *mf, MTFace *tf
|
||||
if (projCo2D[0]==IS_CLIPPED)
|
||||
continue;*/
|
||||
if (wtot != -1.0) {
|
||||
|
||||
/* Inline, a bit faster */
|
||||
VECCOPY(pxProjCo, pxWorldCo);
|
||||
pxProjCo[3] = 1.0;
|
||||
|
||||
Mat4MulVec4fl(ps->projectMat, pxProjCo);
|
||||
|
||||
|
||||
if( pxProjCo[3] > 0.001 ) {
|
||||
float pixelScreenCo[3]; /* for testing occlusion we need the depth too, but not for saving into ImagePaintProjectPixel */
|
||||
int bucket_index;
|
||||
|
||||
pixelScreenCo[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*pxProjCo[0]/pxProjCo[3];
|
||||
pixelScreenCo[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*pxProjCo[1]/pxProjCo[3];
|
||||
pixelScreenCo[2] = pxProjCo[2]/pxProjCo[3]; /* Only for depth test */
|
||||
|
||||
bucket_index = project_paint_BucketOffset(ps, pixelScreenCo);
|
||||
|
||||
/* Use viewMin2D to make (0,0) the bottom left of the bounds
|
||||
* Then this can be used to index the bucket array */
|
||||
|
||||
if (ps->projectOcclude) {
|
||||
VECCOPY(ps->isec.start, pxWorldCo);
|
||||
|
||||
if (G.vd->persp==V3D_ORTHO) {
|
||||
VecAddf(ps->isec.end, pxWorldCo, ps->viewDir);
|
||||
} else { /* value dosnt change but it is modified by RE_ray_tree_intersect() - keep this line */
|
||||
VECCOPY(ps->isec.end, ps->viewPoint);
|
||||
}
|
||||
|
||||
ps->isec.faceorig = mf;
|
||||
}
|
||||
|
||||
/* Is this UV visible from the view? - raytrace */
|
||||
if (ps->projectOcclude==0 || !RE_ray_tree_intersect(ps->projectRayTree, &ps->isec)) {
|
||||
if (ps->projectOcclude==0 || !project_bucket_point_occluded(ps, bucket_index, face_index, pixelScreenCo)) {
|
||||
|
||||
/* done with view3d_project_float inline */
|
||||
projPixel = (ImagePaintProjectPixel *)BLI_memarena_alloc( ps->projectArena, sizeof(ImagePaintProjectPixel) );
|
||||
|
||||
/* screenspace unclamped */
|
||||
projPixel->projCo2D[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*pxProjCo[0]/pxProjCo[3];
|
||||
projPixel->projCo2D[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*pxProjCo[1]/pxProjCo[3];
|
||||
VECCOPY2D(projPixel->projCo2D, pixelScreenCo);
|
||||
|
||||
projPixel->pixel = (( char * ) ibuf->rect) + (( x + y * ibuf->x ) * pixel_size);
|
||||
#ifdef PROJ_PAINT_DEBUG
|
||||
@ -536,7 +601,7 @@ static void project_paint_face_init(ProjectPaintState *ps, MFace *mf, MTFace *tf
|
||||
projPixel->image_index = ps->image_index;
|
||||
|
||||
BLI_linklist_prepend_arena(
|
||||
&ps->projectBuckets[ project_paint_BucketOffset(ps, projPixel->projCo2D) ],
|
||||
&ps->projectBuckets[ bucket_index ],
|
||||
projPixel,
|
||||
ps->projectArena
|
||||
);
|
||||
@ -575,7 +640,6 @@ static void project_bucket_bounds(ProjectPaintState *ps, int bucket_x, int bucke
|
||||
bucket_bounds[ PROJ_BUCKET_TOP ] = ps->viewMin2D[1]+((bucket_y+1)*(ps->viewHeight / ps->bucketsY)); /* top */
|
||||
}
|
||||
|
||||
#ifdef PROJ_LAZY_INIT
|
||||
static void project_paint_bucket_init(ProjectPaintState *ps, int bucket_index)
|
||||
{
|
||||
|
||||
@ -599,7 +663,7 @@ static void project_paint_bucket_init(ProjectPaintState *ps, int bucket_index)
|
||||
tf = ps->dm_mtface+face_index;
|
||||
ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow */
|
||||
|
||||
project_paint_face_init(ps, ps->dm_mface + face_index, tf, ibuf);
|
||||
project_paint_face_init(ps, face_index, ibuf);
|
||||
}
|
||||
node = node->next;
|
||||
} while (node);
|
||||
@ -614,7 +678,7 @@ static void project_paint_bucket_init(ProjectPaintState *ps, int bucket_index)
|
||||
|
||||
static int project_bucket_face_isect(ProjectPaintState *ps, float min[2], float max[2], int bucket_x, int bucket_y, int bucket_index, MFace *mf)
|
||||
{
|
||||
/* TODO - replace this with a tricker method that uses sideofline for all projectVertCos2D's edges against the closest bucket corner */
|
||||
/* TODO - replace this with a tricker method that uses sideofline for all projectVertScreenCos's edges against the closest bucket corner */
|
||||
float bucket_bounds[4];
|
||||
float p1[2], p2[2], p3[2], p4[2];
|
||||
float *v, *v1,*v2,*v3,*v4;
|
||||
@ -626,7 +690,7 @@ static int project_bucket_face_isect(ProjectPaintState *ps, float min[2], float
|
||||
|
||||
i = mf->v4 ? 3:2;
|
||||
do {
|
||||
v = ps->projectVertCos2D[ (*(&mf->v1 + i)) ];
|
||||
v = ps->projectVertScreenCos[ (*(&mf->v1 + i)) ];
|
||||
|
||||
if ((v[0] > bucket_bounds[PROJ_BUCKET_LEFT]) &&
|
||||
(v[0] < bucket_bounds[PROJ_BUCKET_RIGHT]) &&
|
||||
@ -637,11 +701,11 @@ static int project_bucket_face_isect(ProjectPaintState *ps, float min[2], float
|
||||
}
|
||||
} while (i--);
|
||||
|
||||
v1 = ps->projectVertCos2D[mf->v1];
|
||||
v2 = ps->projectVertCos2D[mf->v2];
|
||||
v3 = ps->projectVertCos2D[mf->v3];
|
||||
v1 = ps->projectVertScreenCos[mf->v1];
|
||||
v2 = ps->projectVertScreenCos[mf->v2];
|
||||
v3 = ps->projectVertScreenCos[mf->v3];
|
||||
if (mf->v4) {
|
||||
v4 = ps->projectVertCos2D[mf->v4];
|
||||
v4 = ps->projectVertScreenCos[mf->v4];
|
||||
}
|
||||
|
||||
p1[0] = bucket_bounds[PROJ_BUCKET_LEFT]; p1[1] = bucket_bounds[PROJ_BUCKET_BOTTOM];
|
||||
@ -684,7 +748,7 @@ static void project_paint_begin_face_delayed_init(ProjectPaintState *ps, MFace *
|
||||
|
||||
i = mf->v4 ? 3:2;
|
||||
do {
|
||||
DO_MINMAX2(ps->projectVertCos2D[ (*(&mf->v1 + i)) ], min, max);
|
||||
DO_MINMAX2(ps->projectVertScreenCos[ (*(&mf->v1 + i)) ], min, max);
|
||||
} while (i--);
|
||||
|
||||
project_paint_rect(ps, min, max, bucket_min, bucket_max);
|
||||
@ -704,7 +768,6 @@ static void project_paint_begin_face_delayed_init(ProjectPaintState *ps, MFace *
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
{
|
||||
@ -713,7 +776,7 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
float f_no[3];
|
||||
|
||||
float projCo[4];
|
||||
float (*projCo2D)[2];
|
||||
float (*projScreenCo)[3];
|
||||
|
||||
/* Image Vars - keep track of images we have used */
|
||||
LinkNode *image_LinkList = NULL;
|
||||
@ -728,9 +791,6 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
|
||||
int a, i; /* generic looping vars */
|
||||
|
||||
/* raytrace for occlusion */
|
||||
float min[3], max[3];
|
||||
|
||||
/* memory sized to add to arena size */
|
||||
int tot_bucketMem=0;
|
||||
int tot_faceFlagMem=0;
|
||||
@ -750,70 +810,35 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
ps->dm_totvert = ps->dm->getNumVerts( ps->dm );
|
||||
ps->dm_totface = ps->dm->getNumFaces( ps->dm );
|
||||
|
||||
printf("\n\nstarting\n");
|
||||
|
||||
ps->bucketsX = PROJ_BUCKET_DIV;
|
||||
ps->bucketsY = PROJ_BUCKET_DIV;
|
||||
|
||||
ps->image_index = -1;
|
||||
|
||||
ps->viewPoint[0] = ps->viewPoint[1] = ps->viewPoint[2] = 0.0;
|
||||
|
||||
ps->viewDir[0] = 0.0;
|
||||
ps->viewDir[1] = 0.0;
|
||||
ps->viewDir[2] = 1.0;
|
||||
|
||||
view3d_get_object_project_mat(curarea, s->ob, ps->projectMat, ps->viewMat);
|
||||
|
||||
printmatrix4( "ps->projectMat", ps->projectMat);
|
||||
|
||||
|
||||
|
||||
tot_bucketMem = sizeof(LinkNode *) * ps->bucketsX * ps->bucketsY;
|
||||
#ifdef PROJ_LAZY_INIT
|
||||
tot_faceListMem = sizeof(LinkNode *) * ps->bucketsX * ps->bucketsY;
|
||||
tot_faceFlagMem = sizeof(char) * ps->dm_totface;
|
||||
tot_bucketFlagMem = sizeof(char) * ps->bucketsX * ps->bucketsY;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ps->projectArena = BLI_memarena_new(tot_bucketMem + tot_faceListMem + tot_faceFlagMem + (1<<16) );
|
||||
|
||||
ps->projectBuckets = (LinkNode **)BLI_memarena_alloc( ps->projectArena, tot_bucketMem);
|
||||
#ifdef PROJ_LAZY_INIT
|
||||
ps->projectFaces= (LinkNode **)BLI_memarena_alloc( ps->projectArena, tot_faceListMem);
|
||||
ps->projectFaceFlags = (char *)BLI_memarena_alloc( ps->projectArena, tot_faceFlagMem);
|
||||
ps->projectBucketFlags= (char *)BLI_memarena_alloc( ps->projectArena, tot_bucketFlagMem);
|
||||
#endif
|
||||
|
||||
memset(ps->projectBuckets, 0, tot_bucketMem);
|
||||
#ifdef PROJ_LAZY_INIT
|
||||
memset(ps->projectFaces, 0, tot_faceListMem);
|
||||
memset(ps->projectFaceFlags, 0, tot_faceFlagMem);
|
||||
memset(ps->projectBucketFlags, 0, tot_bucketFlagMem);
|
||||
#endif
|
||||
|
||||
/* view raytrace stuff */
|
||||
mvert_static = ps->dm_mvert;
|
||||
|
||||
memset(&ps->isec, 0, sizeof(ps->isec)); /* Initialize ray intersection */
|
||||
ps->isec.mode= RE_RAY_SHADOW;
|
||||
ps->isec.lay= -1;
|
||||
|
||||
Mat4MulVecfl(G.vd->viewinv, ps->viewPoint);
|
||||
|
||||
|
||||
|
||||
VECCOPY(G.scene->cursor, ps->viewPoint);
|
||||
|
||||
if (G.vd->persp==V3D_ORTHO) { // Use the cem location in this case TODO
|
||||
ps->viewDir[2] = 10000.0; /* ortho view needs a far off point */
|
||||
/* Even Though this dosnt change, we cant set it here because blenders internal raytest changes the value each time */
|
||||
//} else { /* Watch it, same endpoint for all perspective ray casts */
|
||||
// VECCOPY(isec.end, viewPoint);
|
||||
}
|
||||
|
||||
printmatrix4( "G.vd->viewinv", G.vd->viewinv);
|
||||
|
||||
Mat4Invert(s->ob->imat, s->ob->obmat);
|
||||
|
||||
@ -822,41 +847,27 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
Mat3CpyMat4(mat, s->ob->imat);
|
||||
Mat3MulVecfl(mat, ps->viewDir);
|
||||
|
||||
printmatrix3( "mat", mat);
|
||||
|
||||
/* move the viewport center into object space */
|
||||
Mat4MulVec4fl(s->ob->imat, ps->viewPoint);
|
||||
|
||||
printvecf("ps->viewDir", ps->viewDir);
|
||||
printvecf("ps->viewPoint", ps->viewPoint);
|
||||
|
||||
printmatrix4( "s->ob->imat", s->ob->imat);
|
||||
|
||||
/* calculate vert screen coords */
|
||||
ps->projectVertCos2D = BLI_memarena_alloc( ps->projectArena, sizeof(float) * ps->dm_totvert * 2);
|
||||
projCo2D = ps->projectVertCos2D;
|
||||
ps->projectVertScreenCos = BLI_memarena_alloc( ps->projectArena, sizeof(float) * ps->dm_totvert * 3);
|
||||
projScreenCo = ps->projectVertScreenCos;
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
INIT_MINMAX2(ps->viewMin2D, ps->viewMax2D);
|
||||
|
||||
for(a=0; a < ps->dm_totvert; a++, projCo2D++) {
|
||||
for(a=0; a < ps->dm_totvert; a++, projScreenCo++) {
|
||||
VECCOPY(projCo, ps->dm_mvert[a].co);
|
||||
|
||||
/* ray-tree needs worldspace min/max, do here and save another loop */
|
||||
if (ps->projectOcclude) {
|
||||
DO_MINMAX(projCo, min, max);
|
||||
}
|
||||
|
||||
projCo[3] = 1.0;
|
||||
Mat4MulVec4fl(ps->projectMat, projCo);
|
||||
|
||||
if( projCo[3] > 0.001 ) {
|
||||
/* screen space, not clamped */
|
||||
(*projCo2D)[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*projCo[0]/projCo[3];
|
||||
(*projCo2D)[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*projCo[1]/projCo[3]; /* Maybe the Z value is useful too.. but not yet */
|
||||
DO_MINMAX2((*projCo2D), ps->viewMin2D, ps->viewMax2D);
|
||||
(*projScreenCo)[0] = (float)(curarea->winx/2.0)+(curarea->winx/2.0)*projCo[0]/projCo[3];
|
||||
(*projScreenCo)[1] = (float)(curarea->winy/2.0)+(curarea->winy/2.0)*projCo[1]/projCo[3];
|
||||
(*projScreenCo)[2] = projCo[2]/projCo[3]; /* Use the depth for bucket point occlusion */
|
||||
DO_MINMAX2((*projScreenCo), ps->viewMin2D, ps->viewMax2D);
|
||||
} else {
|
||||
(*projCo2D)[0] = (*projCo2D)[1] = MAXFLOAT;
|
||||
/* TODO - deal with cases where 1 side of a face goes behind the view ? */
|
||||
(*projScreenCo)[0] = (*projScreenCo)[1] = MAXFLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -864,53 +875,6 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
ps->viewWidth = ps->viewMax2D[0] - ps->viewMin2D[0];
|
||||
ps->viewHeight = ps->viewMax2D[1] - ps->viewMin2D[1];
|
||||
|
||||
/* Build a ray tree so we can invalidate UV pixels that have a face infront of them */
|
||||
if (ps->projectOcclude) {
|
||||
|
||||
if (G.f & G_FACESELECT) {
|
||||
mf = ps->dm_mface;
|
||||
a = ps->dm_totface - 1;
|
||||
do {
|
||||
if (!(mf->flag & ME_HIDE)) {
|
||||
i++;
|
||||
}
|
||||
mf++;
|
||||
} while (a--);
|
||||
|
||||
ps->projectRayTree = RE_ray_tree_create(
|
||||
64, i, min, max,
|
||||
project_paint_begin_coords_func,
|
||||
project_paint_begin_check_func,
|
||||
NULL, NULL);
|
||||
|
||||
mf = ps->dm_mface;
|
||||
a = ps->dm_totface - 1;
|
||||
|
||||
do {
|
||||
if (!(mf->flag & ME_HIDE)) {
|
||||
RE_ray_tree_add_face(ps->projectRayTree, 0, mf);
|
||||
}
|
||||
} while (a--);
|
||||
|
||||
} else {
|
||||
ps->projectRayTree = RE_ray_tree_create(
|
||||
64, ps->dm_totface, min, max,
|
||||
project_paint_begin_coords_func,
|
||||
project_paint_begin_check_func,
|
||||
NULL, NULL);
|
||||
|
||||
mf = ps->dm_mface;
|
||||
a = ps->dm_totface - 1;
|
||||
do {
|
||||
RE_ray_tree_add_face(ps->projectRayTree, 0, mf);
|
||||
mf++;
|
||||
} while (a--);
|
||||
}
|
||||
|
||||
RE_ray_tree_done(ps->projectRayTree);
|
||||
}
|
||||
|
||||
|
||||
for( a = 0, tf = ps->dm_mtface, mf = ps->dm_mface; a < ps->dm_totface; mf++, tf++, a++ ) {
|
||||
if (tf->tpage && ((G.f & G_FACESELECT)==0 || mf->flag & ME_FACE_SEL)) {
|
||||
|
||||
@ -946,12 +910,8 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
|
||||
if (ibuf) {
|
||||
/* Initialize the faces screen pixels */
|
||||
#ifdef PROJ_LAZY_INIT
|
||||
/* Add this to a list to initialize later */
|
||||
project_paint_begin_face_delayed_init(ps, mf, tf, a);
|
||||
#else
|
||||
project_paint_face_init(ps, mf, tf, ibuf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -972,9 +932,6 @@ static void project_paint_begin( ImagePaintState *s, ProjectPaintState *ps )
|
||||
static void project_paint_end( ProjectPaintState *ps )
|
||||
{
|
||||
BLI_memarena_free(ps->projectArena);
|
||||
if (ps->projectOcclude)
|
||||
RE_ray_tree_free(ps->projectRayTree);
|
||||
|
||||
ps->dm->release(ps->dm);
|
||||
}
|
||||
|
||||
@ -1538,12 +1495,11 @@ static int imapaint_paint_sub_stroke_project(ImagePaintState *s, ProjectPaintSta
|
||||
|
||||
bucket_index = bucket_x + (bucket_y * ps->bucketsX);
|
||||
|
||||
#ifdef PROJ_LAZY_INIT
|
||||
/* Check this bucket and its faces are initialized */
|
||||
if (ps->projectBucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
|
||||
/* This bucket may hold some uninitialized faces, initialize it */
|
||||
project_paint_bucket_init(ps, bucket_index);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((node = ps->projectBuckets[bucket_index])) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user