diff options
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 112 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_arithb.h | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/arithb.c | 12 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 1 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 11 |
5 files changed, 108 insertions, 33 deletions
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index d87d8b528d9..92a4df5ca27 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -2477,6 +2477,7 @@ static void uvprojectModifier_initData(ModifierData *md) umd->image = NULL; umd->flags = MOD_UVPROJECT_ADDUVS; umd->num_projectors = 1; + umd->aspectx = umd->aspecty = 1.0f; } static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target) @@ -2490,6 +2491,8 @@ static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target) tumd->image = umd->image; tumd->flags = umd->flags; tumd->num_projectors = umd->num_projectors; + tumd->aspectx = umd->aspectx; + tumd->aspecty = umd->aspecty; } static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob, @@ -2531,7 +2534,7 @@ static void uvprojectModifier_updateDepgraph(ModifierData *md, typedef struct Projector { Object *ob; /* object this projector is derived from */ - float imat[4][4]; /* world space -> projector space matrix */ + float projmat[4][4]; /* projection matrix */ float normal[3]; /* projector normal in world space */ } Projector; @@ -2546,6 +2549,10 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, int new_tfaces = 0; Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; int num_projectors = 0; + float aspect; + + if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty; + else aspect = 1.0f; for(i = 0; i < umd->num_projectors; ++i) if(umd->projectors[i]) @@ -2573,38 +2580,79 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, for(i = 0, co = coords; i < numVerts; ++i, ++co) Mat4MulVecfl(ob->obmat, *co); - if(num_projectors == 1) { - float imat[4][4]; - - /* get projector space matrix */ - Mat4Invert(imat, projectors[0].ob->obmat); - if(projectors[0].ob->type == OB_CAMERA) { - Camera *cam = (Camera *)projectors[0].ob->data; - if(cam->type == CAM_ORTHO) - Mat4MulFloat3(imat[0], 1 / cam->ortho_scale); - } + /* calculate a projection matrix and normal for each projector */ + for(i = 0; i < num_projectors; ++i) { + float tmpmat[4][4]; + float offsetmat[4][4]; + + /* calculate projection matrix */ + Mat4Invert(projectors[i].projmat, projectors[i].ob->obmat); + + if(projectors[i].ob->type == OB_CAMERA) { + Camera *cam = (Camera *)projectors[i].ob->data; + if(cam->type == CAM_PERSP) { + float perspmat[4][4]; + float xmax; + float xmin; + float ymax; + float ymin; + float pixsize = cam->clipsta * 32.0 / cam->lens; + + if(aspect > 1.0f) { + xmax = 0.5f * pixsize; + ymax = xmax / aspect; + } else { + ymax = 0.5f * pixsize; + xmax = ymax * aspect; + } + xmin = -xmax; + ymin = -ymax; + + i_window(xmin, xmax, ymin, ymax, + cam->clipsta, cam->clipend, perspmat); + Mat4MulMat4(tmpmat, projectors[i].projmat, perspmat); + } else if(cam->type == CAM_ORTHO) { + float orthomat[4][4]; + float xmax; + float xmin; + float ymax; + float ymin; + + if(aspect > 1.0f) { + xmax = 0.5f * cam->ortho_scale; + ymax = xmax / aspect; + } else { + ymax = 0.5f * cam->ortho_scale; + xmax = ymax * aspect; + } + xmin = -xmax; + ymin = -ymax; - /* convert coords to projector space */ - for(i = 0, co = coords; i < numVerts; ++i, ++co) - Mat4MulVecfl(imat, *co); - } else { - /* calculate a world space -> projector space matrix and normal - * for each projector - */ - for(i = 0; i < num_projectors; ++i) { - Mat4Invert(projectors[i].imat, projectors[i].ob->obmat); - if(projectors[i].ob->type == OB_CAMERA) { - Camera *cam = (Camera *)projectors[i].ob->data; - if(cam->type == CAM_ORTHO) - Mat4MulFloat3(*projectors[i].imat, 1 / cam->ortho_scale); + i_ortho(xmin, xmax, ymin, ymax, + cam->clipsta, cam->clipend, orthomat); + Mat4MulMat4(tmpmat, projectors[i].projmat, orthomat); } - projectors[i].normal[0] = 0; - projectors[i].normal[1] = 0; - projectors[i].normal[2] = 1; - Mat4Mul3Vecfl(projectors[i].ob->obmat, projectors[i].normal); + } else { + Mat4CpyMat4(tmpmat, projectors[i].projmat); } + + Mat4One(offsetmat); + Mat4MulFloat3(offsetmat[0], 0.5); + offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5; + Mat4MulMat4(projectors[i].projmat, tmpmat, offsetmat); + + /* calculate worldspace projector normal (for best projector test) */ + projectors[i].normal[0] = 0; + projectors[i].normal[1] = 0; + projectors[i].normal[2] = 1; + Mat4Mul3Vecfl(projectors[i].ob->obmat, projectors[i].normal); } + /* if only one projector, project coords to UVs */ + if(num_projectors == 1) + for(i = 0, co = coords; i < numVerts; ++i, ++co) + Mat4MulVec3Project(projectors[0].projmat, *co); + mface = dm->getFaceArray(dm); numFaces = dm->getNumFaces(dm); @@ -2660,11 +2708,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } } - Mat4MulVecfl(best_projector->imat, co1); - Mat4MulVecfl(best_projector->imat, co2); - Mat4MulVecfl(best_projector->imat, co3); + Mat4MulVec3Project(best_projector->projmat, co1); + Mat4MulVec3Project(best_projector->projmat, co2); + Mat4MulVec3Project(best_projector->projmat, co3); if(mf->v4) - Mat4MulVecfl(best_projector->imat, co4); + Mat4MulVec3Project(best_projector->projmat, co4); /* apply transformed coords as UVs */ tface->uv[0][0] = co1[0]; diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index c478262d500..fa7c05cce7c 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -401,6 +401,11 @@ Mat3Clr( Mat3One( float m[][3] ); + void +Mat4MulVec3Project( + float mat[][4], + float *vec +); void Mat4MulVec( float mat[][4], diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index fd91a4231f6..de06fd3365d 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -838,6 +838,18 @@ void Mat4Mul3Vecfl( float mat[][4], float *vec) vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2]; } +void Mat4MulVec3Project(float mat[][4], float *vec) +{ + float w; + + w = vec[0]*mat[0][3] + vec[1]*mat[1][3] + vec[2]*mat[2][3] + mat[3][3]; + Mat4MulVecfl(mat, vec); + + vec[0] /= w; + vec[1] /= w; + vec[2] /= w; +} + void Mat4MulVec4fl( float mat[][4], float *vec) { float x,y,z; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 50cffb89872..1665c0da983 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -206,6 +206,7 @@ typedef struct UVProjectModifierData { struct Image *image; /* the image to project */ int flags; int num_projectors; + float aspectx, aspecty; } UVProjectModifierData; #define MOD_UVPROJECT_MAXPROJECTORS 10 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index b5e7d2b539e..78771cac20c 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1355,7 +1355,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco height = 124; if(dmd->texmapping == MOD_DISP_MAP_OBJECT) height += 19; } else if (md->type==eModifierType_UVProject) { - height = 67 + ((UVProjectModifierData *)md)->num_projectors * 19; + height = 86 + ((UVProjectModifierData *)md)->num_projectors * 19; } else if (md->type==eModifierType_Decimate) { height = 48; } else if (md->type==eModifierType_Wave) { @@ -1509,6 +1509,15 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco lx, (cy-=19), buttonWidth, 19, &umd->flags, 0, 0, 0, 0, "Add UV coordinates if missing"); + uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:", + lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx, + 1, 1000, 100, 2, + "Horizontal Aspect Ratio"); + uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:", + lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19, + &umd->aspecty, + 1, 1000, 100, 2, + "Vertical Aspect Ratio"); uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:", lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors, 1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0, |