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) 2007 by Nicholas Bishop 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include "MEM_guardedalloc.h" 00034 00035 /* for reading old multires */ 00036 #define DNA_DEPRECATED_ALLOW 00037 00038 #include "DNA_mesh_types.h" 00039 #include "DNA_meshdata_types.h" 00040 #include "DNA_object_types.h" 00041 #include "DNA_scene_types.h" 00042 00043 #include "BLI_blenlib.h" 00044 #include "BLI_math.h" 00045 #include "BLI_pbvh.h" 00046 #include "BLI_editVert.h" 00047 #include "BLI_utildefines.h" 00048 00049 #include "BKE_cdderivedmesh.h" 00050 #include "BKE_mesh.h" 00051 #include "BKE_modifier.h" 00052 #include "BKE_multires.h" 00053 #include "BKE_paint.h" 00054 #include "BKE_scene.h" 00055 #include "BKE_subsurf.h" 00056 00057 #include "BKE_object.h" 00058 00059 #include "CCGSubSurf.h" 00060 00061 #include <math.h> 00062 #include <string.h> 00063 00064 /* MULTIRES MODIFIER */ 00065 static const int multires_max_levels = 13; 00066 static const int multires_grid_tot[] = {0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; 00067 static const int multires_side_tot[] = {0, 2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; 00068 00069 static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert); 00070 static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl); 00071 00072 DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob) 00073 { 00074 ModifierData *md= (ModifierData *)mmd; 00075 ModifierTypeInfo *mti = modifierType_getInfo(md->type); 00076 DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); 00077 DerivedMesh *dm; 00078 00079 dm = mti->applyModifier(md, ob, tdm, 0, 1); 00080 if (dm == tdm) { 00081 dm = CDDM_copy(tdm); 00082 } 00083 00084 return dm; 00085 } 00086 00087 MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData *lastmd) 00088 { 00089 ModifierData *md; 00090 00091 for(md = lastmd; md; md = md->prev) { 00092 if(md->type == eModifierType_Multires) { 00093 if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) 00094 return (MultiresModifierData*)md; 00095 } 00096 } 00097 00098 return NULL; 00099 } 00100 00101 /* used for applying scale on mdisps layer and syncing subdivide levels when joining objects 00102 use_first - return first multires modifier if all multires'es are disabled 00103 */ 00104 MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, int use_first) 00105 { 00106 ModifierData *md; 00107 MultiresModifierData *mmd= NULL, *firstmmd= NULL; 00108 00109 /* find first active multires modifier */ 00110 for(md = ob->modifiers.first; md; md = md->next) { 00111 if(md->type == eModifierType_Multires) { 00112 if(!firstmmd) 00113 firstmmd= (MultiresModifierData*)md; 00114 00115 if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { 00116 mmd= (MultiresModifierData*)md; 00117 break; 00118 } 00119 } 00120 } 00121 00122 if(!mmd && use_first) { 00123 /* active multires have not been found 00124 try to use first one */ 00125 return firstmmd; 00126 } 00127 00128 return mmd; 00129 } 00130 00131 static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render) 00132 { 00133 if(render) 00134 return (mmd->modifier.scene)? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl): mmd->renderlvl; 00135 else if(ob->mode == OB_MODE_SCULPT) 00136 return mmd->sculptlvl; 00137 else 00138 return (mmd->modifier.scene)? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl): mmd->lvl; 00139 } 00140 00141 static void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) 00142 { 00143 mmd->totlvl = lvl; 00144 00145 if(ob->mode != OB_MODE_SCULPT) 00146 mmd->lvl = CLAMPIS(MAX2(mmd->lvl, lvl), 0, mmd->totlvl); 00147 00148 mmd->sculptlvl = CLAMPIS(MAX2(mmd->sculptlvl, lvl), 0, mmd->totlvl); 00149 mmd->renderlvl = CLAMPIS(MAX2(mmd->renderlvl, lvl), 0, mmd->totlvl); 00150 } 00151 00152 static void multires_dm_mark_as_modified(DerivedMesh *dm) 00153 { 00154 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; 00155 ccgdm->multires.modified = 1; 00156 } 00157 00158 void multires_mark_as_modified(Object *ob) 00159 { 00160 if(ob && ob->derivedFinal) 00161 multires_dm_mark_as_modified(ob->derivedFinal); 00162 } 00163 00164 void multires_force_update(Object *ob) 00165 { 00166 if(ob) { 00167 if(ob->derivedFinal) { 00168 ob->derivedFinal->needsFree =1; 00169 ob->derivedFinal->release(ob->derivedFinal); 00170 ob->derivedFinal = NULL; 00171 } 00172 if(ob->sculpt && ob->sculpt->pbvh) { 00173 BLI_pbvh_free(ob->sculpt->pbvh); 00174 ob->sculpt->pbvh= NULL; 00175 } 00176 } 00177 } 00178 00179 void multires_force_external_reload(Object *ob) 00180 { 00181 Mesh *me = get_mesh(ob); 00182 00183 CustomData_external_reload(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); 00184 multires_force_update(ob); 00185 } 00186 00187 void multires_force_render_update(Object *ob) 00188 { 00189 if(ob && (ob->mode & OB_MODE_SCULPT) && modifiers_findByType(ob, eModifierType_Multires)) 00190 multires_force_update(ob); 00191 } 00192 00193 int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd, 00194 Object *ob, DerivedMesh *srcdm) 00195 { 00196 DerivedMesh *mrdm = get_multires_dm (scene, mmd, ob); 00197 00198 if(mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) { 00199 multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm)); 00200 00201 multires_dm_mark_as_modified(mrdm); 00202 multires_force_update(ob); 00203 00204 mrdm->release(mrdm); 00205 00206 return 1; 00207 } 00208 00209 if(mrdm) mrdm->release(mrdm); 00210 00211 return 0; 00212 } 00213 00214 /* Returns 1 on success, 0 if the src's totvert doesn't match */ 00215 int multiresModifier_reshape(Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src) 00216 { 00217 DerivedMesh *srcdm = mesh_get_derived_final(scene, src, CD_MASK_BAREMESH); 00218 return multiresModifier_reshapeFromDM(scene, mmd, dst, srcdm); 00219 } 00220 00221 int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd, 00222 Object *ob, ModifierData *md) 00223 { 00224 ModifierTypeInfo *mti = modifierType_getInfo(md->type); 00225 DerivedMesh *dm, *ndm; 00226 int numVerts, result; 00227 float (*deformedVerts)[3]; 00228 00229 if(multires_get_level(ob, mmd, 0) == 0) 00230 return 0; 00231 00232 /* Create DerivedMesh for deformation modifier */ 00233 dm = get_multires_dm(scene, mmd, ob); 00234 numVerts= dm->getNumVerts(dm); 00235 deformedVerts= MEM_callocN(sizeof(float)*numVerts*3, "multiresReshape_deformVerts"); 00236 00237 dm->getVertCos(dm, deformedVerts); 00238 mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0, 0); 00239 00240 ndm= CDDM_copy(dm); 00241 CDDM_apply_vert_coords(ndm, deformedVerts); 00242 00243 MEM_freeN(deformedVerts); 00244 dm->release(dm); 00245 00246 /* Reshaping */ 00247 result= multiresModifier_reshapeFromDM(scene, mmd, ob, ndm); 00248 00249 /* Cleanup */ 00250 ndm->release(ndm); 00251 00252 return result; 00253 } 00254 00255 /* reset the multires levels to match the number of mdisps */ 00256 static int get_levels_from_disps(Object *ob) 00257 { 00258 Mesh *me = ob->data; 00259 MDisps *mdisp; 00260 int i, totlvl= 0; 00261 00262 mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS); 00263 00264 for(i = 0; i < me->totface; ++i, ++mdisp) { 00265 int S = me->mface[i].v4 ? 4 : 3; 00266 00267 if(mdisp->totdisp == 0) continue; 00268 00269 while(1) { 00270 int side = (1 << (totlvl-1)) + 1; 00271 int lvl_totdisp = side*side*S; 00272 if(mdisp->totdisp == lvl_totdisp) 00273 break; 00274 else if(mdisp->totdisp < lvl_totdisp) 00275 --totlvl; 00276 else 00277 ++totlvl; 00278 00279 } 00280 } 00281 00282 return totlvl; 00283 } 00284 00285 /* reset the multires levels to match the number of mdisps */ 00286 void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob) 00287 { 00288 Mesh *me = ob->data; 00289 MDisps *mdisp; 00290 00291 if(me->edit_mesh) 00292 mdisp = CustomData_get_layer(&me->edit_mesh->fdata, CD_MDISPS); 00293 else 00294 mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS); 00295 00296 if(mdisp) { 00297 mmd->totlvl = get_levels_from_disps(ob); 00298 mmd->lvl = MIN2(mmd->sculptlvl, mmd->totlvl); 00299 mmd->sculptlvl = MIN2(mmd->sculptlvl, mmd->totlvl); 00300 mmd->renderlvl = MIN2(mmd->renderlvl, mmd->totlvl); 00301 } 00302 } 00303 00304 static void multires_set_tot_mdisps(Mesh *me, int lvl) 00305 { 00306 MDisps *mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); 00307 int i; 00308 00309 if(mdisps) { 00310 for(i = 0; i < me->totface; i++) { 00311 if(mdisps[i].totdisp == 0) { 00312 int nvert = (me->mface[i].v4)? 4: 3; 00313 mdisps[i].totdisp = multires_grid_tot[lvl]*nvert; 00314 } 00315 } 00316 } 00317 } 00318 00319 static void multires_reallocate_mdisps(Mesh *me, MDisps *mdisps, int lvl) 00320 { 00321 int i; 00322 00323 /* reallocate displacements to be filled in */ 00324 for(i = 0; i < me->totface; ++i) { 00325 int nvert = (me->mface[i].v4)? 4: 3; 00326 int totdisp = multires_grid_tot[lvl]*nvert; 00327 float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); 00328 00329 if(mdisps[i].disps) 00330 MEM_freeN(mdisps[i].disps); 00331 00332 mdisps[i].disps = disps; 00333 mdisps[i].totdisp = totdisp; 00334 } 00335 } 00336 00337 static void column_vectors_to_mat3(float mat[][3], float v1[3], float v2[3], float v3[3]) 00338 { 00339 copy_v3_v3(mat[0], v1); 00340 copy_v3_v3(mat[1], v2); 00341 copy_v3_v3(mat[2], v3); 00342 } 00343 00344 static void multires_copy_grid(float (*gridA)[3], float (*gridB)[3], int sizeA, int sizeB) 00345 { 00346 int x, y, j, skip; 00347 00348 if(sizeA > sizeB) { 00349 skip = (sizeA-1)/(sizeB-1); 00350 00351 for(j = 0, y = 0; y < sizeB; y++) 00352 for(x = 0; x < sizeB; x++, j++) 00353 copy_v3_v3(gridA[y*skip*sizeA + x*skip], gridB[j]); 00354 } 00355 else { 00356 skip = (sizeB-1)/(sizeA-1); 00357 00358 for(j = 0, y = 0; y < sizeA; y++) 00359 for(x = 0; x < sizeA; x++, j++) 00360 copy_v3_v3(gridA[j], gridB[y*skip*sizeB + x*skip]); 00361 } 00362 } 00363 00364 static void multires_copy_dm_grid(DMGridData *gridA, DMGridData *gridB, int sizeA, int sizeB) 00365 { 00366 int x, y, j, skip; 00367 00368 if(sizeA > sizeB) { 00369 skip = (sizeA-1)/(sizeB-1); 00370 00371 for(j = 0, y = 0; y < sizeB; y++) 00372 for(x = 0; x < sizeB; x++, j++) 00373 copy_v3_v3(gridA[y*skip*sizeA + x*skip].co, gridB[j].co); 00374 } 00375 else { 00376 skip = (sizeB-1)/(sizeA-1); 00377 00378 for(j = 0, y = 0; y < sizeA; y++) 00379 for(x = 0; x < sizeA; x++, j++) 00380 copy_v3_v3(gridA[j].co, gridB[y*skip*sizeB + x*skip].co); 00381 } 00382 } 00383 00384 static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) 00385 { 00386 Mesh *me = (Mesh*)ob->data; 00387 int levels = mmd->totlvl - lvl; 00388 MDisps *mdisps; 00389 00390 multires_set_tot_mdisps(me, mmd->totlvl); 00391 CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); 00392 mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); 00393 00394 multires_force_update(ob); 00395 00396 if(mdisps && levels > 0) { 00397 if(lvl > 0) { 00398 int nsize = multires_side_tot[lvl]; 00399 int hsize = multires_side_tot[mmd->totlvl]; 00400 int i; 00401 00402 for(i = 0; i < me->totface; ++i) { 00403 MDisps *mdisp= &mdisps[i]; 00404 float (*disps)[3], (*ndisps)[3], (*hdisps)[3]; 00405 int nvert = (me->mface[i].v4)? 4: 3; 00406 int totdisp = multires_grid_tot[lvl]*nvert; 00407 int S; 00408 00409 disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); 00410 00411 ndisps = disps; 00412 hdisps = mdisp->disps; 00413 00414 for(S = 0; S < nvert; S++) { 00415 multires_copy_grid(ndisps, hdisps, nsize, hsize); 00416 00417 ndisps += nsize*nsize; 00418 hdisps += hsize*hsize; 00419 } 00420 00421 MEM_freeN(mdisp->disps); 00422 mdisp->disps = disps; 00423 mdisp->totdisp = totdisp; 00424 } 00425 } 00426 else { 00427 CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface); 00428 CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); 00429 } 00430 } 00431 00432 multires_set_tot_level(ob, mmd, lvl); 00433 } 00434 00435 /* direction=1 for delete higher, direction=0 for lower (not implemented yet) */ 00436 void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction) 00437 { 00438 Mesh *me = get_mesh(ob); 00439 int lvl = multires_get_level(ob, mmd, 0); 00440 int levels = mmd->totlvl - lvl; 00441 MDisps *mdisps; 00442 00443 multires_set_tot_mdisps(me, mmd->totlvl); 00444 CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); 00445 mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); 00446 00447 multires_force_update(ob); 00448 00449 if(mdisps && levels > 0 && direction == 1) { 00450 multires_del_higher(mmd, ob, lvl); 00451 } 00452 00453 multires_set_tot_level(ob, mmd, lvl); 00454 } 00455 00456 static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple) 00457 { 00458 MultiresModifierData mmd= {{NULL}}; 00459 00460 mmd.lvl = lvl; 00461 mmd.sculptlvl = lvl; 00462 mmd.renderlvl = lvl; 00463 mmd.totlvl = totlvl; 00464 mmd.simple = simple; 00465 00466 return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0); 00467 } 00468 00469 static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal, int plain_uv) 00470 { 00471 SubsurfModifierData smd= {{NULL}}; 00472 00473 smd.levels = smd.renderLevels = lvl; 00474 if(!plain_uv) 00475 smd.flags |= eSubsurfModifierFlag_SubsurfUv; 00476 if(simple) 00477 smd.subdivType = ME_SIMPLE_SUBSURF; 00478 if(optimal) 00479 smd.flags |= eSubsurfModifierFlag_ControlEdges; 00480 00481 return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0, (ob->mode & OB_MODE_EDIT)); 00482 } 00483 00484 00485 00486 /* assumes no is normalized; return value's sign is negative if v is on 00487 the other side of the plane */ 00488 static float v3_dist_from_plane(float v[3], float center[3], float no[3]) 00489 { 00490 float s[3]; 00491 sub_v3_v3v3(s, v, center); 00492 return dot_v3v3(s, no); 00493 } 00494 00495 void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) 00496 { 00497 DerivedMesh *cddm, *dispdm, *origdm; 00498 Mesh *me; 00499 ListBase *fmap; 00500 float (*origco)[3]; 00501 int i, j, offset, totlvl; 00502 00503 multires_force_update(ob); 00504 00505 me = get_mesh(ob); 00506 totlvl = mmd->totlvl; 00507 00508 /* nothing to do */ 00509 if(!totlvl) 00510 return; 00511 00512 /* XXX - probably not necessary to regenerate the cddm so much? */ 00513 00514 /* generate highest level with displacements */ 00515 cddm = CDDM_from_mesh(me, NULL); 00516 DM_set_only_copy(cddm, CD_MASK_BAREMESH); 00517 dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0); 00518 cddm->release(cddm); 00519 00520 /* copy the new locations of the base verts into the mesh */ 00521 offset = dispdm->getNumVerts(dispdm) - me->totvert; 00522 for(i = 0; i < me->totvert; ++i) { 00523 dispdm->getVertCo(dispdm, offset + i, me->mvert[i].co); 00524 } 00525 00526 /* heuristic to produce a better-fitting base mesh */ 00527 00528 cddm = CDDM_from_mesh(me, NULL); 00529 fmap = cddm->getFaceMap(ob, cddm); 00530 origco = MEM_callocN(sizeof(float)*3*me->totvert, "multires apply base origco"); 00531 for(i = 0; i < me->totvert ;++i) 00532 copy_v3_v3(origco[i], me->mvert[i].co); 00533 00534 for(i = 0; i < me->totvert; ++i) { 00535 IndexNode *n; 00536 float avg_no[3] = {0,0,0}, center[3] = {0,0,0}, push[3]; 00537 float dist; 00538 int tot; 00539 00540 /* don't adjust verts not used by at least one face */ 00541 if(!fmap[i].first) 00542 continue; 00543 00544 /* find center */ 00545 for(n = fmap[i].first, tot = 0; n; n = n->next) { 00546 MFace *f = &me->mface[n->index]; 00547 int S = f->v4 ? 4 : 3; 00548 00549 /* this double counts, not sure if that's bad or good */ 00550 for(j = 0; j < S; ++j) { 00551 int vndx = (&f->v1)[j]; 00552 if(vndx != i) { 00553 add_v3_v3(center, origco[vndx]); 00554 ++tot; 00555 } 00556 } 00557 } 00558 mul_v3_fl(center, 1.0f / tot); 00559 00560 /* find normal */ 00561 for(n = fmap[i].first; n; n = n->next) { 00562 MFace *f = &me->mface[n->index]; 00563 int S = f->v4 ? 4 : 3; 00564 float v[4][3], no[3]; 00565 00566 for(j = 0; j < S; ++j) { 00567 int vndx = (&f->v1)[j]; 00568 if(vndx == i) 00569 copy_v3_v3(v[j], center); 00570 else 00571 copy_v3_v3(v[j], origco[vndx]); 00572 } 00573 00574 if(S == 4) 00575 normal_quad_v3(no, v[0], v[1], v[2], v[3]); 00576 else 00577 normal_tri_v3(no, v[0], v[1], v[2]); 00578 add_v3_v3(avg_no, no); 00579 } 00580 normalize_v3(avg_no); 00581 00582 /* push vertex away from the plane */ 00583 dist = v3_dist_from_plane(me->mvert[i].co, center, avg_no); 00584 copy_v3_v3(push, avg_no); 00585 mul_v3_fl(push, dist); 00586 add_v3_v3(me->mvert[i].co, push); 00587 00588 } 00589 00590 MEM_freeN(origco); 00591 cddm->release(cddm); 00592 00593 /* subdivide the mesh to highest level without displacements */ 00594 cddm = CDDM_from_mesh(me, NULL); 00595 DM_set_only_copy(cddm, CD_MASK_BAREMESH); 00596 origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0, mmd->flags & eMultiresModifierFlag_PlainUv); 00597 cddm->release(cddm); 00598 00599 /* calc disps */ 00600 multiresModifier_disp_run(dispdm, me, 1, 0, origdm->getGridData(origdm), totlvl); 00601 00602 origdm->release(origdm); 00603 dispdm->release(dispdm); 00604 } 00605 00606 static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl, int updateblock, int simple) 00607 { 00608 Mesh *me = ob->data; 00609 MDisps *mdisps; 00610 int lvl= mmd->totlvl; 00611 00612 if(totlvl > multires_max_levels) 00613 return; 00614 00615 multires_force_update(ob); 00616 00617 mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); 00618 if(!mdisps) 00619 mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); 00620 00621 if(mdisps->disps && !updateblock && totlvl > 1) { 00622 /* upsample */ 00623 DerivedMesh *lowdm, *cddm, *highdm; 00624 DMGridData **highGridData, **lowGridData, **subGridData; 00625 CCGSubSurf *ss; 00626 int i, numGrids, highGridSize, lowGridSize; 00627 00628 /* create subsurf DM from original mesh at high level */ 00629 cddm = CDDM_from_mesh(me, NULL); 00630 DM_set_only_copy(cddm, CD_MASK_BAREMESH); 00631 highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); 00632 00633 /* create multires DM from original mesh at low level */ 00634 lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple); 00635 cddm->release(cddm); 00636 00637 /* copy subsurf grids and replace them with low displaced grids */ 00638 numGrids = highdm->getNumGrids(highdm); 00639 highGridSize = highdm->getGridSize(highdm); 00640 highGridData = highdm->getGridData(highdm); 00641 lowGridSize = lowdm->getGridSize(lowdm); 00642 lowGridData = lowdm->getGridData(lowdm); 00643 00644 subGridData = MEM_callocN(sizeof(float*)*numGrids, "subGridData*"); 00645 00646 for(i = 0; i < numGrids; ++i) { 00647 /* backup subsurf grids */ 00648 subGridData[i] = MEM_callocN(sizeof(DMGridData)*highGridSize*highGridSize, "subGridData"); 00649 memcpy(subGridData[i], highGridData[i], sizeof(DMGridData)*highGridSize*highGridSize); 00650 00651 /* overwrite with current displaced grids */ 00652 multires_copy_dm_grid(highGridData[i], lowGridData[i], highGridSize, lowGridSize); 00653 } 00654 00655 /* low lower level dm no longer needed at this point */ 00656 lowdm->release(lowdm); 00657 00658 /* subsurf higher levels again with displaced data */ 00659 ss= ((CCGDerivedMesh*)highdm)->ss; 00660 ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); 00661 ccgSubSurf_updateLevels(ss, lvl, NULL, 0); 00662 00663 /* reallocate displacements */ 00664 multires_reallocate_mdisps(me, mdisps, totlvl); 00665 00666 /* compute displacements */ 00667 multiresModifier_disp_run(highdm, me, 1, 0, subGridData, totlvl); 00668 00669 /* free */ 00670 highdm->release(highdm); 00671 for(i = 0; i < numGrids; ++i) 00672 MEM_freeN(subGridData[i]); 00673 MEM_freeN(subGridData); 00674 } 00675 else { 00676 /* only reallocate, nothing to upsample */ 00677 multires_reallocate_mdisps(me, mdisps, totlvl); 00678 } 00679 00680 multires_set_tot_level(ob, mmd, totlvl); 00681 } 00682 00683 void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple) 00684 { 00685 multires_subdivide(mmd, ob, mmd->totlvl+1, updateblock, simple); 00686 } 00687 00688 static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3]) 00689 { 00690 if(axis == 0) { 00691 if(x == gridSize - 1) { 00692 if(y == gridSize - 1) 00693 sub_v3_v3v3(t, gridData[index][x + gridSize*(y - 1)].co, gridData[index][x - 1 + gridSize*(y - 1)].co); 00694 else 00695 sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x - 1 + gridSize*y].co); 00696 } 00697 else 00698 sub_v3_v3v3(t, gridData[index][x + 1 + gridSize*y].co, gridData[index][x + gridSize*y].co); 00699 } 00700 else if(axis == 1) { 00701 if(y == gridSize - 1) { 00702 if(x == gridSize - 1) 00703 sub_v3_v3v3(t, gridData[index][x - 1 + gridSize*y].co, gridData[index][x - 1 + gridSize*(y - 1)].co); 00704 else 00705 sub_v3_v3v3(t, gridData[index][x + gridSize*y].co, gridData[index][x + gridSize*(y - 1)].co); 00706 } 00707 else 00708 sub_v3_v3v3(t, gridData[index][x + gridSize*(y + 1)].co, gridData[index][x + gridSize*y].co); 00709 } 00710 } 00711 00712 static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, int invert, int add, DMGridData **oldGridData, int totlvl) 00713 { 00714 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)dm; 00715 DMGridData **gridData, **subGridData; 00716 MFace *mface = me->mface; 00717 MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); 00718 int *gridOffset; 00719 int i, /*numGrids,*/ gridSize, dGridSize, dSkip; 00720 00721 if(!mdisps) { 00722 if(invert) 00723 mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); 00724 else 00725 return; 00726 } 00727 00728 /*numGrids = dm->getNumGrids(dm);*/ /*UNUSED*/ 00729 gridSize = dm->getGridSize(dm); 00730 gridData = dm->getGridData(dm); 00731 gridOffset = dm->getGridOffset(dm); 00732 subGridData = (oldGridData)? oldGridData: gridData; 00733 00734 dGridSize = multires_side_tot[totlvl]; 00735 dSkip = (dGridSize-1)/(gridSize-1); 00736 00737 #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT) 00738 for(i = 0; i < me->totface; ++i) { 00739 const int numVerts = mface[i].v4 ? 4 : 3; 00740 MDisps *mdisp = &mdisps[i]; 00741 int S, x, y, gIndex = gridOffset[i]; 00742 00743 /* when adding new faces in edit mode, need to allocate disps */ 00744 if(!mdisp->disps) 00745 #pragma omp critical 00746 { 00747 multires_reallocate_mdisps(me, mdisps, totlvl); 00748 } 00749 00750 for(S = 0; S < numVerts; ++S, ++gIndex) { 00751 DMGridData *grid = gridData[gIndex]; 00752 DMGridData *subgrid = subGridData[gIndex]; 00753 float (*dispgrid)[3] = &mdisp->disps[S*dGridSize*dGridSize]; 00754 00755 for(y = 0; y < gridSize; y++) { 00756 for(x = 0; x < gridSize; x++) { 00757 float *co = grid[x + y*gridSize].co; 00758 float *sco = subgrid[x + y*gridSize].co; 00759 float *no = subgrid[x + y*gridSize].no; 00760 float *data = dispgrid[dGridSize*y*dSkip + x*dSkip]; 00761 float mat[3][3], tx[3], ty[3], disp[3], d[3]; 00762 00763 /* construct tangent space matrix */ 00764 grid_tangent(gridSize, gIndex, x, y, 0, subGridData, tx); 00765 normalize_v3(tx); 00766 00767 grid_tangent(gridSize, gIndex, x, y, 1, subGridData, ty); 00768 normalize_v3(ty); 00769 00770 //mul_v3_fl(tx, 1.0f/(gridSize-1)); 00771 //mul_v3_fl(ty, 1.0f/(gridSize-1)); 00772 //cross_v3_v3v3(no, tx, ty); 00773 00774 column_vectors_to_mat3(mat, tx, ty, no); 00775 00776 if(!invert) { 00777 /* convert to object space and add */ 00778 mul_v3_m3v3(disp, mat, data); 00779 add_v3_v3v3(co, sco, disp); 00780 } 00781 else if(!add) { 00782 /* convert difference to tangent space */ 00783 sub_v3_v3v3(disp, co, sco); 00784 invert_m3(mat); 00785 mul_v3_m3v3(data, mat, disp); 00786 } 00787 else { 00788 /* convert difference to tangent space */ 00789 invert_m3(mat); 00790 mul_v3_m3v3(d, mat, co); 00791 add_v3_v3(data, d); 00792 } 00793 } 00794 } 00795 } 00796 } 00797 00798 if(!invert) { 00799 ccgSubSurf_stitchFaces(ccgdm->ss, 0, NULL, 0); 00800 ccgSubSurf_updateNormals(ccgdm->ss, NULL, 0); 00801 } 00802 } 00803 00804 static void multiresModifier_update(DerivedMesh *dm) 00805 { 00806 CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm; 00807 Object *ob; 00808 Mesh *me; 00809 MDisps *mdisps; 00810 MultiresModifierData *mmd; 00811 00812 ob = ccgdm->multires.ob; 00813 me = ccgdm->multires.ob->data; 00814 mmd = ccgdm->multires.mmd; 00815 multires_set_tot_mdisps(me, mmd->totlvl); 00816 CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); 00817 mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); 00818 00819 if(mdisps) { 00820 int lvl = ccgdm->multires.lvl; 00821 int totlvl = ccgdm->multires.totlvl; 00822 00823 if(lvl < totlvl) { 00824 Mesh *me = ob->data; 00825 DerivedMesh *lowdm, *cddm, *highdm; 00826 DMGridData **highGridData, **lowGridData, **subGridData, **gridData, *diffGrid; 00827 CCGSubSurf *ss; 00828 int i, j, numGrids, highGridSize, lowGridSize; 00829 00830 /* create subsurf DM from original mesh at high level */ 00831 if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); 00832 else cddm = CDDM_from_mesh(me, NULL); 00833 DM_set_only_copy(cddm, CD_MASK_BAREMESH); 00834 00835 highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); 00836 00837 /* create multires DM from original mesh and displacements */ 00838 lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple); 00839 cddm->release(cddm); 00840 00841 /* gather grid data */ 00842 numGrids = highdm->getNumGrids(highdm); 00843 highGridSize = highdm->getGridSize(highdm); 00844 highGridData = highdm->getGridData(highdm); 00845 lowGridSize = lowdm->getGridSize(lowdm); 00846 lowGridData = lowdm->getGridData(lowdm); 00847 gridData = dm->getGridData(dm); 00848 00849 subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*"); 00850 diffGrid = MEM_callocN(sizeof(DMGridData)*lowGridSize*lowGridSize, "diff"); 00851 00852 for(i = 0; i < numGrids; ++i) { 00853 /* backup subsurf grids */ 00854 subGridData[i] = MEM_callocN(sizeof(DMGridData)*highGridSize*highGridSize, "subGridData"); 00855 memcpy(subGridData[i], highGridData[i], sizeof(DMGridData)*highGridSize*highGridSize); 00856 00857 /* write difference of subsurf and displaced low level into high subsurf */ 00858 for(j = 0; j < lowGridSize*lowGridSize; ++j) 00859 sub_v3_v3v3(diffGrid[j].co, gridData[i][j].co, lowGridData[i][j].co); 00860 00861 multires_copy_dm_grid(highGridData[i], diffGrid, highGridSize, lowGridSize); 00862 } 00863 00864 /* lower level dm no longer needed at this point */ 00865 MEM_freeN(diffGrid); 00866 lowdm->release(lowdm); 00867 00868 /* subsurf higher levels again with difference of coordinates */ 00869 ss= ((CCGDerivedMesh*)highdm)->ss; 00870 ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); 00871 ccgSubSurf_updateLevels(ss, lvl, NULL, 0); 00872 00873 /* add to displacements */ 00874 multiresModifier_disp_run(highdm, me, 1, 1, subGridData, mmd->totlvl); 00875 00876 /* free */ 00877 highdm->release(highdm); 00878 for(i = 0; i < numGrids; ++i) 00879 MEM_freeN(subGridData[i]); 00880 MEM_freeN(subGridData); 00881 } 00882 else { 00883 DerivedMesh *cddm, *subdm; 00884 00885 if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); 00886 else cddm = CDDM_from_mesh(me, NULL); 00887 DM_set_only_copy(cddm, CD_MASK_BAREMESH); 00888 00889 subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); 00890 cddm->release(cddm); 00891 00892 multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl); 00893 00894 subdm->release(subdm); 00895 } 00896 } 00897 } 00898 00899 void multires_stitch_grids(Object *ob) 00900 { 00901 /* utility for smooth brush */ 00902 if(ob && ob->derivedFinal) { 00903 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*)ob->derivedFinal; 00904 CCGFace **faces; 00905 int totface; 00906 00907 if(ccgdm->pbvh) { 00908 BLI_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void***)&faces, &totface); 00909 00910 if(totface) { 00911 ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface); 00912 MEM_freeN(faces); 00913 } 00914 } 00915 } 00916 } 00917 00918 DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int local_mmd, DerivedMesh *dm, Object *ob, 00919 int useRenderParams, int UNUSED(isFinalCalc)) 00920 { 00921 Mesh *me= ob->data; 00922 DerivedMesh *result; 00923 CCGDerivedMesh *ccgdm; 00924 DMGridData **gridData, **subGridData; 00925 int lvl= multires_get_level(ob, mmd, useRenderParams); 00926 int i, gridSize, numGrids; 00927 00928 if(lvl == 0) 00929 return dm; 00930 00931 result = subsurf_dm_create_local(ob, dm, lvl, 00932 mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, 00933 mmd->flags & eMultiresModifierFlag_PlainUv); 00934 00935 if(!local_mmd) { 00936 ccgdm = (CCGDerivedMesh*)result; 00937 00938 ccgdm->multires.ob = ob; 00939 ccgdm->multires.mmd = mmd; 00940 ccgdm->multires.local_mmd = local_mmd; 00941 ccgdm->multires.lvl = lvl; 00942 ccgdm->multires.totlvl = mmd->totlvl; 00943 ccgdm->multires.modified = 0; 00944 ccgdm->multires.update = multiresModifier_update; 00945 } 00946 00947 numGrids = result->getNumGrids(result); 00948 gridSize = result->getGridSize(result); 00949 gridData = result->getGridData(result); 00950 00951 subGridData = MEM_callocN(sizeof(DMGridData*)*numGrids, "subGridData*"); 00952 00953 for(i = 0; i < numGrids; i++) { 00954 subGridData[i] = MEM_callocN(sizeof(DMGridData)*gridSize*gridSize, "subGridData"); 00955 memcpy(subGridData[i], gridData[i], sizeof(DMGridData)*gridSize*gridSize); 00956 } 00957 00958 multires_set_tot_mdisps(me, mmd->totlvl); 00959 CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); 00960 multiresModifier_disp_run(result, ob->data, 0, 0, subGridData, mmd->totlvl); 00961 00962 for(i = 0; i < numGrids; i++) 00963 MEM_freeN(subGridData[i]); 00964 MEM_freeN(subGridData); 00965 00966 return result; 00967 } 00968 00969 /**** Old Multires code **** 00970 ***************************/ 00971 00972 /* Adapted from sculptmode.c */ 00973 void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v) 00974 { 00975 int x, y, x2, y2; 00976 const int st_max = st - 1; 00977 float urat, vrat, uopp; 00978 float d[4][3], d2[2][3]; 00979 00980 if(u < 0) 00981 u = 0; 00982 else if(u >= st) 00983 u = st_max; 00984 if(v < 0) 00985 v = 0; 00986 else if(v >= st) 00987 v = st_max; 00988 00989 x = floor(u); 00990 y = floor(v); 00991 x2 = x + 1; 00992 y2 = y + 1; 00993 00994 if(x2 >= st) x2 = st_max; 00995 if(y2 >= st) y2 = st_max; 00996 00997 urat = u - x; 00998 vrat = v - y; 00999 uopp = 1 - urat; 01000 01001 mul_v3_v3fl(d[0], disps[y * st + x], uopp); 01002 mul_v3_v3fl(d[1], disps[y * st + x2], urat); 01003 mul_v3_v3fl(d[2], disps[y2 * st + x], uopp); 01004 mul_v3_v3fl(d[3], disps[y2 * st + x2], urat); 01005 01006 add_v3_v3v3(d2[0], d[0], d[1]); 01007 add_v3_v3v3(d2[1], d[2], d[3]); 01008 mul_v3_fl(d2[0], 1 - vrat); 01009 mul_v3_fl(d2[1], vrat); 01010 01011 add_v3_v3v3(out, d2[0], d2[1]); 01012 } 01013 01014 static void old_mdisps_rotate(int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v) 01015 { 01016 float offset = oldside*0.5f - 0.5f; 01017 01018 if(S == 1) { *u= offset + x; *v = offset - y; } 01019 if(S == 2) { *u= offset + y; *v = offset + x; } 01020 if(S == 3) { *u= offset - x; *v = offset + y; } 01021 if(S == 0) { *u= offset - y; *v = offset - x; } 01022 } 01023 01024 static void old_mdisps_convert(MFace *mface, MDisps *mdisp) 01025 { 01026 int newlvl = log(sqrt(mdisp->totdisp)-1)/M_LN2; 01027 int oldlvl = newlvl+1; 01028 int oldside = multires_side_tot[oldlvl]; 01029 int newside = multires_side_tot[newlvl]; 01030 int nvert = (mface->v4)? 4: 3; 01031 int newtotdisp = multires_grid_tot[newlvl]*nvert; 01032 int x, y, S; 01033 float (*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */ 01034 01035 disps = MEM_callocN(sizeof(float) * 3 * newtotdisp, "multires disps"); 01036 01037 out = disps; 01038 for(S = 0; S < nvert; S++) { 01039 for(y = 0; y < newside; ++y) { 01040 for(x = 0; x < newside; ++x, ++out) { 01041 old_mdisps_rotate(S, newside, oldside, x, y, &u, &v); 01042 old_mdisps_bilinear(*out, mdisp->disps, oldside, u, v); 01043 01044 if(S == 1) { (*out)[1]= -(*out)[1]; } 01045 else if(S == 2) { SWAP(float, (*out)[0], (*out)[1]); } 01046 else if(S == 3) { (*out)[0]= -(*out)[0]; } 01047 else if(S == 0) { SWAP(float, (*out)[0], (*out)[1]); (*out)[0]= -(*out)[0]; (*out)[1]= -(*out)[1]; }; 01048 } 01049 } 01050 } 01051 01052 MEM_freeN(mdisp->disps); 01053 01054 mdisp->totdisp= newtotdisp; 01055 mdisp->disps= disps; 01056 } 01057 01058 void multires_load_old_250(Mesh *me) 01059 { 01060 MDisps *mdisps; 01061 int a; 01062 01063 mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); 01064 01065 if(mdisps) { 01066 for(a=0; a<me->totface; a++) 01067 if(mdisps[a].totdisp) 01068 old_mdisps_convert(&me->mface[a], &mdisps[a]); 01069 } 01070 } 01071 01072 /* Does not actually free lvl itself */ 01073 static void multires_free_level(MultiresLevel *lvl) 01074 { 01075 if(lvl) { 01076 if(lvl->faces) MEM_freeN(lvl->faces); 01077 if(lvl->edges) MEM_freeN(lvl->edges); 01078 if(lvl->colfaces) MEM_freeN(lvl->colfaces); 01079 } 01080 } 01081 01082 void multires_free(Multires *mr) 01083 { 01084 if(mr) { 01085 MultiresLevel* lvl= mr->levels.first; 01086 01087 /* Free the first-level data */ 01088 if(lvl) { 01089 CustomData_free(&mr->vdata, lvl->totvert); 01090 CustomData_free(&mr->fdata, lvl->totface); 01091 if(mr->edge_flags) 01092 MEM_freeN(mr->edge_flags); 01093 if(mr->edge_creases) 01094 MEM_freeN(mr->edge_creases); 01095 } 01096 01097 while(lvl) { 01098 multires_free_level(lvl); 01099 lvl= lvl->next; 01100 } 01101 01102 MEM_freeN(mr->verts); 01103 01104 BLI_freelistN(&mr->levels); 01105 01106 MEM_freeN(mr); 01107 } 01108 } 01109 01110 static void create_old_vert_face_map(ListBase **map, IndexNode **mem, const MultiresFace *mface, 01111 const int totvert, const int totface) 01112 { 01113 int i,j; 01114 IndexNode *node = NULL; 01115 01116 (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); 01117 (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); 01118 node = *mem; 01119 01120 /* Find the users */ 01121 for(i = 0; i < totface; ++i){ 01122 for(j = 0; j < (mface[i].v[3]?4:3); ++j, ++node) { 01123 node->index = i; 01124 BLI_addtail(&(*map)[mface[i].v[j]], node); 01125 } 01126 } 01127 } 01128 01129 static void create_old_vert_edge_map(ListBase **map, IndexNode **mem, const MultiresEdge *medge, 01130 const int totvert, const int totedge) 01131 { 01132 int i,j; 01133 IndexNode *node = NULL; 01134 01135 (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); 01136 (*mem) = MEM_callocN(sizeof(IndexNode) * totedge*2, "vert edge map mem"); 01137 node = *mem; 01138 01139 /* Find the users */ 01140 for(i = 0; i < totedge; ++i){ 01141 for(j = 0; j < 2; ++j, ++node) { 01142 node->index = i; 01143 BLI_addtail(&(*map)[medge[i].v[j]], node); 01144 } 01145 } 01146 } 01147 01148 static MultiresFace *find_old_face(ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4) 01149 { 01150 IndexNode *n1; 01151 int v[4], i, j; 01152 01153 v[0]= v1; 01154 v[1]= v2; 01155 v[2]= v3; 01156 v[3]= v4; 01157 01158 for(n1 = map[v1].first; n1; n1 = n1->next) { 01159 int fnd[4] = {0, 0, 0, 0}; 01160 01161 for(i = 0; i < 4; ++i) { 01162 for(j = 0; j < 4; ++j) { 01163 if(v[i] == faces[n1->index].v[j]) 01164 fnd[i] = 1; 01165 } 01166 } 01167 01168 if(fnd[0] && fnd[1] && fnd[2] && fnd[3]) 01169 return &faces[n1->index]; 01170 } 01171 01172 return NULL; 01173 } 01174 01175 static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2) 01176 { 01177 IndexNode *n1, *n2; 01178 01179 for(n1 = map[v1].first; n1; n1 = n1->next) { 01180 for(n2 = map[v2].first; n2; n2 = n2->next) { 01181 if(n1->index == n2->index) 01182 return &edges[n1->index]; 01183 } 01184 } 01185 01186 return NULL; 01187 } 01188 01189 static void multires_load_old_edges(ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov) 01190 { 01191 int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid; 01192 vvmap[dst + mov] = emid; 01193 01194 if(lvl->next->next) { 01195 multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2); 01196 multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2); 01197 } 01198 } 01199 01200 static void multires_load_old_faces(ListBase **fmap, ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, 01201 int v1, int v2, int v3, int v4, int st2, int st3) 01202 { 01203 int fmid; 01204 int emid13, emid14, emid23, emid24; 01205 01206 if(lvl && lvl->next) { 01207 fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid; 01208 vvmap[dst] = fmid; 01209 01210 emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid; 01211 emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid; 01212 emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid; 01213 emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid; 01214 01215 01216 multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 + st3, 01217 fmid, v2, emid23, emid24, st2, st3 / 2); 01218 01219 multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 + st3, 01220 emid14, emid24, fmid, v4, st2, st3 / 2); 01221 01222 multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 - st3, 01223 emid13, emid23, v3, fmid, st2, st3 / 2); 01224 01225 multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 - st3, 01226 v1, fmid, emid13, emid14, st2, st3 / 2); 01227 01228 if(lvl->next->next) { 01229 multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3); 01230 multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3); 01231 multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3); 01232 multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3); 01233 } 01234 } 01235 } 01236 01237 static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert) 01238 { 01239 CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; 01240 CCGSubSurf *ss = ccgdm->ss; 01241 DMGridData *vd; 01242 int index; 01243 int totvert, totedge, totface; 01244 int gridSize = ccgSubSurf_getGridSize(ss); 01245 int edgeSize = ccgSubSurf_getEdgeSize(ss); 01246 int i = 0; 01247 01248 totface = ccgSubSurf_getNumFaces(ss); 01249 for(index = 0; index < totface; index++) { 01250 CCGFace *f = ccgdm->faceMap[index].face; 01251 int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); 01252 01253 vd= ccgSubSurf_getFaceCenterData(f); 01254 copy_v3_v3(vd->co, mvert[i].co); 01255 i++; 01256 01257 for(S = 0; S < numVerts; S++) { 01258 for(x = 1; x < gridSize - 1; x++, i++) { 01259 vd= ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); 01260 copy_v3_v3(vd->co, mvert[i].co); 01261 } 01262 } 01263 01264 for(S = 0; S < numVerts; S++) { 01265 for(y = 1; y < gridSize - 1; y++) { 01266 for(x = 1; x < gridSize - 1; x++, i++) { 01267 vd= ccgSubSurf_getFaceGridData(ss, f, S, x, y); 01268 copy_v3_v3(vd->co, mvert[i].co); 01269 } 01270 } 01271 } 01272 } 01273 01274 totedge = ccgSubSurf_getNumEdges(ss); 01275 for(index = 0; index < totedge; index++) { 01276 CCGEdge *e = ccgdm->edgeMap[index].edge; 01277 int x; 01278 01279 for(x = 1; x < edgeSize - 1; x++, i++) { 01280 vd= ccgSubSurf_getEdgeData(ss, e, x); 01281 copy_v3_v3(vd->co, mvert[i].co); 01282 } 01283 } 01284 01285 totvert = ccgSubSurf_getNumVerts(ss); 01286 for(index = 0; index < totvert; index++) { 01287 CCGVert *v = ccgdm->vertMap[index].vert; 01288 01289 vd= ccgSubSurf_getVertData(ss, v); 01290 copy_v3_v3(vd->co, mvert[i].co); 01291 i++; 01292 } 01293 01294 ccgSubSurf_updateToFaces(ss, 0, NULL, 0); 01295 } 01296 01297 /* Loads a multires object stored in the old Multires struct into the new format */ 01298 static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) 01299 { 01300 MultiresLevel *lvl, *lvl1; 01301 Multires *mr= me->mr; 01302 MVert *vsrc, *vdst; 01303 unsigned int src, dst; 01304 int st = multires_side_tot[totlvl - 1] - 1; 01305 int extedgelen = multires_side_tot[totlvl] - 2; 01306 int *vvmap; // inorder for dst, map to src 01307 int crossedgelen; 01308 int s, x, tottri, totquad; 01309 unsigned int i, j, totvert; 01310 01311 src = 0; 01312 vsrc = mr->verts; 01313 vdst = dm->getVertArray(dm); 01314 totvert = (unsigned int)dm->getNumVerts(dm); 01315 vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap"); 01316 01317 lvl1 = mr->levels.first; 01318 /* Load base verts */ 01319 for(i = 0; i < lvl1->totvert; ++i) { 01320 vvmap[totvert - lvl1->totvert + i] = src; 01321 ++src; 01322 } 01323 01324 /* Original edges */ 01325 dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge; 01326 for(i = 0; i < lvl1->totedge; ++i) { 01327 int ldst = dst + extedgelen * i; 01328 int lsrc = src; 01329 lvl = lvl1->next; 01330 01331 for(j = 2; j <= mr->level_count; ++j) { 01332 int base = multires_side_tot[totlvl - j + 1] - 2; 01333 int skip = multires_side_tot[totlvl - j + 2] - 1; 01334 int st = multires_side_tot[j - 1] - 1; 01335 01336 for(x = 0; x < st; ++x) 01337 vvmap[ldst + base + x * skip] = lsrc + st * i + x; 01338 01339 lsrc += lvl->totvert - lvl->prev->totvert; 01340 lvl = lvl->next; 01341 } 01342 } 01343 01344 /* Center points */ 01345 dst = 0; 01346 for(i = 0; i < lvl1->totface; ++i) { 01347 int sides = lvl1->faces[i].v[3] ? 4 : 3; 01348 01349 vvmap[dst] = src + lvl1->totedge + i; 01350 dst += 1 + sides * (st - 1) * st; 01351 } 01352 01353 01354 /* The rest is only for level 3 and up */ 01355 if(lvl1->next && lvl1->next->next) { 01356 ListBase **fmap, **emap; 01357 IndexNode **fmem, **emem; 01358 01359 /* Face edge cross */ 01360 tottri = totquad = 0; 01361 crossedgelen = multires_side_tot[totlvl - 1] - 2; 01362 dst = 0; 01363 for(i = 0; i < lvl1->totface; ++i) { 01364 int sides = lvl1->faces[i].v[3] ? 4 : 3; 01365 01366 lvl = lvl1->next->next; 01367 ++dst; 01368 01369 for(j = 3; j <= mr->level_count; ++j) { 01370 int base = multires_side_tot[totlvl - j + 1] - 2; 01371 int skip = multires_side_tot[totlvl - j + 2] - 1; 01372 int st = pow(2, j - 2); 01373 int st2 = pow(2, j - 3); 01374 int lsrc = lvl->prev->totvert; 01375 01376 /* Skip exterior edge verts */ 01377 lsrc += lvl1->totedge * st; 01378 01379 /* Skip earlier face edge crosses */ 01380 lsrc += st2 * (tottri * 3 + totquad * 4); 01381 01382 for(s = 0; s < sides; ++s) { 01383 for(x = 0; x < st2; ++x) { 01384 vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc; 01385 ++lsrc; 01386 } 01387 } 01388 01389 lvl = lvl->next; 01390 } 01391 01392 dst += sides * (st - 1) * st; 01393 01394 if(sides == 4) ++totquad; 01395 else ++tottri; 01396 01397 } 01398 01399 /* calculate vert to edge/face maps for each level (except the last) */ 01400 fmap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires fmap"); 01401 emap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires emap"); 01402 fmem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires fmem"); 01403 emem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires emem"); 01404 lvl = lvl1; 01405 for(i = 0; i < (unsigned int)mr->level_count - 1; ++i) { 01406 create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface); 01407 create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge); 01408 lvl = lvl->next; 01409 } 01410 01411 /* Interior face verts */ 01412 /* lvl = lvl1->next->next; */ /* UNUSED */ 01413 dst = 0; 01414 for(j = 0; j < lvl1->totface; ++j) { 01415 int sides = lvl1->faces[j].v[3] ? 4 : 3; 01416 int ldst = dst + 1 + sides * (st - 1); 01417 01418 for(s = 0; s < sides; ++s) { 01419 int st2 = multires_side_tot[totlvl - 1] - 2; 01420 int st3 = multires_side_tot[totlvl - 2] - 2; 01421 int st4 = st3 == 0 ? 1 : (st3 + 1) / 2; 01422 int mid = ldst + st2 * st3 + st3; 01423 int cv = lvl1->faces[j].v[s]; 01424 int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1]; 01425 int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1]; 01426 01427 multires_load_old_faces(fmap, emap, lvl1->next, vvmap, mid, 01428 vvmap[dst], cv, 01429 find_old_edge(emap[0], lvl1->edges, pv, cv)->mid, 01430 find_old_edge(emap[0], lvl1->edges, cv, nv)->mid, 01431 st2, st4); 01432 01433 ldst += (st - 1) * (st - 1); 01434 } 01435 01436 01437 dst = ldst; 01438 } 01439 01440 /*lvl = lvl->next;*/ /*UNUSED*/ 01441 01442 for(i = 0; i < (unsigned int)(mr->level_count - 1); ++i) { 01443 MEM_freeN(fmap[i]); 01444 MEM_freeN(fmem[i]); 01445 MEM_freeN(emap[i]); 01446 MEM_freeN(emem[i]); 01447 } 01448 01449 MEM_freeN(fmap); 01450 MEM_freeN(emap); 01451 MEM_freeN(fmem); 01452 MEM_freeN(emem); 01453 } 01454 01455 /* Transfer verts */ 01456 for(i = 0; i < totvert; ++i) 01457 copy_v3_v3(vdst[i].co, vsrc[vvmap[i]].co); 01458 01459 MEM_freeN(vvmap); 01460 01461 multires_mvert_to_ss(dm, vdst); 01462 } 01463 01464 /* Copy the first-level vcol data to the mesh, if it exists */ 01465 /* Warning: higher-level vcol data will be lost */ 01466 static void multires_load_old_vcols(Mesh *me) 01467 { 01468 MultiresLevel *lvl; 01469 MultiresColFace *colface; 01470 MCol *mcol; 01471 int i, j; 01472 01473 if(!(lvl = me->mr->levels.first)) 01474 return; 01475 01476 if(!(colface = lvl->colfaces)) 01477 return; 01478 01479 /* older multires format never supported multiple vcol layers, 01480 so we can assume the active vcol layer is the correct one */ 01481 if(!(mcol = CustomData_get_layer(&me->fdata, CD_MCOL))) 01482 return; 01483 01484 for(i = 0; i < me->totface; ++i) { 01485 for(j = 0; j < 4; ++j) { 01486 mcol[i*4 + j].a = colface[i].col[j].a; 01487 mcol[i*4 + j].r = colface[i].col[j].r; 01488 mcol[i*4 + j].g = colface[i].col[j].g; 01489 mcol[i*4 + j].b = colface[i].col[j].b; 01490 } 01491 } 01492 } 01493 01494 /* Copy the first-level face-flag data to the mesh */ 01495 static void multires_load_old_face_flags(Mesh *me) 01496 { 01497 MultiresLevel *lvl; 01498 MultiresFace *faces; 01499 int i; 01500 01501 if(!(lvl = me->mr->levels.first)) 01502 return; 01503 01504 if(!(faces = lvl->faces)) 01505 return; 01506 01507 for(i = 0; i < me->totface; ++i) 01508 me->mface[i].flag = faces[i].flag; 01509 } 01510 01511 void multires_load_old(Object *ob, Mesh *me) 01512 { 01513 MultiresLevel *lvl; 01514 ModifierData *md; 01515 MultiresModifierData *mmd; 01516 DerivedMesh *dm, *orig; 01517 CustomDataLayer *l; 01518 int i; 01519 01520 /* Load original level into the mesh */ 01521 lvl = me->mr->levels.first; 01522 CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert); 01523 CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge); 01524 CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface); 01525 me->totvert = lvl->totvert; 01526 me->totedge = lvl->totedge; 01527 me->totface = lvl->totface; 01528 me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); 01529 me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge); 01530 me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); 01531 memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert); 01532 for(i = 0; i < me->totedge; ++i) { 01533 me->medge[i].v1 = lvl->edges[i].v[0]; 01534 me->medge[i].v2 = lvl->edges[i].v[1]; 01535 } 01536 for(i = 0; i < me->totface; ++i) { 01537 me->mface[i].v1 = lvl->faces[i].v[0]; 01538 me->mface[i].v2 = lvl->faces[i].v[1]; 01539 me->mface[i].v3 = lvl->faces[i].v[2]; 01540 me->mface[i].v4 = lvl->faces[i].v[3]; 01541 me->mface[i].mat_nr = lvl->faces[i].mat_nr; 01542 } 01543 01544 /* Add a multires modifier to the object */ 01545 md = ob->modifiers.first; 01546 while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) 01547 md = md->next; 01548 mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires); 01549 BLI_insertlinkbefore(&ob->modifiers, md, mmd); 01550 01551 for(i = 0; i < me->mr->level_count - 1; ++i) 01552 multiresModifier_subdivide(mmd, ob, 1, 0); 01553 01554 mmd->lvl = mmd->totlvl; 01555 orig = CDDM_from_mesh(me, NULL); 01556 dm = multires_dm_create_from_derived(mmd, 0, orig, ob, 0, 0); 01557 01558 multires_load_old_dm(dm, me, mmd->totlvl+1); 01559 01560 multires_dm_mark_as_modified(dm); 01561 dm->release(dm); 01562 orig->release(orig); 01563 01564 /* Copy the first-level data to the mesh */ 01565 for(i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; ++i, ++l) 01566 CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert); 01567 for(i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; ++i, ++l) 01568 CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface); 01569 memset(&me->mr->vdata, 0, sizeof(CustomData)); 01570 memset(&me->mr->fdata, 0, sizeof(CustomData)); 01571 01572 multires_load_old_vcols(me); 01573 multires_load_old_face_flags(me); 01574 01575 /* Remove the old multires */ 01576 multires_free(me->mr); 01577 me->mr= NULL; 01578 } 01579 01580 static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob) 01581 { 01582 MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); 01583 MultiresModifierData *to_mmd= get_multires_modifier(scene, to_ob, 1); 01584 01585 if(!mmd) { 01586 /* object could have MDISP even when there is no multires modifier 01587 this could lead to troubles due to i've got no idea how mdisp could be 01588 upsampled correct without modifier data. 01589 just remove mdisps if no multires present (nazgul) */ 01590 01591 Mesh *me= (Mesh*)ob->data; 01592 01593 CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface); 01594 CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); 01595 } 01596 01597 if(!mmd || !to_mmd) return; 01598 01599 if(mmd->totlvl>to_mmd->totlvl) multires_del_higher(mmd, ob, to_mmd->totlvl); 01600 else multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple); 01601 } 01602 01603 static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) 01604 { 01605 DerivedMesh *dm= NULL, *cddm= NULL, *subdm= NULL; 01606 DMGridData **gridData, **subGridData; 01607 Mesh *me= (Mesh*)ob->data; 01608 MFace *mface= me->mface; 01609 MDisps *mdisps; 01610 int *gridOffset; 01611 int i, /*numGrids,*/ gridSize, dGridSize, dSkip, totvert; 01612 float (*vertCos)[3] = NULL; 01613 MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); 01614 MultiresModifierData high_mmd; 01615 01616 CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); 01617 mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS); 01618 01619 if(!mdisps || !mmd || !mmd->totlvl) return; 01620 01621 /* we need derived mesh created from highest resolution */ 01622 high_mmd= *mmd; 01623 high_mmd.lvl= high_mmd.totlvl; 01624 01625 /* unscaled multires with applied displacement */ 01626 subdm= get_multires_dm(scene, &high_mmd, ob); 01627 01628 /* prepare scaled CDDM to create ccgDN */ 01629 cddm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); 01630 01631 totvert= cddm->getNumVerts(cddm); 01632 vertCos= MEM_mallocN(sizeof(*vertCos) * totvert, "multiresScale vertCos"); 01633 cddm->getVertCos(cddm, vertCos); 01634 for(i=0; i<totvert; i++) 01635 mul_m3_v3(smat, vertCos[i]); 01636 CDDM_apply_vert_coords(cddm, vertCos); 01637 MEM_freeN(vertCos); 01638 01639 /* scaled ccgDM for tangent space of object with applied scale */ 01640 dm= subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); 01641 cddm->release(cddm); 01642 01643 /*numGrids= dm->getNumGrids(dm);*/ /*UNUSED*/ 01644 gridSize= dm->getGridSize(dm); 01645 gridData= dm->getGridData(dm); 01646 gridOffset= dm->getGridOffset(dm); 01647 subGridData= subdm->getGridData(subdm); 01648 01649 dGridSize= multires_side_tot[high_mmd.totlvl]; 01650 dSkip= (dGridSize-1)/(gridSize-1); 01651 01652 #pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT) 01653 for(i = 0; i < me->totface; ++i) { 01654 const int numVerts= mface[i].v4 ? 4 : 3; 01655 MDisps *mdisp= &mdisps[i]; 01656 int S, x, y, gIndex = gridOffset[i]; 01657 01658 for(S = 0; S < numVerts; ++S, ++gIndex) { 01659 DMGridData *grid= gridData[gIndex]; 01660 DMGridData *subgrid= subGridData[gIndex]; 01661 float (*dispgrid)[3]= &mdisp->disps[S*dGridSize*dGridSize]; 01662 01663 for(y = 0; y < gridSize; y++) { 01664 for(x = 0; x < gridSize; x++) { 01665 float *co= grid[x + y*gridSize].co; 01666 float *sco= subgrid[x + y*gridSize].co; 01667 float *no= grid[x + y*gridSize].no; 01668 float *data= dispgrid[dGridSize*y*dSkip + x*dSkip]; 01669 float mat[3][3], tx[3], ty[3], disp[3]; 01670 01671 /* construct tangent space matrix */ 01672 grid_tangent(gridSize, gIndex, x, y, 0, gridData, tx); 01673 normalize_v3(tx); 01674 01675 grid_tangent(gridSize, gIndex, x, y, 1, gridData, ty); 01676 normalize_v3(ty); 01677 01678 column_vectors_to_mat3(mat, tx, ty, no); 01679 01680 /* scale subgrid coord and calculate displacement */ 01681 mul_m3_v3(smat, sco); 01682 sub_v3_v3v3(disp, sco, co); 01683 01684 /* convert difference to tangent space */ 01685 invert_m3(mat); 01686 mul_v3_m3v3(data, mat, disp); 01687 } 01688 } 01689 } 01690 } 01691 01692 dm->release(dm); 01693 subdm->release(subdm); 01694 } 01695 01696 int multires_mdisp_corners(MDisps *s) 01697 { 01698 int lvl= 13; 01699 01700 while(lvl > 0) { 01701 int side = (1 << (lvl-1)) + 1; 01702 if ((s->totdisp % (side*side)) == 0) return s->totdisp / (side*side); 01703 lvl--; 01704 } 01705 01706 return 0; 01707 } 01708 01709 void multiresModifier_scale_disp(Scene *scene, Object *ob) 01710 { 01711 float smat[3][3]; 01712 01713 /* object's scale matrix */ 01714 object_scale_to_mat3(ob, smat); 01715 01716 multires_apply_smat(scene, ob, smat); 01717 } 01718 01719 void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) 01720 { 01721 float smat[3][3], tmat[3][3], mat[3][3]; 01722 multires_sync_levels(scene, ob, to_ob); 01723 01724 /* construct scale matrix for displacement */ 01725 object_scale_to_mat3(to_ob, tmat); 01726 invert_m3(tmat); 01727 object_scale_to_mat3(ob, smat); 01728 mul_m3_m3m3(mat, smat, tmat); 01729 01730 multires_apply_smat(scene, ob, mat); 01731 } 01732 01733 /* update multires data after topology changing */ 01734 void multires_topology_changed(Scene *scene, Object *ob) 01735 { 01736 Mesh *me= (Mesh*)ob->data; 01737 MDisps *mdisp= NULL, *cur= NULL; 01738 int i, grid= 0, corners; 01739 MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); 01740 01741 if(mmd) 01742 multires_set_tot_mdisps(me, mmd->totlvl); 01743 01744 CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); 01745 mdisp= CustomData_get_layer(&me->fdata, CD_MDISPS); 01746 01747 if(!mdisp) return; 01748 01749 cur= mdisp; 01750 for(i = 0; i < me->totface; i++, cur++) { 01751 if(mdisp->totdisp) { 01752 corners= multires_mdisp_corners(mdisp); 01753 grid= mdisp->totdisp / corners; 01754 01755 break; 01756 } 01757 } 01758 01759 for(i = 0; i < me->totface; i++, mdisp++) { 01760 int nvert= me->mface[i].v4 ? 4 : 3; 01761 01762 /* allocate memory for mdisp, the whole disp layer would be erased otherwise */ 01763 if(!mdisp->totdisp || !mdisp->disps) { 01764 if(grid) { 01765 mdisp->totdisp= nvert*grid; 01766 mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology"); 01767 } 01768 01769 continue; 01770 } 01771 01772 corners= multires_mdisp_corners(mdisp); 01773 01774 if(corners!=nvert) { 01775 mdisp->totdisp= (mdisp->totdisp/corners)*nvert; 01776 01777 if(mdisp->disps) 01778 MEM_freeN(mdisp->disps); 01779 01780 mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology"); 01781 } 01782 } 01783 } 01784 01785 /* makes displacement along grid boundary symmetrical */ 01786 void multires_mdisp_smooth_bounds(MDisps *disps) 01787 { 01788 int x, y, side, S, corners; 01789 float (*out)[3]; 01790 01791 corners = multires_mdisp_corners(disps); 01792 side = sqrt(disps->totdisp / corners); 01793 01794 out = disps->disps; 01795 for(S = 0; S < corners; S++) { 01796 for(y = 0; y < side; ++y) { 01797 for(x = 0; x < side; ++x, ++out) { 01798 float (*dispgrid)[3]; 01799 float *data; 01800 01801 if(x != 0 && y != 0) continue; 01802 01803 if(corners == 4) { 01804 if(S == 0) { 01805 if(y == 0) { 01806 dispgrid = &disps->disps[1*side*side]; 01807 data = dispgrid[side * x + 0]; 01808 01809 (*out)[0] = (*out)[0] + data[1]; 01810 (*out)[1] = (*out)[1] - data[0]; 01811 (*out)[2] = (*out)[2] + data[2]; 01812 01813 mul_v3_fl(*out, 0.5); 01814 01815 data[0] = -(*out)[1]; 01816 data[1] = (*out)[0]; 01817 data[2] = (*out)[2]; 01818 } else if (x == 0) { 01819 dispgrid = &disps->disps[3 * side * side]; 01820 data = dispgrid[side * 0 + y]; 01821 01822 (*out)[0] = (*out)[0] - data[1]; 01823 (*out)[1] = (*out)[1] + data[0]; 01824 (*out)[2] = (*out)[2] + data[2]; 01825 01826 mul_v3_fl(*out, 0.5); 01827 01828 data[0] = (*out)[1]; 01829 data[1] = -(*out)[0]; 01830 data[2] = (*out)[2]; 01831 } 01832 } else if (S == 2) { 01833 if(y == 0) { 01834 dispgrid = &disps->disps[3 * side * side]; 01835 data = dispgrid[side * x + 0]; 01836 01837 (*out)[0] = (*out)[0] + data[1]; 01838 (*out)[1] = (*out)[1] - data[0]; 01839 (*out)[2] = (*out)[2] + data[2]; 01840 01841 mul_v3_fl(*out, 0.5); 01842 01843 data[0] = -(*out)[1]; 01844 data[1] = (*out)[0]; 01845 data[2] = (*out)[2]; 01846 } else if(x == 0) { 01847 dispgrid = &disps->disps[1 * side * side]; 01848 data = dispgrid[side * 0 + y]; 01849 01850 (*out)[0] = (*out)[0] - data[1]; 01851 (*out)[1] = (*out)[1] + data[0]; 01852 (*out)[2] = (*out)[2] + data[2]; 01853 01854 mul_v3_fl(*out, 0.5); 01855 01856 data[0] = (*out)[1]; 01857 data[1] = -(*out)[0]; 01858 data[2] = (*out)[2]; 01859 } 01860 } 01861 } else if (corners == 3) { 01862 if(S == 0) { 01863 if(y == 0) { 01864 dispgrid = &disps->disps[1*side*side]; 01865 data = dispgrid[side * x + 0]; 01866 01867 (*out)[0] = (*out)[0] + data[1]; 01868 (*out)[1] = (*out)[1] - data[0]; 01869 (*out)[2] = (*out)[2] + data[2]; 01870 01871 mul_v3_fl(*out, 0.5); 01872 01873 data[0] = -(*out)[1]; 01874 data[1] = (*out)[0]; 01875 data[2] = (*out)[2]; 01876 } else if (x == 0) { 01877 dispgrid = &disps->disps[2 * side * side]; 01878 data = dispgrid[side * 0 + y]; 01879 01880 (*out)[0] = (*out)[0] - data[1]; 01881 (*out)[1] = (*out)[1] + data[0]; 01882 (*out)[2] = (*out)[2] + data[2]; 01883 01884 mul_v3_fl(*out, 0.5); 01885 01886 data[0] = (*out)[1]; 01887 data[1] = -(*out)[0]; 01888 data[2] = (*out)[2]; 01889 } 01890 } else if (S == 2) { 01891 if(x == 0) { 01892 dispgrid = &disps->disps[1 * side * side]; 01893 data = dispgrid[side * 0 + y]; 01894 01895 (*out)[0] = (*out)[0] - data[1]; 01896 (*out)[1] = (*out)[1] + data[0]; 01897 (*out)[2] = (*out)[2] + data[2]; 01898 01899 mul_v3_fl(*out, 0.5); 01900 01901 data[0] = (*out)[1]; 01902 data[1] = -(*out)[0]; 01903 data[2] = (*out)[2]; 01904 } 01905 } 01906 } 01907 } 01908 } 01909 } 01910 } 01911 01912 /***************** Multires interpolation stuff *****************/ 01913 01914 static void mdisp_get_crn_rect(int face_side, float crn[3][4][2]) 01915 { 01916 float offset = face_side*0.5f - 0.5f; 01917 float mid[2]; 01918 01919 mid[0] = offset * 4 / 3; 01920 mid[1] = offset * 2 / 3; 01921 01922 crn[0][0][0] = mid[0]; crn[0][0][1] = mid[1]; 01923 crn[0][1][0] = offset; crn[0][1][1] = 0; 01924 crn[0][2][0] = 0; crn[0][2][1] = 0; 01925 crn[0][3][0] = offset; crn[0][3][1] = offset; 01926 01927 crn[1][0][0] = mid[0]; crn[1][0][1] = mid[1]; 01928 crn[1][1][0] = offset * 2; crn[1][1][1] = offset; 01929 crn[1][2][0] = offset * 2; crn[1][2][1] = 0; 01930 crn[1][3][0] = offset; crn[1][3][1] = 0; 01931 01932 crn[2][0][0] = mid[0]; crn[2][0][1] = mid[1]; 01933 crn[2][1][0] = offset; crn[2][1][1] = offset; 01934 crn[2][2][0] = offset * 2; crn[2][2][1] = offset * 2; 01935 crn[2][3][0] = offset * 2; crn[2][3][1] = offset; 01936 } 01937 01938 static int mdisp_pt_in_crn(float p[2], float crn[4][2]) 01939 { 01940 float v[2][2]; 01941 float a[2][2]; 01942 01943 sub_v2_v2v2(v[0], crn[1], crn[0]); 01944 sub_v2_v2v2(v[1], crn[3], crn[0]); 01945 01946 sub_v2_v2v2(a[0], p, crn[0]); 01947 sub_v2_v2v2(a[1], crn[2], crn[0]); 01948 01949 if(cross_v2v2(a[0], v[0]) * cross_v2v2(a[1], v[0]) < 0) 01950 return 0; 01951 01952 if(cross_v2v2(a[0], v[1]) * cross_v2v2(a[1], v[1]) < 0) 01953 return 0; 01954 01955 return 1; 01956 } 01957 01958 static void face_to_crn_interp(float u, float v, float v1[2], float v2[2], float v3[2], float v4[2], float *x) 01959 { 01960 float a = (v4[1]-v3[1])*v2[0]+(-v4[1]+v3[1])*v1[0]+(-v2[1]+v1[1])*v4[0]+(v2[1]-v1[1])*v3[0]; 01961 float b = (v3[1]-v)*v2[0]+(v4[1]-2*v3[1]+v)*v1[0]+(-v4[1]+v3[1]+v2[1]-v1[1])*u+(v4[0]-v3[0])*v-v1[1]*v4[0]+(-v2[1]+2*v1[1])*v3[0]; 01962 float c = (v3[1]-v)*v1[0]+(-v3[1]+v1[1])*u+v3[0]*v-v1[1]*v3[0]; 01963 float d = b * b - 4 * a * c; 01964 float x1, x2; 01965 01966 if(a == 0) { 01967 *x = -c / b; 01968 return; 01969 } 01970 01971 x1 = (-b - sqrtf(d)) / (2 * a); 01972 x2 = (-b + sqrtf(d)) / (2 * a); 01973 01974 *x = maxf(x1, x2); 01975 } 01976 01977 void mdisp_rot_crn_to_face(const int S, const int corners, const int face_side, const float x, const float y, float *u, float *v) 01978 { 01979 float offset = face_side*0.5f - 0.5f; 01980 01981 if(corners == 4) { 01982 if(S == 1) { *u= offset + x; *v = offset - y; } 01983 if(S == 2) { *u= offset + y; *v = offset + x; } 01984 if(S == 3) { *u= offset - x; *v = offset + y; } 01985 if(S == 0) { *u= offset - y; *v = offset - x; } 01986 } else { 01987 float crn[3][4][2], vec[4][2]; 01988 float p[2]; 01989 01990 mdisp_get_crn_rect(face_side, crn); 01991 01992 interp_v2_v2v2(vec[0], crn[S][0], crn[S][1], x / offset); 01993 interp_v2_v2v2(vec[1], crn[S][3], crn[S][2], x / offset); 01994 interp_v2_v2v2(vec[2], crn[S][0], crn[S][3], y / offset); 01995 interp_v2_v2v2(vec[3], crn[S][1], crn[S][2], y / offset); 01996 01997 isect_seg_seg_v2_point(vec[0], vec[1], vec[2], vec[3], p); 01998 01999 (*u) = p[0]; 02000 (*v) = p[1]; 02001 } 02002 } 02003 02004 /* Find per-corner coordinate with given per-face UV coord */ 02005 int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y) 02006 { 02007 const float offset = face_side*0.5f - 0.5f; 02008 int S = 0; 02009 02010 if (corners == 4) { 02011 if(u <= offset && v <= offset) S = 0; 02012 else if(u > offset && v <= offset) S = 1; 02013 else if(u > offset && v > offset) S = 2; 02014 else if(u <= offset && v >= offset) S = 3; 02015 02016 if(S == 0) { 02017 *y = offset - u; 02018 *x = offset - v; 02019 } else if(S == 1) { 02020 *x = u - offset; 02021 *y = offset - v; 02022 } else if(S == 2) { 02023 *y = u - offset; 02024 *x = v - offset; 02025 } else if(S == 3) { 02026 *x= offset - u; 02027 *y = v - offset; 02028 } 02029 } else { 02030 int grid_size = offset; 02031 float w = (face_side - 1) - u - v; 02032 float W1, W2; 02033 02034 if (u >= v && u >= w) {S = 0; W1= w; W2= v;} 02035 else if (v >= u && v >= w) {S = 1; W1 = u; W2 = w;} 02036 else {S = 2; W1 = v; W2 = u;} 02037 02038 W1 /= (face_side-1); 02039 W2 /= (face_side-1); 02040 02041 *x = (1-(2*W1)/(1-W2)) * grid_size; 02042 *y = (1-(2*W2)/(1-W1)) * grid_size; 02043 } 02044 02045 return S; 02046 } 02047 02048 /* Find per-corner coordinate with given per-face UV coord 02049 Practically as the previous funciton but it assumes a bit different coordinate system for triangles 02050 which is optimized for MDISP layer interpolation: 02051 02052 v 02053 ^ 02054 | /| 02055 | / | 02056 | / | 02057 |/______|___> u 02058 02059 */ 02060 int mdisp_rot_face_to_quad_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y) 02061 { 02062 const float offset = face_side*0.5f - 0.5f; 02063 int S = 0; 02064 02065 if (corners == 4) { 02066 if(u <= offset && v <= offset) S = 0; 02067 else if(u > offset && v <= offset) S = 1; 02068 else if(u > offset && v > offset) S = 2; 02069 else if(u <= offset && v >= offset) S = 3; 02070 02071 if(S == 0) { 02072 *y = offset - u; 02073 *x = offset - v; 02074 } else if(S == 1) { 02075 *x = u - offset; 02076 *y = offset - v; 02077 } else if(S == 2) { 02078 *y = u - offset; 02079 *x = v - offset; 02080 } else if(S == 3) { 02081 *x= offset - u; 02082 *y = v - offset; 02083 } 02084 } else { 02085 float crn[3][4][2]; 02086 float p[2] = {u, v}; 02087 02088 mdisp_get_crn_rect(face_side, crn); 02089 02090 for (S = 0; S < 3; ++S) { 02091 if (mdisp_pt_in_crn(p, crn[S])) 02092 break; 02093 } 02094 02095 face_to_crn_interp(u, v, crn[S][0], crn[S][1], crn[S][3], crn[S][2], &p[0]); 02096 face_to_crn_interp(u, v, crn[S][0], crn[S][3], crn[S][1], crn[S][2], &p[1]); 02097 02098 *x = p[0] * offset; 02099 *y = p[1] * offset; 02100 } 02101 02102 return S; 02103 } 02104 02105 void mdisp_apply_weight(const int S, const int corners, int x, int y, const int face_side, 02106 float crn_weight[4][2], float *u_r, float *v_r) 02107 { 02108 float u, v, xl, yl; 02109 float mid1[2], mid2[2], mid3[2]; 02110 02111 mdisp_rot_crn_to_face(S, corners, face_side, x, y, &u, &v); 02112 02113 if(corners == 4) { 02114 xl = u / (face_side - 1); 02115 yl = v / (face_side - 1); 02116 02117 mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; 02118 mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; 02119 mid2[0] = crn_weight[3][0] * (1 - xl) + crn_weight[2][0] * xl; 02120 mid2[1] = crn_weight[3][1] * (1 - xl) + crn_weight[2][1] * xl; 02121 mid3[0] = mid1[0] * (1 - yl) + mid2[0] * yl; 02122 mid3[1] = mid1[1] * (1 - yl) + mid2[1] * yl; 02123 } else { 02124 yl = v / (face_side - 1); 02125 02126 if(v == face_side - 1) xl = 1; 02127 else xl = 1 - (face_side - 1 - u) / (face_side - 1 - v); 02128 02129 mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; 02130 mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; 02131 mid3[0] = mid1[0] * (1 - yl) + crn_weight[2][0] * yl; 02132 mid3[1] = mid1[1] * (1 - yl) + crn_weight[2][1] * yl; 02133 } 02134 02135 *u_r = mid3[0]; 02136 *v_r = mid3[1]; 02137 } 02138 02139 void mdisp_flip_disp(const int S, const int corners, const float axis_x[2], const float axis_y[2], float disp[3]) 02140 { 02141 float crn_x[2], crn_y[2]; 02142 float vx[2], vy[2], coord[2]; 02143 02144 if (corners == 4) { 02145 float x[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; 02146 float y[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; 02147 02148 copy_v2_v2(crn_x, x[S]); 02149 copy_v2_v2(crn_y, y[S]); 02150 02151 mul_v2_v2fl(vx, crn_x, disp[0]); 02152 mul_v2_v2fl(vy, crn_y, disp[1]); 02153 add_v2_v2v2(coord, vx, vy); 02154 02155 project_v2_v2v2(vx, coord, axis_x); 02156 project_v2_v2v2(vy, coord, axis_y); 02157 02158 disp[0] = len_v2(vx); 02159 disp[1] = len_v2(vy); 02160 02161 if(dot_v2v2(vx, axis_x) < 0) 02162 disp[0] = -disp[0]; 02163 02164 if(dot_v2v2(vy, axis_y) < 0) 02165 disp[1] = -disp[1]; 02166 } else { 02167 /* XXX: it was very overhead code to support displacement flipping 02168 for case of tris without visible profit. 02169 Maybe its not really big limitation? for now? (nazgul) */ 02170 disp[0] = 0; 02171 disp[1] = 0; 02172 } 02173 } 02174 02175 /* Join two triangular displacements into one quad 02176 Corners mapping: 02177 2 -------- 3 02178 | \ tri2 | 02179 | \ | 02180 | tri1 \ | 02181 0 -------- 1 */ 02182 void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2) 02183 { 02184 int side, st; 02185 int S, x, y, crn; 02186 float face_u, face_v, crn_u, crn_v; 02187 float (*out)[3]; 02188 MDisps *src; 02189 02190 if(dst->disps) 02191 MEM_freeN(dst->disps); 02192 02193 side = sqrt(tri1->totdisp / 3); 02194 st = (side<<1)-1; 02195 02196 dst->totdisp = 4 * side * side; 02197 out = dst->disps = MEM_callocN(3*dst->totdisp*sizeof(float), "join disps"); 02198 02199 for(S = 0; S < 4; S++) 02200 for(y = 0; y < side; ++y) 02201 for(x = 0; x < side; ++x, ++out) { 02202 mdisp_rot_crn_to_face(S, 4, st, x, y, &face_u, &face_v); 02203 face_u = st - 1 - face_u; 02204 02205 if(face_v > face_u) { 02206 src = tri2; 02207 face_u = st - 1 - face_u; 02208 face_v = st - 1 - face_v; 02209 } else src = tri1; 02210 02211 crn = mdisp_rot_face_to_quad_crn(3, st, face_u, face_v, &crn_u, &crn_v); 02212 02213 old_mdisps_bilinear((*out), &src->disps[crn*side*side], side, crn_u, crn_v); 02214 (*out)[0] = 0; 02215 (*out)[1] = 0; 02216 } 02217 }