|
|
|
|
@@ -46,6 +46,7 @@
|
|
|
|
|
#include "BKE_scene.h"
|
|
|
|
|
#include "BKE_subsurf.h"
|
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
#include "BKE_object.h"
|
|
|
|
|
|
|
|
|
|
#include "CCGSubSurf.h"
|
|
|
|
|
|
|
|
|
|
@@ -89,6 +90,34 @@ MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData *
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* used for applying scale on mdisps layer and syncing subdivide levels when joining objects */
|
|
|
|
|
static MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob)
|
|
|
|
|
{
|
|
|
|
|
ModifierData *md;
|
|
|
|
|
MultiresModifierData *mmd= NULL, *firstmmd= NULL;
|
|
|
|
|
|
|
|
|
|
/* find first active multires modifier */
|
|
|
|
|
for(md = ob->modifiers.first; md; md = md->next) {
|
|
|
|
|
if(md->type == eModifierType_Multires) {
|
|
|
|
|
if(!firstmmd)
|
|
|
|
|
firstmmd= (MultiresModifierData*)md;
|
|
|
|
|
|
|
|
|
|
if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
|
|
|
|
|
mmd= (MultiresModifierData*)md;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!mmd) {
|
|
|
|
|
/* active multires have not been found
|
|
|
|
|
try to use first one */
|
|
|
|
|
return firstmmd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mmd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int multires_get_level(Object *ob, MultiresModifierData *mmd, int render)
|
|
|
|
|
{
|
|
|
|
|
if(render)
|
|
|
|
|
@@ -389,11 +418,9 @@ static void multires_copy_dm_grid(DMGridData *gridA, DMGridData *gridB, int size
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */
|
|
|
|
|
void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction)
|
|
|
|
|
static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
|
|
|
|
|
{
|
|
|
|
|
Mesh *me = get_mesh(ob);
|
|
|
|
|
int lvl = multires_get_level(ob, mmd, 0);
|
|
|
|
|
Mesh *me = (Mesh*)ob->data;
|
|
|
|
|
int levels = mmd->totlvl - lvl;
|
|
|
|
|
MDisps *mdisps;
|
|
|
|
|
|
|
|
|
|
@@ -403,7 +430,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire
|
|
|
|
|
|
|
|
|
|
multires_force_update(ob);
|
|
|
|
|
|
|
|
|
|
if(mdisps && levels > 0 && direction == 1) {
|
|
|
|
|
if(mdisps && levels > 0) {
|
|
|
|
|
if(lvl > 0) {
|
|
|
|
|
int nsize = multires_side_tot[lvl];
|
|
|
|
|
int hsize = multires_side_tot[mmd->totlvl];
|
|
|
|
|
@@ -442,6 +469,27 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire
|
|
|
|
|
multires_set_tot_level(ob, mmd, lvl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */
|
|
|
|
|
void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction)
|
|
|
|
|
{
|
|
|
|
|
Mesh *me = get_mesh(ob);
|
|
|
|
|
int lvl = multires_get_level(ob, mmd, 0);
|
|
|
|
|
int levels = mmd->totlvl - lvl;
|
|
|
|
|
MDisps *mdisps;
|
|
|
|
|
|
|
|
|
|
multires_set_tot_mdisps(me, mmd->totlvl);
|
|
|
|
|
CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
|
|
|
|
|
mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
|
|
|
|
|
|
|
|
|
|
multires_force_update(ob);
|
|
|
|
|
|
|
|
|
|
if(mdisps && levels > 0 && direction == 1) {
|
|
|
|
|
multires_del_higher(mmd, ob, lvl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
multires_set_tot_level(ob, mmd, lvl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple)
|
|
|
|
|
{
|
|
|
|
|
MultiresModifierData mmd;
|
|
|
|
|
@@ -471,12 +519,11 @@ static DerivedMesh *subsurf_dm_create_local(Object *UNUSED(ob), DerivedMesh *dm,
|
|
|
|
|
return subsurf_make_derived_from_derived(dm, &smd, 0, NULL, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple)
|
|
|
|
|
void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl, int updateblock, int simple)
|
|
|
|
|
{
|
|
|
|
|
Mesh *me = ob->data;
|
|
|
|
|
MDisps *mdisps;
|
|
|
|
|
int lvl= mmd->totlvl;
|
|
|
|
|
int totlvl= mmd->totlvl+1;
|
|
|
|
|
|
|
|
|
|
if(totlvl > multires_max_levels)
|
|
|
|
|
return;
|
|
|
|
|
@@ -549,6 +596,11 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat
|
|
|
|
|
multires_set_tot_level(ob, mmd, totlvl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple)
|
|
|
|
|
{
|
|
|
|
|
multires_subdivide(mmd, ob, mmd->totlvl+1, updateblock, simple);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void grid_tangent(int gridSize, int index, int x, int y, int axis, DMGridData **gridData, float t[3])
|
|
|
|
|
{
|
|
|
|
|
if(axis == 0) {
|
|
|
|
|
@@ -1386,3 +1438,141 @@ void multires_load_old(Object *ob, Mesh *me)
|
|
|
|
|
me->mr= NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
|
|
|
|
|
{
|
|
|
|
|
MultiresModifierData *mmd= get_multires_modifier(scene, ob);
|
|
|
|
|
MultiresModifierData *to_mmd= get_multires_modifier(scene, to_ob);
|
|
|
|
|
|
|
|
|
|
if(!mmd) {
|
|
|
|
|
/* object could have MDISP even when there is no multires modifier
|
|
|
|
|
this could lead to troubles due to i've got no idea how mdisp could be
|
|
|
|
|
upsampled correct without modifier data.
|
|
|
|
|
just remove mdisps if no multires present (nazgul) */
|
|
|
|
|
|
|
|
|
|
Mesh *me= (Mesh*)ob->data;
|
|
|
|
|
|
|
|
|
|
CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
|
|
|
|
|
CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!mmd || !to_mmd) return;
|
|
|
|
|
|
|
|
|
|
if(mmd->totlvl>to_mmd->totlvl) multires_del_higher(mmd, ob, to_mmd->totlvl);
|
|
|
|
|
else multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
|
|
|
|
|
{
|
|
|
|
|
DerivedMesh *dm= NULL, *cddm= NULL, *subdm= NULL;
|
|
|
|
|
DMGridData **gridData, **subGridData;
|
|
|
|
|
Mesh *me= (Mesh*)ob->data;
|
|
|
|
|
MFace *mface= me->mface;
|
|
|
|
|
MVert *mvert= NULL;
|
|
|
|
|
MDisps *mdisps;
|
|
|
|
|
int *gridOffset;
|
|
|
|
|
int i, numGrids, gridSize, dGridSize, dSkip, totvert;
|
|
|
|
|
float (*vertCos)[3] = NULL;
|
|
|
|
|
MultiresModifierData *mmd= get_multires_modifier(scene, ob);
|
|
|
|
|
|
|
|
|
|
CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface);
|
|
|
|
|
mdisps= CustomData_get_layer(&me->fdata, CD_MDISPS);
|
|
|
|
|
|
|
|
|
|
if(!mdisps || !mmd) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* unscaled multires with applied displacement */
|
|
|
|
|
subdm= get_multires_dm(scene, mmd, ob);
|
|
|
|
|
|
|
|
|
|
/* prepare scaled CDDM to create ccgDN */
|
|
|
|
|
cddm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
|
|
|
|
|
|
|
|
|
|
totvert= cddm->getNumVerts(cddm);
|
|
|
|
|
vertCos= MEM_mallocN(sizeof(*vertCos) * totvert, "multiresScale vertCos");
|
|
|
|
|
cddm->getVertCos(cddm, vertCos);
|
|
|
|
|
for(i=0; i<totvert; i++)
|
|
|
|
|
mul_m3_v3(smat, vertCos[i]);
|
|
|
|
|
CDDM_apply_vert_coords(cddm, vertCos);
|
|
|
|
|
MEM_freeN(vertCos);
|
|
|
|
|
|
|
|
|
|
mvert= cddm->getVertArray(cddm);
|
|
|
|
|
|
|
|
|
|
/* scaled ccgDM for tangent space of object with applied scale */
|
|
|
|
|
dm= subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0);
|
|
|
|
|
cddm->release(cddm);
|
|
|
|
|
|
|
|
|
|
numGrids= dm->getNumGrids(dm);
|
|
|
|
|
gridSize= dm->getGridSize(dm);
|
|
|
|
|
gridData= dm->getGridData(dm);
|
|
|
|
|
gridOffset= dm->getGridOffset(dm);
|
|
|
|
|
subGridData= subdm->getGridData(subdm);
|
|
|
|
|
|
|
|
|
|
dGridSize= multires_side_tot[mmd->totlvl];
|
|
|
|
|
dSkip= (dGridSize-1)/(gridSize-1);
|
|
|
|
|
|
|
|
|
|
#pragma omp parallel for private(i) if(me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT)
|
|
|
|
|
for(i = 0; i < me->totface; ++i) {
|
|
|
|
|
const int numVerts= mface[i].v4 ? 4 : 3;
|
|
|
|
|
MDisps *mdisp= &mdisps[i];
|
|
|
|
|
int S, x, y, gIndex = gridOffset[i];
|
|
|
|
|
|
|
|
|
|
for(S = 0; S < numVerts; ++S, ++gIndex) {
|
|
|
|
|
DMGridData *grid= gridData[gIndex];
|
|
|
|
|
DMGridData *subgrid= subGridData[gIndex];
|
|
|
|
|
float (*dispgrid)[3]= &mdisp->disps[S*dGridSize*dGridSize];
|
|
|
|
|
|
|
|
|
|
for(y = 0; y < gridSize; y++) {
|
|
|
|
|
for(x = 0; x < gridSize; x++) {
|
|
|
|
|
float *co= grid[x + y*gridSize].co;
|
|
|
|
|
float *sco= subgrid[x + y*gridSize].co;
|
|
|
|
|
float *no= grid[x + y*gridSize].no;
|
|
|
|
|
float *data= dispgrid[dGridSize*y*dSkip + x*dSkip];
|
|
|
|
|
float mat[3][3], tx[3], ty[3], disp[3];
|
|
|
|
|
|
|
|
|
|
/* construct tangent space matrix */
|
|
|
|
|
grid_tangent(gridSize, gIndex, x, y, 0, gridData, tx);
|
|
|
|
|
normalize_v3(tx);
|
|
|
|
|
|
|
|
|
|
grid_tangent(gridSize, gIndex, x, y, 1, gridData, ty);
|
|
|
|
|
normalize_v3(ty);
|
|
|
|
|
|
|
|
|
|
column_vectors_to_mat3(mat, tx, ty, no);
|
|
|
|
|
|
|
|
|
|
/* scale subgrid coord and calculate displacement */
|
|
|
|
|
mul_m3_v3(smat, sco);
|
|
|
|
|
sub_v3_v3v3(disp, sco, co);
|
|
|
|
|
|
|
|
|
|
/* convert difference to tangent space */
|
|
|
|
|
invert_m3(mat);
|
|
|
|
|
mul_v3_m3v3(data, mat, disp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dm->release(dm);
|
|
|
|
|
subdm->release(subdm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void multiresModifier_scale_disp(Scene *scene, Object *ob)
|
|
|
|
|
{
|
|
|
|
|
float smat[3][3];
|
|
|
|
|
|
|
|
|
|
/* object's scale matrix */
|
|
|
|
|
object_scale_to_mat3(ob, smat);
|
|
|
|
|
|
|
|
|
|
multires_apply_smat(scene, ob, smat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
|
|
|
|
|
{
|
|
|
|
|
float smat[3][3], tmat[3][3], mat[3][3];
|
|
|
|
|
multires_sync_levels(scene, ob, to_ob);
|
|
|
|
|
|
|
|
|
|
/* construct scale matrix for displacement */
|
|
|
|
|
object_scale_to_mat3(to_ob, tmat);
|
|
|
|
|
invert_m3(tmat);
|
|
|
|
|
object_scale_to_mat3(ob, smat);
|
|
|
|
|
mul_m3_m3m3(mat, smat, tmat);
|
|
|
|
|
|
|
|
|
|
multires_apply_smat(scene, ob, mat);
|
|
|
|
|
}
|
|
|
|
|
|