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 * The Original Code is Copyright (C) 2005 by the Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Daniel Dunbar 00022 * Ton Roosendaal, 00023 * Ben Batt, 00024 * Brecht Van Lommel, 00025 * Campbell Barton 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * 00029 */ 00030 00036 /* UV Project modifier: Generates UVs projected from an object */ 00037 00038 #include "DNA_meshdata_types.h" 00039 #include "DNA_camera_types.h" 00040 #include "DNA_object_types.h" 00041 #include "DNA_scene_types.h" 00042 00043 #include "BLI_math.h" 00044 #include "BLI_string.h" 00045 #include "BLI_uvproject.h" 00046 #include "BLI_utildefines.h" 00047 00048 00049 #include "BKE_camera.h" 00050 #include "BKE_DerivedMesh.h" 00051 00052 #include "MOD_modifiertypes.h" 00053 #include "MOD_util.h" 00054 00055 #include "MEM_guardedalloc.h" 00056 #include "depsgraph_private.h" 00057 00058 static void initData(ModifierData *md) 00059 { 00060 UVProjectModifierData *umd = (UVProjectModifierData*) md; 00061 int i; 00062 00063 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i) 00064 umd->projectors[i] = NULL; 00065 umd->image = NULL; 00066 umd->flags = 0; 00067 umd->num_projectors = 1; 00068 umd->aspectx = umd->aspecty = 1.0f; 00069 umd->scalex = umd->scaley = 1.0f; 00070 } 00071 00072 static void copyData(ModifierData *md, ModifierData *target) 00073 { 00074 UVProjectModifierData *umd = (UVProjectModifierData*) md; 00075 UVProjectModifierData *tumd = (UVProjectModifierData*) target; 00076 int i; 00077 00078 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i) 00079 tumd->projectors[i] = umd->projectors[i]; 00080 tumd->image = umd->image; 00081 tumd->flags = umd->flags; 00082 tumd->num_projectors = umd->num_projectors; 00083 tumd->aspectx = umd->aspectx; 00084 tumd->aspecty = umd->aspecty; 00085 tumd->scalex = umd->scalex; 00086 tumd->scaley = umd->scaley; 00087 BLI_strncpy(tumd->uvlayer_name, umd->uvlayer_name, sizeof(umd->uvlayer_name)); 00088 } 00089 00090 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) 00091 { 00092 CustomDataMask dataMask = 0; 00093 00094 /* ask for UV coordinates */ 00095 dataMask |= CD_MASK_MTFACE; 00096 00097 return dataMask; 00098 } 00099 00100 static void foreachObjectLink(ModifierData *md, Object *ob, 00101 ObjectWalkFunc walk, void *userData) 00102 { 00103 UVProjectModifierData *umd = (UVProjectModifierData*) md; 00104 int i; 00105 00106 for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i) 00107 walk(userData, ob, &umd->projectors[i]); 00108 } 00109 00110 static void foreachIDLink(ModifierData *md, Object *ob, 00111 IDWalkFunc walk, void *userData) 00112 { 00113 UVProjectModifierData *umd = (UVProjectModifierData*) md; 00114 00115 walk(userData, ob, (ID **)&umd->image); 00116 00117 foreachObjectLink(md, ob, (ObjectWalkFunc)walk, 00118 userData); 00119 } 00120 00121 static void updateDepgraph(ModifierData *md, DagForest *forest, 00122 struct Scene *UNUSED(scene), 00123 Object *UNUSED(ob), 00124 DagNode *obNode) 00125 { 00126 UVProjectModifierData *umd = (UVProjectModifierData*) md; 00127 int i; 00128 00129 for(i = 0; i < umd->num_projectors; ++i) { 00130 if(umd->projectors[i]) { 00131 DagNode *curNode = dag_get_node(forest, umd->projectors[i]); 00132 00133 dag_add_relation(forest, curNode, obNode, 00134 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "UV Project Modifier"); 00135 } 00136 } 00137 } 00138 00139 typedef struct Projector { 00140 Object *ob; /* object this projector is derived from */ 00141 float projmat[4][4]; /* projection matrix */ 00142 float normal[3]; /* projector normal in world space */ 00143 void *uci; /* optional uv-project info (panorama projection) */ 00144 } Projector; 00145 00146 static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, 00147 Object *ob, DerivedMesh *dm) 00148 { 00149 float (*coords)[3], (*co)[3]; 00150 MTFace *tface; 00151 int i, numVerts, numFaces; 00152 Image *image = umd->image; 00153 MFace *mface, *mf; 00154 int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0); 00155 Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; 00156 int num_projectors = 0; 00157 float aspect; 00158 char uvname[MAX_CUSTOMDATA_LAYER_NAME]; 00159 float aspx= umd->aspectx ? umd->aspectx : 1.0f; 00160 float aspy= umd->aspecty ? umd->aspecty : 1.0f; 00161 float scax= umd->scalex ? umd->scalex : 1.0f; 00162 float scay= umd->scaley ? umd->scaley : 1.0f; 00163 int free_uci= 0; 00164 00165 aspect = aspx / aspy; 00166 00167 for(i = 0; i < umd->num_projectors; ++i) 00168 if(umd->projectors[i]) 00169 projectors[num_projectors++].ob = umd->projectors[i]; 00170 00171 if(num_projectors == 0) return dm; 00172 00173 /* make sure there are UV Maps available */ 00174 00175 if(!CustomData_has_layer(&dm->faceData, CD_MTFACE)) return dm; 00176 00177 /* make sure we're using an existing layer */ 00178 CustomData_validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname); 00179 00180 /* calculate a projection matrix and normal for each projector */ 00181 for(i = 0; i < num_projectors; ++i) { 00182 float tmpmat[4][4]; 00183 float offsetmat[4][4]; 00184 Camera *cam = NULL; 00185 /* calculate projection matrix */ 00186 invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat); 00187 00188 projectors[i].uci= NULL; 00189 00190 if(projectors[i].ob->type == OB_CAMERA) { 00191 00192 cam = (Camera *)projectors[i].ob->data; 00193 if(cam->flag & CAM_PANORAMA) { 00194 projectors[i].uci= project_camera_info(projectors[i].ob, NULL, aspx, aspy); 00195 project_camera_info_scale(projectors[i].uci, scax, scay); 00196 free_uci= 1; 00197 } 00198 else { 00199 float sensor= camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); 00200 int sensor_fit= camera_sensor_fit(cam->sensor_fit, aspx, aspy); 00201 float scale= (cam->type == CAM_PERSP) ? cam->clipsta * sensor / cam->lens : cam->ortho_scale; 00202 float xmax, xmin, ymax, ymin; 00203 00204 if(sensor_fit==CAMERA_SENSOR_FIT_HOR) { 00205 xmax = 0.5f * scale; 00206 ymax = xmax / aspect; 00207 } 00208 else { 00209 ymax = 0.5f * scale; 00210 xmax = ymax * aspect; 00211 } 00212 00213 xmin = -xmax; 00214 ymin = -ymax; 00215 00216 /* scale the matrix */ 00217 xmin *= scax; 00218 xmax *= scax; 00219 ymin *= scay; 00220 ymax *= scay; 00221 00222 if(cam->type == CAM_PERSP) { 00223 float perspmat[4][4]; 00224 perspective_m4( perspmat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend); 00225 mult_m4_m4m4(tmpmat, perspmat, projectors[i].projmat); 00226 } else { /* if(cam->type == CAM_ORTHO) */ 00227 float orthomat[4][4]; 00228 orthographic_m4( orthomat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend); 00229 mult_m4_m4m4(tmpmat, orthomat, projectors[i].projmat); 00230 } 00231 } 00232 } else { 00233 copy_m4_m4(tmpmat, projectors[i].projmat); 00234 } 00235 00236 unit_m4(offsetmat); 00237 mul_mat3_m4_fl(offsetmat, 0.5); 00238 offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5; 00239 00240 if (cam) { 00241 if (aspx == aspy) { 00242 offsetmat[3][0] -= cam->shiftx; 00243 offsetmat[3][1] -= cam->shifty; 00244 } else if (aspx < aspy) { 00245 offsetmat[3][0] -=(cam->shiftx * aspy/aspx); 00246 offsetmat[3][1] -= cam->shifty; 00247 } else { 00248 offsetmat[3][0] -= cam->shiftx; 00249 offsetmat[3][1] -=(cam->shifty * aspx/aspy); 00250 } 00251 } 00252 00253 mult_m4_m4m4(projectors[i].projmat, offsetmat, tmpmat); 00254 00255 /* calculate worldspace projector normal (for best projector test) */ 00256 projectors[i].normal[0] = 0; 00257 projectors[i].normal[1] = 0; 00258 projectors[i].normal[2] = 1; 00259 mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); 00260 } 00261 00262 numFaces = dm->getNumFaces(dm); 00263 00264 /* make sure we are not modifying the original UV map */ 00265 tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, 00266 CD_MTFACE, uvname, numFaces); 00267 00268 numVerts = dm->getNumVerts(dm); 00269 00270 coords = MEM_callocN(sizeof(*coords) * numVerts, 00271 "uvprojectModifier_do coords"); 00272 dm->getVertCos(dm, coords); 00273 00274 /* convert coords to world space */ 00275 for(i = 0, co = coords; i < numVerts; ++i, ++co) 00276 mul_m4_v3(ob->obmat, *co); 00277 00278 /* if only one projector, project coords to UVs */ 00279 if(num_projectors == 1 && projectors[0].uci==NULL) 00280 for(i = 0, co = coords; i < numVerts; ++i, ++co) 00281 mul_project_m4_v3(projectors[0].projmat, *co); 00282 00283 mface = dm->getFaceArray(dm); 00284 00285 /* apply coords as UVs, and apply image if tfaces are new */ 00286 for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) { 00287 if(override_image || !image || tface->tpage == image) { 00288 if(num_projectors == 1) { 00289 if(projectors[0].uci) { 00290 unsigned int fidx= mf->v4 ? 3:2; 00291 do { 00292 unsigned int vidx= *(&mf->v1 + fidx); 00293 project_from_camera(tface->uv[fidx], coords[vidx], projectors[0].uci); 00294 } while (fidx--); 00295 } 00296 else { 00297 /* apply transformed coords as UVs */ 00298 unsigned int fidx= mf->v4 ? 3:2; 00299 do { 00300 unsigned int vidx= *(&mf->v1 + fidx); 00301 copy_v2_v2(tface->uv[fidx], coords[vidx]); 00302 } while (fidx--); 00303 } 00304 } else { 00305 /* multiple projectors, select the closest to face normal 00306 * direction 00307 */ 00308 float face_no[3]; 00309 int j; 00310 Projector *best_projector; 00311 float best_dot; 00312 00313 /* get the untransformed face normal */ 00314 if(mf->v4) { 00315 normal_quad_v3(face_no, coords[mf->v1], coords[mf->v2], coords[mf->v3], coords[mf->v4]); 00316 } else { 00317 normal_tri_v3(face_no, coords[mf->v1], coords[mf->v2], coords[mf->v3]); 00318 } 00319 00320 /* find the projector which the face points at most directly 00321 * (projector normal with largest dot product is best) 00322 */ 00323 best_dot = dot_v3v3(projectors[0].normal, face_no); 00324 best_projector = &projectors[0]; 00325 00326 for(j = 1; j < num_projectors; ++j) { 00327 float tmp_dot = dot_v3v3(projectors[j].normal, 00328 face_no); 00329 if(tmp_dot > best_dot) { 00330 best_dot = tmp_dot; 00331 best_projector = &projectors[j]; 00332 } 00333 } 00334 00335 if(best_projector->uci) { 00336 unsigned int fidx= mf->v4 ? 3:2; 00337 do { 00338 unsigned int vidx= *(&mf->v1 + fidx); 00339 project_from_camera(tface->uv[fidx], coords[vidx], best_projector->uci); 00340 } while (fidx--); 00341 } 00342 else { 00343 unsigned int fidx= mf->v4 ? 3:2; 00344 do { 00345 unsigned int vidx= *(&mf->v1 + fidx); 00346 float tco[3]; 00347 00348 copy_v3_v3(tco, coords[vidx]); 00349 mul_project_m4_v3(best_projector->projmat, tco); 00350 copy_v2_v2(tface->uv[fidx], tco); 00351 00352 } while (fidx--); 00353 } 00354 } 00355 } 00356 00357 if(override_image) { 00358 tface->tpage = image; 00359 } 00360 } 00361 00362 MEM_freeN(coords); 00363 00364 if(free_uci) { 00365 int j; 00366 for(j = 0; j < num_projectors; ++j) { 00367 if(projectors[j].uci) { 00368 MEM_freeN(projectors[j].uci); 00369 } 00370 } 00371 } 00372 return dm; 00373 } 00374 00375 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, 00376 DerivedMesh *derivedData, 00377 int UNUSED(useRenderParams), 00378 int UNUSED(isFinalCalc)) 00379 { 00380 DerivedMesh *result; 00381 UVProjectModifierData *umd = (UVProjectModifierData*) md; 00382 00383 result = uvprojectModifier_do(umd, ob, derivedData); 00384 00385 return result; 00386 } 00387 00388 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, 00389 struct EditMesh *UNUSED(editData), 00390 DerivedMesh *derivedData) 00391 { 00392 return applyModifier(md, ob, derivedData, 0, 1); 00393 } 00394 00395 00396 ModifierTypeInfo modifierType_UVProject = { 00397 /* name */ "UVProject", 00398 /* structName */ "UVProjectModifierData", 00399 /* structSize */ sizeof(UVProjectModifierData), 00400 /* type */ eModifierTypeType_NonGeometrical, 00401 /* flags */ eModifierTypeFlag_AcceptsMesh 00402 | eModifierTypeFlag_SupportsMapping 00403 | eModifierTypeFlag_SupportsEditmode 00404 | eModifierTypeFlag_EnableInEditmode, 00405 00406 /* copyData */ copyData, 00407 /* deformVerts */ NULL, 00408 /* deformMatrices */ NULL, 00409 /* deformVertsEM */ NULL, 00410 /* deformMatricesEM */ NULL, 00411 /* applyModifier */ applyModifier, 00412 /* applyModifierEM */ applyModifierEM, 00413 /* initData */ initData, 00414 /* requiredDataMask */ requiredDataMask, 00415 /* freeData */ NULL, 00416 /* isDisabled */ NULL, 00417 /* updateDepgraph */ updateDepgraph, 00418 /* dependsOnTime */ NULL, 00419 /* dependsOnNormals */ NULL, 00420 /* foreachObjectLink */ foreachObjectLink, 00421 /* foreachIDLink */ foreachIDLink, 00422 /* foreachTexLink */ NULL, 00423 };