diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-03-23 23:04:05 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-03-23 23:04:05 +0300 |
commit | c76a069bd16fe580ebb741493918a9793718f999 (patch) | |
tree | 468c7b10cdd62f1b3f0535d79510794ecc0cb4bf | |
parent | 169c4bf8a8f1853d482433ebae1e9de81cfd4b09 (diff) |
Panorama camera support for UV project modifier
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 139 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_uvproject.h | 1 | ||||
-rw-r--r-- | source/blender/blenlib/intern/uvproject.c | 19 |
3 files changed, 102 insertions, 57 deletions
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index b10456c53e0..8739a9c8b48 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -42,6 +42,7 @@ #include "BLI_kdtree.h" #include "BLI_rand.h" +#include "BLI_uvproject.h" #include "MEM_guardedalloc.h" @@ -3673,6 +3674,7 @@ typedef struct Projector { Object *ob; /* object this projector is derived from */ float projmat[4][4]; /* projection matrix */ float normal[3]; /* projector normal in world space */ + void *uci; /* optional uv-project info (panorama projection) */ } Projector; static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, @@ -3688,9 +3690,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, int num_projectors = 0; float aspect; char uvname[32]; + float aspx= umd->aspectx ? 1.0f : umd->aspectx; + float aspy= umd->aspecty ? 1.0f : umd->aspecty; + int free_uci= 0; - if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty; - else aspect = 1.0f; + aspect = aspx / aspy; for(i = 0; i < umd->num_projectors; ++i) if(umd->projectors[i]) @@ -3705,20 +3709,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, /* make sure we're using an existing layer */ validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname); - /* make sure we are not modifying the original UV layer */ - tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, - CD_MTFACE, uvname); - - numVerts = dm->getNumVerts(dm); - - coords = MEM_callocN(sizeof(*coords) * numVerts, - "uvprojectModifier_do coords"); - dm->getVertCos(dm, coords); - - /* convert coords to world space */ - for(i = 0, co = coords; i < numVerts; ++i, ++co) - mul_m4_v3(ob->obmat, *co); - /* calculate a projection matrix and normal for each projector */ for(i = 0; i < num_projectors; ++i) { float tmpmat[4][4]; @@ -3729,7 +3719,13 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, if(projectors[i].ob->type == OB_CAMERA) { cam = (Camera *)projectors[i].ob->data; - if(cam->type == CAM_PERSP) { + projectors[i].uci= NULL; + + if(cam->flag & CAM_PANORAMA) { + projectors[i].uci= project_camera_info(projectors[i].ob, NULL, aspx, aspy); + free_uci= 1; + } + else if(cam->type == CAM_PERSP) { float perspmat[4][4]; float xmax; float xmin; @@ -3778,15 +3774,15 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5; if (cam) { - if (umd->aspectx == umd->aspecty) { + if (aspx == aspy) { offsetmat[3][0] -= cam->shiftx; offsetmat[3][1] -= cam->shifty; - } else if (umd->aspectx < umd->aspecty) { - offsetmat[3][0] -=(cam->shiftx * umd->aspecty/umd->aspectx); + } else if (aspx < aspy) { + offsetmat[3][0] -=(cam->shiftx * aspy/aspx); offsetmat[3][1] -= cam->shifty; } else { offsetmat[3][0] -= cam->shiftx; - offsetmat[3][1] -=(cam->shifty * umd->aspectx/umd->aspecty); + offsetmat[3][1] -=(cam->shifty * aspx/aspy); } } @@ -3799,8 +3795,23 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); } + /* make sure we are not modifying the original UV layer */ + tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, + CD_MTFACE, uvname); + + + numVerts = dm->getNumVerts(dm); + + coords = MEM_callocN(sizeof(*coords) * numVerts, + "uvprojectModifier_do coords"); + dm->getVertCos(dm, coords); + + /* convert coords to world space */ + for(i = 0, co = coords; i < numVerts; ++i, ++co) + mul_m4_v3(ob->obmat, *co); + /* if only one projector, project coords to UVs */ - if(num_projectors == 1) + if(num_projectors == 1 && projectors[0].uci==NULL) for(i = 0, co = coords; i < numVerts; ++i, ++co) mul_project_m4_v4(projectors[0].projmat, *co); @@ -3810,17 +3821,26 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, /* apply coords as UVs, and apply image if tfaces are new */ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) { if(override_image || !image || tface->tpage == image) { - if(num_projectors == 1) { - /* apply transformed coords as UVs */ - tface->uv[0][0] = coords[mf->v1][0]; - tface->uv[0][1] = coords[mf->v1][1]; - tface->uv[1][0] = coords[mf->v2][0]; - tface->uv[1][1] = coords[mf->v2][1]; - tface->uv[2][0] = coords[mf->v3][0]; - tface->uv[2][1] = coords[mf->v3][1]; - if(mf->v4) { - tface->uv[3][0] = coords[mf->v4][0]; - tface->uv[3][1] = coords[mf->v4][1]; + if(num_projectors == 1) { + if(projectors[0].uci) { + project_from_camera(tface->uv[0], coords[mf->v1], projectors[0].uci); + project_from_camera(tface->uv[1], coords[mf->v2], projectors[0].uci); + project_from_camera(tface->uv[2], coords[mf->v3], projectors[0].uci); + if(mf->v3) + project_from_camera(tface->uv[3], coords[mf->v4], projectors[0].uci); + } + else { + /* apply transformed coords as UVs */ + tface->uv[0][0] = coords[mf->v1][0]; + tface->uv[0][1] = coords[mf->v1][1]; + tface->uv[1][0] = coords[mf->v2][0]; + tface->uv[1][1] = coords[mf->v2][1]; + tface->uv[2][0] = coords[mf->v3][0]; + tface->uv[2][1] = coords[mf->v3][1]; + if(mf->v4) { + tface->uv[3][0] = coords[mf->v4][0]; + tface->uv[3][1] = coords[mf->v4][1]; + } } } else { /* multiple projectors, select the closest to face normal @@ -3858,23 +3878,32 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, best_projector = &projectors[j]; } } - - mul_project_m4_v4(best_projector->projmat, co1); - mul_project_m4_v4(best_projector->projmat, co2); - mul_project_m4_v4(best_projector->projmat, co3); - if(mf->v4) - mul_project_m4_v4(best_projector->projmat, co4); - - /* apply transformed coords as UVs */ - tface->uv[0][0] = co1[0]; - tface->uv[0][1] = co1[1]; - tface->uv[1][0] = co2[0]; - tface->uv[1][1] = co2[1]; - tface->uv[2][0] = co3[0]; - tface->uv[2][1] = co3[1]; - if(mf->v4) { - tface->uv[3][0] = co4[0]; - tface->uv[3][1] = co4[1]; + + if(best_projector->uci) { + project_from_camera(tface->uv[0], coords[mf->v1], best_projector->uci); + project_from_camera(tface->uv[1], coords[mf->v2], best_projector->uci); + project_from_camera(tface->uv[2], coords[mf->v3], best_projector->uci); + if(mf->v3) + project_from_camera(tface->uv[3], coords[mf->v4], best_projector->uci); + } + else { + mul_project_m4_v4(best_projector->projmat, co1); + mul_project_m4_v4(best_projector->projmat, co2); + mul_project_m4_v4(best_projector->projmat, co3); + if(mf->v4) + mul_project_m4_v4(best_projector->projmat, co4); + + /* apply transformed coords as UVs */ + tface->uv[0][0] = co1[0]; + tface->uv[0][1] = co1[1]; + tface->uv[1][0] = co2[0]; + tface->uv[1][1] = co2[1]; + tface->uv[2][0] = co3[0]; + tface->uv[2][1] = co3[1]; + if(mf->v4) { + tface->uv[3][0] = co4[0]; + tface->uv[3][1] = co4[1]; + } } } } @@ -3886,7 +3915,15 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } MEM_freeN(coords); - + + if(free_uci) { + int j; + for(j = 0; j < num_projectors; ++j) { + if(projectors[j].uci) { + MEM_freeN(projectors[j].uci); + } + } + } return dm; } diff --git a/source/blender/blenlib/BLI_uvproject.h b/source/blender/blenlib/BLI_uvproject.h index 8e9a85136bb..a77ca60fc15 100644 --- a/source/blender/blenlib/BLI_uvproject.h +++ b/source/blender/blenlib/BLI_uvproject.h @@ -23,6 +23,7 @@ #define BKE_UVPROJECT_H struct UvCameraInfo; +struct Object; /* create uv info from the camera, needs to be freed */ struct UvCameraInfo *project_camera_info(struct Object *ob, float rotmat[4][4], float winx, float winy); diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c index d6ba2d7da94..273cb01ce1c 100644 --- a/source/blender/blenlib/intern/uvproject.c +++ b/source/blender/blenlib/intern/uvproject.c @@ -36,7 +36,7 @@ typedef struct UvCameraInfo { float shiftx, shifty; float rotmat[4][4]; float caminv[4][4]; - short do_persp, do_pano; + short do_persp, do_pano, do_rotmat; } UvCameraInfo; void project_from_camera(float target[2], float source[3], UvCameraInfo *uci) @@ -47,7 +47,8 @@ void project_from_camera(float target[2], float source[3], UvCameraInfo *uci) pv4[3]= 1.0; /* rotmat is the object matrix in this case */ - mul_m4_v4(uci->rotmat, pv4); + if(uci->do_rotmat) + mul_m4_v4(uci->rotmat, pv4); /* caminv is the inverse camera matrix */ mul_m4_v4(uci->caminv, pv4); @@ -87,7 +88,7 @@ void project_from_view(float target[2], float source[3], float persmat[4][4], fl { float pv[3], pv4[4], x= 0.0, y= 0.0; - mul_m4_v3(rotmat, pv); + mul_v3_m4v3(pv, rotmat, source); copy_v3_v3(pv4, source); pv4[3]= 1.0; @@ -123,7 +124,7 @@ void project_from_view(float target[2], float source[3], float persmat[4][4], fl /* 'rotmat' can be obedit->obmat when uv project is used. * 'winx' and 'winy' can be from scene->r.xsch/ysch */ -UvCameraInfo *project_camera_info(Object *ob, float rotmat[4][4], float winx, float winy) +UvCameraInfo *project_camera_info(Object *ob, float (*rotmat)[4], float winx, float winy) { UvCameraInfo uci; Camera *camera= ob->data; @@ -138,7 +139,13 @@ UvCameraInfo *project_camera_info(Object *ob, float rotmat[4][4], float winx, fl UvCameraInfo *uci_pt; /* normal projection */ - copy_m4_m4(uci.rotmat, rotmat); + if(rotmat) { + copy_m4_m4(uci.rotmat, rotmat); + uci.do_rotmat= 1; + } + else { + uci.do_rotmat= 0; + } /* also make aspect ratio adjustment factors */ if (winx > winy) { @@ -166,7 +173,7 @@ void project_from_view_ortho(float target[2], float source[3], float rotmat[4][4 { float pv[3]; - mul_m4_v3(rotmat, pv); + mul_v3_m4v3(pv, rotmat, source); /* ortho projection */ target[0] = -pv[0]; |