Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * ***** END GPL LICENSE BLOCK ***** 00019 */ 00020 00026 #include <math.h> 00027 00028 #include "MEM_guardedalloc.h" 00029 00030 #include "DNA_camera_types.h" 00031 #include "DNA_object_types.h" 00032 00033 #include "BLI_math.h" 00034 #include "BLI_uvproject.h" 00035 00036 typedef struct UvCameraInfo { 00037 float camangle; 00038 float camsize; 00039 float xasp, yasp; 00040 float shiftx, shifty; 00041 float rotmat[4][4]; 00042 float caminv[4][4]; 00043 short do_persp, do_pano, do_rotmat; 00044 } UvCameraInfo; 00045 00046 void project_from_camera(float target[2], float source[3], UvCameraInfo *uci) 00047 { 00048 float pv4[4]; 00049 00050 copy_v3_v3(pv4, source); 00051 pv4[3]= 1.0; 00052 00053 /* rotmat is the object matrix in this case */ 00054 if(uci->do_rotmat) 00055 mul_m4_v4(uci->rotmat, pv4); 00056 00057 /* caminv is the inverse camera matrix */ 00058 mul_m4_v4(uci->caminv, pv4); 00059 00060 if(uci->do_pano) { 00061 float angle= atan2f(pv4[0], -pv4[2]) / ((float)M_PI * 2.0f); /* angle around the camera */ 00062 if (uci->do_persp==0) { 00063 target[0]= angle; /* no correct method here, just map to 0-1 */ 00064 target[1]= pv4[1] / uci->camsize; 00065 } 00066 else { 00067 float vec2d[2]; /* 2D position from the camera */ 00068 vec2d[0]= pv4[0]; 00069 vec2d[1]= pv4[2]; 00070 target[0]= angle * ((float)M_PI / uci->camangle); 00071 target[1]= pv4[1] / (len_v2(vec2d) * (uci->camsize * 2.0f)); 00072 } 00073 } 00074 else { 00075 if (pv4[2]==0.0f) pv4[2]= 0.00001f; /* don't allow div by 0 */ 00076 00077 if (uci->do_persp==0) { 00078 target[0]= (pv4[0]/uci->camsize); 00079 target[1]= (pv4[1]/uci->camsize); 00080 } 00081 else { 00082 target[0]= (-pv4[0]*((1.0f/uci->camsize)/pv4[2])) / 2.0f; 00083 target[1]= (-pv4[1]*((1.0f/uci->camsize)/pv4[2])) / 2.0f; 00084 } 00085 } 00086 00087 target[0] *= uci->xasp; 00088 target[1] *= uci->yasp; 00089 00090 /* adds camera shift + 0.5 */ 00091 target[0] += uci->shiftx; 00092 target[1] += uci->shifty; 00093 } 00094 00095 /* could rv3d->persmat */ 00096 void project_from_view(float target[2], float source[3], float persmat[4][4], float rotmat[4][4], float winx, float winy) 00097 { 00098 float pv[3], pv4[4], x= 0.0, y= 0.0; 00099 00100 mul_v3_m4v3(pv, rotmat, source); 00101 00102 copy_v3_v3(pv4, source); 00103 pv4[3]= 1.0; 00104 00105 /* rotmat is the object matrix in this case */ 00106 mul_m4_v4(rotmat, pv4); 00107 00108 /* almost project_short */ 00109 mul_m4_v4(persmat, pv4); 00110 if(fabsf(pv4[3]) > 0.00001f) { /* avoid division by zero */ 00111 target[0] = winx/2.0f + (winx/2.0f) * pv4[0] / pv4[3]; 00112 target[1] = winy/2.0f + (winy/2.0f) * pv4[1] / pv4[3]; 00113 } 00114 else { 00115 /* scaling is lost but give a valid result */ 00116 target[0] = winx/2.0f + (winx/2.0f) * pv4[0]; 00117 target[1] = winy/2.0f + (winy/2.0f) * pv4[1]; 00118 } 00119 00120 /* v3d->persmat seems to do this funky scaling */ 00121 if(winx > winy) { 00122 y= (winx - winy)/2.0f; 00123 winy = winx; 00124 } 00125 else { 00126 x= (winy - winx)/2.0f; 00127 winx = winy; 00128 } 00129 00130 target[0]= (x + target[0]) / winx; 00131 target[1]= (y + target[1]) / winy; 00132 } 00133 00134 /* 'rotmat' can be obedit->obmat when uv project is used. 00135 * 'winx' and 'winy' can be from scene->r.xsch/ysch */ 00136 UvCameraInfo *project_camera_info(Object *ob, float (*rotmat)[4], float winx, float winy) 00137 { 00138 UvCameraInfo uci; 00139 Camera *camera= ob->data; 00140 00141 uci.do_pano = (camera->flag & CAM_PANORAMA); 00142 uci.do_persp = (camera->type==CAM_PERSP); 00143 00144 uci.camangle= focallength_to_fov(camera->lens, camera->sensor_x) / 2.0f; 00145 uci.camsize= uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale; 00146 00147 /* account for scaled cameras */ 00148 copy_m4_m4(uci.caminv, ob->obmat); 00149 normalize_m4(uci.caminv); 00150 00151 if (invert_m4(uci.caminv)) { 00152 UvCameraInfo *uci_pt; 00153 00154 /* normal projection */ 00155 if(rotmat) { 00156 copy_m4_m4(uci.rotmat, rotmat); 00157 uci.do_rotmat= 1; 00158 } 00159 else { 00160 uci.do_rotmat= 0; 00161 } 00162 00163 /* also make aspect ratio adjustment factors */ 00164 if (winx > winy) { 00165 uci.xasp= 1.0f; 00166 uci.yasp= winx / winy; 00167 } 00168 else { 00169 uci.xasp= winy / winx; 00170 uci.yasp= 1.0f; 00171 } 00172 00173 /* include 0.5f here to move the UVs into the center */ 00174 uci.shiftx = 0.5f - (camera->shiftx * uci.xasp); 00175 uci.shifty = 0.5f - (camera->shifty * uci.yasp); 00176 00177 uci_pt= MEM_mallocN(sizeof(UvCameraInfo), "UvCameraInfo"); 00178 *uci_pt= uci; 00179 return uci_pt; 00180 } 00181 00182 return NULL; 00183 } 00184 00185 void project_from_view_ortho(float target[2], float source[3], float rotmat[4][4]) 00186 { 00187 float pv[3]; 00188 00189 mul_v3_m4v3(pv, rotmat, source); 00190 00191 /* ortho projection */ 00192 target[0] = -pv[0]; 00193 target[1] = pv[2]; 00194 } 00195 00196 00197 void project_camera_info_scale(UvCameraInfo *uci, float scale_x, float scale_y) 00198 { 00199 uci->xasp *= scale_x; 00200 uci->yasp *= scale_y; 00201 }