[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [27698] trunk/blender/source/blender: Panorama camera support for UV project modifier

Campbell Barton ideasman42 at gmail.com
Tue Mar 23 21:04:08 CET 2010


Revision: 27698
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=27698
Author:   campbellbarton
Date:     2010-03-23 21:04:05 +0100 (Tue, 23 Mar 2010)

Log Message:
-----------
Panorama camera support for UV project modifier

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/modifier.c
    trunk/blender/source/blender/blenlib/BLI_uvproject.h
    trunk/blender/source/blender/blenlib/intern/uvproject.c

Modified: trunk/blender/source/blender/blenkernel/intern/modifier.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/modifier.c	2010-03-23 19:00:48 UTC (rev 27697)
+++ trunk/blender/source/blender/blenkernel/intern/modifier.c	2010-03-23 20:04:05 UTC (rev 27698)
@@ -42,6 +42,7 @@
 
 #include "BLI_kdtree.h"
 #include "BLI_rand.h"
+#include "BLI_uvproject.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -3673,6 +3674,7 @@
 	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 @@
 	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 @@
 	/* 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 @@
 
 		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 @@
 		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 @@
 		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 @@
 	/* 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 @@
 						best_projector = &projectors[j];
 					}
 				}
+				
+				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);
 
-				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];
+					/* 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 @@
 	}
 
 	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;
 }
 

Modified: trunk/blender/source/blender/blenlib/BLI_uvproject.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_uvproject.h	2010-03-23 19:00:48 UTC (rev 27697)
+++ trunk/blender/source/blender/blenlib/BLI_uvproject.h	2010-03-23 20:04:05 UTC (rev 27698)
@@ -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);

Modified: trunk/blender/source/blender/blenlib/intern/uvproject.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/uvproject.c	2010-03-23 19:00:48 UTC (rev 27697)
+++ trunk/blender/source/blender/blenlib/intern/uvproject.c	2010-03-23 20:04:05 UTC (rev 27698)
@@ -36,7 +36,7 @@
 	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 @@
 	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 @@
 {
 	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 @@
 
 /* '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 *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 @@
 {
 	float pv[3];
 
-	mul_m4_v3(rotmat, pv);
+	mul_v3_m4v3(pv, rotmat, source);
 
 	/* ortho projection */
 	target[0] = -pv[0];





More information about the Bf-blender-cvs mailing list