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